--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2004 - 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
+\r
+ Module Name:\r
+\r
+ UsbBus.c\r
+\r
+ Abstract:\r
+\r
+ Usb Bus Driver Binding and Bus IO Protocol\r
+\r
+ Revision History\r
+\r
+\r
+**/\r
+\r
+#include "UsbBus.h"\r
+\r
+//\r
+// USB_BUS_PROTOCOL is only used to locate USB_BUS\r
+//\r
+EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;\r
+\r
+\r
+/**\r
+ USB_IO function to execute a control transfer. This\r
+ function will execute the USB transfer. If transfer\r
+ successes, it will sync the internal state of USB bus\r
+ with device state.\r
+\r
+ @param This The USB_IO instance\r
+ @param Request The control transfer request\r
+ @param Direction Direction for data stage\r
+ @param Timeout The time to wait before timeout\r
+ @param Data The buffer holding the data\r
+ @param DataLength Then length of the data\r
+ @param UsbStatus USB result\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid\r
+ @retval EFI_SUCCESS The control transfer succeded.\r
+ @retval Others Failed to execute the transfer\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoControlTransfer (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ IN EFI_USB_DEVICE_REQUEST *Request,\r
+ IN EFI_USB_DATA_DIRECTION Direction,\r
+ IN UINT32 Timeout,\r
+ IN OUT VOID *Data, OPTIONAL\r
+ IN UINTN DataLength, OPTIONAL\r
+ OUT UINT32 *UsbStatus\r
+ )\r
+{\r
+ USB_DEVICE *Dev;\r
+ USB_INTERFACE *UsbIf;\r
+ USB_ENDPOINT_DESC *EpDesc;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+\r
+ if (UsbStatus == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ Status = UsbHcControlTransfer (\r
+ Dev->Bus,\r
+ Dev->Address,\r
+ Dev->Speed,\r
+ Dev->MaxPacket0,\r
+ Request,\r
+ Direction,\r
+ Data,\r
+ &DataLength,\r
+ (UINTN) Timeout,\r
+ &Dev->Translator,\r
+ UsbStatus\r
+ );\r
+\r
+ if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
+ //\r
+ // Clear TT buffer when CTRL/BULK split transaction failes\r
+ // Clear the TRANSLATOR TT buffer, not parent's buffer\r
+ //\r
+ if (Dev->Translator.TranslatorHubAddress != 0) {\r
+ UsbHubCtrlClearTTBuffer (\r
+ Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
+ Dev->Translator.TranslatorPortNumber,\r
+ Dev->Address,\r
+ 0,\r
+ USB_ENDPOINT_CONTROL\r
+ );\r
+ }\r
+\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Some control transfer will change the device's internal\r
+ // status, such as Set_Configuration and Set_Interface.\r
+ // We must synchronize the bus driver's status with that in\r
+ // device. We ignore the Set_Descriptor request because it's\r
+ // hardly used by any device, especially in pre-boot environment\r
+ //\r
+\r
+ //\r
+ // Reset the endpoint toggle when endpoint stall is cleared\r
+ //\r
+ if ((Request->Request == USB_REQ_CLEAR_FEATURE) &&\r
+ (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
+ USB_TARGET_ENDPOINT)) &&\r
+ (Request->Value == USB_FEATURE_ENDPOINT_HALT)) {\r
+\r
+ EpDesc = UsbGetEndpointDesc (UsbIf, (UINT8) Request->Index);\r
+\r
+ if (EpDesc != NULL) {\r
+ EpDesc->Toggle = 0;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Select a new configuration. This is a dangerous action. Upper driver\r
+ // should stop use its current UsbIo after calling this driver. The old\r
+ // UsbIo will be uninstalled and new UsbIo be installed. We can't use\r
+ // ReinstallProtocol since interfaces in different configuration may be\r
+ // completely irrellvant.\r
+ //\r
+ if ((Request->Request == USB_REQ_SET_CONFIG) &&\r
+ (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
+ USB_TARGET_DEVICE))) {\r
+ //\r
+ // Don't re-create the USB interfaces if configuration isn't changed.\r
+ //\r
+ if ((Dev->ActiveConfig != NULL) &&\r
+ (Request->Value == Dev->ActiveConfig->Desc.ConfigurationValue)) {\r
+\r
+ goto ON_EXIT;\r
+ }\r
+ DEBUG ((EFI_D_INFO, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));\r
+\r
+ if (Dev->ActiveConfig != NULL) {\r
+ UsbRemoveConfig (Dev);\r
+ }\r
+\r
+ if (Request->Value != 0) {\r
+ Status = UsbSelectConfig (Dev, (UINT8) Request->Value);\r
+ }\r
+\r
+ //\r
+ // Exit now, Old USB_IO is invalid now\r
+ //\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // A new alternative setting is selected for the interface.\r
+ // No need to reinstall UsbIo in this case because only\r
+ // underlying communication endpoints are changed. Functionality\r
+ // should remains the same.\r
+ //\r
+ if ((Request->Request == USB_REQ_SET_INTERFACE) &&\r
+ (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
+ USB_TARGET_INTERFACE)) &&\r
+ (Request->Index == UsbIf->IfSetting->Desc.InterfaceNumber)) {\r
+\r
+ Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];\r
+ }\r
+ }\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Execute a bulk transfer to the device endpoint\r
+\r
+ @param This The USB IO instance\r
+ @param Endpoint The device endpoint\r
+ @param Data The data to transfer\r
+ @param DataLength The length of the data to transfer\r
+ @param Timeout Time to wait before timeout\r
+ @param UsbStatus The result of USB transfer\r
+\r
+ @retval EFI_SUCCESS The bulk transfer is OK\r
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
+ @retval Others Failed to execute transfer, reason returned in\r
+ UsbStatus\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoBulkTransfer (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ IN UINT8 Endpoint,\r
+ IN OUT VOID *Data,\r
+ IN OUT UINTN *DataLength,\r
+ IN UINTN Timeout,\r
+ OUT UINT32 *UsbStatus\r
+ )\r
+{\r
+ USB_DEVICE *Dev;\r
+ USB_INTERFACE *UsbIf;\r
+ USB_ENDPOINT_DESC *EpDesc;\r
+ UINT8 BufNum;\r
+ UINT8 Toggle;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+\r
+ if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
+ (UsbStatus == NULL)) {\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
+\r
+ if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_BULK)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ BufNum = 1;\r
+ Toggle = EpDesc->Toggle;\r
+ Status = UsbHcBulkTransfer (\r
+ Dev->Bus,\r
+ Dev->Address,\r
+ Endpoint,\r
+ Dev->Speed,\r
+ EpDesc->Desc.MaxPacketSize,\r
+ BufNum,\r
+ &Data,\r
+ DataLength,\r
+ &Toggle,\r
+ Timeout,\r
+ &Dev->Translator,\r
+ UsbStatus\r
+ );\r
+\r
+ EpDesc->Toggle = Toggle;\r
+\r
+ if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
+ //\r
+ // Clear TT buffer when CTRL/BULK split transaction failes.\r
+ // Clear the TRANSLATOR TT buffer, not parent's buffer\r
+ //\r
+ if (Dev->Translator.TranslatorHubAddress != 0) {\r
+ UsbHubCtrlClearTTBuffer (\r
+ Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
+ Dev->Translator.TranslatorPortNumber,\r
+ Dev->Address,\r
+ 0,\r
+ USB_ENDPOINT_BULK\r
+ );\r
+ }\r
+ }\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Execute a synchronous interrupt transfer\r
+\r
+ @param This The USB IO instance\r
+ @param Endpoint The device endpoint\r
+ @param Data The data to transfer\r
+ @param DataLength The length of the data to transfer\r
+ @param Timeout Time to wait before timeout\r
+ @param UsbStatus The result of USB transfer\r
+\r
+ @retval EFI_SUCCESS The synchronous interrupt transfer is OK\r
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
+ @retval Others Failed to execute transfer, reason returned in\r
+ UsbStatus\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoSyncInterruptTransfer (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ IN UINT8 Endpoint,\r
+ IN OUT VOID *Data,\r
+ IN OUT UINTN *DataLength,\r
+ IN UINTN Timeout,\r
+ OUT UINT32 *UsbStatus\r
+ )\r
+{\r
+ USB_DEVICE *Dev;\r
+ USB_INTERFACE *UsbIf;\r
+ USB_ENDPOINT_DESC *EpDesc;\r
+ EFI_TPL OldTpl;\r
+ UINT8 Toggle;\r
+ EFI_STATUS Status;\r
+\r
+ if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
+ (UsbStatus == NULL)) {\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
+\r
+ if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Toggle = EpDesc->Toggle;\r
+ Status = UsbHcSyncInterruptTransfer (\r
+ Dev->Bus,\r
+ Dev->Address,\r
+ Endpoint,\r
+ Dev->Speed,\r
+ EpDesc->Desc.MaxPacketSize,\r
+ Data,\r
+ DataLength,\r
+ &Toggle,\r
+ Timeout,\r
+ &Dev->Translator,\r
+ UsbStatus\r
+ );\r
+\r
+ EpDesc->Toggle = Toggle;\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Queue a new asynchronous interrupt transfer, or remove the old\r
+ request if (IsNewTransfer == FALSE)\r
+\r
+ @param This The USB_IO instance\r
+ @param Endpoint The device endpoint\r
+ @param IsNewTransfer Whether this is a new request, if it's old, remove\r
+ the request\r
+ @param PollInterval The interval to poll the transfer result, (in ms)\r
+ @param DataLength The length of perodic data transfer\r
+ @param Callback The function to call periodicaly when transfer is\r
+ ready\r
+ @param Context The context to the callback\r
+\r
+ @retval EFI_SUCCESS New transfer is queued or old request is removed\r
+ @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
+ @retval Others Failed to queue the new request or remove the old\r
+ request\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoAsyncInterruptTransfer (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ IN UINT8 Endpoint,\r
+ IN BOOLEAN IsNewTransfer,\r
+ IN UINTN PollInterval, OPTIONAL\r
+ IN UINTN DataLength, OPTIONAL\r
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, OPTIONAL\r
+ IN VOID *Context OPTIONAL\r
+ )\r
+{\r
+ USB_DEVICE *Dev;\r
+ USB_INTERFACE *UsbIf;\r
+ USB_ENDPOINT_DESC *EpDesc;\r
+ EFI_TPL OldTpl;\r
+ UINT8 Toggle;\r
+ EFI_STATUS Status;\r
+\r
+ if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR (Endpoint) > 15)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
+\r
+ if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Toggle = EpDesc->Toggle;\r
+ Status = UsbHcAsyncInterruptTransfer (\r
+ Dev->Bus,\r
+ Dev->Address,\r
+ Endpoint,\r
+ Dev->Speed,\r
+ EpDesc->Desc.MaxPacketSize,\r
+ IsNewTransfer,\r
+ &Toggle,\r
+ PollInterval,\r
+ DataLength,\r
+ &Dev->Translator,\r
+ Callback,\r
+ Context\r
+ );\r
+\r
+ EpDesc->Toggle = Toggle;\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Execute a synchronous isochronous transfer\r
+\r
+ @param This The USB IO instance\r
+ @param DeviceEndpoint The device endpoint\r
+ @param Data The data to transfer\r
+ @param DataLength The length of the data to transfer\r
+ @param UsbStatus The result of USB transfer\r
+\r
+ @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoIsochronousTransfer (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ IN UINT8 DeviceEndpoint,\r
+ IN OUT VOID *Data,\r
+ IN UINTN DataLength,\r
+ OUT UINT32 *Status\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+ Queue an asynchronous isochronous transfer\r
+\r
+ @param This The USB_IO instance\r
+ @param DeviceEndpoint The device endpoint\r
+ @param DataLength The length of perodic data transfer\r
+ @param IsochronousCallBack The function to call periodicaly when transfer is\r
+ ready\r
+ @param Context The context to the callback\r
+\r
+ @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoAsyncIsochronousTransfer (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ IN UINT8 DeviceEndpoint,\r
+ IN OUT VOID *Data,\r
+ IN UINTN DataLength,\r
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
+ IN VOID *Context OPTIONAL\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+ Retrieve the device descriptor of the device\r
+\r
+ @param This The USB IO instance\r
+ @param Descriptor The variable to receive the device descriptor\r
+\r
+ @retval EFI_SUCCESS The device descriptor is returned\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetDeviceDescriptor (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ OUT EFI_USB_DEVICE_DESCRIPTOR *Descriptor\r
+ )\r
+{\r
+ USB_DEVICE *Dev;\r
+ USB_INTERFACE *UsbIf;\r
+ EFI_TPL OldTpl;\r
+\r
+ if (Descriptor == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ CopyMem (Descriptor, &Dev->DevDesc->Desc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Return the configuration descriptor of the current active configuration\r
+\r
+ @param This The USB IO instance\r
+ @param Descriptor The USB configuration descriptor\r
+\r
+ @retval EFI_SUCCESS The active configuration descriptor is returned\r
+ @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
+ @retval EFI_NOT_FOUND Currently no active configuration is selected.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetActiveConfigDescriptor (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ OUT EFI_USB_CONFIG_DESCRIPTOR *Descriptor\r
+ )\r
+{\r
+ USB_DEVICE *Dev;\r
+ USB_INTERFACE *UsbIf;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ if (Descriptor == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ if (Dev->ActiveConfig == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ CopyMem (Descriptor, &(Dev->ActiveConfig->Desc), sizeof (EFI_USB_CONFIG_DESCRIPTOR));\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Retrieve the active interface setting descriptor for this USB IO instance\r
+\r
+ @param This The USB IO instance\r
+ @param Descriptor The variable to receive active interface setting\r
+\r
+ @retval EFI_SUCCESS The active interface setting is returned\r
+ @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetInterfaceDescriptor (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ OUT EFI_USB_INTERFACE_DESCRIPTOR *Descriptor\r
+ )\r
+{\r
+ USB_INTERFACE *UsbIf;\r
+ EFI_TPL OldTpl;\r
+\r
+ if (Descriptor == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ CopyMem (Descriptor, &(UsbIf->IfSetting->Desc), sizeof (EFI_USB_INTERFACE_DESCRIPTOR));\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Retrieve the endpoint descriptor from this interface setting\r
+\r
+ @param This The USB IO instance\r
+ @param Index The index (start from zero) of the endpoint to\r
+ retrieve\r
+ @param Descriptor The variable to receive the descriptor\r
+\r
+ @retval EFI_SUCCESS The endpoint descriptor is returned\r
+ @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetEndpointDescriptor (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ IN UINT8 Index,\r
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor\r
+ )\r
+{\r
+ USB_INTERFACE *UsbIf;\r
+ EFI_TPL OldTpl;\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+\r
+ if ((Descriptor == NULL) || (Index > 15)) {\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ CopyMem (\r
+ Descriptor,\r
+ &(UsbIf->IfSetting->Endpoints[Index]->Desc),\r
+ sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)\r
+ );\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Retrieve the supported language ID table from the device\r
+\r
+ @param This The USB IO instance\r
+ @param LangIDTable The table to return the language IDs\r
+ @param TableSize The number of supported languanges\r
+\r
+ @retval EFI_SUCCESS The language ID is return\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetSupportedLanguages (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ OUT UINT16 **LangIDTable,\r
+ OUT UINT16 *TableSize\r
+ )\r
+{\r
+ USB_DEVICE *Dev;\r
+ USB_INTERFACE *UsbIf;\r
+ EFI_TPL OldTpl;\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ *LangIDTable = Dev->LangId;\r
+ *TableSize = Dev->TotalLangId;\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Retrieve an indexed string in the language of LangID\r
+\r
+ @param This The USB IO instance\r
+ @param LangID The language ID of the string to retrieve\r
+ @param StringIndex The index of the string\r
+ @param String The variable to receive the string\r
+\r
+ @retval EFI_SUCCESS The string is returned\r
+ @retval EFI_NOT_FOUND No such string existed\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoGetStringDescriptor (\r
+ IN EFI_USB_IO_PROTOCOL *This,\r
+ IN UINT16 LangID,\r
+ IN UINT8 StringIndex,\r
+ OUT CHAR16 **String\r
+ )\r
+{\r
+ USB_DEVICE *Dev;\r
+ USB_INTERFACE *UsbIf;\r
+ EFI_USB_STRING_DESCRIPTOR *StrDesc;\r
+ EFI_TPL OldTpl;\r
+ UINT8 *Buf;\r
+ UINT8 Index;\r
+ EFI_STATUS Status;\r
+\r
+ if ((StringIndex == 0) || (LangID == 0)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ //\r
+ // Check whether language ID is supported\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+\r
+ for (Index = 0; Index < Dev->TotalLangId; Index++) {\r
+ if (Dev->LangId[Index] == LangID) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index == Dev->TotalLangId) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Retrieve the string descriptor then allocate a buffer\r
+ // to hold the string itself.\r
+ //\r
+ StrDesc = UsbGetOneString (Dev, StringIndex, LangID);\r
+\r
+ if (StrDesc == NULL) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (StrDesc->Length <= 2) {\r
+ goto FREE_STR;\r
+ }\r
+\r
+ Buf = AllocateZeroPool (StrDesc->Length);\r
+\r
+ if (Buf == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto FREE_STR;\r
+ }\r
+\r
+ CopyMem (Buf, StrDesc->String, StrDesc->Length - 2);\r
+ *String = (CHAR16 *) Buf;\r
+ Status = EFI_SUCCESS;\r
+\r
+FREE_STR:\r
+ gBS->FreePool (StrDesc);\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Reset the device, then if that succeeds, reconfigure the\r
+ device with its address and current active configuration.\r
+\r
+ @param This The USB IO instance\r
+\r
+ @retval EFI_SUCCESS The device is reset and configured\r
+ @retval Others Failed to reset the device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbIoPortReset (\r
+ IN EFI_USB_IO_PROTOCOL *This\r
+ )\r
+{\r
+ USB_INTERFACE *UsbIf;\r
+ USB_INTERFACE *HubIf;\r
+ USB_DEVICE *Dev;\r
+ UINT8 Address;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+\r
+ OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
+ Dev = UsbIf->Device;\r
+\r
+ if (UsbIf->IsHub == TRUE) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ HubIf = Dev->ParentIf;\r
+ Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",\r
+ Dev->ParentPort, Dev->ParentAddr, Status));\r
+\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Reset the device to its current address. The device now has a\r
+ // address of ZERO, so need to set Dev->Address to zero first for\r
+ // host to communicate with the device\r
+ //\r
+ Address = Dev->Address;\r
+ Dev->Address = 0;\r
+ Status = UsbSetAddress (Dev, Address);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",\r
+ Address, Status));\r
+\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Dev->Address = Address;\r
+\r
+ //\r
+ // Reset the current active configure, after this device\r
+ // is in CONFIGURED state.\r
+ //\r
+ if (Dev->ActiveConfig != NULL) {\r
+ Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",\r
+ Address, Status));\r
+ }\r
+ }\r
+\r
+ON_EXIT:\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Install Usb Bus Protocol on host controller, and start the Usb bus\r
+\r
+ @param This The USB bus driver binding instance\r
+ @param Controller The controller to check\r
+ @param RemainingDevicePath The remaining device patch\r
+\r
+ @retval EFI_SUCCESS The controller is controlled by the usb bus\r
+ @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusBuildProtocol (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ USB_BUS *UsbBus;\r
+ USB_DEVICE *RootHub;\r
+ USB_INTERFACE *RootIf;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS Status2;\r
+\r
+ UsbBus = AllocateZeroPool (sizeof (USB_BUS));\r
+\r
+ if (UsbBus == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ UsbBus->Signature = USB_BUS_SIGNATURE;\r
+ UsbBus->HostHandle = Controller;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &UsbBus->DevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));\r
+\r
+ gBS->FreePool (UsbBus);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).\r
+ // This is for backward compatbility with EFI 1.x. In UEFI\r
+ // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2\r
+ // and USB_HC because EHCI driver will install both protocols\r
+ // (for the same reason). If we don't consume both of them,\r
+ // the unconsumed one may be opened by others.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ (VOID **) &(UsbBus->Usb2Hc),\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ Status2 = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsbHcProtocolGuid,\r
+ (VOID **) &(UsbBus->UsbHc),\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));\r
+\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto CLOSE_HC;\r
+ }\r
+\r
+ UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
+ UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
+\r
+ //\r
+ // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Controller,\r
+ &mUsbBusProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &UsbBus->BusId\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));\r
+ goto CLOSE_HC;\r
+ }\r
+\r
+ //\r
+ // Initial the wanted child device path list, and add first RemainingDevicePath\r
+ //\r
+ InitializeListHead (&UsbBus->WantedUsbIoDPList);\r
+ Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ //\r
+ // Create a fake usb device for root hub\r
+ //\r
+ RootHub = AllocateZeroPool (sizeof (USB_DEVICE));\r
+\r
+ if (RootHub == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto UNINSTALL_USBBUS;\r
+ }\r
+\r
+ RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
+\r
+ if (RootIf == NULL) {\r
+ gBS->FreePool (RootHub);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto FREE_ROOTHUB;\r
+ }\r
+\r
+ RootHub->Bus = UsbBus;\r
+ RootHub->NumOfInterface = 1;\r
+ RootHub->Interfaces[0] = RootIf;\r
+ RootIf->Signature = USB_INTERFACE_SIGNATURE;\r
+ RootIf->Device = RootHub;\r
+ RootIf->DevicePath = UsbBus->DevicePath;\r
+\r
+ Status = mUsbRootHubApi.Init (RootIf);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));\r
+ goto FREE_ROOTHUB;\r
+ }\r
+\r
+ UsbBus->Devices[0] = RootHub;\r
+\r
+ DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));\r
+ return EFI_SUCCESS;\r
+\r
+FREE_ROOTHUB:\r
+ if (RootIf != NULL) {\r
+ gBS->FreePool (RootIf);\r
+ }\r
+ if (RootHub != NULL) {\r
+ gBS->FreePool (RootHub);\r
+ }\r
+\r
+UNINSTALL_USBBUS:\r
+ gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);\r
+\r
+CLOSE_HC:\r
+ if (UsbBus->Usb2Hc != NULL) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+ if (UsbBus->UsbHc != NULL) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsbHcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ gBS->FreePool (UsbBus);\r
+\r
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));\r
+ return Status;\r
+}\r
+\r
+EFI_USB_IO_PROTOCOL mUsbIoProtocol = {\r
+ UsbIoControlTransfer,\r
+ UsbIoBulkTransfer,\r
+ UsbIoAsyncInterruptTransfer,\r
+ UsbIoSyncInterruptTransfer,\r
+ UsbIoIsochronousTransfer,\r
+ UsbIoAsyncIsochronousTransfer,\r
+ UsbIoGetDeviceDescriptor,\r
+ UsbIoGetActiveConfigDescriptor,\r
+ UsbIoGetInterfaceDescriptor,\r
+ UsbIoGetEndpointDescriptor,\r
+ UsbIoGetStringDescriptor,\r
+ UsbIoGetSupportedLanguages,\r
+ UsbIoPortReset\r
+};\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ The USB bus driver entry pointer\r
+\r
+Arguments:\r
+\r
+ ImageHandle - The driver image handle\r
+ SystemTable - The system table\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - The component name protocol is installed\r
+ Others - Failed to init the usb driver\r
+\r
+--*/\r
+{\r
+ return EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &mUsbBusDriverBinding,\r
+ ImageHandle,\r
+ &mUsbBusComponentName,\r
+ &mUsbBusComponentName2\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Check whether USB bus driver support this device\r
+\r
+ @param This The USB bus driver binding protocol\r
+ @param Controller The controller handle to test againist\r
+ @param RemainingDevicePath The remaining device path\r
+\r
+ @retval EFI_SUCCESS The bus supports this controller.\r
+ @retval EFI_UNSUPPORTED This device isn't supported\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusControllerDriverSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_DEV_PATH_PTR DevicePathNode;\r
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
+ EFI_USB_HC_PROTOCOL *UsbHc;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Check whether device path is valid\r
+ //\r
+ if (RemainingDevicePath != NULL) {\r
+ DevicePathNode.DevPath = RemainingDevicePath;\r
+\r
+ if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||\r
+ (DevicePathNode.DevPath->SubType != MSG_USB_DP &&\r
+ DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP\r
+ && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP\r
+ )) {\r
+\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ParentDevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ //\r
+ // Check whether USB_HC2 protocol is installed\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ (VOID **) &Usb2Hc,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // If failed to open USB_HC2, fall back to USB_HC\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsbHcProtocolGuid,\r
+ (VOID **) &UsbHc,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsbHcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Start to process the controller\r
+\r
+ @param This The USB bus driver binding instance\r
+ @param Controller The controller to check\r
+ @param RemainingDevicePath The remaining device patch\r
+\r
+ @retval EFI_SUCCESS The controller is controlled by the usb bus\r
+ @retval EFI_ALREADY_STARTED The controller is already controlled by the usb\r
+ bus\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusControllerDriverStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ )\r
+{\r
+ EFI_USB_BUS_PROTOCOL *UsbBusId;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Locate the USB bus protocol, if it is found, USB bus\r
+ // is already started on this controller.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &mUsbBusProtocolGuid,\r
+ (VOID **) &UsbBusId,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If first start, build the bus execute enviorment and install bus protocol\r
+ //\r
+ Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Try get the Usb Bus protocol interface again\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &mUsbBusProtocolGuid,\r
+ (VOID **) &UsbBusId,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ ASSERT (!EFI_ERROR (Status));\r
+ } else {\r
+ //\r
+ // USB Bus driver need to control the recursive connect policy of the bus, only those wanted\r
+ // usb child device will be recursively connected.\r
+ // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.\r
+ // All wanted usb child devices will be remembered by the usb bus driver itself.\r
+ // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.\r
+ //\r
+ // Save the passed in RemainingDevicePath this time\r
+ //\r
+ Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ //\r
+ // Ensure all wanted child usb devices are fully recursively connected\r
+ //\r
+ Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ }\r
+\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Stop handle the controller by this USB bus driver\r
+\r
+ @param This The USB bus driver binding protocol\r
+ @param Controller The controller to release\r
+ @param NumberOfChildren The child of USB bus that opened controller\r
+ BY_CHILD\r
+ @param ChildHandleBuffer The array of child handle\r
+\r
+ @retval EFI_SUCCESS The controller or children are stopped\r
+ @retval EFI_DEVICE_ERROR Failed to stop the driver\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UsbBusControllerDriverStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ USB_BUS *Bus;\r
+ USB_DEVICE *RootHub;\r
+ USB_DEVICE *UsbDev;\r
+ USB_INTERFACE *RootIf;\r
+ USB_INTERFACE *UsbIf;\r
+ EFI_USB_BUS_PROTOCOL *BusId;\r
+ EFI_USB_IO_PROTOCOL *UsbIo;\r
+ EFI_TPL OldTpl;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (NumberOfChildren > 0) {\r
+ //\r
+ // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+ for (Index = 0; Index < NumberOfChildren; Index++) {\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandleBuffer[Index],\r
+ &gEfiUsbIoProtocolGuid,\r
+ (VOID **) &UsbIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // It is possible that the child has already been released:\r
+ // 1. For combo device, free one device will release others.\r
+ // 2. If a hub is released, all devices on its down facing\r
+ // ports are released also.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);\r
+ UsbDev = UsbIf->Device;\r
+\r
+ UsbRemoveDevice (UsbDev);\r
+ }\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %x\n", Controller));\r
+\r
+ //\r
+ // Locate USB_BUS for the current host controller\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &mUsbBusProtocolGuid,\r
+ (VOID **) &BusId,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Bus = USB_BUS_FROM_THIS (BusId);\r
+\r
+ //\r
+ // Stop the root hub, then free all the devices\r
+ //\r
+ // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ UsbHcSetState (Bus, EfiUsbHcStateHalt);\r
+\r
+ RootHub = Bus->Devices[0];\r
+ RootIf = RootHub->Interfaces[0];\r
+\r
+ mUsbRootHubApi.Release (RootIf);\r
+\r
+ for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
+ if (Bus->Devices[Index] != NULL) {\r
+ UsbRemoveDevice (Bus->Devices[Index]);\r
+ }\r
+ }\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ gBS->FreePool (RootIf);\r
+ gBS->FreePool (RootHub);\r
+ Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
+ ASSERT (!EFI_ERROR (Status));\r
+\r
+ //\r
+ // Uninstall the bus identifier and close USB_HC/USB2_HC protocols\r
+ //\r
+ gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);\r
+\r
+ if (Bus->Usb2Hc != NULL) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+\r
+ if (Bus->UsbHc != NULL) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsbHcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
+\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ gBS->FreePool (Bus);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {\r
+ UsbBusControllerDriverSupported,\r
+ UsbBusControllerDriverStart,\r
+ UsbBusControllerDriverStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+++ /dev/null
-/** @file\r
-\r
-Copyright (c) 2004 - 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
-\r
- Module Name:\r
-\r
- UsbBus.c\r
-\r
- Abstract:\r
-\r
- Usb Bus Driver Binding and Bus IO Protocol\r
-\r
- Revision History\r
-\r
-\r
-**/\r
-\r
-#include "UsbBus.h"\r
-\r
-//\r
-// USB_BUS_PROTOCOL is only used to locate USB_BUS\r
-//\r
-EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;\r
-\r
-\r
-/**\r
- USB_IO function to execute a control transfer. This\r
- function will execute the USB transfer. If transfer\r
- successes, it will sync the internal state of USB bus\r
- with device state.\r
-\r
- @param This The USB_IO instance\r
- @param Request The control transfer request\r
- @param Direction Direction for data stage\r
- @param Timeout The time to wait before timeout\r
- @param Data The buffer holding the data\r
- @param DataLength Then length of the data\r
- @param UsbStatus USB result\r
-\r
- @retval EFI_INVALID_PARAMETER The parameters are invalid\r
- @retval EFI_SUCCESS The control transfer succeded.\r
- @retval Others Failed to execute the transfer\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoControlTransfer (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- IN EFI_USB_DEVICE_REQUEST *Request,\r
- IN EFI_USB_DATA_DIRECTION Direction,\r
- IN UINT32 Timeout,\r
- IN OUT VOID *Data, OPTIONAL\r
- IN UINTN DataLength, OPTIONAL\r
- OUT UINT32 *UsbStatus\r
- )\r
-{\r
- USB_DEVICE *Dev;\r
- USB_INTERFACE *UsbIf;\r
- USB_ENDPOINT_DESC *EpDesc;\r
- EFI_TPL OldTpl;\r
- EFI_STATUS Status;\r
-\r
- if (UsbStatus == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- Status = UsbHcControlTransfer (\r
- Dev->Bus,\r
- Dev->Address,\r
- Dev->Speed,\r
- Dev->MaxPacket0,\r
- Request,\r
- Direction,\r
- Data,\r
- &DataLength,\r
- (UINTN) Timeout,\r
- &Dev->Translator,\r
- UsbStatus\r
- );\r
-\r
- if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
- //\r
- // Clear TT buffer when CTRL/BULK split transaction failes\r
- // Clear the TRANSLATOR TT buffer, not parent's buffer\r
- //\r
- if (Dev->Translator.TranslatorHubAddress != 0) {\r
- UsbHubCtrlClearTTBuffer (\r
- Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
- Dev->Translator.TranslatorPortNumber,\r
- Dev->Address,\r
- 0,\r
- USB_ENDPOINT_CONTROL\r
- );\r
- }\r
-\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Some control transfer will change the device's internal\r
- // status, such as Set_Configuration and Set_Interface.\r
- // We must synchronize the bus driver's status with that in\r
- // device. We ignore the Set_Descriptor request because it's\r
- // hardly used by any device, especially in pre-boot environment\r
- //\r
-\r
- //\r
- // Reset the endpoint toggle when endpoint stall is cleared\r
- //\r
- if ((Request->Request == USB_REQ_CLEAR_FEATURE) &&\r
- (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
- USB_TARGET_ENDPOINT)) &&\r
- (Request->Value == USB_FEATURE_ENDPOINT_HALT)) {\r
-\r
- EpDesc = UsbGetEndpointDesc (UsbIf, (UINT8) Request->Index);\r
-\r
- if (EpDesc != NULL) {\r
- EpDesc->Toggle = 0;\r
- }\r
- }\r
-\r
- //\r
- // Select a new configuration. This is a dangerous action. Upper driver\r
- // should stop use its current UsbIo after calling this driver. The old\r
- // UsbIo will be uninstalled and new UsbIo be installed. We can't use\r
- // ReinstallProtocol since interfaces in different configuration may be\r
- // completely irrellvant.\r
- //\r
- if ((Request->Request == USB_REQ_SET_CONFIG) &&\r
- (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
- USB_TARGET_DEVICE))) {\r
- //\r
- // Don't re-create the USB interfaces if configuration isn't changed.\r
- //\r
- if ((Dev->ActiveConfig != NULL) &&\r
- (Request->Value == Dev->ActiveConfig->Desc.ConfigurationValue)) {\r
-\r
- goto ON_EXIT;\r
- }\r
- DEBUG ((EFI_D_INFO, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));\r
-\r
- if (Dev->ActiveConfig != NULL) {\r
- UsbRemoveConfig (Dev);\r
- }\r
-\r
- if (Request->Value != 0) {\r
- Status = UsbSelectConfig (Dev, (UINT8) Request->Value);\r
- }\r
-\r
- //\r
- // Exit now, Old USB_IO is invalid now\r
- //\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // A new alternative setting is selected for the interface.\r
- // No need to reinstall UsbIo in this case because only\r
- // underlying communication endpoints are changed. Functionality\r
- // should remains the same.\r
- //\r
- if ((Request->Request == USB_REQ_SET_INTERFACE) &&\r
- (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
- USB_TARGET_INTERFACE)) &&\r
- (Request->Index == UsbIf->IfSetting->Desc.InterfaceNumber)) {\r
-\r
- Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);\r
-\r
- if (!EFI_ERROR (Status)) {\r
- UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];\r
- }\r
- }\r
-\r
-ON_EXIT:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Execute a bulk transfer to the device endpoint\r
-\r
- @param This The USB IO instance\r
- @param Endpoint The device endpoint\r
- @param Data The data to transfer\r
- @param DataLength The length of the data to transfer\r
- @param Timeout Time to wait before timeout\r
- @param UsbStatus The result of USB transfer\r
-\r
- @retval EFI_SUCCESS The bulk transfer is OK\r
- @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
- @retval Others Failed to execute transfer, reason returned in\r
- UsbStatus\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoBulkTransfer (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- IN UINT8 Endpoint,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- IN UINTN Timeout,\r
- OUT UINT32 *UsbStatus\r
- )\r
-{\r
- USB_DEVICE *Dev;\r
- USB_INTERFACE *UsbIf;\r
- USB_ENDPOINT_DESC *EpDesc;\r
- UINT8 BufNum;\r
- UINT8 Toggle;\r
- EFI_TPL OldTpl;\r
- EFI_STATUS Status;\r
-\r
- if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
- (UsbStatus == NULL)) {\r
-\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
-\r
- if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_BULK)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto ON_EXIT;\r
- }\r
-\r
- BufNum = 1;\r
- Toggle = EpDesc->Toggle;\r
- Status = UsbHcBulkTransfer (\r
- Dev->Bus,\r
- Dev->Address,\r
- Endpoint,\r
- Dev->Speed,\r
- EpDesc->Desc.MaxPacketSize,\r
- BufNum,\r
- &Data,\r
- DataLength,\r
- &Toggle,\r
- Timeout,\r
- &Dev->Translator,\r
- UsbStatus\r
- );\r
-\r
- EpDesc->Toggle = Toggle;\r
-\r
- if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
- //\r
- // Clear TT buffer when CTRL/BULK split transaction failes.\r
- // Clear the TRANSLATOR TT buffer, not parent's buffer\r
- //\r
- if (Dev->Translator.TranslatorHubAddress != 0) {\r
- UsbHubCtrlClearTTBuffer (\r
- Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
- Dev->Translator.TranslatorPortNumber,\r
- Dev->Address,\r
- 0,\r
- USB_ENDPOINT_BULK\r
- );\r
- }\r
- }\r
-\r
-ON_EXIT:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Execute a synchronous interrupt transfer\r
-\r
- @param This The USB IO instance\r
- @param Endpoint The device endpoint\r
- @param Data The data to transfer\r
- @param DataLength The length of the data to transfer\r
- @param Timeout Time to wait before timeout\r
- @param UsbStatus The result of USB transfer\r
-\r
- @retval EFI_SUCCESS The synchronous interrupt transfer is OK\r
- @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
- @retval Others Failed to execute transfer, reason returned in\r
- UsbStatus\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoSyncInterruptTransfer (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- IN UINT8 Endpoint,\r
- IN OUT VOID *Data,\r
- IN OUT UINTN *DataLength,\r
- IN UINTN Timeout,\r
- OUT UINT32 *UsbStatus\r
- )\r
-{\r
- USB_DEVICE *Dev;\r
- USB_INTERFACE *UsbIf;\r
- USB_ENDPOINT_DESC *EpDesc;\r
- EFI_TPL OldTpl;\r
- UINT8 Toggle;\r
- EFI_STATUS Status;\r
-\r
- if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
- (UsbStatus == NULL)) {\r
-\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
-\r
- if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto ON_EXIT;\r
- }\r
-\r
- Toggle = EpDesc->Toggle;\r
- Status = UsbHcSyncInterruptTransfer (\r
- Dev->Bus,\r
- Dev->Address,\r
- Endpoint,\r
- Dev->Speed,\r
- EpDesc->Desc.MaxPacketSize,\r
- Data,\r
- DataLength,\r
- &Toggle,\r
- Timeout,\r
- &Dev->Translator,\r
- UsbStatus\r
- );\r
-\r
- EpDesc->Toggle = Toggle;\r
-\r
-ON_EXIT:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Queue a new asynchronous interrupt transfer, or remove the old\r
- request if (IsNewTransfer == FALSE)\r
-\r
- @param This The USB_IO instance\r
- @param Endpoint The device endpoint\r
- @param IsNewTransfer Whether this is a new request, if it's old, remove\r
- the request\r
- @param PollInterval The interval to poll the transfer result, (in ms)\r
- @param DataLength The length of perodic data transfer\r
- @param Callback The function to call periodicaly when transfer is\r
- ready\r
- @param Context The context to the callback\r
-\r
- @retval EFI_SUCCESS New transfer is queued or old request is removed\r
- @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
- @retval Others Failed to queue the new request or remove the old\r
- request\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoAsyncInterruptTransfer (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- IN UINT8 Endpoint,\r
- IN BOOLEAN IsNewTransfer,\r
- IN UINTN PollInterval, OPTIONAL\r
- IN UINTN DataLength, OPTIONAL\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, OPTIONAL\r
- IN VOID *Context OPTIONAL\r
- )\r
-{\r
- USB_DEVICE *Dev;\r
- USB_INTERFACE *UsbIf;\r
- USB_ENDPOINT_DESC *EpDesc;\r
- EFI_TPL OldTpl;\r
- UINT8 Toggle;\r
- EFI_STATUS Status;\r
-\r
- if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR (Endpoint) > 15)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
-\r
- if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto ON_EXIT;\r
- }\r
-\r
- Toggle = EpDesc->Toggle;\r
- Status = UsbHcAsyncInterruptTransfer (\r
- Dev->Bus,\r
- Dev->Address,\r
- Endpoint,\r
- Dev->Speed,\r
- EpDesc->Desc.MaxPacketSize,\r
- IsNewTransfer,\r
- &Toggle,\r
- PollInterval,\r
- DataLength,\r
- &Dev->Translator,\r
- Callback,\r
- Context\r
- );\r
-\r
- EpDesc->Toggle = Toggle;\r
-\r
-ON_EXIT:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Execute a synchronous isochronous transfer\r
-\r
- @param This The USB IO instance\r
- @param DeviceEndpoint The device endpoint\r
- @param Data The data to transfer\r
- @param DataLength The length of the data to transfer\r
- @param UsbStatus The result of USB transfer\r
-\r
- @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoIsochronousTransfer (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- IN UINT8 DeviceEndpoint,\r
- IN OUT VOID *Data,\r
- IN UINTN DataLength,\r
- OUT UINT32 *Status\r
- )\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-/**\r
- Queue an asynchronous isochronous transfer\r
-\r
- @param This The USB_IO instance\r
- @param DeviceEndpoint The device endpoint\r
- @param DataLength The length of perodic data transfer\r
- @param IsochronousCallBack The function to call periodicaly when transfer is\r
- ready\r
- @param Context The context to the callback\r
-\r
- @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoAsyncIsochronousTransfer (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- IN UINT8 DeviceEndpoint,\r
- IN OUT VOID *Data,\r
- IN UINTN DataLength,\r
- IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
- IN VOID *Context OPTIONAL\r
- )\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-/**\r
- Retrieve the device descriptor of the device\r
-\r
- @param This The USB IO instance\r
- @param Descriptor The variable to receive the device descriptor\r
-\r
- @retval EFI_SUCCESS The device descriptor is returned\r
- @retval EFI_INVALID_PARAMETER The parameter is invalid\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetDeviceDescriptor (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- OUT EFI_USB_DEVICE_DESCRIPTOR *Descriptor\r
- )\r
-{\r
- USB_DEVICE *Dev;\r
- USB_INTERFACE *UsbIf;\r
- EFI_TPL OldTpl;\r
-\r
- if (Descriptor == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- CopyMem (Descriptor, &Dev->DevDesc->Desc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Return the configuration descriptor of the current active configuration\r
-\r
- @param This The USB IO instance\r
- @param Descriptor The USB configuration descriptor\r
-\r
- @retval EFI_SUCCESS The active configuration descriptor is returned\r
- @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
- @retval EFI_NOT_FOUND Currently no active configuration is selected.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetActiveConfigDescriptor (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- OUT EFI_USB_CONFIG_DESCRIPTOR *Descriptor\r
- )\r
-{\r
- USB_DEVICE *Dev;\r
- USB_INTERFACE *UsbIf;\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
-\r
- if (Descriptor == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- if (Dev->ActiveConfig == NULL) {\r
- Status = EFI_NOT_FOUND;\r
- goto ON_EXIT;\r
- }\r
-\r
- CopyMem (Descriptor, &(Dev->ActiveConfig->Desc), sizeof (EFI_USB_CONFIG_DESCRIPTOR));\r
-\r
-ON_EXIT:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Retrieve the active interface setting descriptor for this USB IO instance\r
-\r
- @param This The USB IO instance\r
- @param Descriptor The variable to receive active interface setting\r
-\r
- @retval EFI_SUCCESS The active interface setting is returned\r
- @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetInterfaceDescriptor (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- OUT EFI_USB_INTERFACE_DESCRIPTOR *Descriptor\r
- )\r
-{\r
- USB_INTERFACE *UsbIf;\r
- EFI_TPL OldTpl;\r
-\r
- if (Descriptor == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- CopyMem (Descriptor, &(UsbIf->IfSetting->Desc), sizeof (EFI_USB_INTERFACE_DESCRIPTOR));\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Retrieve the endpoint descriptor from this interface setting\r
-\r
- @param This The USB IO instance\r
- @param Index The index (start from zero) of the endpoint to\r
- retrieve\r
- @param Descriptor The variable to receive the descriptor\r
-\r
- @retval EFI_SUCCESS The endpoint descriptor is returned\r
- @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetEndpointDescriptor (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- IN UINT8 Index,\r
- OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor\r
- )\r
-{\r
- USB_INTERFACE *UsbIf;\r
- EFI_TPL OldTpl;\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
-\r
- if ((Descriptor == NULL) || (Index > 15)) {\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- CopyMem (\r
- Descriptor,\r
- &(UsbIf->IfSetting->Endpoints[Index]->Desc),\r
- sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)\r
- );\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Retrieve the supported language ID table from the device\r
-\r
- @param This The USB IO instance\r
- @param LangIDTable The table to return the language IDs\r
- @param TableSize The number of supported languanges\r
-\r
- @retval EFI_SUCCESS The language ID is return\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetSupportedLanguages (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- OUT UINT16 **LangIDTable,\r
- OUT UINT16 *TableSize\r
- )\r
-{\r
- USB_DEVICE *Dev;\r
- USB_INTERFACE *UsbIf;\r
- EFI_TPL OldTpl;\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- *LangIDTable = Dev->LangId;\r
- *TableSize = Dev->TotalLangId;\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Retrieve an indexed string in the language of LangID\r
-\r
- @param This The USB IO instance\r
- @param LangID The language ID of the string to retrieve\r
- @param StringIndex The index of the string\r
- @param String The variable to receive the string\r
-\r
- @retval EFI_SUCCESS The string is returned\r
- @retval EFI_NOT_FOUND No such string existed\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoGetStringDescriptor (\r
- IN EFI_USB_IO_PROTOCOL *This,\r
- IN UINT16 LangID,\r
- IN UINT8 StringIndex,\r
- OUT CHAR16 **String\r
- )\r
-{\r
- USB_DEVICE *Dev;\r
- USB_INTERFACE *UsbIf;\r
- EFI_USB_STRING_DESCRIPTOR *StrDesc;\r
- EFI_TPL OldTpl;\r
- UINT8 *Buf;\r
- UINT8 Index;\r
- EFI_STATUS Status;\r
-\r
- if ((StringIndex == 0) || (LangID == 0)) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- //\r
- // Check whether language ID is supported\r
- //\r
- Status = EFI_NOT_FOUND;\r
-\r
- for (Index = 0; Index < Dev->TotalLangId; Index++) {\r
- if (Dev->LangId[Index] == LangID) {\r
- break;\r
- }\r
- }\r
-\r
- if (Index == Dev->TotalLangId) {\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Retrieve the string descriptor then allocate a buffer\r
- // to hold the string itself.\r
- //\r
- StrDesc = UsbGetOneString (Dev, StringIndex, LangID);\r
-\r
- if (StrDesc == NULL) {\r
- goto ON_EXIT;\r
- }\r
-\r
- if (StrDesc->Length <= 2) {\r
- goto FREE_STR;\r
- }\r
-\r
- Buf = AllocateZeroPool (StrDesc->Length);\r
-\r
- if (Buf == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto FREE_STR;\r
- }\r
-\r
- CopyMem (Buf, StrDesc->String, StrDesc->Length - 2);\r
- *String = (CHAR16 *) Buf;\r
- Status = EFI_SUCCESS;\r
-\r
-FREE_STR:\r
- gBS->FreePool (StrDesc);\r
-\r
-ON_EXIT:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Reset the device, then if that succeeds, reconfigure the\r
- device with its address and current active configuration.\r
-\r
- @param This The USB IO instance\r
-\r
- @retval EFI_SUCCESS The device is reset and configured\r
- @retval Others Failed to reset the device\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbIoPortReset (\r
- IN EFI_USB_IO_PROTOCOL *This\r
- )\r
-{\r
- USB_INTERFACE *UsbIf;\r
- USB_INTERFACE *HubIf;\r
- USB_DEVICE *Dev;\r
- UINT8 Address;\r
- EFI_TPL OldTpl;\r
- EFI_STATUS Status;\r
-\r
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
- Dev = UsbIf->Device;\r
-\r
- if (UsbIf->IsHub == TRUE) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto ON_EXIT;\r
- }\r
-\r
- HubIf = Dev->ParentIf;\r
- Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",\r
- Dev->ParentPort, Dev->ParentAddr, Status));\r
-\r
- goto ON_EXIT;\r
- }\r
-\r
- //\r
- // Reset the device to its current address. The device now has a\r
- // address of ZERO, so need to set Dev->Address to zero first for\r
- // host to communicate with the device\r
- //\r
- Address = Dev->Address;\r
- Dev->Address = 0;\r
- Status = UsbSetAddress (Dev, Address);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",\r
- Address, Status));\r
-\r
- goto ON_EXIT;\r
- }\r
-\r
- Dev->Address = Address;\r
-\r
- //\r
- // Reset the current active configure, after this device\r
- // is in CONFIGURED state.\r
- //\r
- if (Dev->ActiveConfig != NULL) {\r
- Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",\r
- Address, Status));\r
- }\r
- }\r
-\r
-ON_EXIT:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Install Usb Bus Protocol on host controller, and start the Usb bus\r
-\r
- @param This The USB bus driver binding instance\r
- @param Controller The controller to check\r
- @param RemainingDevicePath The remaining device patch\r
-\r
- @retval EFI_SUCCESS The controller is controlled by the usb bus\r
- @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus\r
- @retval EFI_OUT_OF_RESOURCES Failed to allocate resources\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusBuildProtocol (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- USB_BUS *UsbBus;\r
- USB_DEVICE *RootHub;\r
- USB_INTERFACE *RootIf;\r
- EFI_STATUS Status;\r
- EFI_STATUS Status2;\r
-\r
- UsbBus = AllocateZeroPool (sizeof (USB_BUS));\r
-\r
- if (UsbBus == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- UsbBus->Signature = USB_BUS_SIGNATURE;\r
- UsbBus->HostHandle = Controller;\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &UsbBus->DevicePath,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));\r
-\r
- gBS->FreePool (UsbBus);\r
- return Status;\r
- }\r
-\r
- //\r
- // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).\r
- // This is for backward compatbility with EFI 1.x. In UEFI\r
- // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2\r
- // and USB_HC because EHCI driver will install both protocols\r
- // (for the same reason). If we don't consume both of them,\r
- // the unconsumed one may be opened by others.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- (VOID **) &(UsbBus->Usb2Hc),\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- Status2 = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- (VOID **) &(UsbBus->UsbHc),\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {\r
- DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));\r
-\r
- Status = EFI_DEVICE_ERROR;\r
- goto CLOSE_HC;\r
- }\r
-\r
- UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
- UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
-\r
- //\r
- // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.\r
- //\r
- Status = gBS->InstallProtocolInterface (\r
- &Controller,\r
- &mUsbBusProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &UsbBus->BusId\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));\r
- goto CLOSE_HC;\r
- }\r
-\r
- //\r
- // Initial the wanted child device path list, and add first RemainingDevicePath\r
- //\r
- InitializeListHead (&UsbBus->WantedUsbIoDPList);\r
- Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);\r
- ASSERT (!EFI_ERROR (Status));\r
- //\r
- // Create a fake usb device for root hub\r
- //\r
- RootHub = AllocateZeroPool (sizeof (USB_DEVICE));\r
-\r
- if (RootHub == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto UNINSTALL_USBBUS;\r
- }\r
-\r
- RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
-\r
- if (RootIf == NULL) {\r
- gBS->FreePool (RootHub);\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto FREE_ROOTHUB;\r
- }\r
-\r
- RootHub->Bus = UsbBus;\r
- RootHub->NumOfInterface = 1;\r
- RootHub->Interfaces[0] = RootIf;\r
- RootIf->Signature = USB_INTERFACE_SIGNATURE;\r
- RootIf->Device = RootHub;\r
- RootIf->DevicePath = UsbBus->DevicePath;\r
-\r
- Status = mUsbRootHubApi.Init (RootIf);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));\r
- goto FREE_ROOTHUB;\r
- }\r
-\r
- UsbBus->Devices[0] = RootHub;\r
-\r
- DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));\r
- return EFI_SUCCESS;\r
-\r
-FREE_ROOTHUB:\r
- if (RootIf != NULL) {\r
- gBS->FreePool (RootIf);\r
- }\r
- if (RootHub != NULL) {\r
- gBS->FreePool (RootHub);\r
- }\r
-\r
-UNINSTALL_USBBUS:\r
- gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);\r
-\r
-CLOSE_HC:\r
- if (UsbBus->Usb2Hc != NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- }\r
- if (UsbBus->UsbHc != NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- }\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- gBS->FreePool (UsbBus);\r
-\r
- DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));\r
- return Status;\r
-}\r
-\r
-EFI_USB_IO_PROTOCOL mUsbIoProtocol = {\r
- UsbIoControlTransfer,\r
- UsbIoBulkTransfer,\r
- UsbIoAsyncInterruptTransfer,\r
- UsbIoSyncInterruptTransfer,\r
- UsbIoIsochronousTransfer,\r
- UsbIoAsyncIsochronousTransfer,\r
- UsbIoGetDeviceDescriptor,\r
- UsbIoGetActiveConfigDescriptor,\r
- UsbIoGetInterfaceDescriptor,\r
- UsbIoGetEndpointDescriptor,\r
- UsbIoGetStringDescriptor,\r
- UsbIoGetSupportedLanguages,\r
- UsbIoPortReset\r
-};\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusDriverEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- The USB bus driver entry pointer\r
-\r
-Arguments:\r
-\r
- ImageHandle - The driver image handle\r
- SystemTable - The system table\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The component name protocol is installed\r
- Others - Failed to init the usb driver\r
-\r
---*/\r
-{\r
- return EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &mUsbBusDriverBinding,\r
- ImageHandle,\r
- &mUsbBusComponentName,\r
- &mUsbBusComponentName2\r
- );\r
-}\r
-\r
-\r
-/**\r
- Check whether USB bus driver support this device\r
-\r
- @param This The USB bus driver binding protocol\r
- @param Controller The controller handle to test againist\r
- @param RemainingDevicePath The remaining device path\r
-\r
- @retval EFI_SUCCESS The bus supports this controller.\r
- @retval EFI_UNSUPPORTED This device isn't supported\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusControllerDriverSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_DEV_PATH_PTR DevicePathNode;\r
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
- EFI_USB_HC_PROTOCOL *UsbHc;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Check whether device path is valid\r
- //\r
- if (RemainingDevicePath != NULL) {\r
- DevicePathNode.DevPath = RemainingDevicePath;\r
-\r
- if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||\r
- (DevicePathNode.DevPath->SubType != MSG_USB_DP &&\r
- DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP\r
- && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP\r
- )) {\r
-\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &ParentDevicePath,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (Status == EFI_ALREADY_STARTED) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- //\r
- // Check whether USB_HC2 protocol is installed\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- (VOID **) &Usb2Hc,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (Status == EFI_ALREADY_STARTED) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // If failed to open USB_HC2, fall back to USB_HC\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- (VOID **) &UsbHc,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (Status == EFI_ALREADY_STARTED) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Start to process the controller\r
-\r
- @param This The USB bus driver binding instance\r
- @param Controller The controller to check\r
- @param RemainingDevicePath The remaining device patch\r
-\r
- @retval EFI_SUCCESS The controller is controlled by the usb bus\r
- @retval EFI_ALREADY_STARTED The controller is already controlled by the usb\r
- bus\r
- @retval EFI_OUT_OF_RESOURCES Failed to allocate resources\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusControllerDriverStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-{\r
- EFI_USB_BUS_PROTOCOL *UsbBusId;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Locate the USB bus protocol, if it is found, USB bus\r
- // is already started on this controller.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &mUsbBusProtocolGuid,\r
- (VOID **) &UsbBusId,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If first start, build the bus execute enviorment and install bus protocol\r
- //\r
- Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- //\r
- // Try get the Usb Bus protocol interface again\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &mUsbBusProtocolGuid,\r
- (VOID **) &UsbBusId,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- ASSERT (!EFI_ERROR (Status));\r
- } else {\r
- //\r
- // USB Bus driver need to control the recursive connect policy of the bus, only those wanted\r
- // usb child device will be recursively connected.\r
- // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.\r
- // All wanted usb child devices will be remembered by the usb bus driver itself.\r
- // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.\r
- //\r
- // Save the passed in RemainingDevicePath this time\r
- //\r
- Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);\r
- ASSERT (!EFI_ERROR (Status));\r
- //\r
- // Ensure all wanted child usb devices are fully recursively connected\r
- //\r
- Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);\r
- ASSERT (!EFI_ERROR (Status));\r
- }\r
-\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Stop handle the controller by this USB bus driver\r
-\r
- @param This The USB bus driver binding protocol\r
- @param Controller The controller to release\r
- @param NumberOfChildren The child of USB bus that opened controller\r
- BY_CHILD\r
- @param ChildHandleBuffer The array of child handle\r
-\r
- @retval EFI_SUCCESS The controller or children are stopped\r
- @retval EFI_DEVICE_ERROR Failed to stop the driver\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UsbBusControllerDriverStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-{\r
- USB_BUS *Bus;\r
- USB_DEVICE *RootHub;\r
- USB_DEVICE *UsbDev;\r
- USB_INTERFACE *RootIf;\r
- USB_INTERFACE *UsbIf;\r
- EFI_USB_BUS_PROTOCOL *BusId;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
- EFI_TPL OldTpl;\r
- UINTN Index;\r
- EFI_STATUS Status;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- if (NumberOfChildren > 0) {\r
- //\r
- // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
- //\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- for (Index = 0; Index < NumberOfChildren; Index++) {\r
- Status = gBS->OpenProtocol (\r
- ChildHandleBuffer[Index],\r
- &gEfiUsbIoProtocolGuid,\r
- (VOID **) &UsbIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // It is possible that the child has already been released:\r
- // 1. For combo device, free one device will release others.\r
- // 2. If a hub is released, all devices on its down facing\r
- // ports are released also.\r
- //\r
- continue;\r
- }\r
-\r
- UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);\r
- UsbDev = UsbIf->Device;\r
-\r
- UsbRemoveDevice (UsbDev);\r
- }\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %x\n", Controller));\r
-\r
- //\r
- // Locate USB_BUS for the current host controller\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &mUsbBusProtocolGuid,\r
- (VOID **) &BusId,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Bus = USB_BUS_FROM_THIS (BusId);\r
-\r
- //\r
- // Stop the root hub, then free all the devices\r
- //\r
- // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
- //\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- UsbHcSetState (Bus, EfiUsbHcStateHalt);\r
-\r
- RootHub = Bus->Devices[0];\r
- RootIf = RootHub->Interfaces[0];\r
-\r
- mUsbRootHubApi.Release (RootIf);\r
-\r
- for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
- if (Bus->Devices[Index] != NULL) {\r
- UsbRemoveDevice (Bus->Devices[Index]);\r
- }\r
- }\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- gBS->FreePool (RootIf);\r
- gBS->FreePool (RootHub);\r
- Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
- ASSERT (!EFI_ERROR (Status));\r
-\r
- //\r
- // Uninstall the bus identifier and close USB_HC/USB2_HC protocols\r
- //\r
- gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);\r
-\r
- if (Bus->Usb2Hc != NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- }\r
-\r
- if (Bus->UsbHc != NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- gBS->FreePool (Bus);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {\r
- UsbBusControllerDriverSupported,\r
- UsbBusControllerDriverStart,\r
- UsbBusControllerDriverStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r