\r
Usb bus enumeration support.\r
\r
-Copyright (c) 2007 - 2014, 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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\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
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