Example #1
0
File: device.c Project: iXit/wine
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;
}
Example #2
0
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;
}