Example #1
0
File: device.c Project: iXit/wine
NTSTATUS WINAPI HID_Device_ioctl(DEVICE_OBJECT *device, IRP *irp)
{
    NTSTATUS rc = STATUS_SUCCESS;
    IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
    BASE_DEVICE_EXTENSION *extension = device->DeviceExtension;

    irp->IoStatus.Information = 0;

    TRACE("device %p ioctl(%x)\n", device, irpsp->Parameters.DeviceIoControl.IoControlCode);

    switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
    {
        case IOCTL_HID_GET_POLL_FREQUENCY_MSEC:
            TRACE("IOCTL_HID_GET_POLL_FREQUENCY_MSEC\n");
            if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
            {
                irp->IoStatus.u.Status = STATUS_BUFFER_OVERFLOW;
                irp->IoStatus.Information = 0;
                break;
            }
            *((ULONG*)irp->AssociatedIrp.SystemBuffer) = extension->poll_interval;
            irp->IoStatus.Information = sizeof(ULONG);
            irp->IoStatus.u.Status = STATUS_SUCCESS;
            break;
        case IOCTL_HID_SET_POLL_FREQUENCY_MSEC:
        {
            ULONG poll_interval;
            TRACE("IOCTL_HID_SET_POLL_FREQUENCY_MSEC\n");
            if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
            {
                irp->IoStatus.u.Status = STATUS_BUFFER_TOO_SMALL;
                break;
            }
            poll_interval = *(ULONG *)irp->AssociatedIrp.SystemBuffer;
            if (poll_interval <= MAX_POLL_INTERVAL_MSEC)
            {
                extension->poll_interval = poll_interval;
                irp->IoStatus.u.Status = STATUS_SUCCESS;
            }
            else
                irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER;
            break;
        }
        case IOCTL_HID_GET_PRODUCT_STRING:
        {
            rc = handle_minidriver_string(device, irp, HID_STRING_ID_IPRODUCT);
            break;
        }
        case IOCTL_HID_GET_SERIALNUMBER_STRING:
        {
            rc = handle_minidriver_string(device, irp, HID_STRING_ID_ISERIALNUMBER);
            break;
        }
        case IOCTL_HID_GET_MANUFACTURER_STRING:
        {
            rc = handle_minidriver_string(device, irp, HID_STRING_ID_IMANUFACTURER);
            break;
        }
        case IOCTL_HID_GET_COLLECTION_INFORMATION:
        {
            rc = handle_IOCTL_HID_GET_COLLECTION_INFORMATION(irp, extension);
            break;
        }
        case IOCTL_HID_GET_COLLECTION_DESCRIPTOR:
        {
            rc = handle_IOCTL_HID_GET_COLLECTION_DESCRIPTOR(irp, extension);
            break;
        }
        case IOCTL_HID_GET_INPUT_REPORT:
        {
            HID_XFER_PACKET *packet;
            UINT packet_size = sizeof(*packet) + irpsp->Parameters.DeviceIoControl.OutputBufferLength;
            BYTE *buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
            ULONG out_length;

            packet = HeapAlloc(GetProcessHeap(), 0, packet_size);

            if (extension->preparseData->InputReports[0].reportID)
                packet->reportId = buffer[0];
            else
                packet->reportId = 0;
            packet->reportBuffer = (BYTE *)packet + sizeof(*packet);
            packet->reportBufferLen = irpsp->Parameters.DeviceIoControl.OutputBufferLength - 1;

            rc = call_minidriver(IOCTL_HID_GET_INPUT_REPORT, device, NULL, 0, packet, sizeof(*packet));
            if (rc == STATUS_SUCCESS)
            {
                rc = copy_packet_into_buffer(packet, buffer, irpsp->Parameters.DeviceIoControl.OutputBufferLength, &out_length);
                irp->IoStatus.Information = out_length;
            }
            else
                irp->IoStatus.Information = 0;
            irp->IoStatus.u.Status = rc;
            HeapFree(GetProcessHeap(), 0, packet);
            break;
        }
        case IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS:
        {
            irp->IoStatus.Information = 0;

            if (irpsp->Parameters.DeviceIoControl.InputBufferLength != sizeof(ULONG))
            {
                irp->IoStatus.u.Status = rc = STATUS_BUFFER_OVERFLOW;
            }
            else
            {
                rc = RingBuffer_SetSize(extension->ring_buffer, *(ULONG*)irp->AssociatedIrp.SystemBuffer);
                irp->IoStatus.u.Status = rc;
            }
            break;
        }
        case IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS:
        {
            if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
            {
                irp->IoStatus.u.Status = rc = STATUS_BUFFER_TOO_SMALL;
            }
            else
            {
                *(ULONG*)irp->AssociatedIrp.SystemBuffer = RingBuffer_GetSize(extension->ring_buffer);
                rc = irp->IoStatus.u.Status = STATUS_SUCCESS;
            }
            break;
        }
        case IOCTL_HID_GET_FEATURE:
            rc = HID_get_feature(device, irp);
            break;
        case IOCTL_HID_SET_FEATURE:
        case IOCTL_HID_SET_OUTPUT_REPORT:
            rc = HID_set_to_device(device, irp);
            break;
        default:
        {
            ULONG code = irpsp->Parameters.DeviceIoControl.IoControlCode;
            FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
                  code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
            irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
            rc = STATUS_UNSUCCESSFUL;
            break;
        }
    }

    if (rc != STATUS_PENDING)
        IoCompleteRequest( irp, IO_NO_INCREMENT );

    return rc;
}
Example #2
0
File: device.c Project: hejin/wine
NTSTATUS WINAPI HID_Device_ioctl(DEVICE_OBJECT *device, IRP *irp)
{
    NTSTATUS rc = STATUS_SUCCESS;
    IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
    BASE_DEVICE_EXTENSION *extension = device->DeviceExtension;

    irp->IoStatus.Information = 0;

    TRACE("device %p ioctl(%x)\n", device, irpsp->Parameters.DeviceIoControl.IoControlCode);

    switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
    {
        case IOCTL_HID_GET_POLL_FREQUENCY_MSEC:
            TRACE("IOCTL_HID_GET_POLL_FREQUENCY_MSEC\n");
            if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
            {
                irp->IoStatus.u.Status = STATUS_BUFFER_OVERFLOW;
                irp->IoStatus.Information = 0;
                break;
            }
            *((ULONG*)irp->AssociatedIrp.SystemBuffer) = extension->poll_interval;
            irp->IoStatus.Information = sizeof(ULONG);
            irp->IoStatus.u.Status = STATUS_SUCCESS;
            break;
        case IOCTL_HID_SET_POLL_FREQUENCY_MSEC:
        {
            ULONG poll_interval;
            TRACE("IOCTL_HID_SET_POLL_FREQUENCY_MSEC\n");
            if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
            {
                irp->IoStatus.u.Status = STATUS_BUFFER_TOO_SMALL;
                break;
            }
            poll_interval = *(ULONG *)irp->AssociatedIrp.SystemBuffer;
            if (poll_interval == 0)
                FIXME("Handle opportunistic reads\n");
            else if (poll_interval <= MAX_POLL_INTERVAL_MSEC)
            {
                extension->poll_interval = poll_interval;
                irp->IoStatus.u.Status = STATUS_SUCCESS;
            }
            else
                irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER;
            break;
        }
        case IOCTL_HID_GET_PRODUCT_STRING:
        {
            rc = handle_minidriver_string(device, irp, HID_STRING_ID_IPRODUCT);
            break;
        }
        case IOCTL_HID_GET_MANUFACTURER_STRING:
        {
            rc = handle_minidriver_string(device, irp, HID_STRING_ID_IMANUFACTURER);
            break;
        }
        case IOCTL_HID_GET_COLLECTION_INFORMATION:
        {
            rc = handle_IOCTL_HID_GET_COLLECTION_INFORMATION(irp, extension);
            break;
        }
        case IOCTL_HID_GET_COLLECTION_DESCRIPTOR:
        {
            rc = handle_IOCTL_HID_GET_COLLECTION_DESCRIPTOR(irp, extension);
            break;
        }
        case IOCTL_HID_GET_INPUT_REPORT:
        {
            HID_XFER_PACKET packet;
            BYTE* buffer = ((BYTE*)irp->MdlAddress->StartVa) + irp->MdlAddress->ByteOffset;

            if (extension->preparseData->InputReports[0].reportID)
                packet.reportId = buffer[0];
            else
                packet.reportId = 0;
            packet.reportBuffer = buffer;
            packet.reportBufferLen = irpsp->Parameters.DeviceIoControl.OutputBufferLength;

            call_minidriver(IOCTL_HID_GET_INPUT_REPORT, device, NULL, 0, &packet, sizeof(packet));
            irp->IoStatus.Information = packet.reportBufferLen;
            irp->IoStatus.u.Status = STATUS_SUCCESS;
            break;
        }
        case IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS:
        {
            irp->IoStatus.Information = 0;

            if (irpsp->Parameters.DeviceIoControl.InputBufferLength != sizeof(ULONG))
            {
                irp->IoStatus.u.Status = rc = STATUS_BUFFER_OVERFLOW;
            }
            else
            {
                rc = RingBuffer_SetSize(extension->ring_buffer, *(ULONG*)irp->AssociatedIrp.SystemBuffer);
                irp->IoStatus.u.Status = rc;
            }
            break;
        }
        case IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS:
        {
            if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
            {
                irp->IoStatus.u.Status = rc = STATUS_BUFFER_TOO_SMALL;
            }
            else
            {
                *(ULONG*)irp->AssociatedIrp.SystemBuffer = RingBuffer_GetSize(extension->ring_buffer);
                rc = irp->IoStatus.u.Status = STATUS_SUCCESS;
            }
            break;
        }
        default:
        {
            ULONG code = irpsp->Parameters.DeviceIoControl.IoControlCode;
            FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
                  code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
            irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
            rc = STATUS_UNSUCCESSFUL;
            break;
        }
    }

    if (rc != STATUS_PENDING)
        IoCompleteRequest( irp, IO_NO_INCREMENT );

    return rc;
}