On Wed, Sep 02, 2015 at 07:02:18AM -0500, Aric Stewart wrote:
dlls/hidclass.sys/buffer.c | 21 ++++++ dlls/hidclass.sys/device.c | 175 +++++++++++++++++++++++++++++++++++++++++++++ dlls/hidclass.sys/hid.h | 2 + dlls/hidclass.sys/pnp.c | 2 + 4 files changed, 200 insertions(+)
diff --git a/dlls/hidclass.sys/buffer.c b/dlls/hidclass.sys/buffer.c index 6f09393..94e3372 100644 --- a/dlls/hidclass.sys/buffer.c +++ b/dlls/hidclass.sys/buffer.c @@ -140,3 +140,24 @@ void RingBuffer_RemovePointer(struct ReportRingBuffer *ring, UINT index) ring->pointers[index] = 0xffffffff; LeaveCriticalSection(&ring->lock); }
+void RingBuffer_Write(struct ReportRingBuffer *ring, void *data) +{
- UINT i;
- EnterCriticalSection(&ring->lock);
- memcpy(&ring->buffer[ring->end * ring->buffer_size], data, ring->buffer_size);
- ring->end++;
- if (ring->end == ring->size)
ring->end = 0;
- if (ring->start == ring->end)
- {
ring->start++;
if (ring->start == ring->size)
ring->start = 0;
- }
- for (i = 0; i < ring->pointer_alloc; i++)
if (ring->pointers[i] == ring->end)
ring->pointers[i] = ring->start;
- LeaveCriticalSection(&ring->lock);
+} diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 326c994..e09a96c 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -198,6 +198,181 @@ void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device IoDeleteDevice(device); }
+static void HID_Device_processQueue(DEVICE_OBJECT *device) +{
- LIST_ENTRY *entry;
- IRP *irp;
- BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
- UINT buffer_size = RingBuffer_GetBufferSize(ext->ring_buffer);
- HID_XFER_PACKET *packet;
- packet = HeapAlloc(GetProcessHeap(), 0, buffer_size);
- entry = RemoveHeadList(&ext->irp_queue);
- while(entry != &ext->irp_queue)
- {
int ptr;
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
ptr = (int)irp->Tail.Overlay.OriginalFileObject->FsContext;
buffer_size = RingBuffer_GetBufferSize(ext->ring_buffer);
RingBuffer_Read(ext->ring_buffer, ptr, packet, &buffer_size);
if (buffer_size)
{
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
TRACE_(hid_report)("Processing Request (%i)\n",ptr);
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;
}
}
else
{
irp->IoStatus.Information = 0;
irp->IoStatus.u.Status = STATUS_UNSUCCESSFUL;
}
IoCompleteRequest( irp, IO_NO_INCREMENT );
entry = RemoveHeadList(&ext->irp_queue);
- }
- HeapFree(GetProcessHeap(), 0, packet);
+}
+static NTSTATUS WINAPI read_Completion(DEVICE_OBJECT *deviceObject, IRP *irp, void *context ) +{
- SetEvent(irp->UserEvent);
- return STATUS_MORE_PROCESSING_REQUIRED;
+}
+static DWORD CALLBACK hid_device_thread(void *args) +{
- DEVICE_OBJECT *device = (DEVICE_OBJECT*)args;
- IRP *irp;
- IO_STATUS_BLOCK irp_status;
- IO_STACK_LOCATION *irpsp;
- DWORD rc;
- HANDLE events[2];
- NTSTATUS ntrc;
- BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
- events[0] = CreateEventA(NULL, FALSE, FALSE, NULL);
- events[1] = ext->halt_event;
- if (ext->information.Polled)
- {
while(1)
{
HID_XFER_PACKET *packet;
ResetEvent(events[0]);
packet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*packet) + ext->preparseData->caps.InputReportByteLength);
packet->reportBufferLen = ext->preparseData->caps.InputReportByteLength;
packet->reportBuffer = ((BYTE*)packet) + sizeof(*packet);
packet->reportId = 0;
irp = IoBuildDeviceIoControlRequest(IOCTL_HID_GET_INPUT_REPORT,
device, NULL, 0, packet, sizeof(packet), TRUE, events[0],
&irp_status);
irpsp = IoGetNextIrpStackLocation(irp);
irpsp->CompletionRoutine = read_Completion;
irpsp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
ntrc = IoCallDriver(device, irp);
if (ntrc == STATUS_PENDING)
rc = WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (irp->IoStatus.u.Status == STATUS_SUCCESS)
{
RingBuffer_Write(ext->ring_buffer, packet);
I'm not opposed to what you have here, but a get-buffer/commit-buffer model would avoid an allocation and a memcpy. Although this would complicate simultaneous writes, if that's a concern.
+static DWORD CALLBACK hid_device_thread(void *args) +{
- DEVICE_OBJECT *device = (DEVICE_OBJECT*)args;
- IRP *irp;
- IO_STATUS_BLOCK irp_status;
- IO_STACK_LOCATION *irpsp;
- DWORD rc;
- HANDLE events[2];
- NTSTATUS ntrc;
- BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
- events[0] = CreateEventA(NULL, FALSE, FALSE, NULL);
- events[1] = ext->halt_event;
- if (ext->information.Polled)
- {
while(1)
{
HID_XFER_PACKET *packet;
ResetEvent(events[0]);
packet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*packet) + ext->preparseData->caps.InputReportByteLength);
packet->reportBufferLen = ext->preparseData->caps.InputReportByteLength;
packet->reportBuffer = ((BYTE*)packet) + sizeof(*packet);
packet->reportId = 0;
irp = IoBuildDeviceIoControlRequest(IOCTL_HID_GET_INPUT_REPORT,
device, NULL, 0, packet, sizeof(packet), TRUE, events[0],
&irp_status);
irpsp = IoGetNextIrpStackLocation(irp);
irpsp->CompletionRoutine = read_Completion;
irpsp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
ntrc = IoCallDriver(device, irp);
if (ntrc == STATUS_PENDING)
rc = WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (irp->IoStatus.u.Status == STATUS_SUCCESS)
{
RingBuffer_Write(ext->ring_buffer, packet);
I'm not opposed to what you have here, but a get-buffer/commit-buffer model would avoid an allocation and a memcpy. Although this would complicate simultaneous writes, if that's a concern.
Part of the trickiness here is that the the packet gets 'consumed' by the IoCallDriver/IoCompleteRequest process. It needs to be a stack pointer. So I end up having to allocate it on the stack and then copy the result out of it.
-aric