From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
Power Rangers: Battle for the Grid.
0514:trace:hidp:HidP_GetCaps preparsed_data 000000004C9566B0, caps 000000000010EF00. 0514:trace:hidp:HidP_GetCaps preparsed_data 0000000000000000, caps 000000000010F020.
Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 6259e0f56a9..37715ccfbca 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -39,7 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(hidp); static NTSTATUS get_value_caps_range( WINE_HIDP_PREPARSED_DATA *preparsed, HIDP_REPORT_TYPE report_type, ULONG report_len, const struct hid_value_caps **caps, const struct hid_value_caps **caps_end ) { - if (preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
switch (report_type) { @@ -167,7 +167,7 @@ NTSTATUS WINAPI HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *ca
TRACE( "preparsed_data %p, caps %p.\n", preparsed_data, caps );
- if (preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
*caps = preparsed->caps; return HIDP_STATUS_SUCCESS; @@ -787,7 +787,7 @@ NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, U
TRACE( "nodes %p, nodes_len %p, preparsed_data %p.\n", nodes, nodes_len, preparsed_data );
- if (preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
count = *nodes_len = preparsed->caps.NumberLinkCollectionNodes; if (capacity < count) return HIDP_STATUS_BUFFER_TOO_SMALL;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 36 +++++++++++++++++----------------- dlls/hidclass.sys/descriptor.c | 14 ++++++------- dlls/hidclass.sys/device.c | 28 +++++++++++++------------- dlls/hidclass.sys/hid.h | 4 ++-- dlls/hidclass.sys/pnp.c | 2 +- dlls/user32/rawinput.c | 2 +- include/wine/hid.h | 6 +++--- 7 files changed, 46 insertions(+), 46 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 37715ccfbca..2690b9b0f27 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -36,7 +36,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(hidp);
-static NTSTATUS get_value_caps_range( WINE_HIDP_PREPARSED_DATA *preparsed, HIDP_REPORT_TYPE report_type, ULONG report_len, +static NTSTATUS get_value_caps_range( struct hid_preparsed_data *preparsed, HIDP_REPORT_TYPE report_type, ULONG report_len, const struct hid_value_caps **caps, const struct hid_value_caps **caps_end ) { if (!preparsed || preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA; @@ -90,7 +90,7 @@ static BOOL match_value_caps( const struct hid_value_caps *caps, const struct ca
typedef NTSTATUS (*enum_value_caps_callback)( const struct hid_value_caps *caps, void *user );
-static NTSTATUS enum_value_caps( WINE_HIDP_PREPARSED_DATA *preparsed, HIDP_REPORT_TYPE report_type, +static NTSTATUS enum_value_caps( struct hid_preparsed_data *preparsed, HIDP_REPORT_TYPE report_type, ULONG report_len, const struct caps_filter *filter, enum_value_caps_callback callback, void *user, USHORT *count ) { @@ -163,7 +163,7 @@ NTSTATUS WINAPI HidP_GetButtonCaps( HIDP_REPORT_TYPE report_type, HIDP_BUTTON_CA
NTSTATUS WINAPI HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data;
TRACE( "preparsed_data %p, caps %p.\n", preparsed_data, caps );
@@ -214,7 +214,7 @@ NTSTATUS WINAPI HidP_GetScaledUsageValue( HIDP_REPORT_TYPE report_type, USAGE us char *report_buf, ULONG report_len ) { struct usage_value_params params = {.value_buf = value, .value_len = sizeof(*value), .report_buf = report_buf}; - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage }; USHORT count = 1;
@@ -242,7 +242,7 @@ NTSTATUS WINAPI HidP_GetUsageValue( HIDP_REPORT_TYPE report_type, USAGE usage_pa ULONG *value, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { struct usage_value_params params = {.value_buf = value, .value_len = sizeof(*value), .report_buf = report_buf}; - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage}; USHORT count = 1;
@@ -260,7 +260,7 @@ NTSTATUS WINAPI HidP_GetUsageValueArray( HIDP_REPORT_TYPE report_type, USAGE usa PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { struct usage_value_params params = {.value_buf = value_buf, .value_len = value_len, .report_buf = report_buf}; - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {.values = TRUE, .array = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage}; USHORT count = 1;
@@ -312,7 +312,7 @@ static NTSTATUS get_usage( const struct hid_value_caps *caps, void *user ) NTSTATUS WINAPI HidP_GetUsages( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, USAGE *usages, ULONG *usages_len, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct get_usage_params params = {.usages = usages, .usages_end = usages + *usages_len, .report_buf = report_buf}; struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection}; NTSTATUS status; @@ -342,7 +342,7 @@ NTSTATUS WINAPI HidP_GetValueCaps( HIDP_REPORT_TYPE report_type, HIDP_VALUE_CAPS NTSTATUS WINAPI HidP_InitializeReportForID( HIDP_REPORT_TYPE report_type, UCHAR report_id, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; const struct hid_value_caps *caps, *end; NTSTATUS status;
@@ -370,7 +370,7 @@ static NTSTATUS get_usage_list_length( const struct hid_value_caps *caps, void *
ULONG WINAPI HidP_MaxUsageListLength( HIDP_REPORT_TYPE report_type, USAGE usage_page, PHIDP_PREPARSED_DATA preparsed_data ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page}; USHORT limit = -1; ULONG count = 0; @@ -394,7 +394,7 @@ NTSTATUS WINAPI HidP_SetUsageValue( HIDP_REPORT_TYPE report_type, USAGE usage_pa ULONG value, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { struct usage_value_params params = {.value_buf = &value, .value_len = sizeof(value), .report_buf = report_buf}; - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage}; USHORT count = 1;
@@ -412,7 +412,7 @@ NTSTATUS WINAPI HidP_SetUsageValueArray( HIDP_REPORT_TYPE report_type, USAGE usa PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { struct usage_value_params params = {.value_buf = value_buf, .value_len = value_len, .report_buf = report_buf}; - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {.values = TRUE, .array = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage}; USHORT count = 1;
@@ -458,7 +458,7 @@ static NTSTATUS set_usage( const struct hid_value_caps *caps, void *user ) NTSTATUS WINAPI HidP_SetUsages( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, USAGE *usages, ULONG *usage_count, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct set_usage_params params = {.report_buf = report_buf}; struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection}; NTSTATUS status; @@ -539,7 +539,7 @@ NTSTATUS WINAPI HidP_GetSpecificButtonCaps( HIDP_REPORT_TYPE report_type, USAGE USAGE usage, HIDP_BUTTON_CAPS *caps, USHORT *caps_count, PHIDP_PREPARSED_DATA preparsed_data ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; const struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage};
TRACE( "report_type %d, usage_page %x, collection %d, usage %x, caps %p, caps_count %p, preparsed_data %p.\n", @@ -602,7 +602,7 @@ NTSTATUS WINAPI HidP_GetSpecificValueCaps( HIDP_REPORT_TYPE report_type, USAGE u USAGE usage, HIDP_VALUE_CAPS *caps, USHORT *caps_count, PHIDP_PREPARSED_DATA preparsed_data ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; const struct caps_filter filter = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage};
TRACE( "report_type %d, usage_page %x, collection %d, usage %x, caps %p, caps_count %p, preparsed_data %p.\n", @@ -657,7 +657,7 @@ NTSTATUS WINAPI HidP_GetUsagesEx( HIDP_REPORT_TYPE report_type, USHORT collectio ULONG *usages_len, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { struct get_usage_and_page_params params = {.usages = usages, .usages_end = usages + *usages_len, .report_buf = report_buf}; - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {.buttons = TRUE, .collection = collection}; NTSTATUS status; USHORT limit = -1; @@ -686,7 +686,7 @@ static NTSTATUS count_data( const struct hid_value_caps *caps, void *user )
ULONG WINAPI HidP_MaxDataListLength( HIDP_REPORT_TYPE report_type, PHIDP_PREPARSED_DATA preparsed_data ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {}; USHORT limit = -1; ULONG count = 0; @@ -760,7 +760,7 @@ NTSTATUS WINAPI HidP_GetData( HIDP_REPORT_TYPE report_type, HIDP_DATA *data, ULO PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) { struct find_all_data_params params = {.data = data, .data_end = data + *data_len, .report_buf = report_buf}; - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct caps_filter filter = {}; NTSTATUS status; USHORT limit = -1; @@ -781,7 +781,7 @@ NTSTATUS WINAPI HidP_GetData( HIDP_REPORT_TYPE report_type, HIDP_DATA *data, ULO
NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, ULONG *nodes_len, PHIDP_PREPARSED_DATA preparsed_data ) { - WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; struct hid_value_caps *caps = HID_COLLECTION_VALUE_CAPS( preparsed ); ULONG i, count, capacity = *nodes_len;
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index f8a26d87c9f..546e589d01b 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -96,7 +96,7 @@ static inline const char *debugstr_hid_value_caps( struct hid_value_caps *caps ) caps->units, caps->units_exp, caps->logical_min, caps->logical_max, caps->physical_min, caps->physical_max ); }
-static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA *data) +static void debug_print_preparsed( struct hid_preparsed_data *data ) { unsigned int i, end; if (TRACE_ON(hid)) @@ -391,19 +391,19 @@ static void free_parser_state( struct hid_parser_state *state ) free( state ); }
-static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct hid_parser_state *state ) +static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state *state ) { - WINE_HIDP_PREPARSED_DATA *data; + struct hid_preparsed_data *data; struct hid_value_caps *caps; DWORD i, button, filler, caps_len, size;
caps_len = state->caps.NumberInputValueCaps + state->caps.NumberOutputValueCaps + state->caps.NumberFeatureValueCaps + state->caps.NumberLinkCollectionNodes; - size = FIELD_OFFSET( WINE_HIDP_PREPARSED_DATA, value_caps[caps_len] ); + size = FIELD_OFFSET( struct hid_preparsed_data, value_caps[caps_len] );
if (!(data = calloc( 1, size ))) return NULL; data->magic = HID_MAGIC; - data->dwSize = size; + data->size = size; data->caps = state->caps; data->value_caps_count[HidP_Input] = state->caps.NumberInputValueCaps; data->value_caps_count[HidP_Output] = state->caps.NumberOutputValueCaps; @@ -449,9 +449,9 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct hid_parser_state * return data; }
-WINE_HIDP_PREPARSED_DATA *parse_descriptor( BYTE *descriptor, unsigned int length ) +struct hid_preparsed_data *parse_descriptor( BYTE *descriptor, unsigned int length ) { - WINE_HIDP_PREPARSED_DATA *data = NULL; + struct hid_preparsed_data *data = NULL; struct hid_parser_state *state; UINT32 size, value; INT32 signed_value; diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 1990142f955..307b2fd3b77 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -114,7 +114,7 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device) IRP *irp; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer); - const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; + struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data; HID_XFER_PACKET *packet;
packet = malloc(buffer_size); @@ -127,7 +127,7 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device) if (buffer_size) { TRACE_(hid_report)("Processing Request (%i)\n",ptr); - memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, data->caps.InputReportByteLength ); + memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, preparsed->caps.InputReportByteLength ); irp->IoStatus.Information = packet->reportBufferLen; irp->IoStatus.Status = STATUS_SUCCESS; } @@ -145,9 +145,9 @@ static DWORD CALLBACK hid_device_thread(void *args) { DEVICE_OBJECT *device = (DEVICE_OBJECT*)args; 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; - ULONG buffer_len = data->caps.InputReportByteLength; + 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; IO_STATUS_BLOCK io; HID_XFER_PACKET *packet; BYTE *buffer; @@ -263,17 +263,17 @@ 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 ) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); - const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; + struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data;
- if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < data->dwSize) + if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < preparsed->size) { irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE; irp->IoStatus.Information = 0; } else { - memcpy(irp->UserBuffer, data, data->dwSize); - irp->IoStatus.Information = data->dwSize; + memcpy( irp->UserBuffer, preparsed, preparsed->size ); + irp->IoStatus.Information = preparsed->size; irp->IoStatus.Status = STATUS_SUCCESS; } } @@ -301,7 +301,7 @@ 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 ) { - WINE_HIDP_PREPARSED_DATA *preparsed = ext->u.pdo.preparsed_data; + struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data; IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); struct hid_value_caps *caps = NULL, *caps_end = NULL; ULONG report_len = 0, buffer_len = 0; @@ -523,10 +523,10 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) { HID_XFER_PACKET *packet; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; + struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data; UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer); IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); - BYTE report_id = HID_INPUT_VALUE_CAPS( data )->report_id; + BYTE report_id = HID_INPUT_VALUE_CAPS( preparsed )->report_id; NTSTATUS status; int ptr = -1; BOOL removed; @@ -543,7 +543,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) return STATUS_DELETE_PENDING; }
- if (irpsp->Parameters.Read.Length < data->caps.InputReportByteLength) + if (irpsp->Parameters.Read.Length < preparsed->caps.InputReportByteLength) { irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE; IoCompleteRequest( irp, IO_NO_INCREMENT ); @@ -558,7 +558,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp)
if (buffer_size) { - memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, data->caps.InputReportByteLength ); + memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, preparsed->caps.InputReportByteLength ); irp->IoStatus.Information = packet->reportBufferLen; irp->IoStatus.Status = STATUS_SUCCESS; } diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index c00f014bb2c..675114d22a6 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -54,7 +54,7 @@ typedef struct _BASE_DEVICE_EXTENSION DEVICE_OBJECT *parent_fdo;
HID_COLLECTION_INFORMATION information; - WINE_HIDP_PREPARSED_DATA *preparsed_data; + struct hid_preparsed_data *preparsed_data;
ULONG poll_interval; struct ReportRingBuffer *ring_buffer; @@ -123,4 +123,4 @@ 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 */ -WINE_HIDP_PREPARSED_DATA *parse_descriptor( BYTE *descriptor, unsigned int length ) DECLSPEC_HIDDEN; +struct hid_preparsed_data *parse_descriptor( BYTE *descriptor, unsigned int length ) DECLSPEC_HIDDEN; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index d792e5d3ddd..dc95a48fc08 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -260,7 +260,7 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) return; }
- pdo_ext->u.pdo.information.DescriptorSize = pdo_ext->u.pdo.preparsed_data->dwSize; + pdo_ext->u.pdo.information.DescriptorSize = pdo_ext->u.pdo.preparsed_data->size;
page = pdo_ext->u.pdo.preparsed_data->caps.UsagePage; usage = pdo_ext->u.pdo.preparsed_data->caps.Usage; diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index e08d11bc20a..39f8c622fee 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -751,7 +751,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT break;
case RIDI_PREPARSEDDATA: - len = device->data ? ((WINE_HIDP_PREPARSED_DATA*)device->data)->dwSize : 0; + len = device->data ? ((struct hid_preparsed_data *)device->data)->size : 0; if (device->data && len <= data_len && data) memcpy(data, device->data, len); *data_size = len; diff --git a/include/wine/hid.h b/include/wine/hid.h index 2bb26ff280e..e76676ac8c2 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -67,14 +67,14 @@ struct hid_value_caps #define HID_VALUE_CAPS_IS_ARRAY(c) (((c)->bit_field & 2) == 0) #define HID_VALUE_CAPS_IS_BUTTON(c) ((c)->bit_size == 1 || HID_VALUE_CAPS_IS_ARRAY(c))
-typedef struct __WINE_HIDP_PREPARSED_DATA +struct hid_preparsed_data { DWORD magic; - DWORD dwSize; + DWORD size; HIDP_CAPS caps; USHORT value_caps_count[3]; struct hid_value_caps value_caps[1]; -} WINE_HIDP_PREPARSED_DATA, *PWINE_HIDP_PREPARSED_DATA; +};
#define HID_INPUT_VALUE_CAPS(d) ((d)->value_caps) #define HID_OUTPUT_VALUE_CAPS(d) (HID_INPUT_VALUE_CAPS(d) + (d)->value_caps_count[0])
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 127 +++++++++++++++++++---------- dlls/hidclass.sys/hid.h | 10 ++- dlls/hidclass.sys/pnp.c | 7 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 4 +- 4 files changed, 95 insertions(+), 53 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 307b2fd3b77..a3c82d03269 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -24,11 +24,13 @@ #include "winreg.h" #include "winuser.h"
-#include "wine/debug.h" #include "ddk/hidsdi.h" #include "ddk/hidtypes.h" #include "ddk/wdm.h"
+#include "wine/debug.h" +#include "wine/list.h" + WINE_DEFAULT_DEBUG_CHANNEL(hid); WINE_DECLARE_DEBUG_CHANNEL(hid_report);
@@ -77,56 +79,60 @@ static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp) IoCompleteRequest(irp, IO_NO_INCREMENT); }
-static void hid_device_send_input(DEVICE_OBJECT *device, HID_XFER_PACKET *packet) +static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *packet ) { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + struct hid_report_queue *queue; RAWINPUT *rawinput; - ULONG data_size; - INPUT input; - - data_size = offsetof(RAWINPUT, data.hid.bRawData) + packet->reportBufferLen; + ULONG size; + KIRQL irql;
- if (!(rawinput = malloc(data_size))) + size = offsetof( RAWINPUT, data.hid.bRawData[packet->reportBufferLen] ); + if (!(rawinput = malloc( size ))) ERR( "Failed to allocate rawinput data!\n" ); + else { - ERR("Failed to allocate rawinput data!\n"); - return; + INPUT input; + + rawinput->header.dwType = RIM_TYPEHID; + rawinput->header.dwSize = size; + rawinput->header.hDevice = ULongToHandle( ext->u.pdo.rawinput_handle ); + rawinput->header.wParam = RIM_INPUT; + rawinput->data.hid.dwCount = 1; + rawinput->data.hid.dwSizeHid = packet->reportBufferLen; + memcpy( rawinput->data.hid.bRawData, packet->reportBuffer, packet->reportBufferLen ); + + input.type = INPUT_HARDWARE; + input.hi.uMsg = WM_INPUT; + input.hi.wParamH = 0; + input.hi.wParamL = 0; + __wine_send_input( 0, &input, rawinput ); + + free( rawinput ); }
- rawinput->header.dwType = RIM_TYPEHID; - rawinput->header.dwSize = data_size; - rawinput->header.hDevice = ULongToHandle(ext->u.pdo.rawinput_handle); - rawinput->header.wParam = RIM_INPUT; - rawinput->data.hid.dwCount = 1; - rawinput->data.hid.dwSizeHid = data_size - offsetof(RAWINPUT, data.hid.bRawData); - memcpy( rawinput->data.hid.bRawData, packet->reportBuffer, packet->reportBufferLen ); - - input.type = INPUT_HARDWARE; - input.hi.uMsg = WM_INPUT; - input.hi.wParamH = 0; - input.hi.wParamL = 0; - __wine_send_input(0, &input, rawinput); - - free(rawinput); + KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql ); + LIST_FOR_EACH_ENTRY( queue, &ext->u.pdo.report_queues, struct hid_report_queue, entry ) + RingBuffer_Write( queue->buffer, packet ); + KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql ); }
static void HID_Device_processQueue(DEVICE_OBJECT *device) { - IRP *irp; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer); struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data; + struct hid_report_queue *queue; HID_XFER_PACKET *packet; + UINT buffer_size; + IRP *irp;
- packet = malloc(buffer_size); + packet = malloc( sizeof(*packet) + preparsed->caps.InputReportByteLength );
while((irp = pop_irp_from_queue(ext))) { - int ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext ); - - RingBuffer_Read(ext->u.pdo.ring_buffer, ptr, packet, &buffer_size); + queue = irp->Tail.Overlay.OriginalFileObject->FsContext; + RingBuffer_Read( queue->buffer, 0, packet, &buffer_size ); if (buffer_size) { - TRACE_(hid_report)("Processing Request (%i)\n",ptr); memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, preparsed->caps.InputReportByteLength ); irp->IoStatus.Information = packet->reportBufferLen; irp->IoStatus.Status = STATUS_SUCCESS; @@ -180,8 +186,7 @@ static DWORD CALLBACK hid_device_thread(void *args) packet->reportBuffer = buffer; packet->reportBufferLen = io.Information;
- RingBuffer_Write(ext->u.pdo.ring_buffer, packet); - hid_device_send_input(device, packet); + hid_device_queue_input( device, packet ); HID_Device_processQueue(device); }
@@ -223,8 +228,7 @@ static DWORD CALLBACK hid_device_thread(void *args) packet->reportBuffer = buffer; packet->reportBufferLen = io.Information;
- RingBuffer_Write(ext->u.pdo.ring_buffer, packet); - hid_device_send_input(device, packet); + hid_device_queue_input( device, packet ); HID_Device_processQueue(device); }
@@ -393,6 +397,7 @@ static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP
NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) { + struct hid_report_queue *queue = irp->Tail.Overlay.OriginalFileObject->FsContext; IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; NTSTATUS status; @@ -480,7 +485,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) if (irpsp->Parameters.DeviceIoControl.InputBufferLength != sizeof(ULONG)) irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; else - irp->IoStatus.Status = RingBuffer_SetSize( ext->u.pdo.ring_buffer, *(ULONG *)irp->AssociatedIrp.SystemBuffer ); + irp->IoStatus.Status = RingBuffer_SetSize( queue->buffer, *(ULONG *)irp->AssociatedIrp.SystemBuffer ); break; } case IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS: @@ -492,7 +497,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) } else { - *(ULONG *)irp->AssociatedIrp.SystemBuffer = RingBuffer_GetSize(ext->u.pdo.ring_buffer); + *(ULONG *)irp->AssociatedIrp.SystemBuffer = RingBuffer_GetSize( queue->buffer ); irp->IoStatus.Information = sizeof(ULONG); irp->IoStatus.Status = STATUS_SUCCESS; } @@ -521,12 +526,13 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp)
NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) { - HID_XFER_PACKET *packet; + 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; - UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer); IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); BYTE report_id = HID_INPUT_VALUE_CAPS( preparsed )->report_id; + HID_XFER_PACKET *packet; + UINT buffer_size; NTSTATUS status; int ptr = -1; BOOL removed; @@ -550,11 +556,11 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) return STATUS_INVALID_BUFFER_SIZE; }
- packet = malloc(buffer_size); + packet = malloc( sizeof(*packet) + preparsed->caps.InputReportByteLength ); ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext );
irp->IoStatus.Information = 0; - RingBuffer_ReadNew(ext->u.pdo.ring_buffer, ptr, packet, &buffer_size); + RingBuffer_ReadNew( queue->buffer, ptr, packet, &buffer_size );
if (buffer_size) { @@ -631,20 +637,51 @@ NTSTATUS WINAPI pdo_write(DEVICE_OBJECT *device, IRP *irp) NTSTATUS WINAPI pdo_create(DEVICE_OBJECT *device, IRP *irp) { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data; + struct hid_report_queue *queue; + KIRQL irql;
TRACE("Open handle on device %p\n", device); - irp->Tail.Overlay.OriginalFileObject->FsContext = UlongToPtr(RingBuffer_AddPointer(ext->u.pdo.ring_buffer)); - irp->IoStatus.Status = STATUS_SUCCESS; + + if (!(queue = malloc( sizeof(*queue) )) || + !(queue->buffer = RingBuffer_Create( sizeof(HID_XFER_PACKET) + preparsed->caps.InputReportByteLength ))) + { + free( queue ); + irp->IoStatus.Status = STATUS_NO_MEMORY; + } + else + { + RingBuffer_AddPointer( queue->buffer ); + KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql ); + list_add_tail( &ext->u.pdo.report_queues, &queue->entry ); + KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql ); + + irp->Tail.Overlay.OriginalFileObject->FsContext = queue; + irp->IoStatus.Status = STATUS_SUCCESS; + } + IoCompleteRequest( irp, IO_NO_INCREMENT ); return STATUS_SUCCESS; }
NTSTATUS WINAPI pdo_close(DEVICE_OBJECT *device, IRP *irp) { + struct hid_report_queue *queue = irp->Tail.Overlay.OriginalFileObject->FsContext; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - int ptr = PtrToUlong(irp->Tail.Overlay.OriginalFileObject->FsContext); + KIRQL irql; + TRACE("Close handle on device %p\n", device); - RingBuffer_RemovePointer(ext->u.pdo.ring_buffer, ptr); + + if (queue) + { + KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql ); + list_remove( &queue->entry ); + KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql ); + + RingBuffer_Destroy( queue->buffer ); + free( queue ); + } + irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( irp, IO_NO_INCREMENT ); return STATUS_SUCCESS; diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 675114d22a6..d886672ec10 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -57,11 +57,13 @@ typedef struct _BASE_DEVICE_EXTENSION struct hid_preparsed_data *preparsed_data;
ULONG poll_interval; - struct ReportRingBuffer *ring_buffer; HANDLE halt_event; HANDLE thread; UINT32 rawinput_handle;
+ KSPIN_LOCK report_queues_lock; + struct list report_queues; + UNICODE_STRING link_name;
KSPIN_LOCK irp_queue_lock; @@ -85,6 +87,12 @@ typedef struct _BASE_DEVICE_EXTENSION BOOL is_fdo; } BASE_DEVICE_EXTENSION;
+struct hid_report_queue +{ + struct list entry; + struct ReportRingBuffer *buffer; +}; + void RingBuffer_Write(struct ReportRingBuffer *buffer, void *data) DECLSPEC_HIDDEN; UINT RingBuffer_AddPointer(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index) DECLSPEC_HIDDEN; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index dc95a48fc08..9752a47326f 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -212,6 +212,8 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo)
pdo_ext = child_pdo->DeviceExtension; pdo_ext->u.pdo.parent_fdo = fdo; + list_init( &pdo_ext->u.pdo.report_queues ); + KeInitializeSpinLock( &pdo_ext->u.pdo.report_queues_lock ); InitializeListHead(&pdo_ext->u.pdo.irp_queue); KeInitializeSpinLock(&pdo_ext->u.pdo.irp_queue_lock); wcscpy(pdo_ext->device_id, fdo_ext->device_id); @@ -284,9 +286,6 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo)
pdo_ext->u.pdo.poll_interval = DEFAULT_POLL_INTERVAL;
- pdo_ext->u.pdo.ring_buffer = RingBuffer_Create( - sizeof(HID_XFER_PACKET) + pdo_ext->u.pdo.preparsed_data->caps.InputReportByteLength); - HID_StartDeviceThread(child_pdo);
send_wm_input_device_change(pdo_ext, GIDC_ARRIVAL); @@ -490,8 +489,6 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) CloseHandle(ext->u.pdo.halt_event);
free(ext->u.pdo.preparsed_data); - if (ext->u.pdo.ring_buffer) - RingBuffer_Destroy(ext->u.pdo.ring_buffer);
RtlFreeUnicodeString(&ext->u.pdo.link_name);
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index d49f6fe3c7e..40f9b8622e3 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2797,7 +2797,7 @@ static void test_hid_device(DWORD report_id, DWORD polled) SetLastError(0xdeadbeef); ret = HidD_GetNumInputBuffers(async_file, &count); ok(ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError()); - todo_wine ok(count == 32, "HidD_GetNumInputBuffers returned %u\n", count); + ok(count == 32, "HidD_GetNumInputBuffers returned %u\n", count);
SetLastError(0xdeadbeef); ret = HidD_SetNumInputBuffers(async_file, 2); @@ -2812,7 +2812,7 @@ static void test_hid_device(DWORD report_id, DWORD polled) SetLastError(0xdeadbeef); ret = HidD_GetNumInputBuffers(file, &count); ok(ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError()); - todo_wine ok(count == 16, "HidD_GetNumInputBuffers returned %u\n", count); + ok(count == 16, "HidD_GetNumInputBuffers returned %u\n", count);
if (polled) {
Instead of requiring the ring buffer to keep previously read packets.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/buffer.c | 34 ---------------------------- dlls/hidclass.sys/device.c | 45 +++++++++++++++----------------------- dlls/hidclass.sys/hid.h | 1 - 3 files changed, 18 insertions(+), 62 deletions(-)
diff --git a/dlls/hidclass.sys/buffer.c b/dlls/hidclass.sys/buffer.c index 720ca4eeb20..59c0edf29f9 100644 --- a/dlls/hidclass.sys/buffer.c +++ b/dlls/hidclass.sys/buffer.c @@ -154,40 +154,6 @@ void RingBuffer_ReadNew(struct ReportRingBuffer *ring, UINT index, void *output, } }
-void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size) -{ - int pointer; - void *ret = NULL; - - EnterCriticalSection(&ring->lock); - if (index >= ring->pointer_alloc || ring->pointers[index] == POINTER_UNUSED - || ring->end == ring->start) - { - LeaveCriticalSection(&ring->lock); - *size = 0; - return; - } - - pointer = ring->pointers[index]; - - if (pointer == ring->end) - pointer--; - - if (pointer < 0) - pointer = ring->size - 1; - - ret = &ring->buffer[pointer * ring->buffer_size]; - memcpy(output, ret, ring->buffer_size); - if (pointer == ring->pointers[index]) - { - ring->pointers[index]++; - if (ring->pointers[index] == ring->size) - ring->pointers[index] = 0; - } - LeaveCriticalSection(&ring->lock); - *size = ring->buffer_size; -} - UINT RingBuffer_AddPointer(struct ReportRingBuffer *ring) { UINT idx; diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index a3c82d03269..8510f25ae41 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -82,10 +82,13 @@ static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp) 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; + HID_XFER_PACKET *read_packet, *last_packet = packet; struct hid_report_queue *queue; RAWINPUT *rawinput; ULONG size; KIRQL irql; + IRP *irp;
size = offsetof( RAWINPUT, data.hid.bRawData[packet->reportBufferLen] ); if (!(rawinput = malloc( size ))) ERR( "Failed to allocate rawinput data!\n" ); @@ -114,37 +117,27 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack LIST_FOR_EACH_ENTRY( queue, &ext->u.pdo.report_queues, struct hid_report_queue, entry ) RingBuffer_Write( queue->buffer, packet ); KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql ); -} - -static void HID_Device_processQueue(DEVICE_OBJECT *device) -{ - BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data; - struct hid_report_queue *queue; - HID_XFER_PACKET *packet; - UINT buffer_size; - IRP *irp;
- packet = malloc( sizeof(*packet) + preparsed->caps.InputReportByteLength ); + if (!(read_packet = malloc( sizeof(*packet) + preparsed->caps.InputReportByteLength ))) + { + ERR( "Failed to allocate read_packet!\n" ); + return; + }
- while((irp = pop_irp_from_queue(ext))) + while ((irp = pop_irp_from_queue( ext ))) { queue = irp->Tail.Overlay.OriginalFileObject->FsContext; - RingBuffer_Read( queue->buffer, 0, packet, &buffer_size ); - if (buffer_size) - { - memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, preparsed->caps.InputReportByteLength ); - irp->IoStatus.Information = packet->reportBufferLen; - irp->IoStatus.Status = STATUS_SUCCESS; - } - else - { - irp->IoStatus.Information = 0; - irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - } + RingBuffer_ReadNew( queue->buffer, 0, read_packet, &size ); + if (!size) packet = last_packet; + else packet = read_packet; + + memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, preparsed->caps.InputReportByteLength ); + irp->IoStatus.Information = packet->reportBufferLen; + irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( irp, IO_NO_INCREMENT ); } - free(packet); + + free( read_packet ); }
static DWORD CALLBACK hid_device_thread(void *args) @@ -187,7 +180,6 @@ static DWORD CALLBACK hid_device_thread(void *args) packet->reportBufferLen = io.Information;
hid_device_queue_input( device, packet ); - HID_Device_processQueue(device); }
rc = WaitForSingleObject(ext->u.pdo.halt_event, @@ -229,7 +221,6 @@ static DWORD CALLBACK hid_device_thread(void *args) packet->reportBufferLen = io.Information;
hid_device_queue_input( device, packet ); - HID_Device_processQueue(device); }
if (exit_now) diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index d886672ec10..6bfba100007 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -96,7 +96,6 @@ struct hid_report_queue void RingBuffer_Write(struct ReportRingBuffer *buffer, void *data) DECLSPEC_HIDDEN; UINT RingBuffer_AddPointer(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index) DECLSPEC_HIDDEN; -void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size) DECLSPEC_HIDDEN; void RingBuffer_ReadNew(struct ReportRingBuffer *buffer, UINT index, void *output, UINT *size) DECLSPEC_HIDDEN; UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; UINT RingBuffer_GetSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/Makefile.in | 1 - dlls/hidclass.sys/buffer.c | 204 ---------------------------------- dlls/hidclass.sys/device.c | 162 ++++++++++++++++++++------- dlls/hidclass.sys/hid.h | 25 +++-- 4 files changed, 136 insertions(+), 256 deletions(-) delete mode 100644 dlls/hidclass.sys/buffer.c
diff --git a/dlls/hidclass.sys/Makefile.in b/dlls/hidclass.sys/Makefile.in index 09281c118b4..344fd10bc86 100644 --- a/dlls/hidclass.sys/Makefile.in +++ b/dlls/hidclass.sys/Makefile.in @@ -5,7 +5,6 @@ IMPORTS = hal ntoskrnl user32 EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \ - buffer.c \ descriptor.c \ device.c \ pnp.c diff --git a/dlls/hidclass.sys/buffer.c b/dlls/hidclass.sys/buffer.c deleted file mode 100644 index 59c0edf29f9..00000000000 --- a/dlls/hidclass.sys/buffer.c +++ /dev/null @@ -1,204 +0,0 @@ -/* Implementation of a ring buffer for reports - * - * Copyright 2015 CodeWeavers, Aric Stewart - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include <stdarg.h> -#include <stdlib.h> -#include "hid.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(hid); - -#define POINTER_UNUSED 0xffffffff -#define BASE_BUFFER_SIZE 32 -#define MIN_BUFFER_SIZE 2 -#define MAX_BUFFER_SIZE 512 - -struct ReportRingBuffer -{ - UINT start, end, size; - - UINT *pointers; - UINT pointer_alloc; - UINT buffer_size; - - CRITICAL_SECTION lock; - - BYTE *buffer; -}; - -struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size) -{ - struct ReportRingBuffer *ring; - int i; - - TRACE("Create Ring Buffer with buffer size %i\n",buffer_size); - - ring = malloc(sizeof(*ring)); - if (!ring) - return NULL; - ring->start = ring->end = 0; - ring->size = BASE_BUFFER_SIZE; - ring->buffer_size = buffer_size; - ring->pointer_alloc = 2; - ring->pointers = malloc(sizeof(UINT) * ring->pointer_alloc); - if (!ring->pointers) - { - free(ring); - return NULL; - } - for (i = 0; i < ring->pointer_alloc; i++) - ring->pointers[i] = POINTER_UNUSED; - ring->buffer = malloc(buffer_size * ring->size); - if (!ring->buffer) - { - free(ring->pointers); - free(ring); - return NULL; - } - InitializeCriticalSection(&ring->lock); - ring->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RingBuffer.lock"); - return ring; -} - -void RingBuffer_Destroy(struct ReportRingBuffer *ring) -{ - free(ring->buffer); - free(ring->pointers); - ring->lock.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&ring->lock); - free(ring); -} - -UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *ring) -{ - return ring->buffer_size; -} - -UINT RingBuffer_GetSize(struct ReportRingBuffer *ring) -{ - return ring->size; -} - -NTSTATUS RingBuffer_SetSize(struct ReportRingBuffer *ring, UINT size) -{ - BYTE* new_buffer; - int i; - - if (size < MIN_BUFFER_SIZE || size > MAX_BUFFER_SIZE) - return STATUS_INVALID_PARAMETER; - if (size == ring->size) - return STATUS_SUCCESS; - - EnterCriticalSection(&ring->lock); - ring->start = ring->end = 0; - for (i = 0; i < ring->pointer_alloc; i++) - { - if (ring->pointers[i] != POINTER_UNUSED) - ring->pointers[i] = 0; - } - new_buffer = malloc(ring->buffer_size * size); - if (!new_buffer) - { - LeaveCriticalSection(&ring->lock); - return STATUS_NO_MEMORY; - } - free(ring->buffer); - ring->buffer = new_buffer; - ring->size = size; - LeaveCriticalSection(&ring->lock); - return STATUS_SUCCESS; -} - -void RingBuffer_ReadNew(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size) -{ - void *ret = NULL; - - EnterCriticalSection(&ring->lock); - if (index >= ring->pointer_alloc || ring->pointers[index] == POINTER_UNUSED) - { - LeaveCriticalSection(&ring->lock); - *size = 0; - return; - } - if (ring->pointers[index] == ring->end) - { - LeaveCriticalSection(&ring->lock); - *size = 0; - } - else - { - ret = &ring->buffer[ring->pointers[index] * ring->buffer_size]; - memcpy(output, ret, ring->buffer_size); - ring->pointers[index]++; - if (ring->pointers[index] == ring->size) - ring->pointers[index] = 0; - LeaveCriticalSection(&ring->lock); - *size = ring->buffer_size; - } -} - -UINT RingBuffer_AddPointer(struct ReportRingBuffer *ring) -{ - UINT idx; - EnterCriticalSection(&ring->lock); - for (idx = 0; idx < ring->pointer_alloc; idx++) - if (ring->pointers[idx] == POINTER_UNUSED) - break; - if (idx >= ring->pointer_alloc) - { - int count = idx = ring->pointer_alloc; - ring->pointer_alloc *= 2; - ring->pointers = realloc(ring->pointers, sizeof(UINT) * ring->pointer_alloc); - for( ;count < ring->pointer_alloc; count++) - ring->pointers[count] = POINTER_UNUSED; - } - ring->pointers[idx] = ring->end; - LeaveCriticalSection(&ring->lock); - return idx; -} - -void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index) -{ - EnterCriticalSection(&ring->lock); - if (index < ring->pointer_alloc) - ring->pointers[index] = POINTER_UNUSED; - LeaveCriticalSection(&ring->lock); -} - -void RingBuffer_Write(struct ReportRingBuffer *ring, void *data) -{ - UINT i; - - EnterCriticalSection(&ring->lock); - memcpy(&ring->buffer[ring->end * ring->buffer_size], data, ring->buffer_size); - ring->end++; - if (ring->end == ring->size) - ring->end = 0; - if (ring->start == ring->end) - { - ring->start++; - if (ring->start == ring->size) - ring->start = 0; - } - for (i = 0; i < ring->pointer_alloc; i++) - if (ring->pointers[i] == ring->end) - ring->pointers[i] = ring->start; - LeaveCriticalSection(&ring->lock); -} diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 8510f25ae41..6e82608aa2e 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -79,11 +79,111 @@ static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp) IoCompleteRequest(irp, IO_NO_INCREMENT); }
+static struct hid_report *hid_report_create( HID_XFER_PACKET *packet ) +{ + struct hid_report *report; + + if (!(report = malloc( offsetof( struct hid_report, buffer[packet->reportBufferLen] ) ))) + return NULL; + report->ref = 1; + report->length = packet->reportBufferLen; + memcpy( report->buffer, packet->reportBuffer, report->length ); + + return report; +} + +static void hid_report_incref( struct hid_report *report ) +{ + InterlockedIncrement( &report->ref ); +} + +static void hid_report_decref( struct hid_report *report ) +{ + if (!report) return; + if (InterlockedDecrement( &report->ref ) == 0) free( report ); +} + +static struct hid_report_queue *hid_report_queue_create( void ) +{ + struct hid_report_queue *queue; + + if (!(queue = calloc( 1, sizeof(struct hid_report_queue) ))) return NULL; + KeInitializeSpinLock( &queue->lock ); + list_init( &queue->entry ); + queue->length = 32; + queue->read_idx = 0; + queue->write_idx = 0; + + return queue; +} + +static void hid_report_queue_destroy( struct hid_report_queue *queue ) +{ + while (queue->length--) hid_report_decref( queue->reports[queue->length] ); + free( queue ); +} + +static NTSTATUS hid_report_queue_resize( struct hid_report_queue *queue, ULONG length ) +{ + struct hid_report *old_reports[512]; + LONG old_length = queue->length; + KIRQL irql; + + if (length < 2 || length > 512) return STATUS_INVALID_PARAMETER; + if (length == queue->length) return STATUS_SUCCESS; + + KeAcquireSpinLock( &queue->lock, &irql ); + memcpy( old_reports, queue->reports, old_length * sizeof(void *) ); + memset( queue->reports, 0, old_length * sizeof(void *) ); + queue->length = length; + queue->write_idx = 0; + queue->read_idx = 0; + KeReleaseSpinLock( &queue->lock, irql ); + + while (old_length--) hid_report_decref( old_reports[old_length] ); + return STATUS_SUCCESS; +} + +static void hid_report_queue_push( struct hid_report_queue *queue, struct hid_report *report ) +{ + ULONG i = queue->write_idx, next = i + 1; + struct hid_report *prev; + KIRQL irql; + + if (next >= queue->length) next = 0; + hid_report_incref( report ); + + KeAcquireSpinLock( &queue->lock, &irql ); + prev = queue->reports[i]; + queue->reports[i] = report; + if (next != queue->read_idx) queue->write_idx = next; + KeReleaseSpinLock( &queue->lock, irql ); + + hid_report_decref( prev ); +} + +static struct hid_report *hid_report_queue_pop( struct hid_report_queue *queue ) +{ + ULONG i = queue->read_idx, next = i + 1; + struct hid_report *report; + KIRQL irql; + + if (next >= queue->length) next = 0; + + KeAcquireSpinLock( &queue->lock, &irql ); + report = queue->reports[i]; + queue->reports[i] = NULL; + if (i != queue->write_idx) queue->read_idx = next; + KeReleaseSpinLock( &queue->lock, irql ); + + return report; +} + 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; - HID_XFER_PACKET *read_packet, *last_packet = packet; + struct hid_report *last_report, *report; struct hid_report_queue *queue; RAWINPUT *rawinput; ULONG size; @@ -113,31 +213,31 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack free( rawinput ); }
- KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql ); - LIST_FOR_EACH_ENTRY( queue, &ext->u.pdo.report_queues, struct hid_report_queue, entry ) - RingBuffer_Write( queue->buffer, packet ); - KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql ); - - if (!(read_packet = malloc( sizeof(*packet) + preparsed->caps.InputReportByteLength ))) + if (!(last_report = hid_report_create( packet ))) { - ERR( "Failed to allocate read_packet!\n" ); + ERR( "Failed to allocate hid_report!\n" ); return; }
+ KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql ); + LIST_FOR_EACH_ENTRY( queue, &ext->u.pdo.report_queues, struct hid_report_queue, entry ) + hid_report_queue_push( queue, last_report ); + KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql ); + while ((irp = pop_irp_from_queue( ext ))) { queue = irp->Tail.Overlay.OriginalFileObject->FsContext; - RingBuffer_ReadNew( queue->buffer, 0, read_packet, &size ); - if (!size) packet = last_packet; - else packet = read_packet;
- memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, preparsed->caps.InputReportByteLength ); - irp->IoStatus.Information = packet->reportBufferLen; + if (!(report = hid_report_queue_pop( queue ))) hid_report_incref( (report = last_report) ); + memcpy( irp->AssociatedIrp.SystemBuffer, report->buffer, preparsed->caps.InputReportByteLength ); + irp->IoStatus.Information = report->length; irp->IoStatus.Status = STATUS_SUCCESS; + hid_report_decref( report ); + IoCompleteRequest( irp, IO_NO_INCREMENT ); }
- free( read_packet ); + hid_report_decref( last_report ); }
static DWORD CALLBACK hid_device_thread(void *args) @@ -476,7 +576,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) if (irpsp->Parameters.DeviceIoControl.InputBufferLength != sizeof(ULONG)) irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; else - irp->IoStatus.Status = RingBuffer_SetSize( queue->buffer, *(ULONG *)irp->AssociatedIrp.SystemBuffer ); + irp->IoStatus.Status = hid_report_queue_resize( queue, *(ULONG *)irp->AssociatedIrp.SystemBuffer ); break; } case IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS: @@ -488,7 +588,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) } else { - *(ULONG *)irp->AssociatedIrp.SystemBuffer = RingBuffer_GetSize( queue->buffer ); + *(ULONG *)irp->AssociatedIrp.SystemBuffer = queue->length; irp->IoStatus.Information = sizeof(ULONG); irp->IoStatus.Status = STATUS_SUCCESS; } @@ -522,10 +622,8 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data; IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); BYTE report_id = HID_INPUT_VALUE_CAPS( preparsed )->report_id; - HID_XFER_PACKET *packet; - UINT buffer_size; + struct hid_report *report; NTSTATUS status; - int ptr = -1; BOOL removed; KIRQL irql;
@@ -547,17 +645,13 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) return STATUS_INVALID_BUFFER_SIZE; }
- packet = malloc( sizeof(*packet) + preparsed->caps.InputReportByteLength ); - ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext ); - irp->IoStatus.Information = 0; - RingBuffer_ReadNew( queue->buffer, ptr, packet, &buffer_size ); - - if (buffer_size) + if ((report = hid_report_queue_pop( queue ))) { - memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, preparsed->caps.InputReportByteLength ); - irp->IoStatus.Information = packet->reportBufferLen; + memcpy( irp->AssociatedIrp.SystemBuffer, report->buffer, preparsed->caps.InputReportByteLength ); + irp->IoStatus.Information = report->length; irp->IoStatus.Status = STATUS_SUCCESS; + hid_report_decref( report ); } else { @@ -606,7 +700,6 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) sizeof(packet), &irp->IoStatus ); } } - free(packet);
status = irp->IoStatus.Status; if (status != STATUS_PENDING) IoCompleteRequest( irp, IO_NO_INCREMENT ); @@ -628,21 +721,14 @@ NTSTATUS WINAPI pdo_write(DEVICE_OBJECT *device, IRP *irp) NTSTATUS WINAPI pdo_create(DEVICE_OBJECT *device, IRP *irp) { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - struct hid_preparsed_data *preparsed = ext->u.pdo.preparsed_data; struct hid_report_queue *queue; KIRQL irql;
TRACE("Open handle on device %p\n", device);
- if (!(queue = malloc( sizeof(*queue) )) || - !(queue->buffer = RingBuffer_Create( sizeof(HID_XFER_PACKET) + preparsed->caps.InputReportByteLength ))) - { - free( queue ); - irp->IoStatus.Status = STATUS_NO_MEMORY; - } + if (!(queue = hid_report_queue_create())) irp->IoStatus.Status = STATUS_NO_MEMORY; else { - RingBuffer_AddPointer( queue->buffer ); KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql ); list_add_tail( &ext->u.pdo.report_queues, &queue->entry ); KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql ); @@ -668,9 +754,7 @@ NTSTATUS WINAPI pdo_close(DEVICE_OBJECT *device, IRP *irp) KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql ); list_remove( &queue->entry ); KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql ); - - RingBuffer_Destroy( queue->buffer ); - free( queue ); + hid_report_queue_destroy( queue ); }
irp->IoStatus.Status = STATUS_SUCCESS; diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 6bfba100007..2dfdfe4d0f7 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -87,21 +87,22 @@ typedef struct _BASE_DEVICE_EXTENSION BOOL is_fdo; } BASE_DEVICE_EXTENSION;
-struct hid_report_queue +struct hid_report { - struct list entry; - struct ReportRingBuffer *buffer; + LONG ref; + ULONG length; + BYTE buffer[1]; };
-void RingBuffer_Write(struct ReportRingBuffer *buffer, void *data) DECLSPEC_HIDDEN; -UINT RingBuffer_AddPointer(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; -void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index) DECLSPEC_HIDDEN; -void RingBuffer_ReadNew(struct ReportRingBuffer *buffer, UINT index, void *output, UINT *size) DECLSPEC_HIDDEN; -UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; -UINT RingBuffer_GetSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; -void RingBuffer_Destroy(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; -struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size) DECLSPEC_HIDDEN; -NTSTATUS RingBuffer_SetSize(struct ReportRingBuffer *buffer, UINT size) DECLSPEC_HIDDEN; +struct hid_report_queue +{ + struct list entry; + KSPIN_LOCK lock; + ULONG length; + ULONG read_idx; + ULONG write_idx; + struct hid_report *reports[512]; +};
typedef struct _minidriver {
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/tests/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/tests/utils.h b/dlls/ntoskrnl.exe/tests/utils.h index aa84890f6af..f73f6f938ca 100644 --- a/dlls/ntoskrnl.exe/tests/utils.h +++ b/dlls/ntoskrnl.exe/tests/utils.h @@ -51,7 +51,7 @@ static int winetest_debug; static int winetest_report_success;
/* silence todos and skips above this threshold */ -static int winetest_mute_threshold = 1; +static int winetest_mute_threshold = 42;
/* counts how many times a given line printed a message */ static LONG line_counters[16384];