\r
Usb bus enumeration support.\r
\r
-Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
USB_ENDPOINT_DESC *EpDesc;\r
UINT8 Index;\r
UINT8 NumEndpoints;\r
- \r
+\r
NumEndpoints = UsbIf->IfSetting->Desc.NumEndpoints;\r
- \r
+\r
for (Index = 0; Index < NumEndpoints; Index++) {\r
EpDesc = UsbIf->IfSetting->Endpoints[Index];\r
\r
\r
@param UsbIf The USB interface to free.\r
\r
+ @retval EFI_ACCESS_DENIED The interface is still occupied.\r
+ @retval EFI_SUCCESS The interface is freed.\r
**/\r
-VOID\r
+EFI_STATUS\r
UsbFreeInterface (\r
IN USB_INTERFACE *UsbIf\r
)\r
{\r
- UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);\r
+ EFI_STATUS Status;\r
\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- UsbIf->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- UsbIf->DevicePath,\r
- &gEfiUsbIoProtocolGuid,\r
- &UsbIf->UsbIo,\r
- NULL\r
- );\r
+ UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);\r
\r
- if (UsbIf->DevicePath != NULL) {\r
- FreePool (UsbIf->DevicePath);\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ UsbIf->Handle,\r
+ &gEfiDevicePathProtocolGuid, UsbIf->DevicePath,\r
+ &gEfiUsbIoProtocolGuid, &UsbIf->UsbIo,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (UsbIf->DevicePath != NULL) {\r
+ FreePool (UsbIf->DevicePath);\r
+ }\r
+ FreePool (UsbIf);\r
+ } else {\r
+ UsbOpenHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);\r
}\r
-\r
- FreePool (UsbIf);\r
+ return Status;\r
}\r
\r
\r
// twisted TPL used. It should be no problem for us to connect\r
// or disconnect at CALLBACK.\r
//\r
- \r
+\r
//\r
// Only recursively wanted usb child device\r
//\r
UsbIf = UsbCreateInterface (Device, ConfigDesc->Interfaces[Index]);\r
\r
if (UsbIf == NULL) {\r
+ Device->NumOfInterface = Index;\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
Status = UsbConnectDriver (UsbIf);\r
\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "UsbSelectConfig: failed to connect driver %r, ignored\n", Status));\r
+ DEBUG ((\r
+ DEBUG_WARN,\r
+ "UsbSelectConfig: failed to connect driver %r, ignored\n",\r
+ Status\r
+ ));\r
}\r
}\r
\r
if (!EFI_ERROR (Status)) {\r
UsbIf->IsManaged = FALSE;\r
}\r
- \r
+\r
DEBUG (( EFI_D_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl(), Status));\r
ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);\r
\r
gBS->RaiseTPL (OldTpl);\r
}\r
- \r
+\r
return Status;\r
}\r
\r
// Remove each interface of the device\r
//\r
ReturnStatus = EFI_SUCCESS;\r
- for (Index = 0; Index < Device->NumOfInterface; Index++) { \r
+ for (Index = 0; Index < Device->NumOfInterface; Index++) {\r
ASSERT (Index < USB_MAX_INTERFACE);\r
UsbIf = Device->Interfaces[Index];\r
\r
\r
Status = UsbDisconnectDriver (UsbIf);\r
if (!EFI_ERROR (Status)) {\r
- UsbFreeInterface (UsbIf);\r
+ Status = UsbFreeInterface (UsbIf);\r
+ if (EFI_ERROR (Status)) {\r
+ UsbConnectDriver (UsbIf);\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
Device->Interfaces[Index] = NULL;\r
} else {\r
ReturnStatus = Status;\r
\r
@param HubIf The HUB that has the device connected.\r
@param Port The port index of the hub (started with zero).\r
+ @param ResetIsNeeded The boolean to control whether skip the reset of the port.\r
\r
@retval EFI_SUCCESS The device is enumerated (added or removed).\r
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device.\r
EFI_STATUS\r
UsbEnumerateNewDev (\r
IN USB_INTERFACE *HubIf,\r
- IN UINT8 Port\r
+ IN UINT8 Port,\r
+ IN BOOLEAN ResetIsNeeded\r
)\r
{\r
USB_BUS *Bus;\r
\r
Parent = HubIf->Device;\r
Bus = Parent->Bus;\r
- HubApi = HubIf->HubApi; \r
+ HubApi = HubIf->HubApi;\r
Address = Bus->MaxDevices;\r
\r
gBS->Stall (USB_WAIT_PORT_STABLE_STALL);\r
- \r
+\r
//\r
// Hub resets the device for at least 10 milliseconds.\r
// Host learns device speed. If device is of low/full speed\r
// and the hub is a EHCI root hub, ResetPort will release\r
// the device to its companion UHCI and return an error.\r
//\r
- Status = HubApi->ResetPort (HubIf, Port);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));\r
+ if (ResetIsNeeded) {\r
+ Status = HubApi->ResetPort (HubIf, Port);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));\r
\r
- return Status;\r
+ return Status;\r
+ }\r
+ DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port));\r
+ } else {\r
+ DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d reset is skipped\n", Port));\r
}\r
\r
- DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port));\r
-\r
Child = UsbCreateDevice (HubIf, Port);\r
\r
if (Child == NULL) {\r
// connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.\r
// ENABLE/RESET is used to reset port. SUSPEND isn't supported.\r
//\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 (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {\r
//\r
// Case1:\r
- // Both OverCurrent and OverCurrentChange set, means over current occurs, \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
DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port));\r
return EFI_DEVICE_ERROR;\r
- \r
- } \r
+\r
+ }\r
//\r
// Case2:\r
- // Only OverCurrentChange set, means system has been recoveried from \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
+ // it's necessary to detach and enumerate all ports again.\r
//\r
- DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); \r
+ DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port));\r
}\r
\r
- if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) { \r
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {\r
//\r
// Case3:\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
+ // 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
DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port));\r
}\r
- \r
+\r
if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {\r
//\r
// Case4:\r
- // Device connected or disconnected normally. \r
+ // Device connected or disconnected normally.\r
//\r
DEBUG ((EFI_D_INFO, "UsbEnumeratePort: Device Connect/Disconnect Normally\n", Port));\r
}\r
\r
- // \r
+ //\r
// Following as the above cases, it's safety to remove and create again.\r
//\r
Child = UsbFindChild (HubIf, Port);\r
- \r
+\r
if (Child != NULL) {\r
DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device at port %d removed from root hub %p\n", Port, HubIf));\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
+ // Now, new device connected, enumerate and configure the device\r
//\r
DEBUG (( EFI_D_INFO, "UsbEnumeratePort: new device connected at port %d\n", Port));\r
- Status = UsbEnumerateNewDev (HubIf, Port);\r
- \r
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {\r
+ Status = UsbEnumerateNewDev (HubIf, Port, FALSE);\r
+ } else {\r
+ Status = UsbEnumerateNewDev (HubIf, Port, TRUE);\r
+ }\r
+\r
} else {\r
DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device disconnected event on port %d\n", Port));\r
}\r
- \r
+\r
HubApi->ClearPortChange (HubIf, Port);\r
return Status;\r
}\r
UINT8 Bit;\r
UINT8 Index;\r
USB_DEVICE *Child;\r
- \r
+\r
ASSERT (Context != NULL);\r
\r
HubIf = (USB_INTERFACE *) Context;\r
DEBUG (( EFI_D_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from root hub %p, try again\n", Index, RootHub));\r
UsbRemoveDevice (Child);\r
}\r
- \r
+\r
UsbEnumeratePort (RootHub, Index);\r
}\r
}\r