3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Usb Bus Driver Binding and Bus IO Protocol
28 // USB_BUS_PROTOCOL is only used to locate USB_BUS
30 EFI_GUID mUsbBusProtocolGuid
= EFI_USB_BUS_PROTOCOL_GUID
;
34 USB_IO function to execute a control transfer. This
35 function will execute the USB transfer. If transfer
36 successes, it will sync the internal state of USB bus
39 @param This The USB_IO instance
40 @param Request The control transfer request
41 @param Direction Direction for data stage
42 @param Timeout The time to wait before timeout
43 @param Data The buffer holding the data
44 @param DataLength Then length of the data
45 @param UsbStatus USB result
47 @retval EFI_INVALID_PARAMETER The parameters are invalid
48 @retval EFI_SUCCESS The control transfer succeded.
49 @retval Others Failed to execute the transfer
55 UsbIoControlTransfer (
56 IN EFI_USB_IO_PROTOCOL
*This
,
57 IN EFI_USB_DEVICE_REQUEST
*Request
,
58 IN EFI_USB_DATA_DIRECTION Direction
,
60 IN OUT VOID
*Data
, OPTIONAL
61 IN UINTN DataLength
, OPTIONAL
67 USB_ENDPOINT_DESC
*EpDesc
;
71 if (UsbStatus
== NULL
) {
72 return EFI_INVALID_PARAMETER
;
75 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
77 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
80 Status
= UsbHcControlTransfer (
94 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
96 // Clear TT buffer when CTRL/BULK split transaction failes
97 // Clear the TRANSLATOR TT buffer, not parent's buffer
99 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
100 UsbHubCtrlClearTTBuffer (
101 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
102 Dev
->Translator
.TranslatorPortNumber
,
113 // Some control transfer will change the device's internal
114 // status, such as Set_Configuration and Set_Interface.
115 // We must synchronize the bus driver's status with that in
116 // device. We ignore the Set_Descriptor request because it's
117 // hardly used by any device, especially in pre-boot environment
121 // Reset the endpoint toggle when endpoint stall is cleared
123 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
124 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
125 USB_TARGET_ENDPOINT
)) &&
126 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
128 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
130 if (EpDesc
!= NULL
) {
136 // Select a new configuration. This is a dangerous action. Upper driver
137 // should stop use its current UsbIo after calling this driver. The old
138 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
139 // ReinstallProtocol since interfaces in different configuration may be
140 // completely irrellvant.
142 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
143 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
144 USB_TARGET_DEVICE
))) {
146 // Don't re-create the USB interfaces if configuration isn't changed.
148 if ((Dev
->ActiveConfig
!= NULL
) &&
149 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
154 USB_DEBUG (("UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
156 if (Dev
->ActiveConfig
!= NULL
) {
157 UsbRemoveConfig (Dev
);
160 if (Request
->Value
!= 0) {
161 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
165 // Exit now, Old USB_IO is invalid now
171 // A new alternative setting is selected for the interface.
172 // No need to reinstall UsbIo in this case because only
173 // underlying communication endpoints are changed. Functionality
174 // should remains the same.
176 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
177 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
178 USB_TARGET_INTERFACE
)) &&
179 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
181 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
183 if (!EFI_ERROR (Status
)) {
184 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
189 gBS
->RestoreTPL (OldTpl
);
195 Execute a bulk transfer to the device endpoint
197 @param This The USB IO instance
198 @param Endpoint The device endpoint
199 @param Data The data to transfer
200 @param DataLength The length of the data to transfer
201 @param Timeout Time to wait before timeout
202 @param UsbStatus The result of USB transfer
204 @retval EFI_SUCCESS The bulk transfer is OK
205 @retval EFI_INVALID_PARAMETER Some parameters are invalid
206 @retval Others Failed to execute transfer, reason returned in
214 IN EFI_USB_IO_PROTOCOL
*This
,
217 IN OUT UINTN
*DataLength
,
219 OUT UINT32
*UsbStatus
223 USB_INTERFACE
*UsbIf
;
224 USB_ENDPOINT_DESC
*EpDesc
;
230 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
231 (UsbStatus
== NULL
)) {
233 return EFI_INVALID_PARAMETER
;
236 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
238 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
241 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
243 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
244 Status
= EFI_INVALID_PARAMETER
;
249 Toggle
= EpDesc
->Toggle
;
250 Status
= UsbHcBulkTransfer (
255 EpDesc
->Desc
.MaxPacketSize
,
265 EpDesc
->Toggle
= Toggle
;
267 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
269 // Clear TT buffer when CTRL/BULK split transaction failes.
270 // Clear the TRANSLATOR TT buffer, not parent's buffer
272 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
273 UsbHubCtrlClearTTBuffer (
274 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
275 Dev
->Translator
.TranslatorPortNumber
,
284 gBS
->RestoreTPL (OldTpl
);
290 Execute a synchronous interrupt transfer
292 @param This The USB IO instance
293 @param Endpoint The device endpoint
294 @param Data The data to transfer
295 @param DataLength The length of the data to transfer
296 @param Timeout Time to wait before timeout
297 @param UsbStatus The result of USB transfer
299 @retval EFI_SUCCESS The synchronous interrupt transfer is OK
300 @retval EFI_INVALID_PARAMETER Some parameters are invalid
301 @retval Others Failed to execute transfer, reason returned in
308 UsbIoSyncInterruptTransfer (
309 IN EFI_USB_IO_PROTOCOL
*This
,
312 IN OUT UINTN
*DataLength
,
314 OUT UINT32
*UsbStatus
318 USB_INTERFACE
*UsbIf
;
319 USB_ENDPOINT_DESC
*EpDesc
;
324 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
325 (UsbStatus
== NULL
)) {
327 return EFI_INVALID_PARAMETER
;
330 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
332 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
335 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
337 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
338 Status
= EFI_INVALID_PARAMETER
;
342 Toggle
= EpDesc
->Toggle
;
343 Status
= UsbHcSyncInterruptTransfer (
348 EpDesc
->Desc
.MaxPacketSize
,
357 EpDesc
->Toggle
= Toggle
;
360 gBS
->RestoreTPL (OldTpl
);
366 Queue a new asynchronous interrupt transfer, or remove the old
367 request if (IsNewTransfer == FALSE)
369 @param This The USB_IO instance
370 @param Endpoint The device endpoint
371 @param IsNewTransfer Whether this is a new request, if it's old, remove
373 @param PollInterval The interval to poll the transfer result, (in ms)
374 @param DataLength The length of perodic data transfer
375 @param Callback The function to call periodicaly when transfer is
377 @param Context The context to the callback
379 @retval EFI_SUCCESS New transfer is queued or old request is removed
380 @retval EFI_INVALID_PARAMETER Some parameters are invalid
381 @retval Others Failed to queue the new request or remove the old
388 UsbIoAsyncInterruptTransfer (
389 IN EFI_USB_IO_PROTOCOL
*This
,
391 IN BOOLEAN IsNewTransfer
,
392 IN UINTN PollInterval
, OPTIONAL
393 IN UINTN DataLength
, OPTIONAL
394 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
395 IN VOID
*Context OPTIONAL
399 USB_INTERFACE
*UsbIf
;
400 USB_ENDPOINT_DESC
*EpDesc
;
405 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
406 return EFI_INVALID_PARAMETER
;
409 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
410 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
413 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
415 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
416 Status
= EFI_INVALID_PARAMETER
;
420 Toggle
= EpDesc
->Toggle
;
421 Status
= UsbHcAsyncInterruptTransfer (
426 EpDesc
->Desc
.MaxPacketSize
,
436 EpDesc
->Toggle
= Toggle
;
439 gBS
->RestoreTPL (OldTpl
);
445 Execute a synchronous isochronous transfer
447 @param This The USB IO instance
448 @param DeviceEndpoint The device endpoint
449 @param Data The data to transfer
450 @param DataLength The length of the data to transfer
451 @param UsbStatus The result of USB transfer
453 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported
459 UsbIoIsochronousTransfer (
460 IN EFI_USB_IO_PROTOCOL
*This
,
461 IN UINT8 DeviceEndpoint
,
467 return EFI_UNSUPPORTED
;
472 Queue an asynchronous isochronous transfer
474 @param This The USB_IO instance
475 @param DeviceEndpoint The device endpoint
476 @param DataLength The length of perodic data transfer
477 @param IsochronousCallBack The function to call periodicaly when transfer is
479 @param Context The context to the callback
481 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported
487 UsbIoAsyncIsochronousTransfer (
488 IN EFI_USB_IO_PROTOCOL
*This
,
489 IN UINT8 DeviceEndpoint
,
492 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
493 IN VOID
*Context OPTIONAL
496 return EFI_UNSUPPORTED
;
501 Retrieve the device descriptor of the device
503 @param This The USB IO instance
504 @param Descriptor The variable to receive the device descriptor
506 @retval EFI_SUCCESS The device descriptor is returned
507 @retval EFI_INVALID_PARAMETER The parameter is invalid
513 UsbIoGetDeviceDescriptor (
514 IN EFI_USB_IO_PROTOCOL
*This
,
515 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
519 USB_INTERFACE
*UsbIf
;
522 if (Descriptor
== NULL
) {
523 return EFI_INVALID_PARAMETER
;
526 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
528 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
531 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
533 gBS
->RestoreTPL (OldTpl
);
539 Return the configuration descriptor of the current active configuration
541 @param This The USB IO instance
542 @param Descriptor The USB configuration descriptor
544 @retval EFI_SUCCESS The active configuration descriptor is returned
545 @retval EFI_INVALID_PARAMETER Some parameter is invalid
546 @retval EFI_NOT_FOUND Currently no active configuration is selected.
552 UsbIoGetActiveConfigDescriptor (
553 IN EFI_USB_IO_PROTOCOL
*This
,
554 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
558 USB_INTERFACE
*UsbIf
;
562 if (Descriptor
== NULL
) {
563 return EFI_INVALID_PARAMETER
;
566 Status
= EFI_SUCCESS
;
567 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
569 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
572 if (Dev
->ActiveConfig
== NULL
) {
573 Status
= EFI_NOT_FOUND
;
577 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
580 gBS
->RestoreTPL (OldTpl
);
586 Retrieve the active interface setting descriptor for this USB IO instance
588 @param This The USB IO instance
589 @param Descriptor The variable to receive active interface setting
591 @retval EFI_SUCCESS The active interface setting is returned
592 @retval EFI_INVALID_PARAMETER Some parameter is invalid
598 UsbIoGetInterfaceDescriptor (
599 IN EFI_USB_IO_PROTOCOL
*This
,
600 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
603 USB_INTERFACE
*UsbIf
;
606 if (Descriptor
== NULL
) {
607 return EFI_INVALID_PARAMETER
;
610 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
612 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
613 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
615 gBS
->RestoreTPL (OldTpl
);
621 Retrieve the endpoint descriptor from this interface setting
623 @param This The USB IO instance
624 @param Index The index (start from zero) of the endpoint to
626 @param Descriptor The variable to receive the descriptor
628 @retval EFI_SUCCESS The endpoint descriptor is returned
629 @retval EFI_INVALID_PARAMETER Some parameter is invalid
635 UsbIoGetEndpointDescriptor (
636 IN EFI_USB_IO_PROTOCOL
*This
,
638 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
641 USB_INTERFACE
*UsbIf
;
644 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
646 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
648 if ((Descriptor
== NULL
) || (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
)) {
649 gBS
->RestoreTPL (OldTpl
);
650 return EFI_INVALID_PARAMETER
;
655 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
656 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
659 gBS
->RestoreTPL (OldTpl
);
665 Retrieve the supported language ID table from the device
667 @param This The USB IO instance
668 @param LangIDTable The table to return the language IDs
669 @param TableSize The number of supported languanges
671 @retval EFI_SUCCESS The language ID is return
677 UsbIoGetSupportedLanguages (
678 IN EFI_USB_IO_PROTOCOL
*This
,
679 OUT UINT16
**LangIDTable
,
680 OUT UINT16
*TableSize
684 USB_INTERFACE
*UsbIf
;
687 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
689 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
692 *LangIDTable
= Dev
->LangId
;
693 *TableSize
= Dev
->TotalLangId
;
695 gBS
->RestoreTPL (OldTpl
);
701 Retrieve an indexed string in the language of LangID
703 @param This The USB IO instance
704 @param LangID The language ID of the string to retrieve
705 @param StringIndex The index of the string
706 @param String The variable to receive the string
708 @retval EFI_SUCCESS The string is returned
709 @retval EFI_NOT_FOUND No such string existed
715 UsbIoGetStringDescriptor (
716 IN EFI_USB_IO_PROTOCOL
*This
,
718 IN UINT8 StringIndex
,
723 USB_INTERFACE
*UsbIf
;
724 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
730 if ((StringIndex
== 0) || (LangID
== 0)) {
731 return EFI_NOT_FOUND
;
734 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
736 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
740 // Check whether language ID is supported
742 Status
= EFI_NOT_FOUND
;
744 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
745 if (Dev
->LangId
[Index
] == LangID
) {
750 if (Index
== Dev
->TotalLangId
) {
755 // Retrieve the string descriptor then allocate a buffer
756 // to hold the string itself.
758 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
760 if (StrDesc
== NULL
) {
764 if (StrDesc
->Length
<= 2) {
768 Buf
= AllocateZeroPool (StrDesc
->Length
);
771 Status
= EFI_OUT_OF_RESOURCES
;
775 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
776 *String
= (CHAR16
*) Buf
;
777 Status
= EFI_SUCCESS
;
780 gBS
->FreePool (StrDesc
);
783 gBS
->RestoreTPL (OldTpl
);
789 Reset the device, then if that succeeds, reconfigure the
790 device with its address and current active configuration.
792 @param This The USB IO instance
794 @retval EFI_SUCCESS The device is reset and configured
795 @retval Others Failed to reset the device
801 IN EFI_USB_IO_PROTOCOL
*This
804 USB_INTERFACE
*UsbIf
;
805 USB_INTERFACE
*HubIf
;
811 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
813 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
816 HubIf
= Dev
->ParentIf
;
817 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
819 if (EFI_ERROR (Status
)) {
820 USB_ERROR (("UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
821 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
827 // Reset the device to its current address. The device now has a
828 // address of ZERO, so need to set Dev->Address to zero first for
829 // host to communicate with the device
831 Address
= Dev
->Address
;
833 Status
= UsbSetAddress (Dev
, Address
);
835 if (EFI_ERROR (Status
)) {
836 USB_ERROR (("UsbIoPortReset: failed to set address for device %d - %r\n",
842 Dev
->Address
= Address
;
845 // Reset the current active configure, after this device
846 // is in CONFIGURED state.
848 if (Dev
->ActiveConfig
!= NULL
) {
849 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
851 if (EFI_ERROR (Status
)) {
852 USB_ERROR (("UsbIoPortReset: failed to set configure for device %d - %r\n",
858 gBS
->RestoreTPL (OldTpl
);
862 EFI_USB_IO_PROTOCOL mUsbIoProtocol
= {
863 UsbIoControlTransfer
,
865 UsbIoAsyncInterruptTransfer
,
866 UsbIoSyncInterruptTransfer
,
867 UsbIoIsochronousTransfer
,
868 UsbIoAsyncIsochronousTransfer
,
869 UsbIoGetDeviceDescriptor
,
870 UsbIoGetActiveConfigDescriptor
,
871 UsbIoGetInterfaceDescriptor
,
872 UsbIoGetEndpointDescriptor
,
873 UsbIoGetStringDescriptor
,
874 UsbIoGetSupportedLanguages
,
878 //@MT: EFI_DRIVER_ENTRY_POINT (UsbBusDriverEntryPoint)
882 UsbBusDriverEntryPoint (
883 IN EFI_HANDLE ImageHandle
,
884 IN EFI_SYSTEM_TABLE
*SystemTable
890 The USB bus driver entry pointer
894 ImageHandle - The driver image handle
895 SystemTable - The system table
899 EFI_SUCCESS - The component name protocol is installed
900 Others - Failed to init the usb driver
904 return EfiLibInstallAllDriverProtocols (
907 &mUsbBusDriverBinding
,
909 &mUsbBusComponentName
,
917 Check whether USB bus driver support this device
919 @param This The USB bus driver binding protocol
920 @param Controller The controller handle to test againist
921 @param RemainingDevicePath The remaining device path
923 @retval EFI_SUCCESS The bus supports this controller.
924 @retval EFI_UNSUPPORTED This device isn't supported
929 UsbBusControllerDriverSupported (
930 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
931 IN EFI_HANDLE Controller
,
932 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
935 EFI_DEV_PATH_PTR DevicePathNode
;
936 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
937 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
938 EFI_USB_HC_PROTOCOL
*UsbHc
;
942 // Check whether device path is valid
944 if (RemainingDevicePath
!= NULL
) {
945 DevicePathNode
.DevPath
= RemainingDevicePath
;
947 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
948 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
) ||
949 (DevicePathNodeLength (DevicePathNode
.DevPath
) != sizeof (USB_DEVICE_PATH
))) {
951 return EFI_UNSUPPORTED
;
955 Status
= gBS
->OpenProtocol (
957 &gEfiDevicePathProtocolGuid
,
958 (VOID
**) &ParentDevicePath
,
959 This
->DriverBindingHandle
,
961 EFI_OPEN_PROTOCOL_BY_DRIVER
964 if (Status
== EFI_ALREADY_STARTED
) {
968 if (EFI_ERROR (Status
)) {
974 &gEfiDevicePathProtocolGuid
,
975 This
->DriverBindingHandle
,
980 // Check whether USB_HC2 protocol is installed
982 Status
= gBS
->OpenProtocol (
984 &gEfiUsb2HcProtocolGuid
,
986 This
->DriverBindingHandle
,
988 EFI_OPEN_PROTOCOL_BY_DRIVER
991 if (Status
== EFI_ALREADY_STARTED
) {
995 if (!EFI_ERROR (Status
)) {
998 &gEfiUsb2HcProtocolGuid
,
999 This
->DriverBindingHandle
,
1007 // If failed to open USB_HC2, fall back to USB_HC
1009 Status
= gBS
->OpenProtocol (
1011 &gEfiUsbHcProtocolGuid
,
1013 This
->DriverBindingHandle
,
1015 EFI_OPEN_PROTOCOL_BY_DRIVER
1018 if (Status
== EFI_ALREADY_STARTED
) {
1022 if (!EFI_ERROR (Status
)) {
1023 gBS
->CloseProtocol (
1025 &gEfiUsbHcProtocolGuid
,
1026 This
->DriverBindingHandle
,
1036 Start to process the controller
1038 @param This The USB bus driver binding instance
1039 @param Controller The controller to check
1040 @param RemainingDevicePath The remaining device patch
1042 @retval EFI_SUCCESS The controller is controlled by the usb bus
1043 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1045 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources
1050 UsbBusControllerDriverStart (
1051 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1052 IN EFI_HANDLE Controller
,
1053 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1057 USB_DEVICE
*RootHub
;
1058 USB_INTERFACE
*RootIf
;
1059 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1064 // Locate the USB bus protocol, if it is found, USB bus
1065 // is already started on this controller.
1067 Status
= gBS
->OpenProtocol (
1069 &mUsbBusProtocolGuid
,
1070 (VOID
**) &UsbBusId
,
1071 This
->DriverBindingHandle
,
1073 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1076 if (!EFI_ERROR (Status
)) {
1077 return EFI_ALREADY_STARTED
;
1080 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
1082 if (UsbBus
== NULL
) {
1083 return EFI_OUT_OF_RESOURCES
;
1086 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
1087 UsbBus
->HostHandle
= Controller
;
1089 Status
= gBS
->OpenProtocol (
1091 &gEfiDevicePathProtocolGuid
,
1092 (VOID
**) &UsbBus
->DevicePath
,
1093 This
->DriverBindingHandle
,
1095 EFI_OPEN_PROTOCOL_BY_DRIVER
1098 if (EFI_ERROR (Status
)) {
1099 USB_ERROR (("UsbBusStart: Failed to open device path %r\n", Status
));
1101 gBS
->FreePool (UsbBus
);
1106 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
1107 // This is for backward compatbility with EFI 1.x. In UEFI
1108 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
1109 // and USB_HC because EHCI driver will install both protocols
1110 // (for the same reason). If we don't consume both of them,
1111 // the unconsumed one may be opened by others.
1113 Status
= gBS
->OpenProtocol (
1115 &gEfiUsb2HcProtocolGuid
,
1116 (VOID
**) &(UsbBus
->Usb2Hc
),
1117 This
->DriverBindingHandle
,
1119 EFI_OPEN_PROTOCOL_BY_DRIVER
1122 Status2
= gBS
->OpenProtocol (
1124 &gEfiUsbHcProtocolGuid
,
1125 (VOID
**) &(UsbBus
->UsbHc
),
1126 This
->DriverBindingHandle
,
1128 EFI_OPEN_PROTOCOL_BY_DRIVER
1131 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
1132 USB_ERROR (("UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
1134 Status
= EFI_DEVICE_ERROR
;
1139 // Create a fake usb device for root hub
1141 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
1143 if (RootHub
== NULL
) {
1144 Status
= EFI_OUT_OF_RESOURCES
;
1148 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1150 if (RootIf
== NULL
) {
1151 gBS
->FreePool (RootHub
);
1152 Status
= EFI_OUT_OF_RESOURCES
;
1156 RootHub
->Bus
= UsbBus
;
1157 RootHub
->NumOfInterface
= 1;
1158 RootHub
->Interfaces
[0] = RootIf
;
1159 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1160 RootIf
->Device
= RootHub
;
1161 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1163 Status
= mUsbRootHubApi
.Init (RootIf
);
1165 if (EFI_ERROR (Status
)) {
1166 USB_ERROR (("UsbBusStart: Failed to init root hub %r\n", Status
));
1170 UsbBus
->Devices
[0] = RootHub
;
1173 // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.
1175 Status
= gBS
->InstallProtocolInterface (
1177 &mUsbBusProtocolGuid
,
1178 EFI_NATIVE_INTERFACE
,
1182 if (EFI_ERROR (Status
)) {
1183 USB_ERROR (("UsbBusStart: Failed to install bus protocol %r\n", Status
));
1185 mUsbRootHubApi
.Release (RootIf
);
1189 UsbHcReset (UsbBus
, EFI_USB_HC_RESET_GLOBAL
);
1190 UsbHcSetState (UsbBus
, EfiUsbHcStateOperational
);
1192 USB_DEBUG (("UsbBusStart: usb bus started on %x, root hub %x\n", Controller
, RootIf
));
1196 gBS
->FreePool (RootIf
);
1197 gBS
->FreePool (RootHub
);
1200 if (UsbBus
->Usb2Hc
!= NULL
) {
1201 gBS
->CloseProtocol (
1203 &gEfiUsb2HcProtocolGuid
,
1204 This
->DriverBindingHandle
,
1209 if (UsbBus
->UsbHc
!= NULL
) {
1210 gBS
->CloseProtocol (
1212 &gEfiUsbHcProtocolGuid
,
1213 This
->DriverBindingHandle
,
1218 gBS
->CloseProtocol (
1220 &gEfiDevicePathProtocolGuid
,
1221 This
->DriverBindingHandle
,
1225 gBS
->FreePool (UsbBus
);
1227 USB_ERROR (("UsbBusStart: Failed to start bus driver %r\n", Status
));
1233 Stop handle the controller by this USB bus driver
1235 @param This The USB bus driver binding protocol
1236 @param Controller The controller to release
1237 @param NumberOfChildren The child of USB bus that opened controller
1239 @param ChildHandleBuffer The array of child handle
1241 @retval EFI_SUCCESS The controller or children are stopped
1242 @retval EFI_DEVICE_ERROR Failed to stop the driver
1247 UsbBusControllerDriverStop (
1248 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1249 IN EFI_HANDLE Controller
,
1250 IN UINTN NumberOfChildren
,
1251 IN EFI_HANDLE
*ChildHandleBuffer
1255 USB_DEVICE
*RootHub
;
1257 USB_INTERFACE
*RootIf
;
1258 USB_INTERFACE
*UsbIf
;
1259 EFI_USB_BUS_PROTOCOL
*BusId
;
1260 EFI_USB_IO_PROTOCOL
*UsbIo
;
1265 Status
= EFI_SUCCESS
;
1267 if (NumberOfChildren
> 0) {
1268 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
1270 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1271 Status
= gBS
->OpenProtocol (
1272 ChildHandleBuffer
[Index
],
1273 &gEfiUsbIoProtocolGuid
,
1275 This
->DriverBindingHandle
,
1277 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1280 if (EFI_ERROR (Status
)) {
1282 // It is possible that the child has already been released:
1283 // 1. For combo device, free one device will release others.
1284 // 2. If a hub is released, all devices on its down facing
1285 // ports are released also.
1290 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1291 UsbDev
= UsbIf
->Device
;
1293 UsbRemoveDevice (UsbDev
);
1296 gBS
->RestoreTPL (OldTpl
);
1300 USB_DEBUG (("UsbBusStop: usb bus stopped on %x\n", Controller
));
1303 // Locate USB_BUS for the current host controller
1305 Status
= gBS
->OpenProtocol (
1307 &mUsbBusProtocolGuid
,
1309 This
->DriverBindingHandle
,
1311 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1314 if (EFI_ERROR (Status
)) {
1318 Bus
= USB_BUS_FROM_THIS (BusId
);
1321 // Stop the root hub, then free all the devices
1323 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
1324 UsbHcSetState (Bus
, EfiUsbHcStateHalt
);
1326 RootHub
= Bus
->Devices
[0];
1327 RootIf
= RootHub
->Interfaces
[0];
1329 mUsbRootHubApi
.Release (RootIf
);
1331 for (Index
= 1; Index
< USB_MAX_DEVICES
; Index
++) {
1332 if (Bus
->Devices
[Index
] != NULL
) {
1333 UsbRemoveDevice (Bus
->Devices
[Index
]);
1337 gBS
->RestoreTPL (OldTpl
);
1339 gBS
->FreePool (RootIf
);
1340 gBS
->FreePool (RootHub
);
1343 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1345 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &Bus
->BusId
);
1347 if (Bus
->Usb2Hc
!= NULL
) {
1348 gBS
->CloseProtocol (
1350 &gEfiUsb2HcProtocolGuid
,
1351 This
->DriverBindingHandle
,
1356 if (Bus
->UsbHc
!= NULL
) {
1357 gBS
->CloseProtocol (
1359 &gEfiUsbHcProtocolGuid
,
1360 This
->DriverBindingHandle
,
1365 gBS
->CloseProtocol (
1367 &gEfiDevicePathProtocolGuid
,
1368 This
->DriverBindingHandle
,
1372 gBS
->FreePool (Bus
);
1377 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding
= {
1378 UsbBusControllerDriverSupported
,
1379 UsbBusControllerDriverStart
,
1380 UsbBusControllerDriverStop
,