Commit d0039106 authored by Aric Stewart's avatar Aric Stewart Committed by Alexandre Julliard

hidclass: All reports read or written to user space lead with a reportId.

parent 95298b44
......@@ -919,10 +919,8 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
new_report(wine_report, input_features[0]);
data->dwInputReportCount++;
if (input_features[0]->caps.ReportID != 0)
bitOffset = 8;
else
bitOffset = 0;
/* Room for the reportID */
bitOffset = 8;
for (i = 0; i < i_count; i++)
{
......@@ -933,10 +931,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
new_report(wine_report, input_features[i]);
data->dwInputReportCount++;
bitLength = max(bitOffset, bitLength);
if (input_features[i]->caps.ReportID != 0)
bitOffset = 8;
else
bitOffset = 0;
bitOffset = 8;
}
build_elements(wine_report, input_features[i], &bitOffset);
count_elements(input_features[i], &data->caps.NumberInputButtonCaps,
......@@ -954,10 +949,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
data->dwOutputReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
new_report(wine_report, output_features[0]);
data->dwOutputReportCount++;
if (output_features[0]->caps.ReportID != 0)
bitOffset = 8;
else
bitOffset = 0;
bitOffset = 8;
for (i = 0; i < o_count; i++)
{
......@@ -968,10 +960,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
new_report(wine_report, output_features[i]);
data->dwOutputReportCount++;
bitLength = max(bitOffset, bitLength);
if (output_features[0]->caps.ReportID != 0)
bitOffset = 8;
else
bitOffset = 0;
bitOffset = 8;
}
build_elements(wine_report, output_features[i], &bitOffset);
count_elements(output_features[i], &data->caps.NumberOutputButtonCaps,
......@@ -989,10 +978,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
data->dwFeatureReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
new_report(wine_report, feature_features[0]);
data->dwFeatureReportCount++;
if (feature_features[0]->caps.ReportID != 0)
bitOffset = 8;
else
bitOffset = 0;
bitOffset = 8;
for (i = 0; i < f_count; i++)
{
......@@ -1003,10 +989,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
new_report(wine_report, feature_features[i]);
data->dwFeatureReportCount++;
bitLength = max(bitOffset, bitLength);
if (feature_features[0]->caps.ReportID != 0)
bitOffset = 8;
else
bitOffset = 0;
bitOffset = 8;
}
build_elements(wine_report, feature_features[i], &bitOffset);
count_elements(feature_features[i], &data->caps.NumberFeatureButtonCaps,
......
......@@ -197,6 +197,32 @@ void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device
IoDeleteDevice(device);
}
static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, ULONG buffer_length, ULONG *out_length)
{
BOOL zero_id = (packet->reportId == 0);
*out_length = 0;
if ((zero_id && buffer_length > packet->reportBufferLen) ||
(!zero_id && buffer_length >= packet->reportBufferLen))
{
if (packet->reportId != 0)
{
memcpy(buffer, packet->reportBuffer, packet->reportBufferLen);
*out_length = packet->reportBufferLen;
}
else
{
buffer[0] = 0;
memcpy(&buffer[1], packet->reportBuffer, packet->reportBufferLen);
*out_length = packet->reportBufferLen + 1;
}
return STATUS_SUCCESS;
}
else
return STATUS_BUFFER_OVERFLOW;
}
static void HID_Device_processQueue(DEVICE_OBJECT *device)
{
LIST_ENTRY *entry;
......@@ -217,20 +243,14 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device)
RingBuffer_Read(ext->ring_buffer, ptr, packet, &buffer_size);
if (buffer_size)
{
NTSTATUS rc;
ULONG out_length;
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
packet->reportBuffer = (BYTE *)packet + sizeof(*packet);
TRACE_(hid_report)("Processing Request (%i)\n",ptr);
if (irpsp->Parameters.Read.Length >= packet->reportBufferLen)
{
memcpy(irp->AssociatedIrp.SystemBuffer, packet->reportBuffer, packet->reportBufferLen);
irp->IoStatus.Information = packet->reportBufferLen;
irp->IoStatus.u.Status = STATUS_SUCCESS;
}
else
{
irp->IoStatus.Information = 0;
irp->IoStatus.u.Status = STATUS_BUFFER_OVERFLOW;
}
rc = copy_packet_into_buffer(packet, irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.Read.Length, &out_length);
irp->IoStatus.u.Status = rc;
irp->IoStatus.Information = out_length;
}
else
{
......@@ -331,7 +351,10 @@ static DWORD CALLBACK hid_device_thread(void *args)
if (!exit_now && irp->IoStatus.u.Status == STATUS_SUCCESS)
{
packet->reportBufferLen = irp->IoStatus.Information;
packet->reportId = packet->reportBuffer[0];
if (ext->preparseData->InputReports[0].reportID)
packet->reportId = packet->reportBuffer[0];
else
packet->reportId = 0;
RingBuffer_Write(ext->ring_buffer, packet);
HID_Device_processQueue(device);
}
......@@ -461,9 +484,17 @@ static NTSTATUS HID_set_to_device(DEVICE_OBJECT *device, IRP *irp)
NTSTATUS rc;
TRACE_(hid_report)("Device %p Buffer length %i Buffer %p\n", device, irpsp->Parameters.DeviceIoControl.InputBufferLength, irp->AssociatedIrp.SystemBuffer);
packet.reportBuffer = irp->AssociatedIrp.SystemBuffer;
packet.reportId = ((char*)irp->AssociatedIrp.SystemBuffer)[0];
packet.reportBufferLen = irpsp->Parameters.DeviceIoControl.InputBufferLength;
packet.reportId = ((BYTE*)irp->AssociatedIrp.SystemBuffer)[0];
if (packet.reportId == 0)
{
packet.reportBuffer = &((BYTE*)irp->AssociatedIrp.SystemBuffer)[1];
packet.reportBufferLen = irpsp->Parameters.DeviceIoControl.InputBufferLength - 1;
}
else
{
packet.reportBuffer = irp->AssociatedIrp.SystemBuffer;
packet.reportBufferLen = irpsp->Parameters.DeviceIoControl.InputBufferLength;
}
TRACE_(hid_report)("(id %i, len %i buffer %p)\n", packet.reportId, packet.reportBufferLen, packet.reportBuffer);
rc = call_minidriver(irpsp->Parameters.DeviceIoControl.IoControlCode,
......@@ -636,20 +667,15 @@ NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp)
if (buffer_size)
{
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
NTSTATUS rc;
ULONG out_length;
packet->reportBuffer = (BYTE *)packet + sizeof(*packet);
TRACE_(hid_report)("Got Packet %p %i\n", packet->reportBuffer, packet->reportBufferLen);
if (irpsp->Parameters.Read.Length >= packet->reportBufferLen)
{
memcpy(irp->AssociatedIrp.SystemBuffer, packet->reportBuffer, packet->reportBufferLen);
irp->IoStatus.Information = packet->reportBufferLen;
irp->IoStatus.u.Status = STATUS_SUCCESS;
}
else
{
irp->IoStatus.Information = 0;
irp->IoStatus.u.Status = STATUS_BUFFER_OVERFLOW;
}
IoCompleteRequest( irp, IO_NO_INCREMENT );
rc = copy_packet_into_buffer(packet, irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.Read.Length, &out_length);
irp->IoStatus.Information = out_length;
irp->IoStatus.u.Status = rc;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
else
{
......@@ -671,9 +697,17 @@ NTSTATUS WINAPI HID_Device_write(DEVICE_OBJECT *device, IRP *irp)
irp->IoStatus.Information = 0;
TRACE_(hid_report)("Device %p Buffer length %i Buffer %p\n", device, irpsp->Parameters.Write.Length, irp->AssociatedIrp.SystemBuffer);
packet.reportBuffer = irp->AssociatedIrp.SystemBuffer;
packet.reportId = ((char*)irp->AssociatedIrp.SystemBuffer)[0];
packet.reportBufferLen = irpsp->Parameters.Write.Length;
packet.reportId = ((BYTE*)irp->AssociatedIrp.SystemBuffer)[0];
if (packet.reportId == 0)
{
packet.reportBuffer = &((BYTE*)irp->AssociatedIrp.SystemBuffer)[1];
packet.reportBufferLen = irpsp->Parameters.Write.Length - 1;
}
else
{
packet.reportBuffer = irp->AssociatedIrp.SystemBuffer;
packet.reportBufferLen = irpsp->Parameters.Write.Length;
}
TRACE_(hid_report)("(id %i, len %i buffer %p)\n", packet.reportId, packet.reportBufferLen, packet.reportBuffer);
rc = call_minidriver(IOCTL_HID_WRITE_REPORT, device, NULL, 0, &packet, sizeof(packet));
......
......@@ -288,7 +288,23 @@ static NTSTATUS hidraw_set_output_report(DEVICE_OBJECT *device, UCHAR id, BYTE *
{
struct platform_private* ext = impl_from_DEVICE_OBJECT(device);
ssize_t rc;
rc = write(ext->device_fd, report, length);
if (id != 0)
rc = write(ext->device_fd, report, length);
else
{
BYTE report_buffer[1024];
if (length + 1 > sizeof(report_buffer))
{
ERR("Output report buffer too small\n");
return STATUS_UNSUCCESSFUL;
}
report_buffer[0] = 0;
memcpy(&report_buffer[1], report, length);
rc = write(ext->device_fd, report_buffer, length + 1);
}
if (rc > 0)
{
*written = rc;
......@@ -306,6 +322,7 @@ static NTSTATUS hidraw_get_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE
#ifdef HAVE_LINUX_HIDRAW_H
int rc;
struct platform_private* ext = impl_from_DEVICE_OBJECT(device);
report[0] = id;
length = min(length, 0x1fff);
rc = ioctl(ext->device_fd, HIDIOCGFEATURE(length), report);
if (rc >= 0)
......@@ -329,8 +346,25 @@ static NTSTATUS hidraw_set_feature_report(DEVICE_OBJECT *device, UCHAR id, BYTE
#ifdef HAVE_LINUX_HIDRAW_H
int rc;
struct platform_private* ext = impl_from_DEVICE_OBJECT(device);
BYTE *feature_buffer;
BYTE buffer[1024];
if (id == 0)
{
if (length + 1 > sizeof(feature_buffer))
{
ERR("Output feature buffer too small\n");
return STATUS_UNSUCCESSFUL;
}
buffer[0] = 0;
memcpy(&buffer[1], report, length);
feature_buffer = buffer;
length = length + 1;
}
else
feature_buffer = report;
length = min(length, 0x1fff);
rc = ioctl(ext->device_fd, HIDIOCSFEATURE(length), report);
rc = ioctl(ext->device_fd, HIDIOCSFEATURE(length), feature_buffer);
if (rc >= 0)
{
*written = rc;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment