Rémi Bernon : winebus.sys: Query and parse device report descriptor on device start.
Alexandre Julliard
julliard at winehq.org
Fri Oct 8 14:12:26 CDT 2021
Module: wine
Branch: master
Commit: 9132979000c90880ab6fbc477bcb7754355f9350
URL: https://source.winehq.org/git/wine.git/?a=commit;h=9132979000c90880ab6fbc477bcb7754355f9350
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Fri Oct 8 10:01:23 2021 +0200
winebus.sys: Query and parse device report descriptor on device start.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51824
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/winebus.sys/Makefile.in | 2 +-
dlls/winebus.sys/main.c | 80 +++++++++++++++++++++++++++-----------------
2 files changed, 50 insertions(+), 32 deletions(-)
diff --git a/dlls/winebus.sys/Makefile.in b/dlls/winebus.sys/Makefile.in
index 4091c925797..6fc6fc5a632 100644
--- a/dlls/winebus.sys/Makefile.in
+++ b/dlls/winebus.sys/Makefile.in
@@ -1,6 +1,6 @@
MODULE = winebus.sys
UNIXLIB = winebus.so
-IMPORTS = ntoskrnl advapi32
+IMPORTS = ntoskrnl hidparse
EXTRALIBS = $(IOKIT_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS)
EXTRAINCL = $(UDEV_CFLAGS) $(SDL2_CFLAGS)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
index 33b2a609077..541f9052ed3 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -32,6 +32,7 @@
#include "ddk/wdm.h"
#include "ddk/hidport.h"
#include "ddk/hidtypes.h"
+#include "ddk/hidpddi.h"
#include "wine/asm.h"
#include "wine/debug.h"
#include "wine/list.h"
@@ -71,6 +72,10 @@ struct device_extension
struct device_desc desc;
DWORD index;
+ BYTE *report_desc;
+ ULONG report_desc_length;
+ HIDP_DEVICE_DESC collection_desc;
+
BYTE *last_report;
DWORD last_report_size;
BOOL last_report_read;
@@ -827,8 +832,27 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
RtlEnterCriticalSection(&ext->cs);
if (ext->state != DEVICE_STATE_STOPPED) status = STATUS_SUCCESS;
else if (ext->state == DEVICE_STATE_REMOVED) status = STATUS_DELETE_PENDING;
- else if (!(status = unix_device_start(device))) ext->state = DEVICE_STATE_STARTED;
- else ERR("failed to start device %p, status %#x\n", device, status);
+ else if ((status = unix_device_start(device)))
+ ERR("Failed to start device %p, status %#x\n", device, status);
+ else
+ {
+ status = unix_device_get_report_descriptor(device, NULL, 0, &ext->report_desc_length);
+ if (status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
+ ERR("Failed to get device %p report descriptor, status %#x\n", device, status);
+ else if (!(ext->report_desc = RtlAllocateHeap(GetProcessHeap(), 0, ext->report_desc_length)))
+ status = STATUS_NO_MEMORY;
+ else if ((status = unix_device_get_report_descriptor(device, ext->report_desc, ext->report_desc_length,
+ &ext->report_desc_length)))
+ ERR("Failed to get device %p report descriptor, status %#x\n", device, status);
+ else if ((status = HidP_GetCollectionDescription(ext->report_desc, ext->report_desc_length,
+ PagedPool, &ext->collection_desc)) != HIDP_STATUS_SUCCESS)
+ ERR("Failed to parse device %p report descriptor, status %#x\n", device, status);
+ else
+ {
+ ext->state = DEVICE_STATE_STARTED;
+ status = STATUS_SUCCESS;
+ }
+ }
RtlLeaveCriticalSection(&ext->cs);
break;
@@ -854,6 +878,9 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(irp, IO_NO_INCREMENT);
+ HidP_FreeCollectionDescription(&ext->collection_desc);
+ RtlFreeHeap(GetProcessHeap(), 0, ext->report_desc);
+
IoDeleteDevice(device);
return STATUS_SUCCESS;
@@ -955,40 +982,31 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
{
HID_DESCRIPTOR *descriptor = (HID_DESCRIPTOR *)irp->UserBuffer;
- DWORD length;
- TRACE("IOCTL_HID_GET_DEVICE_DESCRIPTOR\n");
-
- if (buffer_len < sizeof(*descriptor))
- {
- irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
- break;
- }
-
- irp->IoStatus.Status = unix_device_get_report_descriptor(device, NULL, 0, &length);
- if (irp->IoStatus.Status != STATUS_SUCCESS &&
- irp->IoStatus.Status != STATUS_BUFFER_TOO_SMALL)
+ irp->IoStatus.Information = sizeof(*descriptor);
+ if (buffer_len < sizeof(*descriptor)) irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ else
{
- WARN("Failed to get platform report descriptor length\n");
- break;
+ memset(descriptor, 0, sizeof(*descriptor));
+ descriptor->bLength = sizeof(*descriptor);
+ descriptor->bDescriptorType = HID_HID_DESCRIPTOR_TYPE;
+ descriptor->bcdHID = HID_REVISION;
+ descriptor->bCountry = 0;
+ descriptor->bNumDescriptors = 1;
+ descriptor->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE;
+ descriptor->DescriptorList[0].wReportLength = ext->report_desc_length;
+ irp->IoStatus.Status = STATUS_SUCCESS;
}
-
- memset(descriptor, 0, sizeof(*descriptor));
- descriptor->bLength = sizeof(*descriptor);
- descriptor->bDescriptorType = HID_HID_DESCRIPTOR_TYPE;
- descriptor->bcdHID = HID_REVISION;
- descriptor->bCountry = 0;
- descriptor->bNumDescriptors = 1;
- descriptor->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE;
- descriptor->DescriptorList[0].wReportLength = length;
-
- irp->IoStatus.Status = STATUS_SUCCESS;
- irp->IoStatus.Information = sizeof(*descriptor);
break;
}
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
- TRACE("IOCTL_HID_GET_REPORT_DESCRIPTOR\n");
- irp->IoStatus.Status = unix_device_get_report_descriptor(device, irp->UserBuffer, buffer_len, &buffer_len);
- irp->IoStatus.Information = buffer_len;
+ irp->IoStatus.Information = ext->report_desc_length;
+ if (buffer_len < irp->IoStatus.Information)
+ irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ else
+ {
+ memcpy(irp->UserBuffer, ext->report_desc, ext->report_desc_length);
+ irp->IoStatus.Status = STATUS_SUCCESS;
+ }
break;
case IOCTL_HID_GET_STRING:
{
More information about the wine-cvs
mailing list