\r
Wrapper function for usb host controller interface.\r
\r
-Copyright (c) 2007, Intel Corporation\r
-All rights reserved. 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
}\r
\r
\r
-/**\r
- Reset the host controller.\r
-\r
- @param UsbBus The usb bus driver.\r
- @param Attributes The reset type, only global reset is used by this driver.\r
-\r
- @retval EFI_SUCCESS The reset operation succeeded.\r
- @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
- @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is\r
- not currently supported by the host controller.\r
- @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.\r
-**/\r
-EFI_STATUS\r
-UsbHcReset (\r
- IN USB_BUS *UsbBus,\r
- IN UINT16 Attributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- if (UsbBus->Usb2Hc != NULL) {\r
- Status = UsbBus->Usb2Hc->Reset (UsbBus->Usb2Hc, Attributes);\r
- } else {\r
- Status = UsbBus->UsbHc->Reset (UsbBus->UsbHc, Attributes);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
\r
-/**\r
- Get the current operation state of the host controller.\r
\r
- @param UsbBus The USB bus driver.\r
- @param State The host controller operation state.\r
\r
- @retval EFI_SUCCESS The operation state is returned in State.\r
- @retval Others Failed to get the host controller state.\r
\r
-**/\r
-EFI_STATUS\r
-UsbHcGetState (\r
- IN USB_BUS *UsbBus,\r
- OUT EFI_USB_HC_STATE *State\r
- )\r
-{\r
- EFI_STATUS Status;\r
\r
- if (UsbBus->Usb2Hc != NULL) {\r
- Status = UsbBus->Usb2Hc->GetState (UsbBus->Usb2Hc, State);\r
- } else {\r
- Status = UsbBus->UsbHc->GetState (UsbBus->UsbHc, State);\r
- }\r
\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Set the host controller operation state.\r
-\r
- @param UsbBus The USB bus driver.\r
- @param State The state to set.\r
-\r
- @retval EFI_SUCCESS The host controller is now working at State.\r
- @retval Others Failed to set operation state.\r
-\r
-**/\r
-EFI_STATUS\r
-UsbHcSetState (\r
- IN USB_BUS *UsbBus,\r
- IN EFI_USB_HC_STATE State\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- if (UsbBus->Usb2Hc != NULL) {\r
- Status = UsbBus->Usb2Hc->SetState (UsbBus->Usb2Hc, State);\r
- } else {\r
- Status = UsbBus->UsbHc->SetState (UsbBus->UsbHc, State);\r
- }\r
-\r
- return Status;\r
-}\r
\r
\r
/**\r
}\r
\r
\r
-/**\r
- Execute a synchronous Isochronous USB transfer.\r
\r
- @param UsbBus The USB bus driver.\r
- @param DevAddr The target device address.\r
- @param EpAddr The target endpoint address, with direction encoded in\r
- bit 7.\r
- @param DevSpeed The device's speed.\r
- @param MaxPacket The endpoint's max packet size.\r
- @param BufferNum The number of data buffer.\r
- @param Data Array of pointers to data buffer.\r
- @param DataLength The length of data buffer.\r
- @param Translator The transaction translator for low/full speed device.\r
- @param UsbResult The result of USB execution.\r
\r
- @retval EFI_UNSUPPORTED The isochronous transfer isn't supported now.\r
\r
-**/\r
-EFI_STATUS\r
-UsbHcIsochronousTransfer (\r
- IN USB_BUS *UsbBus,\r
- IN UINT8 DevAddr,\r
- IN UINT8 EpAddr,\r
- IN UINT8 DevSpeed,\r
- IN UINTN MaxPacket,\r
- IN UINT8 BufferNum,\r
- IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
- IN UINTN DataLength,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- OUT UINT32 *UsbResult\r
- )\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-/**\r
- Queue an asynchronous isochronous transfer.\r
\r
- @param UsbBus The USB bus driver.\r
- @param DevAddr The target device address.\r
- @param EpAddr The target endpoint address, with direction encoded in\r
- bit 7.\r
- @param DevSpeed The device's speed.\r
- @param MaxPacket The endpoint's max packet size.\r
- @param BufferNum The number of data buffer.\r
- @param Data Array of pointers to data buffer.\r
- @param DataLength The length of data buffer.\r
- @param Translator The transaction translator for low/full speed device.\r
- @param Callback The function to call when data is transferred.\r
- @param Context The context to the callback function.\r
-\r
- @retval EFI_UNSUPPORTED The asynchronous isochronous transfer isn't supported.\r
-\r
-**/\r
-EFI_STATUS\r
-UsbHcAsyncIsochronousTransfer (\r
- IN USB_BUS *UsbBus,\r
- IN UINT8 DevAddr,\r
- IN UINT8 EpAddr,\r
- IN UINT8 DevSpeed,\r
- IN UINTN MaxPacket,\r
- IN UINT8 BufferNum,\r
- IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
- IN UINTN DataLength,\r
- IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,\r
- IN VOID *Context\r
- )\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
\r
\r
/**\r
}\r
\r
IfDesc = UsbIf->IfDesc;\r
+ ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);\r
ActIfDesc = &(IfDesc->Settings[IfDesc->ActiveIndex]->Desc);\r
DevDesc = &(UsbIf->Device->DevDesc->Desc);\r
\r
(UsbClassDevicePathPtr->ProductId == 0xffff || UsbClassDevicePathPtr->ProductId == DevDesc->IdProduct)) {\r
\r
//\r
- // If class or subclass or protocol is 0, the counterparts in interface should be checked.\r
+ // If Class in Device Descriptor is set to 0, the counterparts in interface should be checked.\r
//\r
- if (DevDesc->DeviceClass == 0 ||\r
- DevDesc->DeviceSubClass == 0 ||\r
- DevDesc->DeviceProtocol == 0) {\r
-\r
+ if (DevDesc->DeviceClass == 0) {\r
if ((UsbClassDevicePathPtr->DeviceClass == ActIfDesc->InterfaceClass ||\r
UsbClassDevicePathPtr->DeviceClass == 0xff) &&\r
(UsbClassDevicePathPtr->DeviceSubClass == ActIfDesc->InterfaceSubClass ||\r
EFI_USB_INTERFACE_DESCRIPTOR *ActIfDesc;\r
EFI_USB_DEVICE_DESCRIPTOR *DevDesc;\r
EFI_USB_STRING_DESCRIPTOR *StrDesc;\r
- UINT16 *SnString;\r
+ UINT16 Index;\r
+ CHAR16 *CompareStr;\r
+ UINTN CompareLen;\r
+ UINTN Length;\r
\r
if ((UsbWWIDDevicePathPtr->Header.Type != MESSAGING_DEVICE_PATH) ||\r
(UsbWWIDDevicePathPtr->Header.SubType != MSG_USB_WWID_DP )){\r
}\r
\r
IfDesc = UsbIf->IfDesc;\r
+ ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);\r
ActIfDesc = &(IfDesc->Settings[IfDesc->ActiveIndex]->Desc);\r
DevDesc = &(UsbIf->Device->DevDesc->Desc);\r
- StrDesc = UsbGetOneString (UsbIf->Device, DevDesc->StrSerialNumber, USB_US_LAND_ID);\r
- SnString = (UINT16 *) ((UINT8 *)UsbWWIDDevicePathPtr + 10);\r
\r
//\r
- //In addtion, hub interface is always matched for this policy.\r
+ // In addition, Hub interface is always matched for this policy.\r
//\r
if ((ActIfDesc->InterfaceClass == USB_HUB_CLASS_CODE) &&\r
(ActIfDesc->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {\r
return TRUE;\r
}\r
+\r
//\r
- // If connect wwid policy, determine the objective device by the serial number of\r
- // device descriptor.\r
- // Get serial number index from device descriptor, then get serial number by index\r
- // and land id, compare the serial number with wwid device path node at last\r
+ // Check Vendor Id, Product Id and Interface Number.\r
//\r
- // BugBug: only check serial number here, should check Interface Number, Device Vendor Id, Device Product Id in later version\r
+ if ((DevDesc->IdVendor != UsbWWIDDevicePathPtr->VendorId) ||\r
+ (DevDesc->IdProduct != UsbWWIDDevicePathPtr->ProductId) ||\r
+ (ActIfDesc->InterfaceNumber != UsbWWIDDevicePathPtr->InterfaceNumber)) {\r
+ return FALSE;\r
+ }\r
+\r
//\r
- if (StrDesc != NULL && !StrnCmp (StrDesc->String, SnString, StrDesc->Length)) {\r
+ // Check SerialNumber.\r
+ //\r
+ if (DevDesc->StrSerialNumber == 0) {\r
+ return FALSE;\r
+ }\r
\r
- return TRUE;\r
+ //\r
+ // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.\r
+ //\r
+ CompareStr = (CHAR16 *) (UINTN) (UsbWWIDDevicePathPtr + 1);\r
+ CompareLen = (DevicePathNodeLength (UsbWWIDDevicePathPtr) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);\r
+ if (CompareStr[CompareLen - 1] == L'\0') {\r
+ CompareLen--;\r
+ }\r
+\r
+ //\r
+ // Compare serial number in each supported language.\r
+ //\r
+ for (Index = 0; Index < UsbIf->Device->TotalLangId; Index++) {\r
+ StrDesc = UsbGetOneString (UsbIf->Device, DevDesc->StrSerialNumber, UsbIf->Device->LangId[Index]);\r
+ if (StrDesc == NULL) {\r
+ continue;\r
+ }\r
+\r
+ Length = (StrDesc->Length - 2) / sizeof (CHAR16);\r
+ if ((Length >= CompareLen) &&\r
+ (CompareMem (StrDesc->String + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0)) {\r
+ return TRUE;\r
+ }\r
}\r
\r
return FALSE;\r
//\r
// Check whether remaining device path is valid\r
//\r
- if (RemainingDevicePath != NULL) {\r
+ if (RemainingDevicePath != NULL && !IsDevicePathEnd (RemainingDevicePath)) {\r
if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) ||\r
(RemainingDevicePath->SubType != MSG_USB_DP &&\r
RemainingDevicePath->SubType != MSG_USB_CLASS_DP\r
\r
if (RemainingDevicePath == NULL) {\r
//\r
- // RemainingDevicePath== NULL means all Usb devices in this bus are wanted.\r
+ // RemainingDevicePath == NULL means all Usb devices in this bus are wanted.\r
// Here use a Usb class Device Path in WantedUsbIoDPList to indicate all Usb devices\r
// are wanted Usb devices\r
//\r
Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
ASSERT (!EFI_ERROR (Status));\r
DevicePathPtr = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) &mAllUsbClassDevicePath);\r
- } else {\r
+ } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
//\r
+ // If RemainingDevicePath isn't the End of Device Path Node,\r
// Create new Usb device path according to the usb part in remaining device path\r
//\r
DevicePathPtr = GetUsbDPFromFullDP (RemainingDevicePath);\r
+ } else {\r
+ //\r
+ // If RemainingDevicePath is the End of Device Path Node,\r
+ // skip enumerate any device and return EFI_SUCESSS\r
+ //\r
+ return EFI_SUCCESS;\r
}\r
\r
ASSERT (DevicePathPtr != NULL);\r
Status = AddUsbDPToList (DevicePathPtr, &Bus->WantedUsbIoDPList);\r
ASSERT (!EFI_ERROR (Status));\r
- gBS->FreePool (DevicePathPtr);\r
+ FreePool (DevicePathPtr);\r
return EFI_SUCCESS;\r
}\r
\r
//\r
// Recursively connect the wanted Usb Io handle\r
//\r
- DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d\n", (UINT32)UsbGetCurrentTpl ()));\r
+ DEBUG ((EFI_D_INFO, "UsbBusRecursivelyConnectWantedUsbIo: TPL before connect is %d\n", (UINT32)UsbGetCurrentTpl ()));\r
Status = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);\r
UsbIf->IsManaged = (BOOLEAN)!EFI_ERROR (Status);\r
- DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl()));\r
+ DEBUG ((EFI_D_INFO, "UsbBusRecursivelyConnectWantedUsbIo: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl()));\r
}\r
}\r
}\r
\r
+ FreePool (UsbIoBuffer);\r
+\r
return EFI_SUCCESS;\r
}\r
\r