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

winebus.sys: Query and parse device report descriptor on device start.

parent bd780ba6
MODULE = winebus.sys MODULE = winebus.sys
UNIXLIB = winebus.so UNIXLIB = winebus.so
IMPORTS = ntoskrnl advapi32 IMPORTS = ntoskrnl hidparse
EXTRALIBS = $(IOKIT_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS) EXTRALIBS = $(IOKIT_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS)
EXTRAINCL = $(UDEV_CFLAGS) $(SDL2_CFLAGS) EXTRAINCL = $(UDEV_CFLAGS) $(SDL2_CFLAGS)
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "ddk/wdm.h" #include "ddk/wdm.h"
#include "ddk/hidport.h" #include "ddk/hidport.h"
#include "ddk/hidtypes.h" #include "ddk/hidtypes.h"
#include "ddk/hidpddi.h"
#include "wine/asm.h" #include "wine/asm.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/list.h" #include "wine/list.h"
...@@ -71,6 +72,10 @@ struct device_extension ...@@ -71,6 +72,10 @@ struct device_extension
struct device_desc desc; struct device_desc desc;
DWORD index; DWORD index;
BYTE *report_desc;
ULONG report_desc_length;
HIDP_DEVICE_DESC collection_desc;
BYTE *last_report; BYTE *last_report;
DWORD last_report_size; DWORD last_report_size;
BOOL last_report_read; BOOL last_report_read;
...@@ -827,8 +832,27 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) ...@@ -827,8 +832,27 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
RtlEnterCriticalSection(&ext->cs); RtlEnterCriticalSection(&ext->cs);
if (ext->state != DEVICE_STATE_STOPPED) status = STATUS_SUCCESS; if (ext->state != DEVICE_STATE_STOPPED) status = STATUS_SUCCESS;
else if (ext->state == DEVICE_STATE_REMOVED) status = STATUS_DELETE_PENDING; else if (ext->state == DEVICE_STATE_REMOVED) status = STATUS_DELETE_PENDING;
else if (!(status = unix_device_start(device))) ext->state = DEVICE_STATE_STARTED; else if ((status = unix_device_start(device)))
else ERR("failed to start device %p, status %#x\n", device, status); 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); RtlLeaveCriticalSection(&ext->cs);
break; break;
...@@ -854,6 +878,9 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) ...@@ -854,6 +878,9 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(irp, IO_NO_INCREMENT); IoCompleteRequest(irp, IO_NO_INCREMENT);
HidP_FreeCollectionDescription(&ext->collection_desc);
RtlFreeHeap(GetProcessHeap(), 0, ext->report_desc);
IoDeleteDevice(device); IoDeleteDevice(device);
return STATUS_SUCCESS; return STATUS_SUCCESS;
...@@ -955,23 +982,10 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) ...@@ -955,23 +982,10 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
case IOCTL_HID_GET_DEVICE_DESCRIPTOR: case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
{ {
HID_DESCRIPTOR *descriptor = (HID_DESCRIPTOR *)irp->UserBuffer; HID_DESCRIPTOR *descriptor = (HID_DESCRIPTOR *)irp->UserBuffer;
DWORD length; irp->IoStatus.Information = sizeof(*descriptor);
TRACE("IOCTL_HID_GET_DEVICE_DESCRIPTOR\n"); if (buffer_len < sizeof(*descriptor)) irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
else
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)
{ {
WARN("Failed to get platform report descriptor length\n");
break;
}
memset(descriptor, 0, sizeof(*descriptor)); memset(descriptor, 0, sizeof(*descriptor));
descriptor->bLength = sizeof(*descriptor); descriptor->bLength = sizeof(*descriptor);
descriptor->bDescriptorType = HID_HID_DESCRIPTOR_TYPE; descriptor->bDescriptorType = HID_HID_DESCRIPTOR_TYPE;
...@@ -979,16 +993,20 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) ...@@ -979,16 +993,20 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp)
descriptor->bCountry = 0; descriptor->bCountry = 0;
descriptor->bNumDescriptors = 1; descriptor->bNumDescriptors = 1;
descriptor->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE; descriptor->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE;
descriptor->DescriptorList[0].wReportLength = length; descriptor->DescriptorList[0].wReportLength = ext->report_desc_length;
irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = sizeof(*descriptor); }
break; break;
} }
case IOCTL_HID_GET_REPORT_DESCRIPTOR: case IOCTL_HID_GET_REPORT_DESCRIPTOR:
TRACE("IOCTL_HID_GET_REPORT_DESCRIPTOR\n"); irp->IoStatus.Information = ext->report_desc_length;
irp->IoStatus.Status = unix_device_get_report_descriptor(device, irp->UserBuffer, buffer_len, &buffer_len); if (buffer_len < irp->IoStatus.Information)
irp->IoStatus.Information = buffer_len; irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
else
{
memcpy(irp->UserBuffer, ext->report_desc, ext->report_desc_length);
irp->IoStatus.Status = STATUS_SUCCESS;
}
break; break;
case IOCTL_HID_GET_STRING: case IOCTL_HID_GET_STRING:
{ {
......
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