]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
Sync USB modules with main trunk.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbEnumer.c
index fc0007dd11cbe418ab0f21327fb6b8576b2138ee..0b5532ec5656af9f3f37d9c56f4c2012a0c4c898 100644 (file)
@@ -120,7 +120,12 @@ UsbCreateInterface (
   UsbIf->Device     = Device;\r
   UsbIf->IfDesc     = IfDesc;\r
   UsbIf->IfSetting  = IfDesc->Settings[IfDesc->ActiveIndex];\r
-  UsbIf->UsbIo      = mUsbIoProtocol;\r
+\r
+  CopyMem (\r
+    &(UsbIf->UsbIo),\r
+    &mUsbIoProtocol,\r
+    sizeof (EFI_USB_IO_PROTOCOL)\r
+    );\r
 \r
   //\r
   // Install protocols for USBIO and device path\r
@@ -876,40 +881,71 @@ UsbEnumeratePort (
   // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.\r
   // ENABLE/RESET is used to reset port. SUSPEND isn't supported.\r
   //\r
-  Status = EFI_SUCCESS;\r
+  \r
+  if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {     \r
 \r
-  if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {\r
-    //\r
-    // If overcurrent condition is cleared, enable the port again\r
-    //\r
-    if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {\r
-      HubApi->SetPortFeature (HubIf, Port, USB_HUB_PORT_POWER);\r
+    if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {\r
+      //\r
+      // Both OverCurrent and OverCurrentChange set, means over current occurs, \r
+      // which probably is caused by short circuit. It has to wait system hardware\r
+      // to perform recovery.\r
+      //\r
+      USB_DEBUG (("UsbEnumeratePort: Critical Over Current\n", Port));\r
+      return EFI_DEVICE_ERROR;\r
+      \r
+    } else {\r
+      //\r
+      // Only OverCurrentChange set, means system has been recoveried from \r
+      // over current. As a result, all ports are nearly power-off, so\r
+      // it's necessary to detach and enumerate all ports again. \r
+      //\r
+      USB_DEBUG (("UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); \r
+      goto ON_ENUMERATE;\r
+      \r
     }\r
+  }\r
 \r
-  } else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {\r
+  if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {  \r
     //\r
-    // Device connected or disconnected. Either way, if there is\r
-    // already a device present in the bus, need to remove it.\r
+    // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart\r
+    // on 2.0 roothub does. When over-current has influence on 1.1 device, the port \r
+    // would be disabled, so it's also necessary to detach and enumerate again.\r
     //\r
-    Child = UsbFindChild (HubIf, Port);\r
-\r
-    if (Child != NULL) {\r
-      USB_DEBUG (("UsbEnumeratePort: device at port %d removed from system\n", Port));\r
-      UsbRemoveDevice (Child);\r
-    }\r
+    USB_DEBUG (("UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port));\r
+    goto ON_ENUMERATE;\r
+  }\r
+  \r
+  if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {\r
+    //\r
+    // Device connected or disconnected normally. \r
+    //\r
+    goto ON_ENUMERATE;\r
+  }\r
 \r
-    if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {\r
-      //\r
-      // Now, new device connected, enumerate and configure the device\r
-      //\r
-      USB_DEBUG (("UsbEnumeratePort: new device connected at port %d\n", Port));\r
-      Status = UsbEnumerateNewDev (HubIf, Port);\r
+ON_ENUMERATE:\r
 \r
-    } else {\r
-      USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port));\r
-    }\r
+  // \r
+  // In case there is already a device on this port logically, it's safety to remove\r
+  // and enumerate again.\r
+  //\r
+  Child = UsbFindChild (HubIf, Port);\r
+  \r
+  if (Child != NULL) {\r
+    USB_DEBUG (("UsbEnumeratePort: device at port %d removed from system\n", Port));\r
+    UsbRemoveDevice (Child);\r
   }\r
-\r
+  \r
+  if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {\r
+    //\r
+    // Now, new device connected, enumerate and configure the device \r
+    //\r
+    USB_DEBUG (("UsbEnumeratePort: new device connected at port %d\n", Port));\r
+    Status = UsbEnumerateNewDev (HubIf, Port);\r
+  \r
+  } else {\r
+    USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port));\r
+  }\r
+  \r
   HubApi->ClearPortChange (HubIf, Port);\r
   return Status;\r
 }\r