+ +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