From: Aric Stewart Subject: [7/12] hidclass.sys: Implement IRP_MJ_READ for HID Devices Message-Id: <55A4FEC4.9030104@codeweavers.com> Date: Tue, 14 Jul 2015 07:21:24 -0500 --- dlls/hidclass.sys/buffer.c | 33 +++++++++++++++++++++++++++++++++ dlls/hidclass.sys/device.c | 43 +++++++++++++++++++++++++++++++++++++++++++ dlls/hidclass.sys/hid.h | 3 +++ dlls/hidclass.sys/main.c | 1 + 4 files changed, 80 insertions(+) diff --git a/dlls/hidclass.sys/buffer.c b/dlls/hidclass.sys/buffer.c index 2561235..6f09393 100644 --- a/dlls/hidclass.sys/buffer.c +++ b/dlls/hidclass.sys/buffer.c @@ -80,6 +80,39 @@ void RingBuffer_Destroy(struct ReportRingBuffer *ring) HeapFree(GetProcessHeap(), 0, ring); } +UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *ring) +{ + return ring->buffer_size; +} + +void RingBuffer_Read(struct ReportRingBuffer *ring, UINT index, void *output, UINT *size) +{ + void *ret = NULL; + + EnterCriticalSection(&ring->lock); + if (index >= ring->pointer_alloc || ring->pointers[index] == 0xffffffff) + { + 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; diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index b0e2473..573b1e7 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -36,6 +36,7 @@ #include "devguid.h" WINE_DEFAULT_DEBUG_CHANNEL(hid); +WINE_DECLARE_DEBUG_CHANNEL(hid_report); static const WCHAR device_name_fmtW[] = {'\\','D','e','v','i','c','e', '\\','H','I','D','#','%','p','&','%','p',0}; @@ -353,6 +354,48 @@ NTSTATUS WINAPI HID_Device_ioctl(DEVICE_OBJECT *device, IRP *irp) return rc; } +NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp) +{ + HID_XFER_PACKET *packet; + BASE_DEVICE_EXTENSION *ext = (BASE_DEVICE_EXTENSION*)device->DeviceExtension; + UINT buffer_size = RingBuffer_GetBufferSize(ext->ring_buffer); + NTSTATUS rc = STATUS_SUCCESS; + int ptr = -1; + + packet = HeapAlloc(GetProcessHeap(), 0, buffer_size); + ptr = (int)irp->Tail.Overlay.OriginalFileObject->FsContext; + + irp->IoStatus.Information = 0; + RingBuffer_Read(ext->ring_buffer, ptr, packet, &buffer_size); + + if (buffer_size) + { + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + TRACE_(hid_report)("Got Packet %p %i\n", packet->reportBuffer, packet->reportBufferLen); + if (irpsp->Parameters.Read.Length >= packet->reportBufferLen) + { + memcpy(irp->AssociatedIrp.SystemBuffer, packet->reportBuffer, packet->reportBufferLen); + irp->IoStatus.Information = packet->reportBufferLen; + irp->IoStatus.u.Status = STATUS_SUCCESS; + } + else + { + irp->IoStatus.Information = 0; + irp->IoStatus.u.Status = STATUS_BUFFER_OVERFLOW; + } + IoCompleteRequest( irp, IO_NO_INCREMENT ); + } + else + { + TRACE_(hid_report)("Queue irp\n"); + InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.ListEntry); + rc = STATUS_PENDING; + } + HeapFree(GetProcessHeap(), 0, packet); + + return rc; +} + NTSTATUS WINAPI HID_Device_create(DEVICE_OBJECT *device, IRP *irp) { BASE_DEVICE_EXTENSION *ext = (BASE_DEVICE_EXTENSION*)device->DeviceExtension; diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 330f8c8ae..dea1ef8 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -56,6 +56,8 @@ typedef struct _BASE_DEVICE_EXTENSTION { UINT RingBuffer_AddPointer(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index) DECLSPEC_HIDDEN; +void RingBuffer_Read(struct ReportRingBuffer *buffer, UINT index, void *output, UINT *size) DECLSPEC_HIDDEN; +UINT RingBuffer_GetBufferSize(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; void RingBuffer_Destroy(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN; struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size) DECLSPEC_HIDDEN; @@ -79,6 +81,7 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device, LPCWSTR serial, LPCWSTR index) DE void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device) DECLSPEC_HIDDEN; NTSTATUS WINAPI HID_Device_ioctl(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN; +NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN; NTSTATUS WINAPI HID_Device_create(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN; NTSTATUS WINAPI HID_Device_close(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN; diff --git a/dlls/hidclass.sys/main.c b/dlls/hidclass.sys/main.c index 1e0e802..4be4409 100644 --- a/dlls/hidclass.sys/main.c +++ b/dlls/hidclass.sys/main.c @@ -69,6 +69,7 @@ NTSTATUS WINAPI HidRegisterMinidriver(HID_MINIDRIVER_REGISTRATION *registration) registration->DriverObject->DriverUnload = UnloadDriver; registration->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HID_Device_ioctl; + registration->DriverObject->MajorFunction[IRP_MJ_READ] = HID_Device_read; registration->DriverObject->MajorFunction[IRP_MJ_CREATE] = HID_Device_create; registration->DriverObject->MajorFunction[IRP_MJ_CLOSE] = HID_Device_close;