Commit de0fb2ad authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

hidclass.sys: Use hidparse.sys instead of internal parser.

parent a290c5bf
MODULE = hidclass.sys
IMPORTLIB = hidclass
IMPORTS = hal ntoskrnl user32
IMPORTS = hal ntoskrnl user32 hidparse
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
descriptor.c \
device.c \
pnp.c
......@@ -181,7 +181,7 @@ static struct hid_report *hid_report_queue_pop( struct hid_report_queue *queue )
static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *packet )
{
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data;
HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc;
struct hid_report *last_report, *report;
struct hid_report_queue *queue;
RAWINPUT *rawinput;
......@@ -228,7 +228,7 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack
queue = irp->Tail.Overlay.OriginalFileObject->FsContext;
if (!(report = hid_report_queue_pop( queue ))) hid_report_incref( (report = last_report) );
memcpy( irp->AssociatedIrp.SystemBuffer, report->buffer, preparsed->caps.InputReportByteLength );
memcpy( irp->AssociatedIrp.SystemBuffer, report->buffer, desc->InputLength );
irp->IoStatus.Information = report->length;
irp->IoStatus.Status = STATUS_SUCCESS;
hid_report_decref( report );
......@@ -243,25 +243,34 @@ static DWORD CALLBACK hid_device_thread(void *args)
{
DEVICE_OBJECT *device = (DEVICE_OBJECT*)args;
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data;
BYTE report_id = HID_INPUT_VALUE_CAPS( preparsed )->report_id;
ULONG buffer_len = preparsed->caps.InputReportByteLength;
HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc;
HIDP_REPORT_IDS *reports = ext->u.pdo.device_desc.ReportIDs;
ULONG report_count = ext->u.pdo.device_desc.ReportIDsLength;
ULONG i, report_id = 0, poll_interval = 0;
HID_XFER_PACKET *packet;
ULONG poll_interval = 0;
IO_STATUS_BLOCK io;
BYTE *buffer;
DWORD res;
packet = malloc( sizeof(*packet) + buffer_len );
packet = malloc( sizeof(*packet) + desc->InputLength );
buffer = (BYTE *)(packet + 1);
packet->reportBuffer = buffer;
if (ext->u.pdo.information.Polled) poll_interval = ext->u.pdo.poll_interval;
for (i = 0; i < report_count; ++i)
{
if (!reports[i].ReportID || reports[i].InputLength)
break;
}
if (i == report_count) WARN("no input report found.\n");
else report_id = reports[i].ReportID;
do
{
packet->reportId = buffer[0] = report_id;
packet->reportBufferLen = buffer_len;
packet->reportBufferLen = desc->InputLength;
if (!report_id)
{
......@@ -318,18 +327,18 @@ static void handle_IOCTL_HID_GET_COLLECTION_INFORMATION( IRP *irp, BASE_DEVICE_E
static void handle_IOCTL_HID_GET_COLLECTION_DESCRIPTOR( IRP *irp, BASE_DEVICE_EXTENSION *ext )
{
HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc;
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data;
if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < preparsed->size)
if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < desc->PreparsedDataLength)
{
irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
irp->IoStatus.Information = 0;
}
else
{
memcpy( irp->UserBuffer, preparsed, preparsed->size );
irp->IoStatus.Information = preparsed->size;
memcpy( irp->UserBuffer, desc->PreparsedData, desc->PreparsedDataLength );
irp->IoStatus.Information = desc->PreparsedDataLength;
irp->IoStatus.Status = STATUS_SUCCESS;
}
}
......@@ -357,10 +366,10 @@ static void handle_minidriver_string( BASE_DEVICE_EXTENSION *ext, IRP *irp, SHOR
static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP *irp )
{
struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data;
HIDP_REPORT_IDS *reports = ext->u.pdo.device_desc.ReportIDs;
ULONG report_count = ext->u.pdo.device_desc.ReportIDsLength;
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
struct hid_value_caps *caps = NULL, *caps_end = NULL;
ULONG report_len = 0, buffer_len = 0;
ULONG i, report_len = 0, buffer_len = 0;
HID_XFER_PACKET packet;
BYTE *buffer = NULL;
......@@ -381,51 +390,48 @@ static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP
buffer = irp->AssociatedIrp.SystemBuffer;
break;
}
if (!buffer || !buffer_len)
{
irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER;
return;
}
for (i = 0; i < report_count; ++i)
{
if (!reports[i].ReportID || reports[i].ReportID == buffer[0])
break;
}
if (i == report_count)
{
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
return;
}
switch (code)
{
case IOCTL_HID_GET_INPUT_REPORT:
report_len = preparsed->caps.InputReportByteLength;
caps = HID_INPUT_VALUE_CAPS( preparsed );
caps_end = caps + preparsed->value_caps_count[HidP_Input];
report_len = reports[i].InputLength;
break;
case IOCTL_HID_SET_OUTPUT_REPORT:
case IOCTL_HID_WRITE_REPORT:
report_len = preparsed->caps.OutputReportByteLength;
caps = HID_OUTPUT_VALUE_CAPS( preparsed );
caps_end = caps + preparsed->value_caps_count[HidP_Output];
report_len = reports[i].OutputLength;
break;
case IOCTL_HID_GET_FEATURE:
case IOCTL_HID_SET_FEATURE:
report_len = preparsed->caps.FeatureReportByteLength;
caps = HID_FEATURE_VALUE_CAPS( preparsed );
caps_end = caps + preparsed->value_caps_count[HidP_Feature];
report_len = reports[i].FeatureLength;
break;
}
if (!buffer || !buffer_len)
{
irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER;
return;
}
if (buffer_len < report_len)
{
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
return;
}
for (; caps != caps_end; ++caps) if (!caps->report_id || caps->report_id == buffer[0]) break;
if (caps == caps_end)
{
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
return;
}
packet.reportId = buffer[0];
packet.reportBuffer = buffer;
packet.reportBufferLen = buffer_len;
if (!caps->report_id)
if (!reports[i].ReportID)
{
packet.reportId = 0;
packet.reportBuffer++;
......@@ -575,7 +581,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp)
{
struct hid_report_queue *queue = irp->Tail.Overlay.OriginalFileObject->FsContext;
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data;
HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc;
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
struct hid_report *report;
NTSTATUS status;
......@@ -593,7 +599,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp)
return STATUS_DELETE_PENDING;
}
if (irpsp->Parameters.Read.Length < preparsed->caps.InputReportByteLength)
if (irpsp->Parameters.Read.Length < desc->InputLength)
{
irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
IoCompleteRequest( irp, IO_NO_INCREMENT );
......@@ -603,7 +609,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp)
irp->IoStatus.Information = 0;
if ((report = hid_report_queue_pop( queue )))
{
memcpy( irp->AssociatedIrp.SystemBuffer, report->buffer, preparsed->caps.InputReportByteLength );
memcpy( irp->AssociatedIrp.SystemBuffer, report->buffer, desc->InputLength );
irp->IoStatus.Information = report->length;
irp->IoStatus.Status = STATUS_SUCCESS;
hid_report_decref( report );
......
......@@ -27,6 +27,7 @@
#include "ddk/hidport.h"
#include "ddk/hidclass.h"
#include "ddk/hidpi.h"
#include "ddk/hidpddi.h"
#include "cfgmgr32.h"
#include "wine/list.h"
#include "wine/hid.h"
......@@ -54,7 +55,7 @@ typedef struct _BASE_DEVICE_EXTENSION
DEVICE_OBJECT *parent_fdo;
HID_COLLECTION_INFORMATION information;
struct hid_preparsed_data *preparsed_data;
HIDP_DEVICE_DESC device_desc;
ULONG poll_interval;
HANDLE halt_event;
......@@ -129,6 +130,3 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN;
NTSTATUS WINAPI pdo_write(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN;
NTSTATUS WINAPI pdo_create(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN;
NTSTATUS WINAPI pdo_close(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN;
/* Parsing HID Report Descriptors into preparsed data */
struct hid_preparsed_data *parse_descriptor( BYTE *descriptor, unsigned int length ) DECLSPEC_HIDDEN;
......@@ -109,6 +109,7 @@ C_ASSERT(offsetof(RAWINPUT, data.hid.bRawData[2 * sizeof(USAGE)]) < sizeof(RAWIN
static void send_wm_input_device_change(BASE_DEVICE_EXTENSION *ext, LPARAM param)
{
HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc;
RAWINPUT rawinput;
INPUT input;
......@@ -118,8 +119,8 @@ static void send_wm_input_device_change(BASE_DEVICE_EXTENSION *ext, LPARAM param
rawinput.header.wParam = param;
rawinput.data.hid.dwCount = 0;
rawinput.data.hid.dwSizeHid = 0;
((USAGE *)rawinput.data.hid.bRawData)[0] = ext->u.pdo.preparsed_data->caps.UsagePage;
((USAGE *)rawinput.data.hid.bRawData)[1] = ext->u.pdo.preparsed_data->caps.Usage;
((USAGE *)rawinput.data.hid.bRawData)[0] = desc->UsagePage;
((USAGE *)rawinput.data.hid.bRawData)[1] = desc->Usage;
input.type = INPUT_HARDWARE;
input.hi.uMsg = WM_INPUT_DEVICE_CHANGE;
......@@ -183,6 +184,7 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo)
{
BASE_DEVICE_EXTENSION *fdo_ext = fdo->DeviceExtension, *pdo_ext;
HID_DEVICE_ATTRIBUTES attr = {0};
HIDP_COLLECTION_DESC *desc;
HID_DESCRIPTOR descriptor;
DEVICE_OBJECT *child_pdo;
BYTE *reportDescriptor;
......@@ -253,19 +255,21 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo)
return;
}
pdo_ext->u.pdo.preparsed_data = parse_descriptor( reportDescriptor, descriptor.DescriptorList[i].wReportLength );
io.Status = HidP_GetCollectionDescription( reportDescriptor, descriptor.DescriptorList[i].wReportLength,
PagedPool, &pdo_ext->u.pdo.device_desc );
free(reportDescriptor);
if (!pdo_ext->u.pdo.preparsed_data)
if (io.Status != HIDP_STATUS_SUCCESS)
{
ERR("Cannot parse Report Descriptor\n");
IoDeleteDevice(child_pdo);
return;
}
pdo_ext->u.pdo.information.DescriptorSize = pdo_ext->u.pdo.preparsed_data->size;
desc = pdo_ext->u.pdo.device_desc.CollectionDesc;
pdo_ext->u.pdo.information.DescriptorSize = desc->PreparsedDataLength;
page = pdo_ext->u.pdo.preparsed_data->caps.UsagePage;
usage = pdo_ext->u.pdo.preparsed_data->caps.Usage;
page = desc->UsagePage;
usage = desc->Usage;
if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_MOUSE)
pdo_ext->u.pdo.rawinput_handle = WINE_MOUSE_HANDLE;
else if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_KEYBOARD)
......@@ -374,6 +378,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp)
{
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc;
NTSTATUS status = irp->IoStatus.Status;
KIRQL irql;
......@@ -447,14 +452,12 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp)
}
/* FIXME: This should probably be done in mouhid.sys. */
if (ext->u.pdo.preparsed_data->caps.UsagePage == HID_USAGE_PAGE_GENERIC
&& ext->u.pdo.preparsed_data->caps.Usage == HID_USAGE_GENERIC_MOUSE)
if (desc->UsagePage == HID_USAGE_PAGE_GENERIC && desc->Usage == HID_USAGE_GENERIC_MOUSE)
{
if (!IoRegisterDeviceInterface(device, &GUID_DEVINTERFACE_MOUSE, NULL, &ext->u.pdo.mouse_link_name))
ext->u.pdo.is_mouse = TRUE;
}
if (ext->u.pdo.preparsed_data->caps.UsagePage == HID_USAGE_PAGE_GENERIC
&& ext->u.pdo.preparsed_data->caps.Usage == HID_USAGE_GENERIC_KEYBOARD)
if (desc->UsagePage == HID_USAGE_PAGE_GENERIC && desc->Usage == HID_USAGE_GENERIC_KEYBOARD)
{
if (!IoRegisterDeviceInterface(device, &GUID_DEVINTERFACE_KEYBOARD, NULL, &ext->u.pdo.keyboard_link_name))
ext->u.pdo.is_keyboard = TRUE;
......@@ -488,7 +491,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp)
}
CloseHandle(ext->u.pdo.halt_event);
free(ext->u.pdo.preparsed_data);
HidP_FreeCollectionDescription(&ext->u.pdo.device_desc);
RtlFreeUnicodeString(&ext->u.pdo.link_name);
......
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