hidclass.sys: Introduce new hid_device_xfer_report helper.
From HID_IOCTL_GET_INPUT_REPORT code, to factor report buffer transfer, and use it for HID_IOCTL_GET_FEATURE. Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1f3fdb3cb6
commit
6fd356e009
|
@ -299,46 +299,48 @@ static void handle_minidriver_string( BASE_DEVICE_EXTENSION *ext, IRP *irp, SHOR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HID_get_feature( BASE_DEVICE_EXTENSION *ext, IRP *irp )
|
static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP *irp )
|
||||||
{
|
{
|
||||||
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
|
const WINE_HIDP_PREPARSED_DATA *preparsed = ext->u.pdo.preparsed_data;
|
||||||
HID_XFER_PACKET *packet;
|
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
|
||||||
DWORD len;
|
ULONG report_len = 0, buffer_len = stack->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
BYTE *out_buffer;
|
BYTE *buffer = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority );
|
||||||
|
BYTE report_id = HID_INPUT_VALUE_CAPS( preparsed )->report_id;
|
||||||
|
HID_XFER_PACKET packet;
|
||||||
|
|
||||||
irp->IoStatus.Information = 0;
|
switch (code)
|
||||||
|
|
||||||
out_buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
|
|
||||||
TRACE_(hid_report)("Device %p Buffer length %i Buffer %p\n", ext, irpsp->Parameters.DeviceIoControl.OutputBufferLength, out_buffer);
|
|
||||||
|
|
||||||
if (!irpsp->Parameters.DeviceIoControl.OutputBufferLength || !out_buffer)
|
|
||||||
{
|
{
|
||||||
irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
case IOCTL_HID_GET_INPUT_REPORT:
|
||||||
|
report_len = preparsed->caps.InputReportByteLength;
|
||||||
|
break;
|
||||||
|
case IOCTL_HID_GET_FEATURE:
|
||||||
|
report_len = preparsed->caps.FeatureReportByteLength;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buffer_len < report_len)
|
||||||
|
{
|
||||||
|
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = sizeof(*packet) + irpsp->Parameters.DeviceIoControl.OutputBufferLength;
|
packet.reportId = buffer[0];
|
||||||
packet = malloc(len);
|
packet.reportBuffer = buffer;
|
||||||
packet->reportBufferLen = irpsp->Parameters.DeviceIoControl.OutputBufferLength;
|
packet.reportBufferLen = buffer_len;
|
||||||
packet->reportBuffer = ((BYTE*)packet) + sizeof(*packet);
|
|
||||||
packet->reportId = out_buffer[0];
|
|
||||||
|
|
||||||
TRACE_(hid_report)("(id %i, len %i buffer %p)\n", packet->reportId, packet->reportBufferLen, packet->reportBuffer);
|
if (!report_id)
|
||||||
|
|
||||||
call_minidriver( IOCTL_HID_GET_FEATURE, ext->u.pdo.parent_fdo, NULL, 0, packet, sizeof(*packet),
|
|
||||||
&irp->IoStatus );
|
|
||||||
|
|
||||||
if (irp->IoStatus.Status == STATUS_SUCCESS)
|
|
||||||
{
|
{
|
||||||
irp->IoStatus.Information = packet->reportBufferLen;
|
packet.reportId = 0;
|
||||||
memcpy(out_buffer, packet->reportBuffer, packet->reportBufferLen);
|
packet.reportBuffer++;
|
||||||
|
packet.reportBufferLen--;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
irp->IoStatus.Information = 0;
|
|
||||||
|
|
||||||
TRACE_(hid_report)( "Result 0x%x get %li bytes\n", irp->IoStatus.Status, irp->IoStatus.Information );
|
call_minidriver( code, ext->u.pdo.parent_fdo, NULL, 0, &packet, sizeof(packet), &irp->IoStatus );
|
||||||
|
|
||||||
free(packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HID_set_to_device( DEVICE_OBJECT *device, IRP *irp )
|
static void HID_set_to_device( DEVICE_OBJECT *device, IRP *irp )
|
||||||
|
@ -390,10 +392,9 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
{
|
{
|
||||||
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
|
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
|
||||||
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
|
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
|
||||||
const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data;
|
|
||||||
BYTE report_id = HID_INPUT_VALUE_CAPS( data )->report_id;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
BOOL removed;
|
BOOL removed;
|
||||||
|
ULONG code;
|
||||||
KIRQL irql;
|
KIRQL irql;
|
||||||
|
|
||||||
irp->IoStatus.Information = 0;
|
irp->IoStatus.Information = 0;
|
||||||
|
@ -411,7 +412,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
return STATUS_DELETE_PENDING;
|
return STATUS_DELETE_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
|
switch ((code = irpsp->Parameters.DeviceIoControl.IoControlCode))
|
||||||
{
|
{
|
||||||
case IOCTL_HID_GET_POLL_FREQUENCY_MSEC:
|
case IOCTL_HID_GET_POLL_FREQUENCY_MSEC:
|
||||||
TRACE("IOCTL_HID_GET_POLL_FREQUENCY_MSEC\n");
|
TRACE("IOCTL_HID_GET_POLL_FREQUENCY_MSEC\n");
|
||||||
|
@ -469,38 +470,6 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
handle_IOCTL_HID_GET_COLLECTION_DESCRIPTOR( irp, ext );
|
handle_IOCTL_HID_GET_COLLECTION_DESCRIPTOR( irp, ext );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_HID_GET_INPUT_REPORT:
|
|
||||||
{
|
|
||||||
HID_XFER_PACKET packet;
|
|
||||||
ULONG buffer_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength;
|
|
||||||
BYTE *buffer = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority );
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (buffer_len < data->caps.InputReportByteLength)
|
|
||||||
{
|
|
||||||
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
packet.reportId = buffer[0];
|
|
||||||
packet.reportBuffer = buffer;
|
|
||||||
packet.reportBufferLen = buffer_len;
|
|
||||||
|
|
||||||
if (!report_id)
|
|
||||||
{
|
|
||||||
packet.reportId = 0;
|
|
||||||
packet.reportBuffer++;
|
|
||||||
packet.reportBufferLen--;
|
|
||||||
}
|
|
||||||
|
|
||||||
call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, &packet,
|
|
||||||
sizeof(packet), &irp->IoStatus );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS:
|
case IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS:
|
||||||
{
|
{
|
||||||
irp->IoStatus.Information = 0;
|
irp->IoStatus.Information = 0;
|
||||||
|
@ -527,7 +496,8 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_HID_GET_FEATURE:
|
case IOCTL_HID_GET_FEATURE:
|
||||||
HID_get_feature( ext, irp );
|
case IOCTL_HID_GET_INPUT_REPORT:
|
||||||
|
hid_device_xfer_report( ext, code, irp );
|
||||||
break;
|
break;
|
||||||
case IOCTL_HID_SET_FEATURE:
|
case IOCTL_HID_SET_FEATURE:
|
||||||
case IOCTL_HID_SET_OUTPUT_REPORT:
|
case IOCTL_HID_SET_OUTPUT_REPORT:
|
||||||
|
|
|
@ -570,9 +570,8 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
||||||
ok(!in_size, "got input size %u\n", in_size);
|
ok(!in_size, "got input size %u\n", in_size);
|
||||||
ok(out_size == sizeof(*packet), "got output size %u\n", out_size);
|
ok(out_size == sizeof(*packet), "got output size %u\n", out_size);
|
||||||
|
|
||||||
todo_wine_if(packet->reportId == 0x5a || packet->reportId == 0xa5)
|
todo_wine_if(packet->reportId == 0x5a)
|
||||||
ok(packet->reportId == report_id, "got id %u\n", packet->reportId);
|
ok(packet->reportId == report_id, "got id %u\n", packet->reportId);
|
||||||
todo_wine_if(packet->reportBufferLen == 16)
|
|
||||||
ok(packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen);
|
ok(packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen);
|
||||||
ok(!!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer);
|
ok(!!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer);
|
||||||
|
|
||||||
|
|
|
@ -2486,13 +2486,11 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = HidD_GetFeature(file, report, 0);
|
ret = HidD_GetFeature(file, report, 0);
|
||||||
ok(!ret, "HidD_GetFeature succeeded\n");
|
ok(!ret, "HidD_GetFeature succeeded\n");
|
||||||
todo_wine ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetFeature returned error %u\n", GetLastError());
|
ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetFeature returned error %u\n", GetLastError());
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = HidD_GetFeature(file, report, caps.FeatureReportByteLength - 1);
|
ret = HidD_GetFeature(file, report, caps.FeatureReportByteLength - 1);
|
||||||
todo_wine
|
|
||||||
ok(!ret, "HidD_GetFeature succeeded\n");
|
ok(!ret, "HidD_GetFeature succeeded\n");
|
||||||
todo_wine
|
|
||||||
ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_CRC),
|
ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_CRC),
|
||||||
"HidD_GetFeature returned error %u\n", GetLastError());
|
"HidD_GetFeature returned error %u\n", GetLastError());
|
||||||
|
|
||||||
|
@ -2510,21 +2508,19 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ok(ret, "HidD_GetFeature failed, last error %u\n", GetLastError());
|
ok(ret, "HidD_GetFeature failed, last error %u\n", GetLastError());
|
||||||
todo_wine ok(buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0]);
|
ok(buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = HidD_GetFeature(file, report, caps.FeatureReportByteLength);
|
ret = HidD_GetFeature(file, report, caps.FeatureReportByteLength);
|
||||||
ok(ret, "HidD_GetFeature failed, last error %u\n", GetLastError());
|
ok(ret, "HidD_GetFeature failed, last error %u\n", GetLastError());
|
||||||
todo_wine_if(!report_id)
|
|
||||||
ok(report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id);
|
ok(report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id);
|
||||||
|
|
||||||
value = caps.FeatureReportByteLength * 2;
|
value = caps.FeatureReportByteLength * 2;
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = sync_ioctl(file, IOCTL_HID_GET_FEATURE, NULL, 0, report, &value);
|
ret = sync_ioctl(file, IOCTL_HID_GET_FEATURE, NULL, 0, report, &value);
|
||||||
ok(ret, "IOCTL_HID_GET_FEATURE failed, last error %u\n", GetLastError());
|
ok(ret, "IOCTL_HID_GET_FEATURE failed, last error %u\n", GetLastError());
|
||||||
todo_wine ok(value == 3, "got length %u, expected 3\n", value);
|
ok(value == 3, "got length %u, expected 3\n", value);
|
||||||
todo_wine_if(!report_id)
|
|
||||||
ok(report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id);
|
ok(report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue