3 Usb Bus Driver Binding and Bus IO Protocol.
5 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 EFI_USB_IO_PROTOCOL mUsbIoProtocol
= {
15 UsbIoAsyncInterruptTransfer
,
16 UsbIoSyncInterruptTransfer
,
17 UsbIoIsochronousTransfer
,
18 UsbIoAsyncIsochronousTransfer
,
19 UsbIoGetDeviceDescriptor
,
20 UsbIoGetActiveConfigDescriptor
,
21 UsbIoGetInterfaceDescriptor
,
22 UsbIoGetEndpointDescriptor
,
23 UsbIoGetStringDescriptor
,
24 UsbIoGetSupportedLanguages
,
28 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding
= {
29 UsbBusControllerDriverSupported
,
30 UsbBusControllerDriverStart
,
31 UsbBusControllerDriverStop
,
38 USB_IO function to execute a control transfer. This
39 function will execute the USB transfer. If transfer
40 successes, it will sync the internal state of USB bus
43 @param This The USB_IO instance
44 @param Request The control transfer request
45 @param Direction Direction for data stage
46 @param Timeout The time to wait before timeout
47 @param Data The buffer holding the data
48 @param DataLength Then length of the data
49 @param UsbStatus USB result
51 @retval EFI_INVALID_PARAMETER The parameters are invalid
52 @retval EFI_SUCCESS The control transfer succeeded.
53 @retval Others Failed to execute the transfer
58 UsbIoControlTransfer (
59 IN EFI_USB_IO_PROTOCOL
*This
,
60 IN EFI_USB_DEVICE_REQUEST
*Request
,
61 IN EFI_USB_DATA_DIRECTION Direction
,
63 IN OUT VOID
*Data OPTIONAL
,
64 IN UINTN DataLength OPTIONAL
,
70 USB_ENDPOINT_DESC
*EpDesc
;
73 UINTN RequestedDataLength
;
75 if (UsbStatus
== NULL
) {
76 return EFI_INVALID_PARAMETER
;
79 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
81 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
84 RequestedDataLength
= DataLength
;
85 Status
= UsbHcControlTransfer (
99 // If the request completed successfully and the Direction of the request is
100 // EfiUsbDataIn or EfiUsbDataOut, then make sure the actual number of bytes
101 // transferred is the same as the number of bytes requested. If a different
102 // number of bytes were transferred, then return EFI_DEVICE_ERROR.
104 if (!EFI_ERROR (Status
)) {
105 if ((Direction
!= EfiUsbNoData
) && (DataLength
!= RequestedDataLength
)) {
106 Status
= EFI_DEVICE_ERROR
;
111 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
113 // Clear TT buffer when CTRL/BULK split transaction failes
114 // Clear the TRANSLATOR TT buffer, not parent's buffer
116 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
117 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
118 UsbHubCtrlClearTTBuffer (
119 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
120 Dev
->Translator
.TranslatorPortNumber
,
131 // Some control transfer will change the device's internal
132 // status, such as Set_Configuration and Set_Interface.
133 // We must synchronize the bus driver's status with that in
134 // device. We ignore the Set_Descriptor request because it's
135 // hardly used by any device, especially in pre-boot environment
139 // Reset the endpoint toggle when endpoint stall is cleared
141 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
142 (Request
->RequestType
== USB_REQUEST_TYPE (
144 USB_REQ_TYPE_STANDARD
,
147 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
))
149 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
)Request
->Index
);
151 if (EpDesc
!= NULL
) {
157 // Select a new configuration. This is a dangerous action. Upper driver
158 // should stop use its current UsbIo after calling this driver. The old
159 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
160 // ReinstallProtocol since interfaces in different configuration may be
161 // completely irrelevant.
163 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
164 (Request
->RequestType
== USB_REQUEST_TYPE (
166 USB_REQ_TYPE_STANDARD
,
171 // Don't re-create the USB interfaces if configuration isn't changed.
173 if ((Dev
->ActiveConfig
!= NULL
) &&
174 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
))
179 DEBUG ((DEBUG_INFO
, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
181 if (Dev
->ActiveConfig
!= NULL
) {
182 UsbRemoveConfig (Dev
);
185 if (Request
->Value
!= 0) {
186 Status
= UsbSelectConfig (Dev
, (UINT8
)Request
->Value
);
190 // Exit now, Old USB_IO is invalid now
196 // A new alternative setting is selected for the interface.
197 // No need to reinstall UsbIo in this case because only
198 // underlying communication endpoints are changed. Functionality
199 // should remains the same.
201 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
202 (Request
->RequestType
== USB_REQUEST_TYPE (
204 USB_REQ_TYPE_STANDARD
,
207 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
))
209 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
)Request
->Value
);
211 if (!EFI_ERROR (Status
)) {
212 ASSERT (UsbIf
->IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
213 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
218 gBS
->RestoreTPL (OldTpl
);
223 Execute a bulk transfer to the device endpoint.
225 @param This The USB IO instance.
226 @param Endpoint The device endpoint.
227 @param Data The data to transfer.
228 @param DataLength The length of the data to transfer.
229 @param Timeout Time to wait before timeout.
230 @param UsbStatus The result of USB transfer.
232 @retval EFI_SUCCESS The bulk transfer is OK.
233 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
234 @retval Others Failed to execute transfer, reason returned in
241 IN EFI_USB_IO_PROTOCOL
*This
,
244 IN OUT UINTN
*DataLength
,
246 OUT UINT32
*UsbStatus
250 USB_INTERFACE
*UsbIf
;
251 USB_ENDPOINT_DESC
*EpDesc
;
257 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15) ||
260 return EFI_INVALID_PARAMETER
;
263 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
265 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
268 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
270 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
271 Status
= EFI_INVALID_PARAMETER
;
276 Toggle
= EpDesc
->Toggle
;
277 Status
= UsbHcBulkTransfer (
282 EpDesc
->Desc
.MaxPacketSize
,
292 EpDesc
->Toggle
= Toggle
;
294 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
296 // Clear TT buffer when CTRL/BULK split transaction failes.
297 // Clear the TRANSLATOR TT buffer, not parent's buffer
299 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
300 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
301 UsbHubCtrlClearTTBuffer (
302 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
303 Dev
->Translator
.TranslatorPortNumber
,
312 gBS
->RestoreTPL (OldTpl
);
317 Execute a synchronous interrupt transfer.
319 @param This The USB IO instance.
320 @param Endpoint The device endpoint.
321 @param Data The data to transfer.
322 @param DataLength The length of the data to transfer.
323 @param Timeout Time to wait before timeout.
324 @param UsbStatus The result of USB transfer.
326 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
327 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
328 @retval Others Failed to execute transfer, reason returned in
334 UsbIoSyncInterruptTransfer (
335 IN EFI_USB_IO_PROTOCOL
*This
,
338 IN OUT UINTN
*DataLength
,
340 OUT UINT32
*UsbStatus
344 USB_INTERFACE
*UsbIf
;
345 USB_ENDPOINT_DESC
*EpDesc
;
350 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15) ||
353 return EFI_INVALID_PARAMETER
;
356 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
358 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
361 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
363 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
364 Status
= EFI_INVALID_PARAMETER
;
368 Toggle
= EpDesc
->Toggle
;
369 Status
= UsbHcSyncInterruptTransfer (
374 EpDesc
->Desc
.MaxPacketSize
,
383 EpDesc
->Toggle
= Toggle
;
386 gBS
->RestoreTPL (OldTpl
);
391 Queue a new asynchronous interrupt transfer, or remove the old
392 request if (IsNewTransfer == FALSE).
394 @param This The USB_IO instance.
395 @param Endpoint The device endpoint.
396 @param IsNewTransfer Whether this is a new request, if it's old, remove
398 @param PollInterval The interval to poll the transfer result, (in ms).
399 @param DataLength The length of perodic data transfer.
400 @param Callback The function to call periodically when transfer is
402 @param Context The context to the callback.
404 @retval EFI_SUCCESS New transfer is queued or old request is removed.
405 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
406 @retval Others Failed to queue the new request or remove the old
412 UsbIoAsyncInterruptTransfer (
413 IN EFI_USB_IO_PROTOCOL
*This
,
415 IN BOOLEAN IsNewTransfer
,
416 IN UINTN PollInterval OPTIONAL
,
417 IN UINTN DataLength OPTIONAL
,
418 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback OPTIONAL
,
419 IN VOID
*Context OPTIONAL
423 USB_INTERFACE
*UsbIf
;
424 USB_ENDPOINT_DESC
*EpDesc
;
429 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
430 return EFI_INVALID_PARAMETER
;
433 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
434 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
437 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
439 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
440 Status
= EFI_INVALID_PARAMETER
;
444 Toggle
= EpDesc
->Toggle
;
445 Status
= UsbHcAsyncInterruptTransfer (
450 EpDesc
->Desc
.MaxPacketSize
,
460 EpDesc
->Toggle
= Toggle
;
463 gBS
->RestoreTPL (OldTpl
);
468 Execute a synchronous isochronous transfer.
470 @param This The USB IO instance.
471 @param DeviceEndpoint The device endpoint.
472 @param Data The data to transfer.
473 @param DataLength The length of the data to transfer.
474 @param UsbStatus The result of USB transfer.
476 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
481 UsbIoIsochronousTransfer (
482 IN EFI_USB_IO_PROTOCOL
*This
,
483 IN UINT8 DeviceEndpoint
,
489 return EFI_UNSUPPORTED
;
493 Queue an asynchronous isochronous transfer.
495 @param This The USB_IO instance.
496 @param DeviceEndpoint The device endpoint.
497 @param Data The data to transfer.
498 @param DataLength The length of perodic data transfer.
499 @param IsochronousCallBack The function to call periodically when transfer is
501 @param Context The context to the callback.
503 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
508 UsbIoAsyncIsochronousTransfer (
509 IN EFI_USB_IO_PROTOCOL
*This
,
510 IN UINT8 DeviceEndpoint
,
513 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
514 IN VOID
*Context OPTIONAL
517 return EFI_UNSUPPORTED
;
521 Retrieve the device descriptor of the device.
523 @param This The USB IO instance.
524 @param Descriptor The variable to receive the device descriptor.
526 @retval EFI_SUCCESS The device descriptor is returned.
527 @retval EFI_INVALID_PARAMETER The parameter is invalid.
532 UsbIoGetDeviceDescriptor (
533 IN EFI_USB_IO_PROTOCOL
*This
,
534 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
538 USB_INTERFACE
*UsbIf
;
541 if (Descriptor
== NULL
) {
542 return EFI_INVALID_PARAMETER
;
545 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
547 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
550 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
552 gBS
->RestoreTPL (OldTpl
);
557 Return the configuration descriptor of the current active configuration.
559 @param This The USB IO instance.
560 @param Descriptor The USB configuration descriptor.
562 @retval EFI_SUCCESS The active configuration descriptor is returned.
563 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
564 @retval EFI_NOT_FOUND Currently no active configuration is selected.
569 UsbIoGetActiveConfigDescriptor (
570 IN EFI_USB_IO_PROTOCOL
*This
,
571 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
575 USB_INTERFACE
*UsbIf
;
579 if (Descriptor
== NULL
) {
580 return EFI_INVALID_PARAMETER
;
583 Status
= EFI_SUCCESS
;
584 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
586 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
589 if (Dev
->ActiveConfig
== NULL
) {
590 Status
= EFI_NOT_FOUND
;
594 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
597 gBS
->RestoreTPL (OldTpl
);
602 Retrieve the active interface setting descriptor for this USB IO instance.
604 @param This The USB IO instance.
605 @param Descriptor The variable to receive active interface setting.
607 @retval EFI_SUCCESS The active interface setting is returned.
608 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
613 UsbIoGetInterfaceDescriptor (
614 IN EFI_USB_IO_PROTOCOL
*This
,
615 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
618 USB_INTERFACE
*UsbIf
;
621 if (Descriptor
== NULL
) {
622 return EFI_INVALID_PARAMETER
;
625 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
627 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
628 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
630 gBS
->RestoreTPL (OldTpl
);
635 Retrieve the endpoint descriptor from this interface setting.
637 @param This The USB IO instance.
638 @param Index The index (start from zero) of the endpoint to
640 @param Descriptor The variable to receive the descriptor.
642 @retval EFI_SUCCESS The endpoint descriptor is returned.
643 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
648 UsbIoGetEndpointDescriptor (
649 IN EFI_USB_IO_PROTOCOL
*This
,
651 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
654 USB_INTERFACE
*UsbIf
;
657 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
659 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
661 if ((Descriptor
== NULL
) || (Index
> 15)) {
662 gBS
->RestoreTPL (OldTpl
);
663 return EFI_INVALID_PARAMETER
;
666 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
667 gBS
->RestoreTPL (OldTpl
);
668 return EFI_NOT_FOUND
;
673 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
674 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
677 gBS
->RestoreTPL (OldTpl
);
682 Retrieve the supported language ID table from the device.
684 @param This The USB IO instance.
685 @param LangIDTable The table to return the language IDs.
686 @param TableSize The size, in bytes, of the table LangIDTable.
688 @retval EFI_SUCCESS The language ID is return.
693 UsbIoGetSupportedLanguages (
694 IN EFI_USB_IO_PROTOCOL
*This
,
695 OUT UINT16
**LangIDTable
,
696 OUT UINT16
*TableSize
700 USB_INTERFACE
*UsbIf
;
703 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
705 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
708 *LangIDTable
= Dev
->LangId
;
709 *TableSize
= (UINT16
)(Dev
->TotalLangId
* sizeof (UINT16
));
711 gBS
->RestoreTPL (OldTpl
);
716 Retrieve an indexed string in the language of LangID.
718 @param This The USB IO instance.
719 @param LangID The language ID of the string to retrieve.
720 @param StringIndex The index of the string.
721 @param String The variable to receive the string.
723 @retval EFI_SUCCESS The string is returned.
724 @retval EFI_NOT_FOUND No such string existed.
729 UsbIoGetStringDescriptor (
730 IN EFI_USB_IO_PROTOCOL
*This
,
732 IN UINT8 StringIndex
,
737 USB_INTERFACE
*UsbIf
;
738 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
744 if ((StringIndex
== 0) || (LangID
== 0)) {
745 return EFI_NOT_FOUND
;
748 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
750 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
754 // Check whether language ID is supported
756 Status
= EFI_NOT_FOUND
;
758 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
759 ASSERT (Index
< USB_MAX_LANG_ID
);
760 if (Dev
->LangId
[Index
] == LangID
) {
765 if (Index
== Dev
->TotalLangId
) {
770 // Retrieve the string descriptor then allocate a buffer
771 // to hold the string itself.
773 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
775 if (StrDesc
== NULL
) {
779 if (StrDesc
->Length
<= 2) {
783 Buf
= AllocateZeroPool (StrDesc
->Length
);
786 Status
= EFI_OUT_OF_RESOURCES
;
790 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
791 *String
= (CHAR16
*)Buf
;
792 Status
= EFI_SUCCESS
;
795 gBS
->FreePool (StrDesc
);
798 gBS
->RestoreTPL (OldTpl
);
803 Reset the device, then if that succeeds, reconfigure the
804 device with its address and current active configuration.
806 @param This The USB IO instance.
808 @retval EFI_SUCCESS The device is reset and configured.
809 @retval Others Failed to reset the device.
815 IN EFI_USB_IO_PROTOCOL
*This
818 USB_INTERFACE
*UsbIf
;
819 USB_INTERFACE
*HubIf
;
825 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
827 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
831 Status
= EFI_INVALID_PARAMETER
;
835 HubIf
= Dev
->ParentIf
;
836 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
838 if (EFI_ERROR (Status
)) {
841 "UsbIoPortReset: failed to reset hub port %d@hub %d - %r\n",
850 HubIf
->HubApi
->ClearPortChange (HubIf
, Dev
->ParentPort
);
853 // Reset the device to its current address. The device now has an address
854 // of ZERO after port reset, so need to set Dev->Address to the device again for
855 // host to communicate with it.
857 DevAddress
= Dev
->Address
;
859 Status
= UsbSetAddress (Dev
, DevAddress
);
860 Dev
->Address
= DevAddress
;
862 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
864 if (EFI_ERROR (Status
)) {
866 // It may fail due to device disconnection or other reasons.
870 "UsbIoPortReset: failed to set address for device %d - %r\n",
878 DEBUG ((DEBUG_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev
->Address
));
881 // Reset the current active configure, after this device
882 // is in CONFIGURED state.
884 if (Dev
->ActiveConfig
!= NULL
) {
885 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
887 if (EFI_ERROR (Status
)) {
890 "UsbIoPortReset: failed to set configure for device %d - %r\n",
898 gBS
->RestoreTPL (OldTpl
);
903 Install Usb Bus Protocol on host controller, and start the Usb bus.
905 @param This The USB bus driver binding instance.
906 @param Controller The controller to check.
907 @param RemainingDevicePath The remaining device patch.
909 @retval EFI_SUCCESS The controller is controlled by the usb bus.
910 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
911 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
916 UsbBusBuildProtocol (
917 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
918 IN EFI_HANDLE Controller
,
919 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
924 USB_INTERFACE
*RootIf
;
928 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
930 if (UsbBus
== NULL
) {
931 return EFI_OUT_OF_RESOURCES
;
934 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
935 UsbBus
->HostHandle
= Controller
;
936 UsbBus
->MaxDevices
= USB_MAX_DEVICES
;
938 Status
= gBS
->OpenProtocol (
940 &gEfiDevicePathProtocolGuid
,
941 (VOID
**)&UsbBus
->DevicePath
,
942 This
->DriverBindingHandle
,
944 EFI_OPEN_PROTOCOL_BY_DRIVER
947 if (EFI_ERROR (Status
)) {
948 DEBUG ((DEBUG_ERROR
, "UsbBusStart: Failed to open device path - %r\n", Status
));
955 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
956 // This is for backward compatibility with EFI 1.x. In UEFI
957 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
958 // and USB_HC because EHCI driver will install both protocols
959 // (for the same reason). If we don't consume both of them,
960 // the unconsumed one may be opened by others.
962 Status
= gBS
->OpenProtocol (
964 &gEfiUsb2HcProtocolGuid
,
965 (VOID
**)&(UsbBus
->Usb2Hc
),
966 This
->DriverBindingHandle
,
968 EFI_OPEN_PROTOCOL_BY_DRIVER
971 Status2
= gBS
->OpenProtocol (
973 &gEfiUsbHcProtocolGuid
,
974 (VOID
**)&(UsbBus
->UsbHc
),
975 This
->DriverBindingHandle
,
977 EFI_OPEN_PROTOCOL_BY_DRIVER
980 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
981 DEBUG ((DEBUG_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC - %r\n", Status
));
983 Status
= EFI_DEVICE_ERROR
;
987 if (!EFI_ERROR (Status
)) {
989 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
990 // Then its max supported devices are 256. Otherwise it's 128.
992 ASSERT (UsbBus
->Usb2Hc
!= NULL
);
993 if (UsbBus
->Usb2Hc
->MajorRevision
== 0x3) {
994 UsbBus
->MaxDevices
= 256;
999 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
1001 Status
= gBS
->InstallProtocolInterface (
1004 EFI_NATIVE_INTERFACE
,
1008 if (EFI_ERROR (Status
)) {
1009 DEBUG ((DEBUG_ERROR
, "UsbBusStart: Failed to install bus protocol - %r\n", Status
));
1014 // Initial the wanted child device path list, and add first RemainingDevicePath
1016 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
1017 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
1018 ASSERT (!EFI_ERROR (Status
));
1020 // Create a fake usb device for root hub
1022 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
1024 if (RootHub
== NULL
) {
1025 Status
= EFI_OUT_OF_RESOURCES
;
1026 goto UNINSTALL_USBBUS
;
1029 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1031 if (RootIf
== NULL
) {
1033 Status
= EFI_OUT_OF_RESOURCES
;
1037 RootHub
->Bus
= UsbBus
;
1038 RootHub
->NumOfInterface
= 1;
1039 RootHub
->Interfaces
[0] = RootIf
;
1041 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1042 RootIf
->Device
= RootHub
;
1043 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1046 // Report Status Code here since we will enumerate the USB devices
1048 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1050 (EFI_IO_BUS_USB
| EFI_IOB_PC_DETECT
),
1054 Status
= mUsbRootHubApi
.Init (RootIf
);
1056 if (EFI_ERROR (Status
)) {
1057 DEBUG ((DEBUG_ERROR
, "UsbBusStart: Failed to init root hub - %r\n", Status
));
1061 UsbBus
->Devices
[0] = RootHub
;
1063 DEBUG ((DEBUG_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1067 if (RootIf
!= NULL
) {
1071 if (RootHub
!= NULL
) {
1076 gBS
->UninstallProtocolInterface (Controller
, &gEfiCallerIdGuid
, &UsbBus
->BusId
);
1079 if (UsbBus
->Usb2Hc
!= NULL
) {
1080 gBS
->CloseProtocol (
1082 &gEfiUsb2HcProtocolGuid
,
1083 This
->DriverBindingHandle
,
1088 if (UsbBus
->UsbHc
!= NULL
) {
1089 gBS
->CloseProtocol (
1091 &gEfiUsbHcProtocolGuid
,
1092 This
->DriverBindingHandle
,
1097 gBS
->CloseProtocol (
1099 &gEfiDevicePathProtocolGuid
,
1100 This
->DriverBindingHandle
,
1105 DEBUG ((DEBUG_ERROR
, "UsbBusStart: Failed to start bus driver - %r\n", Status
));
1110 The USB bus driver entry pointer.
1112 @param ImageHandle The driver image handle.
1113 @param SystemTable The system table.
1115 @return EFI_SUCCESS The component name protocol is installed.
1116 @return Others Failed to init the usb driver.
1121 UsbBusDriverEntryPoint (
1122 IN EFI_HANDLE ImageHandle
,
1123 IN EFI_SYSTEM_TABLE
*SystemTable
1126 return EfiLibInstallDriverBindingComponentName2 (
1129 &mUsbBusDriverBinding
,
1131 &mUsbBusComponentName
,
1132 &mUsbBusComponentName2
1137 Check whether USB bus driver support this device.
1139 @param This The USB bus driver binding protocol.
1140 @param Controller The controller handle to check.
1141 @param RemainingDevicePath The remaining device path.
1143 @retval EFI_SUCCESS The bus supports this controller.
1144 @retval EFI_UNSUPPORTED This device isn't supported.
1149 UsbBusControllerDriverSupported (
1150 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1151 IN EFI_HANDLE Controller
,
1152 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1155 EFI_DEV_PATH_PTR DevicePathNode
;
1156 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1157 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1158 EFI_USB_HC_PROTOCOL
*UsbHc
;
1162 // Check whether device path is valid
1164 if (RemainingDevicePath
!= NULL
) {
1166 // Check if RemainingDevicePath is the End of Device Path Node,
1167 // if yes, go on checking other conditions
1169 if (!IsDevicePathEnd (RemainingDevicePath
)) {
1171 // If RemainingDevicePath isn't the End of Device Path Node,
1172 // check its validation
1174 DevicePathNode
.DevPath
= RemainingDevicePath
;
1176 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1177 ( (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
) &&
1178 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
)
1179 && (DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
)
1182 return EFI_UNSUPPORTED
;
1188 // Check whether USB_HC2 protocol is installed
1190 Status
= gBS
->OpenProtocol (
1192 &gEfiUsb2HcProtocolGuid
,
1194 This
->DriverBindingHandle
,
1196 EFI_OPEN_PROTOCOL_BY_DRIVER
1198 if (Status
== EFI_ALREADY_STARTED
) {
1202 if (EFI_ERROR (Status
)) {
1204 // If failed to open USB_HC2, fall back to USB_HC
1206 Status
= gBS
->OpenProtocol (
1208 &gEfiUsbHcProtocolGuid
,
1210 This
->DriverBindingHandle
,
1212 EFI_OPEN_PROTOCOL_BY_DRIVER
1214 if (Status
== EFI_ALREADY_STARTED
) {
1218 if (EFI_ERROR (Status
)) {
1223 // Close the USB_HC used to perform the supported test
1225 gBS
->CloseProtocol (
1227 &gEfiUsbHcProtocolGuid
,
1228 This
->DriverBindingHandle
,
1233 // Close the USB_HC2 used to perform the supported test
1235 gBS
->CloseProtocol (
1237 &gEfiUsb2HcProtocolGuid
,
1238 This
->DriverBindingHandle
,
1244 // Open the EFI Device Path protocol needed to perform the supported test
1246 Status
= gBS
->OpenProtocol (
1248 &gEfiDevicePathProtocolGuid
,
1249 (VOID
**)&ParentDevicePath
,
1250 This
->DriverBindingHandle
,
1252 EFI_OPEN_PROTOCOL_BY_DRIVER
1254 if (Status
== EFI_ALREADY_STARTED
) {
1258 if (!EFI_ERROR (Status
)) {
1260 // Close protocol, don't use device path protocol in the Support() function
1262 gBS
->CloseProtocol (
1264 &gEfiDevicePathProtocolGuid
,
1265 This
->DriverBindingHandle
,
1276 Start to process the controller.
1278 @param This The USB bus driver binding instance.
1279 @param Controller The controller to check.
1280 @param RemainingDevicePath The remaining device patch.
1282 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1283 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1285 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1290 UsbBusControllerDriverStart (
1291 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1292 IN EFI_HANDLE Controller
,
1293 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1296 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1298 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1300 Status
= gBS
->OpenProtocol (
1302 &gEfiDevicePathProtocolGuid
,
1303 (VOID
**)&ParentDevicePath
,
1304 This
->DriverBindingHandle
,
1306 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1308 ASSERT_EFI_ERROR (Status
);
1311 // Report Status Code here since we will initialize the host controller
1313 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1315 (EFI_IO_BUS_USB
| EFI_IOB_PC_INIT
),
1320 // Locate the USB bus protocol, if it is found, USB bus
1321 // is already started on this controller.
1323 Status
= gBS
->OpenProtocol (
1327 This
->DriverBindingHandle
,
1329 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1332 if (EFI_ERROR (Status
)) {
1334 // If first start, build the bus execute environment and install bus protocol
1336 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_IO_BUS_USB
| EFI_P_PC_ENABLE
));
1337 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1338 if (EFI_ERROR (Status
)) {
1343 // Try get the Usb Bus protocol interface again
1345 Status
= gBS
->OpenProtocol (
1349 This
->DriverBindingHandle
,
1351 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1353 ASSERT (!EFI_ERROR (Status
));
1356 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1357 // usb child device will be recursively connected.
1358 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1359 // All wanted usb child devices will be remembered by the usb bus driver itself.
1360 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1362 // Save the passed in RemainingDevicePath this time
1364 if (RemainingDevicePath
!= NULL
) {
1365 if (IsDevicePathEnd (RemainingDevicePath
)) {
1367 // If RemainingDevicePath is the End of Device Path Node,
1368 // skip enumerate any device and return EFI_SUCCESS
1374 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1375 ASSERT (!EFI_ERROR (Status
));
1377 // Ensure all wanted child usb devices are fully recursively connected
1379 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1380 ASSERT (!EFI_ERROR (Status
));
1387 Stop handle the controller by this USB bus driver.
1389 @param This The USB bus driver binding protocol.
1390 @param Controller The controller to release.
1391 @param NumberOfChildren The child of USB bus that opened controller
1393 @param ChildHandleBuffer The array of child handle.
1395 @retval EFI_SUCCESS The controller or children are stopped.
1396 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1401 UsbBusControllerDriverStop (
1402 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1403 IN EFI_HANDLE Controller
,
1404 IN UINTN NumberOfChildren
,
1405 IN EFI_HANDLE
*ChildHandleBuffer
1409 USB_DEVICE
*RootHub
;
1411 USB_INTERFACE
*RootIf
;
1412 USB_INTERFACE
*UsbIf
;
1413 EFI_USB_BUS_PROTOCOL
*BusId
;
1414 EFI_USB_IO_PROTOCOL
*UsbIo
;
1418 EFI_STATUS ReturnStatus
;
1420 Status
= EFI_SUCCESS
;
1422 if (NumberOfChildren
> 0) {
1424 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1426 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1428 ReturnStatus
= EFI_SUCCESS
;
1429 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1430 Status
= gBS
->OpenProtocol (
1431 ChildHandleBuffer
[Index
],
1432 &gEfiUsbIoProtocolGuid
,
1434 This
->DriverBindingHandle
,
1436 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1439 if (EFI_ERROR (Status
)) {
1441 // It is possible that the child has already been released:
1442 // 1. For combo device, free one device will release others.
1443 // 2. If a hub is released, all devices on its down facing
1444 // ports are released also.
1449 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1450 UsbDev
= UsbIf
->Device
;
1452 ReturnStatus
= UsbRemoveDevice (UsbDev
);
1455 gBS
->RestoreTPL (OldTpl
);
1456 return ReturnStatus
;
1459 DEBUG ((DEBUG_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1462 // Locate USB_BUS for the current host controller
1464 Status
= gBS
->OpenProtocol (
1468 This
->DriverBindingHandle
,
1470 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1473 if (EFI_ERROR (Status
)) {
1477 Bus
= USB_BUS_FROM_THIS (BusId
);
1480 // Stop the root hub, then free all the devices
1482 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1484 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1486 RootHub
= Bus
->Devices
[0];
1487 RootIf
= RootHub
->Interfaces
[0];
1489 ASSERT (Bus
->MaxDevices
<= 256);
1490 ReturnStatus
= EFI_SUCCESS
;
1491 for (Index
= 1; Index
< Bus
->MaxDevices
; Index
++) {
1492 if (Bus
->Devices
[Index
] != NULL
) {
1493 Status
= UsbRemoveDevice (Bus
->Devices
[Index
]);
1494 if (EFI_ERROR (Status
)) {
1495 ReturnStatus
= Status
;
1500 gBS
->RestoreTPL (OldTpl
);
1502 if (!EFI_ERROR (ReturnStatus
)) {
1503 mUsbRootHubApi
.Release (RootIf
);
1504 gBS
->FreePool (RootIf
);
1505 gBS
->FreePool (RootHub
);
1507 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1508 ASSERT (!EFI_ERROR (Status
));
1511 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1513 gBS
->UninstallProtocolInterface (Controller
, &gEfiCallerIdGuid
, &Bus
->BusId
);
1515 if (Bus
->Usb2Hc
!= NULL
) {
1516 Status
= gBS
->CloseProtocol (
1518 &gEfiUsb2HcProtocolGuid
,
1519 This
->DriverBindingHandle
,
1524 if (Bus
->UsbHc
!= NULL
) {
1525 Status
= gBS
->CloseProtocol (
1527 &gEfiUsbHcProtocolGuid
,
1528 This
->DriverBindingHandle
,
1533 if (!EFI_ERROR (Status
)) {
1534 gBS
->CloseProtocol (
1536 &gEfiDevicePathProtocolGuid
,
1537 This
->DriverBindingHandle
,
1541 gBS
->FreePool (Bus
);