[7/13](resend)hidclass.sys: Implement IRP_MJ_READ for HID Devices
Andrew Eikum
aeikum at codeweavers.com
Wed Sep 2 15:34:45 CDT 2015
On Wed, Sep 02, 2015 at 07:02:11AM -0500, Aric Stewart wrote:
> 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);
Is it necessary to make a copy of the data in the ring buffer? Seems
like returning a raw pointer would be more efficient. I flipped
through the rest of the patch sequence and all uses of RingBuffer_Read
seemed to be read-only.
> + 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 a6660db..326c994 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 = 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 = device->DeviceExtension;
> diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h
> index c9bc338..34ec241 100644
> --- a/dlls/hidclass.sys/hid.h
> +++ b/dlls/hidclass.sys/hid.h
> @@ -58,6 +58,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;
>
> @@ -81,6 +83,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;
>
>
>
More information about the wine-devel
mailing list