Sync with trunk r58740.
[reactos.git] / drivers / hid / hidusb / hidusb.c
index 88265c1..7d5d239 100644 (file)
@@ -305,7 +305,7 @@ HidCreate(
     //
     // informal debug print
     //
-    DPRINT1("HIDUSB Request: %x\n", IoStack->MajorFunction);
+    DPRINT("HIDUSB Request: %x\n", IoStack->MajorFunction);
 
     //
     // done
@@ -324,7 +324,7 @@ HidUsb_ResetWorkerRoutine(
     PHID_USB_RESET_CONTEXT ResetContext;
     PHID_DEVICE_EXTENSION DeviceExtension;
 
-    DPRINT1("[HIDUSB] ResetWorkerRoutine\n");
+    DPRINT("[HIDUSB] ResetWorkerRoutine\n");
 
     //
     // get context
@@ -340,7 +340,7 @@ HidUsb_ResetWorkerRoutine(
     // get port status
     //
     Status = HidUsb_GetPortStatus(ResetContext->DeviceObject, &PortStatus);
-    DPRINT1("[HIDUSB] ResetWorkerRoutine GetPortStatus %x PortStatus %x\n", Status, PortStatus);
+    DPRINT("[HIDUSB] ResetWorkerRoutine GetPortStatus %x PortStatus %x\n", Status, PortStatus);
     if (NT_SUCCESS(Status))
     {
         if (!(PortStatus & USB_PORT_STATUS_ENABLE))
@@ -651,17 +651,22 @@ HidUsb_GetReportDescriptor(
     {
         //
         // failed to get descriptor
+        // try with old hid version
         //
-        DPRINT("[HIDUSB] failed to get report descriptor with %x\n", Status);
-        ASSERT(FALSE);
-        return Status;
+        BufferLength = HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength;
+        Status = Hid_GetDescriptor(DeviceObject, URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), &Report, &BufferLength, HidDeviceExtension->HidDescriptor->DescriptorList[0].bReportType, 0, 0 /* FIXME*/);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT("[HIDUSB] failed to get report descriptor with %x\n", Status);
+            return Status;
+        }
     }
 
     //
     // get current stack location
     //
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    DPRINT1("[HIDUSB] GetReportDescriptor: Status %x ReportLength %lu OutputBufferLength %lu TransferredLength %lu\n", Status, HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, BufferLength);
+    DPRINT("[HIDUSB] GetReportDescriptor: Status %x ReportLength %lu OutputBufferLength %lu TransferredLength %lu\n", Status, HidDeviceExtension->HidDescriptor->DescriptorList[0].wReportLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, BufferLength);
 
     //
     // get length to copy
@@ -727,7 +732,7 @@ HidInternalDeviceControl(
             //
             // store result
             //
-            DPRINT1("[HIDUSB] IOCTL_HID_GET_DEVICE_ATTRIBUTES\n");
+            DPRINT("[HIDUSB] IOCTL_HID_GET_DEVICE_ATTRIBUTES\n");
             ASSERT(HidDeviceExtension->DeviceDescriptor);
             Irp->IoStatus.Information = sizeof(HID_DESCRIPTOR);
             Attributes = (PHID_DEVICE_ATTRIBUTES)Irp->UserBuffer;
@@ -749,7 +754,7 @@ HidInternalDeviceControl(
             // sanity check
             //
             ASSERT(HidDeviceExtension->HidDescriptor);
-            DPRINT1("[HIDUSB] IOCTL_HID_GET_DEVICE_DESCRIPTOR DescriptorLength %lu OutputBufferLength %lu\n", HidDeviceExtension->HidDescriptor->bLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+            DPRINT("[HIDUSB] IOCTL_HID_GET_DEVICE_DESCRIPTOR DescriptorLength %lu OutputBufferLength %lu\n", HidDeviceExtension->HidDescriptor->bLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
 
             //
             // store length
@@ -774,7 +779,7 @@ HidInternalDeviceControl(
         case IOCTL_HID_GET_REPORT_DESCRIPTOR:
         {
             Status = HidUsb_GetReportDescriptor(DeviceObject, Irp);
-            DPRINT1("[HIDUSB] IOCTL_HID_GET_REPORT_DESCRIPTOR Status %x\n", Status);
+            DPRINT("[HIDUSB] IOCTL_HID_GET_REPORT_DESCRIPTOR Status %x\n", Status);
             Irp->IoStatus.Status = Status;
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
             return Status;
@@ -1000,7 +1005,7 @@ Hid_DispatchUrb(
         Status = IoStatus.Status;
     }
 
-    DPRINT1("[HIDUSB] DispatchUrb %x\n", Status);
+    DPRINT("[HIDUSB] DispatchUrb %x\n", Status);
 
 
     //
@@ -1168,6 +1173,13 @@ Hid_SelectConfiguration(
                                                               USB_DEVICE_CLASS_HUMAN_INTERFACE,
                                                              -1,
                                                              -1);
+    if (!InterfaceDescriptor)
+    {
+        //
+        // bogus configuration descriptor
+        //
+        return STATUS_INVALID_PARAMETER;
+    }
 
     //
     // sanity check
@@ -1230,6 +1242,156 @@ Hid_SelectConfiguration(
     return Status;
 }
 
+NTSTATUS
+Hid_SetIdle(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
+    PHID_DEVICE_EXTENSION DeviceExtension;
+    PURB Urb;
+    NTSTATUS Status;
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
+
+    //
+    // allocate urb
+    //
+    Urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
+    if (!Urb)
+    {
+        //
+        // no memory
+        //
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    //
+    // zero urb
+    //
+    RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
+
+    //
+    // format urb
+    //
+    UsbBuildVendorRequest(Urb,
+                          URB_FUNCTION_CLASS_INTERFACE, 
+                          sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
+                          0,
+                          0,
+                          USB_SET_IDLE_REQUEST, // HID_SET_IDLE
+                          0,
+                          0,
+                          NULL,
+                          NULL,
+                          0,
+                          NULL);
+
+    //
+    // dispatch urb
+    //
+    Status = Hid_DispatchUrb(DeviceObject, Urb);
+
+    //
+    // free urb
+    //
+    ExFreePool(Urb);
+
+    //
+    // print status
+    //
+    DPRINT1("Status %x\n", Status);
+    return Status;
+}
+
+
+VOID
+Hid_GetProtocol(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
+    PHID_DEVICE_EXTENSION DeviceExtension;
+    PURB Urb;
+    NTSTATUS Status;
+    UCHAR Protocol[1];
+
+    //
+    // get device extension
+    //
+    DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    HidDeviceExtension = (PHID_USB_DEVICE_EXTENSION)DeviceExtension->MiniDeviceExtension;
+    ASSERT(HidDeviceExtension->InterfaceInfo);
+
+    if (HidDeviceExtension->InterfaceInfo->SubClass != 0x1)
+    {
+        //
+        // device does not support the boot protocol
+        //
+        return;
+    }
+
+
+    //
+    // allocate urb
+    //
+    Urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
+    if (!Urb)
+    {
+        //
+        // no memory
+        //
+        return;
+    }
+
+    //
+    // zero urb
+    //
+    RtlZeroMemory(Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
+
+    //
+    // format urb
+    //
+    UsbBuildVendorRequest(Urb,
+                          URB_FUNCTION_CLASS_INTERFACE, 
+                          sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
+                          USBD_TRANSFER_DIRECTION_IN,
+                          0,
+                          USB_GET_PROTOCOL_REQUEST,
+                          0,
+                          0,
+                          Protocol,
+                          NULL,
+                          1,
+                          NULL);
+    Protocol[0] = 0xFF;
+    //
+    // dispatch urb
+    //
+    Status = Hid_DispatchUrb(DeviceObject, Urb);
+
+    //
+    // free urb
+    //
+    ExFreePool(Urb);
+
+    //
+    // boot protocol active 0x00 disabled 0x1
+    //
+    if (Protocol[0] != 0x1)
+    {
+        if (Protocol[0] == 0x00)
+        {
+            DPRINT1("[HIDUSB] Need to disable boot protocol!\n");
+        }
+        else
+        {
+            DPRINT1("[HIDUSB] Unexpected protocol value %x\n", Protocol[0] & 0xFF);
+        }
+    }
+}
 
 NTSTATUS
 Hid_PnpStart(
@@ -1322,7 +1484,7 @@ Hid_PnpStart(
         //
         // no interface class
         //
-        DPRINT1("[HIDUSB] HID Class found\n");
+        DPRINT1("[HIDUSB] HID Interface descriptor not found\n");
         return STATUS_UNSUCCESSFUL;
     }
 
@@ -1353,21 +1515,38 @@ Hid_PnpStart(
         // select configuration
         //
         Status = Hid_SelectConfiguration(DeviceObject);
-        ASSERT(Status == STATUS_SUCCESS);
 
         //
         // done
         //
         DPRINT1("[HIDUSB] SelectConfiguration %x\n", Status);
-        return Status;
-    }
 
-    //
-    // FIXME parse hid descriptor
-    //
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_SUCCESS;
+        if (NT_SUCCESS(Status))
+        {
+            //
+            // now set the device idle
+            //
+            Hid_SetIdle(DeviceObject);
+
+            //
+            // get protocol
+            //
+            Hid_GetProtocol(DeviceObject);
+            return Status;
+        }
+    }
+    else
+    {
+        //
+        // FIXME parse hid descriptor
+        // select configuration
+        // set idle
+        // and get protocol
+        //
+        UNIMPLEMENTED
+        ASSERT(FALSE);
+    }
+    return Status;
 }
 
 
@@ -1393,7 +1572,7 @@ HidPnp(
     // get current stack location
     //
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    DPRINT1("[HIDUSB] Pnp %x\n", IoStack->MinorFunction);
+    DPRINT("[HIDUSB] Pnp %x\n", IoStack->MinorFunction);
 
     //
     // handle requests based on request type
@@ -1411,15 +1590,18 @@ HidPnp(
             //
             // free resources
             //
-            if (HidDeviceExtension->HidDescriptor)
+            if (HidDeviceExtension->ConfigurationDescriptor)
             {
-                ExFreePool(HidDeviceExtension->HidDescriptor);
-                HidDeviceExtension->HidDescriptor = NULL;
+                ExFreePool(HidDeviceExtension->ConfigurationDescriptor);
+                HidDeviceExtension->ConfigurationDescriptor = NULL;
             }
 
             //
-            // done
+            // delete and detach device
             //
+            IoDetachDevice(DeviceExtension->NextDeviceObject);
+            IoDeleteDevice(DeviceObject);
+
             return Status;
         }
         case IRP_MN_QUERY_PNP_DEVICE_STATE:
@@ -1440,6 +1622,25 @@ HidPnp(
             //
             return Status;
         }
+        case IRP_MN_QUERY_STOP_DEVICE:
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+        {
+            //
+            // we're fine with it
+            //
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+
+            //
+            // pass request to next driver
+            //
+            IoSkipCurrentIrpStackLocation(Irp);
+            Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+
+            //
+            // done
+            //
+            return Status;
+        }
         case IRP_MN_STOP_DEVICE:
         {
             //
@@ -1497,14 +1698,8 @@ HidPnp(
                 Status = Irp->IoStatus.Status;
             }
 
-            if (NT_SUCCESS(Status))
+            if (NT_SUCCESS(Status) && IoStack->Parameters.DeviceCapabilities.Capabilities != NULL)
             {
-                //
-                // driver supports D1 & D2
-                //
-                IoStack->Parameters.DeviceCapabilities.Capabilities->DeviceD1 = TRUE;
-                IoStack->Parameters.DeviceCapabilities.Capabilities->DeviceD2 = TRUE;
-
                 //
                 // don't need to safely remove
                 //
@@ -1558,7 +1753,7 @@ HidPnp(
             // complete request
             //
             Irp->IoStatus.Status = Status;
-            DPRINT1("[HIDUSB] IRP_MN_START_DEVICE Status %x\n", Status);
+            DPRINT("[HIDUSB] IRP_MN_START_DEVICE Status %x\n", Status);
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
             return Status;
         }
@@ -1599,6 +1794,15 @@ HidAddDevice(
     return STATUS_SUCCESS;
 }
 
+VOID
+NTAPI
+Hid_Unload(
+    IN PDRIVER_OBJECT DriverObject)
+{
+    UNIMPLEMENTED
+}
+
+
 NTSTATUS
 NTAPI
 DriverEntry(
@@ -1618,6 +1822,7 @@ DriverEntry(
     DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidSystemControl;
     DriverObject->MajorFunction[IRP_MJ_PNP] = HidPnp;
     DriverObject->DriverExtension->AddDevice = HidAddDevice;
+    DriverObject->DriverUnload = Hid_Unload;
 
     //
     // prepare registration info
@@ -1641,8 +1846,8 @@ DriverEntry(
     //
     // informal debug
     //
-    DPRINT1("********* HIDUSB *********\n");
-    DPRINT1("HIDUSB Registration Status %x\n", Status);
+    DPRINT("********* HIDUSB *********\n");
+    DPRINT("HIDUSB Registration Status %x\n", Status);
 
     return Status;
 }