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