[usb/usbehci]
authorMichael Martin <michael.martin@reactos.org>
Fri, 2 Apr 2010 04:49:01 +0000 (04:49 +0000)
committerMichael Martin <michael.martin@reactos.org>
Fri, 2 Apr 2010 04:49:01 +0000 (04:49 +0000)
- Implement tracking port status and change status.
- When device has connected on port, set the port status. For now assume high speed device.
- Fix returning root hubs Status Change Endpoint for URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER.
- Implement USB_REQUEST_GET_STATUS for functions URB_FUNCTION_GET_STATUS_FROM_DEVICE and URB_FUNCTION_CLASS_OTHER. Implement USB_REQUEST_CLEAR_FEATURE and USB_REQUEST_SET_FEATURE.
- Implement IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE to return the root hubs device handle, fix IOCTL_INTERNAL_USB_GET_HUB_COUNT to return 1 vice 0 as the root hub must be accounted for.
- Code based on XEN PV Drivers by James Harper.

svn path=/trunk/; revision=46660

reactos/drivers/usb/usbehci/fdo.c
reactos/drivers/usb/usbehci/irp.c
reactos/drivers/usb/usbehci/pdo.c
reactos/drivers/usb/usbehci/usbehci.h

index eebc0c0..b1ec550 100644 (file)
@@ -100,9 +100,9 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
 
                     tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i)));
 
-                    DPRINT("port tmp %x\n", tmp);
                     GetDeviceDescriptor(FdoDeviceExtension, 0, 0, FALSE);
                     PdoDeviceExtension->ChildDeviceCount++;
+                    PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED | USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE;
                     WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEM_DATA));
                     if (!WorkItemData) ASSERT(FALSE);
                     WorkItemData->IoWorkItem = IoAllocateWorkItem(PdoDeviceExtension->DeviceObject);
index 29af1f9..06d7c50 100644 (file)
@@ -88,35 +88,65 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
         if (UsbDevice == NULL)
             UsbDevice = DeviceExtension->UsbDevices[0];
 
+        /* Assume URB success */
+        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
+        /* Set the DeviceHandle to the Internal Device */
+        Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
+
         switch (Urb->UrbHeader.Function)
         {
             case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
             {
-                /* Are we suppose to only return on this request when a device is connected
-                   or is it the RootHubInitNotification Callback */
                 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:\n");
                 DPRINT1("--->TransferBufferLength %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
                 DPRINT1("--->TransferBuffer %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
                 DPRINT1("--->PipeHandle %x\n",Urb->UrbBulkOrInterruptTransfer.PipeHandle);
+                DPRINT1("---->(PVOID)&UsbDevice->EndPointDescriptor %x\n", (PVOID)&UsbDevice->EndPointDescriptor);
                 DPRINT1("--->TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
-                /* FIXME */
+
                 RtlZeroMemory(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
-                ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1;
-                /* Turn off Irp handling as nothing is handled beyond this */
-                DeviceExtension->HaltUrbHandling = TRUE;
+                if (UsbDevice == DeviceExtension->UsbDevices[0])
+                {
+                    if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK))
+                    {
+                        LONG i;
+                        for (i = 0; i < 8; i++)
+                        {
+                            if (DeviceExtension->Ports[i].PortChange)
+                            {
+                                DPRINT1("Inform hub driver that port %d has changed\n", i+1);
+                                ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << (i + 1);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
+                        Status = STATUS_UNSUCCESSFUL;
+                    }
+                }
                 break;
             }
             case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
             {
-                DPRINT1("Get Status from Device\n");
+                DPRINT("Get Status from Device\n");
+                DPRINT("Index : %d\n", Urb->UrbControlGetStatusRequest.Index);
+
+                /* Copied from pvdrivers */
+                if (Urb->UrbControlGetStatusRequest.Index == 0)
+                {
+                    *(PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer = USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE;
+                }
+                else
+                {
+                    DPRINT1("Uknown identifier\n");
+                    Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
+                    Status = STATUS_UNSUCCESSFUL;
+                }
                 break;
             }
             case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
             {
-                Urb->UrbHeader.Function = 0x08;
-                Urb->UrbHeader.UsbdFlags = 0;
-                Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
-
                 switch(Urb->UrbControlDescriptorRequest.DescriptorType)
                 {
                     case USB_DEVICE_DESCRIPTOR_TYPE:
@@ -130,9 +160,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
                                       &UsbDevice->DeviceDescriptor,
                                       Urb->UrbControlDescriptorRequest.TransferBufferLength);
-
-                        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
-
                         break;
                     }
                     case USB_CONFIGURATION_DESCRIPTOR_TYPE:
@@ -150,9 +177,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
                                       &UsbDevice->ConfigurationDescriptor,
                                       Urb->UrbControlDescriptorRequest.TransferBufferLength);
-
-                        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
-
                         break;
                     }
                     case USB_STRING_DESCRIPTOR_TYPE:
@@ -232,10 +256,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         }
                         InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
                     }
-
-                    Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
-                    Urb->UrbHeader.UsbdFlags = 0;
-                    Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
                 }
                 else
                 {
@@ -252,7 +272,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
                         DPRINT1("Urb->UrbControlVendorClassRequest.Value %x\n", Urb->UrbControlVendorClassRequest.Value);
 
-
                         switch (Urb->UrbControlVendorClassRequest.Value >> 8)
                         {
                             case USB_DEVICE_CLASS_AUDIO:
@@ -328,10 +347,16 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                                 DPRINT1("Unknown UrbControlVendorClassRequest Value\n");
                             }
                         }
-                        Urb->UrbHeader.Function = 0x08;
-                        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
-                        Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
-                        Urb->UrbHeader.UsbdFlags = 0;
+                        break;
+                    }
+                    case USB_REQUEST_GET_STATUS:
+                    {
+                        DPRINT1("DEVICE: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index);
+
+                        if (Urb->UrbControlVendorClassRequest.Index == 1)
+                        {
+                            ((PULONG)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = 0;
+                        }
                         break;
                     }
                     default:
@@ -348,22 +373,51 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                 {
                     case USB_REQUEST_GET_STATUS:
                     {
-                        DPRINT1("USB_REQUEST_GET_STATUS\n");
+                        DPRINT1("OTHER: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index);
+
+                        ((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus;
+                        ((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[1] = DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange;
                         break;
                     }
                     case USB_REQUEST_CLEAR_FEATURE:
                     {
-                        DPRINT1("USB_REQUEST_CLEAR_FEATURE\n");
+                        DPRINT1("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
+                            Urb->UrbControlVendorClassRequest.Value);
+                        switch (Urb->UrbControlVendorClassRequest.Value)
+                        {
+                            case C_PORT_CONNECTION:
+                                DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT;
+                                break;
+                            case C_PORT_RESET:
+                                DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET;
+                                break;
+                            default:
+                                DPRINT1("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
+                                break;
+                        }
                         break;
                     }
                     case USB_REQUEST_SET_FEATURE:
                     {
-                        DPRINT1("USB_REQUEST_SET_FEATURE value %x\n", Urb->UrbControlVendorClassRequest.Value);
+                        DPRINT1("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
+                            Urb->UrbControlVendorClassRequest.Value);
+
                         switch(Urb->UrbControlVendorClassRequest.Value)
                         {
-                            /* FIXME: Needs research */
-                            case 0x01:
+                            case PORT_RESET:
                             {
+                                DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET;
+                                break;
+                            }
+                            case PORT_ENABLE:
+                            {
+                                DPRINT1("Unhandled Set Feature\n");
+                                break;
+                            }
+                            default:
+                            {
+                                DPRINT1("Unknown Set Feature!\n");
+                                break;
                             }
                         }
                         break;
@@ -371,6 +425,7 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                     case USB_REQUEST_SET_ADDRESS:
                     {
                         DPRINT1("USB_REQUEST_SET_ADDRESS\n");
+                        ASSERT(FALSE);
                         break;
                     }
                     case USB_REQUEST_GET_DESCRIPTOR:
@@ -408,6 +463,12 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         DPRINT1("USB_REQUEST_SYNC_FRAME\n");
                         break;
                     }
+                    default:
+                    {
+                        DPRINT1("Unknown Function Class Unknown request\n");
+                        ASSERT(FALSE);
+                        break;
+                    }
                 }
                 break;
             }
@@ -415,6 +476,7 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
             {
                 DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function);
                 Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
+                ASSERT(FALSE);
             }
 
         }
@@ -424,6 +486,13 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
         Irp->IoStatus.Status = Status;
         Irp->IoStatus.Information = Information;
 
+        if (Urb->UrbHeader.Status == USBD_STATUS_SUCCESS)
+        {
+            /* Fake a successful Control Transfer */
+            Urb->UrbHeader.Function = 0x08;
+            Urb->UrbHeader.UsbdFlags = 0;
+        }
+
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
     }
index 3ab717f..6a0d735 100644 (file)
@@ -172,18 +172,24 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
         }
         case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
         {
-            DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
+            DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE);
+            if (Stack->Parameters.Others.Argument1)
+            {
+                /* Return the root hubs devicehandle */
+                *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)PdoDeviceExtension->UsbDevices[0];
+            }
+            else
+                Status = STATUS_INVALID_DEVICE_REQUEST;
             break;
         }
         case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
         {
-            DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
-
+            DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
             if (Stack->Parameters.Others.Argument1)
             {
                 /* FIXME: Determine the number of hubs between the usb device and root hub */
-                /* For now return 0 */
-                *(PVOID *)Stack->Parameters.Others.Argument1 = 0;
+                /* For now return 1, the root hub */
+                *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)1;
             }
             break;
         }
@@ -216,9 +222,8 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
             if (Stack->Parameters.Others.Argument2)
                 *(PVOID *)Stack->Parameters.Others.Argument2 = IoGetAttachedDevice(FdoDeviceExtension->DeviceObject);
 
-            Irp->IoStatus.Information = 0;
-            Irp->IoStatus.Status = STATUS_SUCCESS;
-            return STATUS_SUCCESS;
+            Information = 0;
+            Status = STATUS_SUCCESS;
             break;
         }
         case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
@@ -287,7 +292,6 @@ PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information)
         }
     }
 
-    /* Lifted from hpoussin */
     Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
                                     &SourceString,
                                     &String);
@@ -350,6 +354,7 @@ PdoDispatchPnp(
             PPDO_DEVICE_EXTENSION PdoDeviceExtension;
             PFDO_DEVICE_EXTENSION FdoDeviceExtension;
             UNICODE_STRING InterfaceSymLinkName;
+            LONG i;
 
             PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
             FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
@@ -357,6 +362,12 @@ PdoDispatchPnp(
             /* Create the root hub */
             RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE);
 
+            for (i = 0; i < 8; i++)
+            {
+                PdoDeviceExtension->Ports[i].PortStatus = USB_PORT_STATUS_ENABLE;
+                PdoDeviceExtension->Ports[i].PortChange = 0;
+            }
+
             RtlCopyMemory(&RootHubDevice->DeviceDescriptor,
                           ROOTHUB2_DEVICE_DESCRIPTOR,
                           sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
@@ -409,8 +420,16 @@ PdoDispatchPnp(
                     break;
                 }
                 case BusRelations:
+                    DPRINT1("BusRelations!!!!!\n");
                 case RemovalRelations:
                 case EjectionRelations:
+                {
+                    /* Ignore the request */
+                    Information = Irp->IoStatus.Information;
+                    Status = Irp->IoStatus.Status;
+                    break;
+
+                }
                 default:
                 {
                     DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unhandled type 0x%lx\n",
@@ -534,7 +553,8 @@ PdoDispatchPnp(
             else
             {
                 DPRINT1("Not Supported\n");
-                Status = STATUS_NOT_SUPPORTED;
+                Status = Irp->IoStatus.Status;
+                Information = Irp->IoStatus.Information;
             }
             break;
         }
index f4c440d..13bfabb 100644 (file)
@@ -75,6 +75,25 @@ OR with QUEUE_TRANSFER_DESCRIPTOR Token.SplitTransactionState */
 #define PING_STATE_DO_OUT              0x00
 #define PING_STATE_DO_PING             0x01
 
+#define C_HUB_LOCAL_POWER   0
+#define C_HUB_OVER_CURRENT  1
+#define PORT_CONNECTION     0
+#define PORT_ENABLE         1
+#define PORT_SUSPEND        2
+#define PORT_OVER_CURRENT   3
+#define PORT_RESET          4
+#define PORT_POWER          8
+#define PORT_LOW_SPEED      9
+#define PORT_HIGH_SPEED     9
+#define C_PORT_CONNECTION   16
+#define C_PORT_ENABLE       17
+#define C_PORT_SUSPEND      18
+#define C_PORT_OVER_CURRENT 19
+#define C_PORT_RESET        20
+#define PORT_TEST           21
+#define PORT_INDICATOR      22
+#define USB_PORT_STATUS_CHANGE 0x4000
+
 /* QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN */
 typedef struct _QETD_TOKEN_BITS
 {
@@ -273,16 +292,16 @@ typedef struct _EHCI_HCC_CONTENT
 } EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT;
 
 typedef struct _EHCI_CAPS {
-    UCHAR        Length;
-    UCHAR        Reserved;
-    USHORT        HCIVersion;
+    UCHAR Length;
+    UCHAR Reserved;
+    USHORT HCIVersion;
     union
     {
-        EHCI_HCS_CONTENT        HCSParams;
-        ULONG    HCSParamsLong;
+        EHCI_HCS_CONTENT HCSParams;
+        ULONG HCSParamsLong;
     };
-    ULONG        HCCParams;
-    UCHAR        PortRoute [8];
+    ULONG HCCParams;
+    UCHAR PortRoute [8];
 } EHCI_CAPS, *PEHCI_CAPS;
 
 typedef struct _COMMON_DEVICE_EXTENSION
@@ -292,6 +311,14 @@ typedef struct _COMMON_DEVICE_EXTENSION
     PDEVICE_OBJECT DeviceObject;
 } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
 
+typedef struct _EHCIPORTS
+{
+    ULONG PortNumber;
+    ULONG PortType;
+    USHORT PortStatus;
+    USHORT PortChange;
+} EHCIPORTS, *PEHCIPORTS;
+
 typedef struct _FDO_DEVICE_EXTENSION
 {
     COMMON_DEVICE_EXTENSION Common;
@@ -333,8 +360,8 @@ typedef struct _FDO_DEVICE_EXTENSION
 
     PULONG PeriodicFramList;
     PULONG AsyncListQueueHeadPtr;
-    PHYSICAL_ADDRESS    PeriodicFramListPhysAddr;
-    PHYSICAL_ADDRESS    AsyncListQueueHeadPtrPhysAddr;
+    PHYSICAL_ADDRESS PeriodicFramListPhysAddr;
+    PHYSICAL_ADDRESS AsyncListQueueHeadPtrPhysAddr;
 
     BOOLEAN AsyncComplete;
 
@@ -356,6 +383,8 @@ typedef struct _PDO_DEVICE_EXTENSION
     BOOLEAN HaltUrbHandling;
     PVOID CallbackContext;
     PRH_INIT_CALLBACK CallbackRoutine;
+    ULONG NumberOfPorts;
+    EHCIPORTS Ports[32];
 } PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
 
 typedef struct _WORKITEM_DATA