static DWORD CALLBACK hid_device_thread(void *args) { DEVICE_OBJECT *device = (DEVICE_OBJECT*)args; IRP *irp; IO_STATUS_BLOCK irp_status; HID_XFER_PACKET *packet; DWORD rc; HANDLE events[2]; NTSTATUS ntrc; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; events[0] = CreateEventA(NULL, TRUE, FALSE, NULL); events[1] = ext->halt_event; packet = HeapAlloc(GetProcessHeap(), 0, sizeof(*packet) + ext->preparseData->caps.InputReportByteLength); packet->reportBuffer = (BYTE *)packet + sizeof(*packet); if (ext->information.Polled) { while(1) { ResetEvent(events[0]); packet->reportBufferLen = ext->preparseData->caps.InputReportByteLength; packet->reportId = 0; irp = IoBuildDeviceIoControlRequest(IOCTL_HID_GET_INPUT_REPORT, device, NULL, 0, packet, sizeof(*packet), TRUE, NULL, &irp_status); IoSetCompletionRoutine(irp, read_Completion, events[0], TRUE, TRUE, TRUE); ntrc = IoCallDriver(device, irp); if (ntrc == STATUS_PENDING) WaitForMultipleObjects(2, events, FALSE, INFINITE); if (irp->IoStatus.u.Status == STATUS_SUCCESS) { RingBuffer_Write(ext->ring_buffer, packet); HID_Device_processQueue(device); } IoCompleteRequest(irp, IO_NO_INCREMENT ); rc = WaitForSingleObject(ext->halt_event, ext->poll_interval ? ext->poll_interval : DEFAULT_POLL_INTERVAL); if (rc == WAIT_OBJECT_0) break; else if (rc != WAIT_TIMEOUT) ERR("Wait returned unexpected value %x\n",rc); } } else { INT exit_now = FALSE; while(1) { ResetEvent(events[0]); irp = IoBuildDeviceIoControlRequest(IOCTL_HID_READ_REPORT, device, NULL, 0, packet->reportBuffer, ext->preparseData->caps.InputReportByteLength, TRUE, NULL, &irp_status); IoSetCompletionRoutine(irp, read_Completion, events[0], TRUE, TRUE, TRUE); ntrc = IoCallDriver(device, irp); if (ntrc == STATUS_PENDING) { WaitForMultipleObjects(2, events, FALSE, INFINITE); } rc = WaitForSingleObject(ext->halt_event, 0); if (rc == WAIT_OBJECT_0) exit_now = TRUE; if (!exit_now && irp->IoStatus.u.Status == STATUS_SUCCESS) { packet->reportBufferLen = irp->IoStatus.Information; if (ext->preparseData->InputReports[0].reportID) packet->reportId = packet->reportBuffer[0]; else packet->reportId = 0; RingBuffer_Write(ext->ring_buffer, packet); HID_Device_processQueue(device); } IoCompleteRequest(irp, IO_NO_INCREMENT ); if (exit_now) break; } } /* FIXME: releasing packet requires IRP cancellation support */ CloseHandle(events[0]); TRACE("Device thread exiting\n"); return 1; }
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, TRUE, 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) WaitForMultipleObjects(2, events, FALSE, INFINITE); if (irp->IoStatus.u.Status == STATUS_SUCCESS) { RingBuffer_Write(ext->ring_buffer, packet); HID_Device_processQueue(device); } IoCompleteRequest(irp, IO_NO_INCREMENT ); rc = WaitForSingleObject(ext->halt_event, ext->poll_interval); if (rc == WAIT_OBJECT_0) break; else if (rc != WAIT_TIMEOUT) ERR("Wait returned unexpected value %x\n",rc); } } else { INT exit_now = FALSE; HID_XFER_PACKET *packet; packet = HeapAlloc(GetProcessHeap(), 0, sizeof(*packet) + ext->preparseData->caps.InputReportByteLength); packet->reportBufferLen = ext->preparseData->caps.InputReportByteLength; packet->reportBuffer = ((BYTE*)packet) + sizeof(*packet); packet->reportId = 0; while(1) { BYTE *buffer; buffer = HeapAlloc(GetProcessHeap(), 0, ext->preparseData->caps.InputReportByteLength); ResetEvent(events[0]); irp = IoBuildDeviceIoControlRequest(IOCTL_HID_READ_REPORT, device, NULL, 0, buffer, ext->preparseData->caps.InputReportByteLength, 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) { WaitForMultipleObjects(2, events, FALSE, INFINITE); } rc = WaitForSingleObject(ext->halt_event, 0); if (rc == WAIT_OBJECT_0) exit_now = TRUE; if (!exit_now && irp->IoStatus.u.Status == STATUS_SUCCESS) { packet->reportId = buffer[0]; memcpy(packet->reportBuffer, buffer, ext->preparseData->caps.InputReportByteLength); RingBuffer_Write(ext->ring_buffer, packet); HID_Device_processQueue(device); } IoCompleteRequest(irp, IO_NO_INCREMENT ); if (exit_now) break; } HeapFree(GetProcessHeap(), 0, packet); } CloseHandle(events[0]); TRACE("Device thread exiting\n"); return 1; }