3 Usb Bus Driver Binding and Bus IO Protocol.
5 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 EFI_USB_IO_PROTOCOL mUsbIoProtocol
= {
21 UsbIoAsyncInterruptTransfer
,
22 UsbIoSyncInterruptTransfer
,
23 UsbIoIsochronousTransfer
,
24 UsbIoAsyncIsochronousTransfer
,
25 UsbIoGetDeviceDescriptor
,
26 UsbIoGetActiveConfigDescriptor
,
27 UsbIoGetInterfaceDescriptor
,
28 UsbIoGetEndpointDescriptor
,
29 UsbIoGetStringDescriptor
,
30 UsbIoGetSupportedLanguages
,
34 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding
= {
35 UsbBusControllerDriverSupported
,
36 UsbBusControllerDriverStart
,
37 UsbBusControllerDriverStop
,
44 USB_IO function to execute a control transfer. This
45 function will execute the USB transfer. If transfer
46 successes, it will sync the internal state of USB bus
49 @param This The USB_IO instance
50 @param Request The control transfer request
51 @param Direction Direction for data stage
52 @param Timeout The time to wait before timeout
53 @param Data The buffer holding the data
54 @param DataLength Then length of the data
55 @param UsbStatus USB result
57 @retval EFI_INVALID_PARAMETER The parameters are invalid
58 @retval EFI_SUCCESS The control transfer succeeded.
59 @retval Others Failed to execute the transfer
64 UsbIoControlTransfer (
65 IN EFI_USB_IO_PROTOCOL
*This
,
66 IN EFI_USB_DEVICE_REQUEST
*Request
,
67 IN EFI_USB_DATA_DIRECTION Direction
,
69 IN OUT VOID
*Data
, OPTIONAL
70 IN UINTN DataLength
, OPTIONAL
76 USB_ENDPOINT_DESC
*EpDesc
;
80 if (UsbStatus
== NULL
) {
81 return EFI_INVALID_PARAMETER
;
84 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
86 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
89 Status
= UsbHcControlTransfer (
103 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
105 // Clear TT buffer when CTRL/BULK split transaction failes
106 // Clear the TRANSLATOR TT buffer, not parent's buffer
108 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
109 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
110 UsbHubCtrlClearTTBuffer (
111 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
112 Dev
->Translator
.TranslatorPortNumber
,
123 // Some control transfer will change the device's internal
124 // status, such as Set_Configuration and Set_Interface.
125 // We must synchronize the bus driver's status with that in
126 // device. We ignore the Set_Descriptor request because it's
127 // hardly used by any device, especially in pre-boot environment
131 // Reset the endpoint toggle when endpoint stall is cleared
133 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
134 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
135 USB_TARGET_ENDPOINT
)) &&
136 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
138 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
140 if (EpDesc
!= NULL
) {
146 // Select a new configuration. This is a dangerous action. Upper driver
147 // should stop use its current UsbIo after calling this driver. The old
148 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
149 // ReinstallProtocol since interfaces in different configuration may be
150 // completely irrelevant.
152 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
153 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
154 USB_TARGET_DEVICE
))) {
156 // Don't re-create the USB interfaces if configuration isn't changed.
158 if ((Dev
->ActiveConfig
!= NULL
) &&
159 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
163 DEBUG ((EFI_D_INFO
, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
165 if (Dev
->ActiveConfig
!= NULL
) {
166 UsbRemoveConfig (Dev
);
169 if (Request
->Value
!= 0) {
170 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
174 // Exit now, Old USB_IO is invalid now
180 // A new alternative setting is selected for the interface.
181 // No need to reinstall UsbIo in this case because only
182 // underlying communication endpoints are changed. Functionality
183 // should remains the same.
185 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
186 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
187 USB_TARGET_INTERFACE
)) &&
188 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
190 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
192 if (!EFI_ERROR (Status
)) {
193 ASSERT (UsbIf
->IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
194 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
199 gBS
->RestoreTPL (OldTpl
);
205 Execute a bulk transfer to the device endpoint.
207 @param This The USB IO instance.
208 @param Endpoint The device endpoint.
209 @param Data The data to transfer.
210 @param DataLength The length of the data to transfer.
211 @param Timeout Time to wait before timeout.
212 @param UsbStatus The result of USB transfer.
214 @retval EFI_SUCCESS The bulk transfer is OK.
215 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
216 @retval Others Failed to execute transfer, reason returned in
223 IN EFI_USB_IO_PROTOCOL
*This
,
226 IN OUT UINTN
*DataLength
,
228 OUT UINT32
*UsbStatus
232 USB_INTERFACE
*UsbIf
;
233 USB_ENDPOINT_DESC
*EpDesc
;
239 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
240 (UsbStatus
== NULL
)) {
242 return EFI_INVALID_PARAMETER
;
245 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
247 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
250 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
252 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
253 Status
= EFI_INVALID_PARAMETER
;
258 Toggle
= EpDesc
->Toggle
;
259 Status
= UsbHcBulkTransfer (
264 EpDesc
->Desc
.MaxPacketSize
,
274 EpDesc
->Toggle
= Toggle
;
276 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
278 // Clear TT buffer when CTRL/BULK split transaction failes.
279 // Clear the TRANSLATOR TT buffer, not parent's buffer
281 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
282 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
283 UsbHubCtrlClearTTBuffer (
284 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
285 Dev
->Translator
.TranslatorPortNumber
,
294 gBS
->RestoreTPL (OldTpl
);
300 Execute a synchronous interrupt transfer.
302 @param This The USB IO instance.
303 @param Endpoint The device endpoint.
304 @param Data The data to transfer.
305 @param DataLength The length of the data to transfer.
306 @param Timeout Time to wait before timeout.
307 @param UsbStatus The result of USB transfer.
309 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
310 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
311 @retval Others Failed to execute transfer, reason returned in
317 UsbIoSyncInterruptTransfer (
318 IN EFI_USB_IO_PROTOCOL
*This
,
321 IN OUT UINTN
*DataLength
,
323 OUT UINT32
*UsbStatus
327 USB_INTERFACE
*UsbIf
;
328 USB_ENDPOINT_DESC
*EpDesc
;
333 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
334 (UsbStatus
== NULL
)) {
336 return EFI_INVALID_PARAMETER
;
339 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
341 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
344 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
346 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
347 Status
= EFI_INVALID_PARAMETER
;
351 Toggle
= EpDesc
->Toggle
;
352 Status
= UsbHcSyncInterruptTransfer (
357 EpDesc
->Desc
.MaxPacketSize
,
366 EpDesc
->Toggle
= Toggle
;
369 gBS
->RestoreTPL (OldTpl
);
375 Queue a new asynchronous interrupt transfer, or remove the old
376 request if (IsNewTransfer == FALSE).
378 @param This The USB_IO instance.
379 @param Endpoint The device endpoint.
380 @param IsNewTransfer Whether this is a new request, if it's old, remove
382 @param PollInterval The interval to poll the transfer result, (in ms).
383 @param DataLength The length of perodic data transfer.
384 @param Callback The function to call periodicaly when transfer is
386 @param Context The context to the callback.
388 @retval EFI_SUCCESS New transfer is queued or old request is removed.
389 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
390 @retval Others Failed to queue the new request or remove the old
396 UsbIoAsyncInterruptTransfer (
397 IN EFI_USB_IO_PROTOCOL
*This
,
399 IN BOOLEAN IsNewTransfer
,
400 IN UINTN PollInterval
, OPTIONAL
401 IN UINTN DataLength
, OPTIONAL
402 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
403 IN VOID
*Context OPTIONAL
407 USB_INTERFACE
*UsbIf
;
408 USB_ENDPOINT_DESC
*EpDesc
;
413 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
414 return EFI_INVALID_PARAMETER
;
417 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
418 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
421 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
423 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
424 Status
= EFI_INVALID_PARAMETER
;
428 Toggle
= EpDesc
->Toggle
;
429 Status
= UsbHcAsyncInterruptTransfer (
434 EpDesc
->Desc
.MaxPacketSize
,
444 EpDesc
->Toggle
= Toggle
;
447 gBS
->RestoreTPL (OldTpl
);
453 Execute a synchronous isochronous transfer.
455 @param This The USB IO instance.
456 @param DeviceEndpoint The device endpoint.
457 @param Data The data to transfer.
458 @param DataLength The length of the data to transfer.
459 @param UsbStatus The result of USB transfer.
461 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
466 UsbIoIsochronousTransfer (
467 IN EFI_USB_IO_PROTOCOL
*This
,
468 IN UINT8 DeviceEndpoint
,
474 return EFI_UNSUPPORTED
;
479 Queue an asynchronous isochronous transfer.
481 @param This The USB_IO instance.
482 @param DeviceEndpoint The device endpoint.
483 @param Data The data to transfer.
484 @param DataLength The length of perodic data transfer.
485 @param IsochronousCallBack The function to call periodicaly when transfer is
487 @param Context The context to the callback.
489 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
494 UsbIoAsyncIsochronousTransfer (
495 IN EFI_USB_IO_PROTOCOL
*This
,
496 IN UINT8 DeviceEndpoint
,
499 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
500 IN VOID
*Context OPTIONAL
503 return EFI_UNSUPPORTED
;
508 Retrieve the device descriptor of the device.
510 @param This The USB IO instance.
511 @param Descriptor The variable to receive the device descriptor.
513 @retval EFI_SUCCESS The device descriptor is returned.
514 @retval EFI_INVALID_PARAMETER The parameter is invalid.
519 UsbIoGetDeviceDescriptor (
520 IN EFI_USB_IO_PROTOCOL
*This
,
521 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
525 USB_INTERFACE
*UsbIf
;
528 if (Descriptor
== NULL
) {
529 return EFI_INVALID_PARAMETER
;
532 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
534 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
537 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
539 gBS
->RestoreTPL (OldTpl
);
545 Return the configuration descriptor of the current active configuration.
547 @param This The USB IO instance.
548 @param Descriptor The USB configuration descriptor.
550 @retval EFI_SUCCESS The active configuration descriptor is returned.
551 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
552 @retval EFI_NOT_FOUND Currently no active configuration is selected.
557 UsbIoGetActiveConfigDescriptor (
558 IN EFI_USB_IO_PROTOCOL
*This
,
559 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
563 USB_INTERFACE
*UsbIf
;
567 if (Descriptor
== NULL
) {
568 return EFI_INVALID_PARAMETER
;
571 Status
= EFI_SUCCESS
;
572 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
574 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
577 if (Dev
->ActiveConfig
== NULL
) {
578 Status
= EFI_NOT_FOUND
;
582 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
585 gBS
->RestoreTPL (OldTpl
);
591 Retrieve the active interface setting descriptor for this USB IO instance.
593 @param This The USB IO instance.
594 @param Descriptor The variable to receive active interface setting.
596 @retval EFI_SUCCESS The active interface setting is returned.
597 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
602 UsbIoGetInterfaceDescriptor (
603 IN EFI_USB_IO_PROTOCOL
*This
,
604 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
607 USB_INTERFACE
*UsbIf
;
610 if (Descriptor
== NULL
) {
611 return EFI_INVALID_PARAMETER
;
614 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
616 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
617 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
619 gBS
->RestoreTPL (OldTpl
);
625 Retrieve the endpoint descriptor from this interface setting.
627 @param This The USB IO instance.
628 @param Index The index (start from zero) of the endpoint to
630 @param Descriptor The variable to receive the descriptor.
632 @retval EFI_SUCCESS The endpoint descriptor is returned.
633 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
638 UsbIoGetEndpointDescriptor (
639 IN EFI_USB_IO_PROTOCOL
*This
,
641 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
644 USB_INTERFACE
*UsbIf
;
647 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
649 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
651 if ((Descriptor
== NULL
) || (Index
> 15)) {
652 gBS
->RestoreTPL (OldTpl
);
653 return EFI_INVALID_PARAMETER
;
656 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
657 gBS
->RestoreTPL (OldTpl
);
658 return EFI_NOT_FOUND
;
663 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
664 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
667 gBS
->RestoreTPL (OldTpl
);
673 Retrieve the supported language ID table from the device.
675 @param This The USB IO instance.
676 @param LangIDTable The table to return the language IDs.
677 @param TableSize The size, in bytes, of the table LangIDTable.
679 @retval EFI_SUCCESS The language ID is return.
684 UsbIoGetSupportedLanguages (
685 IN EFI_USB_IO_PROTOCOL
*This
,
686 OUT UINT16
**LangIDTable
,
687 OUT UINT16
*TableSize
691 USB_INTERFACE
*UsbIf
;
694 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
696 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
699 *LangIDTable
= Dev
->LangId
;
700 *TableSize
= (UINT16
) (Dev
->TotalLangId
* sizeof (UINT16
));
702 gBS
->RestoreTPL (OldTpl
);
708 Retrieve an indexed string in the language of LangID.
710 @param This The USB IO instance.
711 @param LangID The language ID of the string to retrieve.
712 @param StringIndex The index of the string.
713 @param String The variable to receive the string.
715 @retval EFI_SUCCESS The string is returned.
716 @retval EFI_NOT_FOUND No such string existed.
721 UsbIoGetStringDescriptor (
722 IN EFI_USB_IO_PROTOCOL
*This
,
724 IN UINT8 StringIndex
,
729 USB_INTERFACE
*UsbIf
;
730 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
736 if ((StringIndex
== 0) || (LangID
== 0)) {
737 return EFI_NOT_FOUND
;
740 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
742 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
746 // Check whether language ID is supported
748 Status
= EFI_NOT_FOUND
;
750 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
751 ASSERT (Index
< USB_MAX_LANG_ID
);
752 if (Dev
->LangId
[Index
] == LangID
) {
757 if (Index
== Dev
->TotalLangId
) {
762 // Retrieve the string descriptor then allocate a buffer
763 // to hold the string itself.
765 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
767 if (StrDesc
== NULL
) {
771 if (StrDesc
->Length
<= 2) {
775 Buf
= AllocateZeroPool (StrDesc
->Length
);
778 Status
= EFI_OUT_OF_RESOURCES
;
782 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
783 *String
= (CHAR16
*) Buf
;
784 Status
= EFI_SUCCESS
;
787 gBS
->FreePool (StrDesc
);
790 gBS
->RestoreTPL (OldTpl
);
796 Reset the device, then if that succeeds, reconfigure the
797 device with its address and current active configuration.
799 @param This The USB IO instance.
801 @retval EFI_SUCCESS The device is reset and configured.
802 @retval Others Failed to reset the device.
808 IN EFI_USB_IO_PROTOCOL
*This
811 USB_INTERFACE
*UsbIf
;
812 USB_INTERFACE
*HubIf
;
818 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
820 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
824 Status
= EFI_INVALID_PARAMETER
;
828 HubIf
= Dev
->ParentIf
;
829 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
831 if (EFI_ERROR (Status
)) {
832 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
833 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
838 HubIf
->HubApi
->ClearPortChange (HubIf
, Dev
->ParentPort
);
841 // Reset the device to its current address. The device now has an address
842 // of ZERO after port reset, so need to set Dev->Address to the device again for
843 // host to communicate with it.
845 DevAddress
= Dev
->Address
;
847 Status
= UsbSetAddress (Dev
, DevAddress
);
848 Dev
->Address
= DevAddress
;
850 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
852 if (EFI_ERROR (Status
)) {
854 // It may fail due to device disconnection or other reasons.
856 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set address for device %d - %r\n",
857 Dev
->Address
, Status
));
862 DEBUG (( EFI_D_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev
->Address
));
865 // Reset the current active configure, after this device
866 // is in CONFIGURED state.
868 if (Dev
->ActiveConfig
!= NULL
) {
869 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
871 if (EFI_ERROR (Status
)) {
872 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set configure for device %d - %r\n",
873 Dev
->Address
, Status
));
878 gBS
->RestoreTPL (OldTpl
);
884 Install Usb Bus Protocol on host controller, and start the Usb bus.
886 @param This The USB bus driver binding instance.
887 @param Controller The controller to check.
888 @param RemainingDevicePath The remaining device patch.
890 @retval EFI_SUCCESS The controller is controlled by the usb bus.
891 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
892 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
897 UsbBusBuildProtocol (
898 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
899 IN EFI_HANDLE Controller
,
900 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
905 USB_INTERFACE
*RootIf
;
909 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
911 if (UsbBus
== NULL
) {
912 return EFI_OUT_OF_RESOURCES
;
915 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
916 UsbBus
->HostHandle
= Controller
;
917 UsbBus
->MaxDevices
= USB_MAX_DEVICES
;
919 Status
= gBS
->OpenProtocol (
921 &gEfiDevicePathProtocolGuid
,
922 (VOID
**) &UsbBus
->DevicePath
,
923 This
->DriverBindingHandle
,
925 EFI_OPEN_PROTOCOL_BY_DRIVER
928 if (EFI_ERROR (Status
)) {
929 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open device path %r\n", Status
));
936 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
937 // This is for backward compatibility with EFI 1.x. In UEFI
938 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
939 // and USB_HC because EHCI driver will install both protocols
940 // (for the same reason). If we don't consume both of them,
941 // the unconsumed one may be opened by others.
943 Status
= gBS
->OpenProtocol (
945 &gEfiUsb2HcProtocolGuid
,
946 (VOID
**) &(UsbBus
->Usb2Hc
),
947 This
->DriverBindingHandle
,
949 EFI_OPEN_PROTOCOL_BY_DRIVER
952 Status2
= gBS
->OpenProtocol (
954 &gEfiUsbHcProtocolGuid
,
955 (VOID
**) &(UsbBus
->UsbHc
),
956 This
->DriverBindingHandle
,
958 EFI_OPEN_PROTOCOL_BY_DRIVER
961 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
962 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
964 Status
= EFI_DEVICE_ERROR
;
968 if (!EFI_ERROR (Status
)) {
970 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
971 // Then its max supported devices are 256. Otherwise it's 128.
973 ASSERT (UsbBus
->Usb2Hc
!= NULL
);
974 if (UsbBus
->Usb2Hc
->MajorRevision
== 0x3) {
975 UsbBus
->MaxDevices
= 256;
979 UsbHcReset (UsbBus
, EFI_USB_HC_RESET_GLOBAL
);
980 UsbHcSetState (UsbBus
, EfiUsbHcStateOperational
);
983 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
985 Status
= gBS
->InstallProtocolInterface (
988 EFI_NATIVE_INTERFACE
,
992 if (EFI_ERROR (Status
)) {
993 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to install bus protocol %r\n", Status
));
998 // Initial the wanted child device path list, and add first RemainingDevicePath
1000 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
1001 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
1002 ASSERT (!EFI_ERROR (Status
));
1004 // Create a fake usb device for root hub
1006 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
1008 if (RootHub
== NULL
) {
1009 Status
= EFI_OUT_OF_RESOURCES
;
1010 goto UNINSTALL_USBBUS
;
1013 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1015 if (RootIf
== NULL
) {
1017 Status
= EFI_OUT_OF_RESOURCES
;
1021 RootHub
->Bus
= UsbBus
;
1022 RootHub
->NumOfInterface
= 1;
1023 RootHub
->Interfaces
[0] = RootIf
;
1025 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1026 RootIf
->Device
= RootHub
;
1027 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1030 // Report Status Code here since we will enumerate the USB devices
1032 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1034 (EFI_IO_BUS_USB
| EFI_IOB_PC_DETECT
),
1038 Status
= mUsbRootHubApi
.Init (RootIf
);
1040 if (EFI_ERROR (Status
)) {
1041 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to init root hub %r\n", Status
));
1045 UsbBus
->Devices
[0] = RootHub
;
1047 DEBUG ((EFI_D_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1051 if (RootIf
!= NULL
) {
1054 if (RootHub
!= NULL
) {
1059 gBS
->UninstallProtocolInterface (Controller
, &gEfiCallerIdGuid
, &UsbBus
->BusId
);
1062 if (UsbBus
->Usb2Hc
!= NULL
) {
1063 gBS
->CloseProtocol (
1065 &gEfiUsb2HcProtocolGuid
,
1066 This
->DriverBindingHandle
,
1070 if (UsbBus
->UsbHc
!= NULL
) {
1071 gBS
->CloseProtocol (
1073 &gEfiUsbHcProtocolGuid
,
1074 This
->DriverBindingHandle
,
1078 gBS
->CloseProtocol (
1080 &gEfiDevicePathProtocolGuid
,
1081 This
->DriverBindingHandle
,
1086 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to start bus driver %r\n", Status
));
1092 The USB bus driver entry pointer.
1094 @param ImageHandle The driver image handle.
1095 @param SystemTable The system table.
1097 @return EFI_SUCCESS The component name protocol is installed.
1098 @return Others Failed to init the usb driver.
1103 UsbBusDriverEntryPoint (
1104 IN EFI_HANDLE ImageHandle
,
1105 IN EFI_SYSTEM_TABLE
*SystemTable
1108 return EfiLibInstallDriverBindingComponentName2 (
1111 &mUsbBusDriverBinding
,
1113 &mUsbBusComponentName
,
1114 &mUsbBusComponentName2
1120 Check whether USB bus driver support this device.
1122 @param This The USB bus driver binding protocol.
1123 @param Controller The controller handle to check.
1124 @param RemainingDevicePath The remaining device path.
1126 @retval EFI_SUCCESS The bus supports this controller.
1127 @retval EFI_UNSUPPORTED This device isn't supported.
1132 UsbBusControllerDriverSupported (
1133 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1134 IN EFI_HANDLE Controller
,
1135 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1138 EFI_DEV_PATH_PTR DevicePathNode
;
1139 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1140 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1141 EFI_USB_HC_PROTOCOL
*UsbHc
;
1145 // Check whether device path is valid
1147 if (RemainingDevicePath
!= NULL
) {
1149 // Check if RemainingDevicePath is the End of Device Path Node,
1150 // if yes, go on checking other conditions
1152 if (!IsDevicePathEnd (RemainingDevicePath
)) {
1154 // If RemainingDevicePath isn't the End of Device Path Node,
1155 // check its validation
1157 DevicePathNode
.DevPath
= RemainingDevicePath
;
1159 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1160 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
&&
1161 DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
1162 && DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
1165 return EFI_UNSUPPORTED
;
1171 // Check whether USB_HC2 protocol is installed
1173 Status
= gBS
->OpenProtocol (
1175 &gEfiUsb2HcProtocolGuid
,
1177 This
->DriverBindingHandle
,
1179 EFI_OPEN_PROTOCOL_BY_DRIVER
1181 if (Status
== EFI_ALREADY_STARTED
) {
1185 if (EFI_ERROR (Status
)) {
1187 // If failed to open USB_HC2, fall back to USB_HC
1189 Status
= gBS
->OpenProtocol (
1191 &gEfiUsbHcProtocolGuid
,
1193 This
->DriverBindingHandle
,
1195 EFI_OPEN_PROTOCOL_BY_DRIVER
1197 if (Status
== EFI_ALREADY_STARTED
) {
1201 if (EFI_ERROR (Status
)) {
1206 // Close the USB_HC used to perform the supported test
1208 gBS
->CloseProtocol (
1210 &gEfiUsbHcProtocolGuid
,
1211 This
->DriverBindingHandle
,
1218 // Close the USB_HC2 used to perform the supported test
1220 gBS
->CloseProtocol (
1222 &gEfiUsb2HcProtocolGuid
,
1223 This
->DriverBindingHandle
,
1229 // Open the EFI Device Path protocol needed to perform the supported test
1231 Status
= gBS
->OpenProtocol (
1233 &gEfiDevicePathProtocolGuid
,
1234 (VOID
**) &ParentDevicePath
,
1235 This
->DriverBindingHandle
,
1237 EFI_OPEN_PROTOCOL_BY_DRIVER
1239 if (Status
== EFI_ALREADY_STARTED
) {
1243 if (!EFI_ERROR (Status
)) {
1245 // Close protocol, don't use device path protocol in the Support() function
1247 gBS
->CloseProtocol (
1249 &gEfiDevicePathProtocolGuid
,
1250 This
->DriverBindingHandle
,
1262 Start to process the controller.
1264 @param This The USB bus driver binding instance.
1265 @param Controller The controller to check.
1266 @param RemainingDevicePath The remaining device patch.
1268 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1269 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1271 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1276 UsbBusControllerDriverStart (
1277 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1278 IN EFI_HANDLE Controller
,
1279 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1282 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1284 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1286 Status
= gBS
->OpenProtocol (
1288 &gEfiDevicePathProtocolGuid
,
1289 (VOID
**) &ParentDevicePath
,
1290 This
->DriverBindingHandle
,
1292 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1294 ASSERT_EFI_ERROR (Status
);
1297 // Report Status Code here since we will initialize the host controller
1299 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1301 (EFI_IO_BUS_USB
| EFI_IOB_PC_INIT
),
1306 // Locate the USB bus protocol, if it is found, USB bus
1307 // is already started on this controller.
1309 Status
= gBS
->OpenProtocol (
1312 (VOID
**) &UsbBusId
,
1313 This
->DriverBindingHandle
,
1315 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1318 if (EFI_ERROR (Status
)) {
1320 // If first start, build the bus execute environment and install bus protocol
1322 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_IO_BUS_USB
| EFI_P_PC_ENABLE
));
1323 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1324 if (EFI_ERROR (Status
)) {
1328 // Try get the Usb Bus protocol interface again
1330 Status
= gBS
->OpenProtocol (
1333 (VOID
**) &UsbBusId
,
1334 This
->DriverBindingHandle
,
1336 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1338 ASSERT (!EFI_ERROR (Status
));
1341 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1342 // usb child device will be recursively connected.
1343 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1344 // All wanted usb child devices will be remembered by the usb bus driver itself.
1345 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1347 // Save the passed in RemainingDevicePath this time
1349 if (RemainingDevicePath
!= NULL
) {
1350 if (IsDevicePathEnd (RemainingDevicePath
)) {
1352 // If RemainingDevicePath is the End of Device Path Node,
1353 // skip enumerate any device and return EFI_SUCESSS
1359 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1360 ASSERT (!EFI_ERROR (Status
));
1362 // Ensure all wanted child usb devices are fully recursively connected
1364 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1365 ASSERT (!EFI_ERROR (Status
));
1374 Stop handle the controller by this USB bus driver.
1376 @param This The USB bus driver binding protocol.
1377 @param Controller The controller to release.
1378 @param NumberOfChildren The child of USB bus that opened controller
1380 @param ChildHandleBuffer The array of child handle.
1382 @retval EFI_SUCCESS The controller or children are stopped.
1383 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1388 UsbBusControllerDriverStop (
1389 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1390 IN EFI_HANDLE Controller
,
1391 IN UINTN NumberOfChildren
,
1392 IN EFI_HANDLE
*ChildHandleBuffer
1396 USB_DEVICE
*RootHub
;
1398 USB_INTERFACE
*RootIf
;
1399 USB_INTERFACE
*UsbIf
;
1400 EFI_USB_BUS_PROTOCOL
*BusId
;
1401 EFI_USB_IO_PROTOCOL
*UsbIo
;
1405 EFI_STATUS ReturnStatus
;
1407 Status
= EFI_SUCCESS
;
1409 if (NumberOfChildren
> 0) {
1411 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1413 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1415 ReturnStatus
= EFI_SUCCESS
;
1416 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1417 Status
= gBS
->OpenProtocol (
1418 ChildHandleBuffer
[Index
],
1419 &gEfiUsbIoProtocolGuid
,
1421 This
->DriverBindingHandle
,
1423 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1426 if (EFI_ERROR (Status
)) {
1428 // It is possible that the child has already been released:
1429 // 1. For combo device, free one device will release others.
1430 // 2. If a hub is released, all devices on its down facing
1431 // ports are released also.
1436 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1437 UsbDev
= UsbIf
->Device
;
1439 ReturnStatus
= UsbRemoveDevice (UsbDev
);
1442 gBS
->RestoreTPL (OldTpl
);
1443 return ReturnStatus
;
1446 DEBUG (( EFI_D_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1449 // Locate USB_BUS for the current host controller
1451 Status
= gBS
->OpenProtocol (
1455 This
->DriverBindingHandle
,
1457 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1460 if (EFI_ERROR (Status
)) {
1464 Bus
= USB_BUS_FROM_THIS (BusId
);
1467 // Stop the root hub, then free all the devices
1469 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1471 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1473 RootHub
= Bus
->Devices
[0];
1474 RootIf
= RootHub
->Interfaces
[0];
1476 ASSERT (Bus
->MaxDevices
<= 256);
1477 ReturnStatus
= EFI_SUCCESS
;
1478 for (Index
= 1; Index
< Bus
->MaxDevices
; Index
++) {
1479 if (Bus
->Devices
[Index
] != NULL
) {
1480 Status
= UsbRemoveDevice (Bus
->Devices
[Index
]);
1481 if (EFI_ERROR (Status
)) {
1482 ReturnStatus
= Status
;
1487 gBS
->RestoreTPL (OldTpl
);
1489 if (!EFI_ERROR (ReturnStatus
)) {
1490 mUsbRootHubApi
.Release (RootIf
);
1491 gBS
->FreePool (RootIf
);
1492 gBS
->FreePool (RootHub
);
1494 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1495 ASSERT (!EFI_ERROR (Status
));
1498 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1500 gBS
->UninstallProtocolInterface (Controller
, &gEfiCallerIdGuid
, &Bus
->BusId
);
1502 if (Bus
->Usb2Hc
!= NULL
) {
1503 Status
= gBS
->CloseProtocol (
1505 &gEfiUsb2HcProtocolGuid
,
1506 This
->DriverBindingHandle
,
1511 if (Bus
->UsbHc
!= NULL
) {
1512 Status
= gBS
->CloseProtocol (
1514 &gEfiUsbHcProtocolGuid
,
1515 This
->DriverBindingHandle
,
1520 if (!EFI_ERROR (Status
)) {
1521 gBS
->CloseProtocol (
1523 &gEfiDevicePathProtocolGuid
,
1524 This
->DriverBindingHandle
,
1528 gBS
->FreePool (Bus
);