[USB-BRINGUP]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Mon, 26 Dec 2011 18:20:32 +0000 (18:20 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Mon, 26 Dec 2011 18:20:32 +0000 (18:20 +0000)
- Implement IOCTL_HID_GET_DEVICE_ATTRIBUTES, IOCTL_HID_GET_DEVICE_DESCRIPTOR for hidusb
- Partly implement pnp dispatch routines for hidusb

svn path=/branches/usb-bringup/; revision=54764

drivers/hid/hidusb/hidusb.c
drivers/hid/hidusb/hidusb.h

index 01b614a..db632c7 100644 (file)
@@ -52,9 +52,103 @@ HidInternalDeviceControl(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp)
 {
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    PIO_STACK_LOCATION IoStack;
+    PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
+    PHID_DEVICE_EXTENSION DeviceExtension;
+    PHID_DEVICE_ATTRIBUTES Attributes;
+    ULONG Length;
+    NTSTATUS Status;
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
+    {
+        case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
+        {
+            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_DEVICE_ATTRIBUTES))
+            {
+                //
+                // invalid request
+                //
+                Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_INVALID_BUFFER_SIZE;
+            }
+            //
+            // store result
+            //
+            ASSERT(HidDeviceExtension->HidDescriptor);
+            Irp->IoStatus.Information = sizeof(HID_DESCRIPTOR);
+            Attributes = (PHID_DEVICE_ATTRIBUTES)Irp->UserBuffer;
+            Attributes->Size = sizeof(HID_DEVICE_ATTRIBUTES);
+            Attributes->VendorID = HidDeviceExtension->VendorID;
+            Attributes->ProductID = HidDeviceExtension->ProductID;
+            Attributes->VersionNumber = HidDeviceExtension->VersionNumber;
+
+            //
+            // complete request
+            //
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_SUCCESS;
+        }
+        case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
+        {
+            //
+            // sanity check
+            //
+            ASSERT(HidDeviceExtension->HidDescriptor);
+
+            //
+            // store length
+            //
+            Length = min(HidDeviceExtension->HidDescriptor->bLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+
+            //
+            // copy descriptor
+            //
+            RtlCopyMemory(Irp->UserBuffer, HidDeviceExtension->HidDescriptor, Length);
+
+            //
+            // store result length
+            //
+            Irp->IoStatus.Information = HidDeviceExtension->HidDescriptor->bLength;
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+
+            /* complete request */
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_SUCCESS;
+        }
+        case IOCTL_HID_GET_REPORT_DESCRIPTOR:
+        case IOCTL_HID_READ_REPORT:
+        case IOCTL_HID_WRITE_REPORT:
+        case IOCTL_GET_PHYSICAL_DESCRIPTOR:
+        case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
+        case IOCTL_HID_GET_FEATURE:
+        case IOCTL_HID_SET_FEATURE:
+        case IOCTL_HID_SET_OUTPUT_REPORT:
+        case IOCTL_HID_GET_INPUT_REPORT:
+        case IOCTL_HID_GET_INDEXED_STRING:
+        case IOCTL_HID_GET_MS_GENRE_DESCRIPTOR:
+        {
+            DPRINT1("UNIMPLEMENTED %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+            Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+            ASSERT(FALSE);
+        }
+        default:
+            Status = Irp->IoStatus.Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
+    }
 }
 
 NTSTATUS
@@ -92,15 +186,225 @@ HidSystemControl(
     return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
 }
 
+NTSTATUS
+Hid_PnpStart(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+Hid_PnpCompletion(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PVOID Context)
+{
+    //
+    // signal event
+    //
+    KeSetEvent((PRKEVENT)Context, 0, FALSE);
+
+    //
+    // done
+    //
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
 NTSTATUS
 NTAPI
 HidPnp(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp)
 {
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    PIO_STACK_LOCATION IoStack;
+    PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
+    PHID_DEVICE_EXTENSION DeviceExtension;
+    KEVENT Event;
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
+
+    //
+    // get current stack location
+    //
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    //
+    // handle requests based on request type
+    //
+    switch(IoStack->MinorFunction)
+    {
+        case IRP_MN_REMOVE_DEVICE:
+        {
+            //
+            // pass request onto lower driver
+            //
+            IoSkipCurrentIrpStackLocation(Irp);
+            Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+            //
+            // free resources
+            //
+            if (HidDeviceExtension->HidDescriptor)
+            {
+                ExFreePool(HidDeviceExtension->HidDescriptor);
+                HidDeviceExtension->HidDescriptor = NULL;
+            }
+
+            //
+            // done
+            //
+            return Status;
+        }
+        case IRP_MN_QUERY_PNP_DEVICE_STATE:
+        {
+            //
+            // device can not be disabled
+            //
+            Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
+
+            //
+            // pass request to next request
+            //
+            IoSkipCurrentIrpStackLocation(Irp);
+            Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+
+            //
+            // done
+            //
+            return Status;
+        }
+        case IRP_MN_STOP_DEVICE:
+        {
+            //
+            // FIXME: unconfigure the device
+            //
+
+            //
+            // prepare irp
+            //
+            KeInitializeEvent(&Event, NotificationEvent, FALSE);
+            IoCopyCurrentIrpStackLocationToNext(Irp);
+            IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
+
+            //
+            // send irp and wait for completion
+            //
+            Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+            if (Status == STATUS_PENDING)
+            {
+                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+                Status = Irp->IoStatus.Status;
+            }
+
+            //
+            // free resources
+            //
+            if (HidDeviceExtension->HidDescriptor)
+            {
+                ExFreePool(HidDeviceExtension->HidDescriptor);
+                HidDeviceExtension->HidDescriptor = NULL;
+            }
+
+            //
+            // done
+            //
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
+        }
+        case IRP_MN_QUERY_CAPABILITIES:
+        {
+            //
+            // prepare irp
+            //
+            KeInitializeEvent(&Event, NotificationEvent, FALSE);
+            IoCopyCurrentIrpStackLocationToNext(Irp);
+            IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
+
+            //
+            // send irp and wait for completion
+            //
+            Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+            if (Status == STATUS_PENDING)
+            {
+                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+                Status = Irp->IoStatus.Status;
+            }
+
+            if (NT_SUCCESS(Status))
+            {
+                //
+                // driver supports D1 & D2
+                //
+                IoStack->Parameters.DeviceCapabilities.Capabilities->DeviceD1 = TRUE;
+                IoStack->Parameters.DeviceCapabilities.Capabilities->DeviceD2 = TRUE;
+            }
+
+            //
+            // done
+            //
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
+        }
+        case IRP_MN_START_DEVICE:
+        {
+            //
+            // prepare irp
+            //
+            KeInitializeEvent(&Event, NotificationEvent, FALSE);
+            IoCopyCurrentIrpStackLocationToNext(Irp);
+            IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
+
+            //
+            // send irp and wait for completion
+            //
+            Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+            if (Status == STATUS_PENDING)
+            {
+                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+                Status = Irp->IoStatus.Status;
+            }
+
+            //
+            // did the device successfully start
+            //
+            if (!NT_SUCCESS(Status))
+            {
+                //
+                // failed
+                //
+                DPRINT1("HIDUSB: IRP_MN_START_DEVICE failed with %x\n", Status);
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return Status;
+            }
+
+            //
+            // start device
+            //
+            Status = Hid_PnpStart(DeviceObject);
+
+            //
+            // complete request
+            //
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
+        }
+        default:
+        {
+             //
+             // forward and forget request
+             //
+             IoSkipCurrentIrpStackLocation(Irp);
+             return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+        }
+    }
 }
 
 NTSTATUS
index e991861..bfe9c6c 100644 (file)
@@ -18,5 +18,14 @@ typedef struct
     //
     LIST_ENTRY PendingRequests;
 
+    //
+    // hid descriptor
+    //
+    PHID_DESCRIPTOR HidDescriptor;
+
+    USHORT VendorID;
+    USHORT ProductID;
+    USHORT VersionNumber;
+
 }HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;