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 sucessfully and the Direction of the request is
100 // EfiUsbDataIn or EfiUsbDataOut, then make sure the actual number of bytes
101 // transfered is the same as the number of bytes requested. If a different
102 // number of bytes were transfered, 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 (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
143 USB_TARGET_ENDPOINT
)) &&
144 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
146 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
148 if (EpDesc
!= NULL
) {
154 // Select a new configuration. This is a dangerous action. Upper driver
155 // should stop use its current UsbIo after calling this driver. The old
156 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
157 // ReinstallProtocol since interfaces in different configuration may be
158 // completely irrelevant.
160 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
161 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
162 USB_TARGET_DEVICE
))) {
164 // Don't re-create the USB interfaces if configuration isn't changed.
166 if ((Dev
->ActiveConfig
!= NULL
) &&
167 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
171 DEBUG ((EFI_D_INFO
, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
173 if (Dev
->ActiveConfig
!= NULL
) {
174 UsbRemoveConfig (Dev
);
177 if (Request
->Value
!= 0) {
178 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
182 // Exit now, Old USB_IO is invalid now
188 // A new alternative setting is selected for the interface.
189 // No need to reinstall UsbIo in this case because only
190 // underlying communication endpoints are changed. Functionality
191 // should remains the same.
193 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
194 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
195 USB_TARGET_INTERFACE
)) &&
196 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
198 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
200 if (!EFI_ERROR (Status
)) {
201 ASSERT (UsbIf
->IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
202 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
207 gBS
->RestoreTPL (OldTpl
);
213 Execute a bulk transfer to the device endpoint.
215 @param This The USB IO instance.
216 @param Endpoint The device endpoint.
217 @param Data The data to transfer.
218 @param DataLength The length of the data to transfer.
219 @param Timeout Time to wait before timeout.
220 @param UsbStatus The result of USB transfer.
222 @retval EFI_SUCCESS The bulk transfer is OK.
223 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
224 @retval Others Failed to execute transfer, reason returned in
231 IN EFI_USB_IO_PROTOCOL
*This
,
234 IN OUT UINTN
*DataLength
,
236 OUT UINT32
*UsbStatus
240 USB_INTERFACE
*UsbIf
;
241 USB_ENDPOINT_DESC
*EpDesc
;
247 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
248 (UsbStatus
== NULL
)) {
250 return EFI_INVALID_PARAMETER
;
253 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
255 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
258 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
260 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
261 Status
= EFI_INVALID_PARAMETER
;
266 Toggle
= EpDesc
->Toggle
;
267 Status
= UsbHcBulkTransfer (
272 EpDesc
->Desc
.MaxPacketSize
,
282 EpDesc
->Toggle
= Toggle
;
284 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
286 // Clear TT buffer when CTRL/BULK split transaction failes.
287 // Clear the TRANSLATOR TT buffer, not parent's buffer
289 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
290 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
291 UsbHubCtrlClearTTBuffer (
292 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
293 Dev
->Translator
.TranslatorPortNumber
,
302 gBS
->RestoreTPL (OldTpl
);
308 Execute a synchronous interrupt transfer.
310 @param This The USB IO instance.
311 @param Endpoint The device endpoint.
312 @param Data The data to transfer.
313 @param DataLength The length of the data to transfer.
314 @param Timeout Time to wait before timeout.
315 @param UsbStatus The result of USB transfer.
317 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
318 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
319 @retval Others Failed to execute transfer, reason returned in
325 UsbIoSyncInterruptTransfer (
326 IN EFI_USB_IO_PROTOCOL
*This
,
329 IN OUT UINTN
*DataLength
,
331 OUT UINT32
*UsbStatus
335 USB_INTERFACE
*UsbIf
;
336 USB_ENDPOINT_DESC
*EpDesc
;
341 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
342 (UsbStatus
== NULL
)) {
344 return EFI_INVALID_PARAMETER
;
347 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
349 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
352 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
354 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
355 Status
= EFI_INVALID_PARAMETER
;
359 Toggle
= EpDesc
->Toggle
;
360 Status
= UsbHcSyncInterruptTransfer (
365 EpDesc
->Desc
.MaxPacketSize
,
374 EpDesc
->Toggle
= Toggle
;
377 gBS
->RestoreTPL (OldTpl
);
383 Queue a new asynchronous interrupt transfer, or remove the old
384 request if (IsNewTransfer == FALSE).
386 @param This The USB_IO instance.
387 @param Endpoint The device endpoint.
388 @param IsNewTransfer Whether this is a new request, if it's old, remove
390 @param PollInterval The interval to poll the transfer result, (in ms).
391 @param DataLength The length of perodic data transfer.
392 @param Callback The function to call periodicaly when transfer is
394 @param Context The context to the callback.
396 @retval EFI_SUCCESS New transfer is queued or old request is removed.
397 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
398 @retval Others Failed to queue the new request or remove the old
404 UsbIoAsyncInterruptTransfer (
405 IN EFI_USB_IO_PROTOCOL
*This
,
407 IN BOOLEAN IsNewTransfer
,
408 IN UINTN PollInterval
, OPTIONAL
409 IN UINTN DataLength
, OPTIONAL
410 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
411 IN VOID
*Context OPTIONAL
415 USB_INTERFACE
*UsbIf
;
416 USB_ENDPOINT_DESC
*EpDesc
;
421 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
422 return EFI_INVALID_PARAMETER
;
425 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
426 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
429 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
431 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
432 Status
= EFI_INVALID_PARAMETER
;
436 Toggle
= EpDesc
->Toggle
;
437 Status
= UsbHcAsyncInterruptTransfer (
442 EpDesc
->Desc
.MaxPacketSize
,
452 EpDesc
->Toggle
= Toggle
;
455 gBS
->RestoreTPL (OldTpl
);
461 Execute a synchronous isochronous transfer.
463 @param This The USB IO instance.
464 @param DeviceEndpoint The device endpoint.
465 @param Data The data to transfer.
466 @param DataLength The length of the data to transfer.
467 @param UsbStatus The result of USB transfer.
469 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
474 UsbIoIsochronousTransfer (
475 IN EFI_USB_IO_PROTOCOL
*This
,
476 IN UINT8 DeviceEndpoint
,
482 return EFI_UNSUPPORTED
;
487 Queue an asynchronous isochronous transfer.
489 @param This The USB_IO instance.
490 @param DeviceEndpoint The device endpoint.
491 @param Data The data to transfer.
492 @param DataLength The length of perodic data transfer.
493 @param IsochronousCallBack The function to call periodicaly when transfer is
495 @param Context The context to the callback.
497 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
502 UsbIoAsyncIsochronousTransfer (
503 IN EFI_USB_IO_PROTOCOL
*This
,
504 IN UINT8 DeviceEndpoint
,
507 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
508 IN VOID
*Context OPTIONAL
511 return EFI_UNSUPPORTED
;
516 Retrieve the device descriptor of the device.
518 @param This The USB IO instance.
519 @param Descriptor The variable to receive the device descriptor.
521 @retval EFI_SUCCESS The device descriptor is returned.
522 @retval EFI_INVALID_PARAMETER The parameter is invalid.
527 UsbIoGetDeviceDescriptor (
528 IN EFI_USB_IO_PROTOCOL
*This
,
529 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
533 USB_INTERFACE
*UsbIf
;
536 if (Descriptor
== NULL
) {
537 return EFI_INVALID_PARAMETER
;
540 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
542 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
545 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
547 gBS
->RestoreTPL (OldTpl
);
553 Return the configuration descriptor of the current active configuration.
555 @param This The USB IO instance.
556 @param Descriptor The USB configuration descriptor.
558 @retval EFI_SUCCESS The active configuration descriptor is returned.
559 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
560 @retval EFI_NOT_FOUND Currently no active configuration is selected.
565 UsbIoGetActiveConfigDescriptor (
566 IN EFI_USB_IO_PROTOCOL
*This
,
567 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
571 USB_INTERFACE
*UsbIf
;
575 if (Descriptor
== NULL
) {
576 return EFI_INVALID_PARAMETER
;
579 Status
= EFI_SUCCESS
;
580 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
582 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
585 if (Dev
->ActiveConfig
== NULL
) {
586 Status
= EFI_NOT_FOUND
;
590 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
593 gBS
->RestoreTPL (OldTpl
);
599 Retrieve the active interface setting descriptor for this USB IO instance.
601 @param This The USB IO instance.
602 @param Descriptor The variable to receive active interface setting.
604 @retval EFI_SUCCESS The active interface setting is returned.
605 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
610 UsbIoGetInterfaceDescriptor (
611 IN EFI_USB_IO_PROTOCOL
*This
,
612 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
615 USB_INTERFACE
*UsbIf
;
618 if (Descriptor
== NULL
) {
619 return EFI_INVALID_PARAMETER
;
622 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
624 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
625 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
627 gBS
->RestoreTPL (OldTpl
);
633 Retrieve the endpoint descriptor from this interface setting.
635 @param This The USB IO instance.
636 @param Index The index (start from zero) of the endpoint to
638 @param Descriptor The variable to receive the descriptor.
640 @retval EFI_SUCCESS The endpoint descriptor is returned.
641 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
646 UsbIoGetEndpointDescriptor (
647 IN EFI_USB_IO_PROTOCOL
*This
,
649 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
652 USB_INTERFACE
*UsbIf
;
655 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
657 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
659 if ((Descriptor
== NULL
) || (Index
> 15)) {
660 gBS
->RestoreTPL (OldTpl
);
661 return EFI_INVALID_PARAMETER
;
664 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
665 gBS
->RestoreTPL (OldTpl
);
666 return EFI_NOT_FOUND
;
671 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
672 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
675 gBS
->RestoreTPL (OldTpl
);
681 Retrieve the supported language ID table from the device.
683 @param This The USB IO instance.
684 @param LangIDTable The table to return the language IDs.
685 @param TableSize The size, in bytes, of the table LangIDTable.
687 @retval EFI_SUCCESS The language ID is return.
692 UsbIoGetSupportedLanguages (
693 IN EFI_USB_IO_PROTOCOL
*This
,
694 OUT UINT16
**LangIDTable
,
695 OUT UINT16
*TableSize
699 USB_INTERFACE
*UsbIf
;
702 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
704 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
707 *LangIDTable
= Dev
->LangId
;
708 *TableSize
= (UINT16
) (Dev
->TotalLangId
* sizeof (UINT16
));
710 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
);
804 Reset the device, then if that succeeds, reconfigure the
805 device with its address and current active configuration.
807 @param This The USB IO instance.
809 @retval EFI_SUCCESS The device is reset and configured.
810 @retval Others Failed to reset the device.
816 IN EFI_USB_IO_PROTOCOL
*This
819 USB_INTERFACE
*UsbIf
;
820 USB_INTERFACE
*HubIf
;
826 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
828 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
832 Status
= EFI_INVALID_PARAMETER
;
836 HubIf
= Dev
->ParentIf
;
837 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
839 if (EFI_ERROR (Status
)) {
840 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
841 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
846 HubIf
->HubApi
->ClearPortChange (HubIf
, Dev
->ParentPort
);
849 // Reset the device to its current address. The device now has an address
850 // of ZERO after port reset, so need to set Dev->Address to the device again for
851 // host to communicate with it.
853 DevAddress
= Dev
->Address
;
855 Status
= UsbSetAddress (Dev
, DevAddress
);
856 Dev
->Address
= DevAddress
;
858 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
860 if (EFI_ERROR (Status
)) {
862 // It may fail due to device disconnection or other reasons.
864 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set address for device %d - %r\n",
865 Dev
->Address
, Status
));
870 DEBUG (( EFI_D_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev
->Address
));
873 // Reset the current active configure, after this device
874 // is in CONFIGURED state.
876 if (Dev
->ActiveConfig
!= NULL
) {
877 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
879 if (EFI_ERROR (Status
)) {
880 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set configure for device %d - %r\n",
881 Dev
->Address
, Status
));
886 gBS
->RestoreTPL (OldTpl
);
892 Install Usb Bus Protocol on host controller, and start the Usb bus.
894 @param This The USB bus driver binding instance.
895 @param Controller The controller to check.
896 @param RemainingDevicePath The remaining device patch.
898 @retval EFI_SUCCESS The controller is controlled by the usb bus.
899 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
900 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
905 UsbBusBuildProtocol (
906 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
907 IN EFI_HANDLE Controller
,
908 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
913 USB_INTERFACE
*RootIf
;
917 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
919 if (UsbBus
== NULL
) {
920 return EFI_OUT_OF_RESOURCES
;
923 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
924 UsbBus
->HostHandle
= Controller
;
925 UsbBus
->MaxDevices
= USB_MAX_DEVICES
;
927 Status
= gBS
->OpenProtocol (
929 &gEfiDevicePathProtocolGuid
,
930 (VOID
**) &UsbBus
->DevicePath
,
931 This
->DriverBindingHandle
,
933 EFI_OPEN_PROTOCOL_BY_DRIVER
936 if (EFI_ERROR (Status
)) {
937 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open device path %r\n", Status
));
944 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
945 // This is for backward compatibility with EFI 1.x. In UEFI
946 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
947 // and USB_HC because EHCI driver will install both protocols
948 // (for the same reason). If we don't consume both of them,
949 // the unconsumed one may be opened by others.
951 Status
= gBS
->OpenProtocol (
953 &gEfiUsb2HcProtocolGuid
,
954 (VOID
**) &(UsbBus
->Usb2Hc
),
955 This
->DriverBindingHandle
,
957 EFI_OPEN_PROTOCOL_BY_DRIVER
960 Status2
= gBS
->OpenProtocol (
962 &gEfiUsbHcProtocolGuid
,
963 (VOID
**) &(UsbBus
->UsbHc
),
964 This
->DriverBindingHandle
,
966 EFI_OPEN_PROTOCOL_BY_DRIVER
969 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
970 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
972 Status
= EFI_DEVICE_ERROR
;
976 if (!EFI_ERROR (Status
)) {
978 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
979 // Then its max supported devices are 256. Otherwise it's 128.
981 ASSERT (UsbBus
->Usb2Hc
!= NULL
);
982 if (UsbBus
->Usb2Hc
->MajorRevision
== 0x3) {
983 UsbBus
->MaxDevices
= 256;
988 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
990 Status
= gBS
->InstallProtocolInterface (
993 EFI_NATIVE_INTERFACE
,
997 if (EFI_ERROR (Status
)) {
998 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to install bus protocol %r\n", Status
));
1003 // Initial the wanted child device path list, and add first RemainingDevicePath
1005 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
1006 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
1007 ASSERT (!EFI_ERROR (Status
));
1009 // Create a fake usb device for root hub
1011 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
1013 if (RootHub
== NULL
) {
1014 Status
= EFI_OUT_OF_RESOURCES
;
1015 goto UNINSTALL_USBBUS
;
1018 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1020 if (RootIf
== NULL
) {
1022 Status
= EFI_OUT_OF_RESOURCES
;
1026 RootHub
->Bus
= UsbBus
;
1027 RootHub
->NumOfInterface
= 1;
1028 RootHub
->Interfaces
[0] = RootIf
;
1030 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1031 RootIf
->Device
= RootHub
;
1032 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1035 // Report Status Code here since we will enumerate the USB devices
1037 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1039 (EFI_IO_BUS_USB
| EFI_IOB_PC_DETECT
),
1043 Status
= mUsbRootHubApi
.Init (RootIf
);
1045 if (EFI_ERROR (Status
)) {
1046 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to init root hub %r\n", Status
));
1050 UsbBus
->Devices
[0] = RootHub
;
1052 DEBUG ((EFI_D_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1056 if (RootIf
!= NULL
) {
1059 if (RootHub
!= NULL
) {
1064 gBS
->UninstallProtocolInterface (Controller
, &gEfiCallerIdGuid
, &UsbBus
->BusId
);
1067 if (UsbBus
->Usb2Hc
!= NULL
) {
1068 gBS
->CloseProtocol (
1070 &gEfiUsb2HcProtocolGuid
,
1071 This
->DriverBindingHandle
,
1075 if (UsbBus
->UsbHc
!= NULL
) {
1076 gBS
->CloseProtocol (
1078 &gEfiUsbHcProtocolGuid
,
1079 This
->DriverBindingHandle
,
1083 gBS
->CloseProtocol (
1085 &gEfiDevicePathProtocolGuid
,
1086 This
->DriverBindingHandle
,
1091 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to start bus driver %r\n", Status
));
1097 The USB bus driver entry pointer.
1099 @param ImageHandle The driver image handle.
1100 @param SystemTable The system table.
1102 @return EFI_SUCCESS The component name protocol is installed.
1103 @return Others Failed to init the usb driver.
1108 UsbBusDriverEntryPoint (
1109 IN EFI_HANDLE ImageHandle
,
1110 IN EFI_SYSTEM_TABLE
*SystemTable
1113 return EfiLibInstallDriverBindingComponentName2 (
1116 &mUsbBusDriverBinding
,
1118 &mUsbBusComponentName
,
1119 &mUsbBusComponentName2
1125 Check whether USB bus driver support this device.
1127 @param This The USB bus driver binding protocol.
1128 @param Controller The controller handle to check.
1129 @param RemainingDevicePath The remaining device path.
1131 @retval EFI_SUCCESS The bus supports this controller.
1132 @retval EFI_UNSUPPORTED This device isn't supported.
1137 UsbBusControllerDriverSupported (
1138 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1139 IN EFI_HANDLE Controller
,
1140 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1143 EFI_DEV_PATH_PTR DevicePathNode
;
1144 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1145 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1146 EFI_USB_HC_PROTOCOL
*UsbHc
;
1150 // Check whether device path is valid
1152 if (RemainingDevicePath
!= NULL
) {
1154 // Check if RemainingDevicePath is the End of Device Path Node,
1155 // if yes, go on checking other conditions
1157 if (!IsDevicePathEnd (RemainingDevicePath
)) {
1159 // If RemainingDevicePath isn't the End of Device Path Node,
1160 // check its validation
1162 DevicePathNode
.DevPath
= RemainingDevicePath
;
1164 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1165 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
&&
1166 DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
1167 && DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
1170 return EFI_UNSUPPORTED
;
1176 // Check whether USB_HC2 protocol is installed
1178 Status
= gBS
->OpenProtocol (
1180 &gEfiUsb2HcProtocolGuid
,
1182 This
->DriverBindingHandle
,
1184 EFI_OPEN_PROTOCOL_BY_DRIVER
1186 if (Status
== EFI_ALREADY_STARTED
) {
1190 if (EFI_ERROR (Status
)) {
1192 // If failed to open USB_HC2, fall back to USB_HC
1194 Status
= gBS
->OpenProtocol (
1196 &gEfiUsbHcProtocolGuid
,
1198 This
->DriverBindingHandle
,
1200 EFI_OPEN_PROTOCOL_BY_DRIVER
1202 if (Status
== EFI_ALREADY_STARTED
) {
1206 if (EFI_ERROR (Status
)) {
1211 // Close the USB_HC used to perform the supported test
1213 gBS
->CloseProtocol (
1215 &gEfiUsbHcProtocolGuid
,
1216 This
->DriverBindingHandle
,
1223 // Close the USB_HC2 used to perform the supported test
1225 gBS
->CloseProtocol (
1227 &gEfiUsb2HcProtocolGuid
,
1228 This
->DriverBindingHandle
,
1234 // Open the EFI Device Path protocol needed to perform the supported test
1236 Status
= gBS
->OpenProtocol (
1238 &gEfiDevicePathProtocolGuid
,
1239 (VOID
**) &ParentDevicePath
,
1240 This
->DriverBindingHandle
,
1242 EFI_OPEN_PROTOCOL_BY_DRIVER
1244 if (Status
== EFI_ALREADY_STARTED
) {
1248 if (!EFI_ERROR (Status
)) {
1250 // Close protocol, don't use device path protocol in the Support() function
1252 gBS
->CloseProtocol (
1254 &gEfiDevicePathProtocolGuid
,
1255 This
->DriverBindingHandle
,
1267 Start to process the controller.
1269 @param This The USB bus driver binding instance.
1270 @param Controller The controller to check.
1271 @param RemainingDevicePath The remaining device patch.
1273 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1274 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1276 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1281 UsbBusControllerDriverStart (
1282 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1283 IN EFI_HANDLE Controller
,
1284 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1287 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1289 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1291 Status
= gBS
->OpenProtocol (
1293 &gEfiDevicePathProtocolGuid
,
1294 (VOID
**) &ParentDevicePath
,
1295 This
->DriverBindingHandle
,
1297 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1299 ASSERT_EFI_ERROR (Status
);
1302 // Report Status Code here since we will initialize the host controller
1304 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1306 (EFI_IO_BUS_USB
| EFI_IOB_PC_INIT
),
1311 // Locate the USB bus protocol, if it is found, USB bus
1312 // is already started on this controller.
1314 Status
= gBS
->OpenProtocol (
1317 (VOID
**) &UsbBusId
,
1318 This
->DriverBindingHandle
,
1320 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1323 if (EFI_ERROR (Status
)) {
1325 // If first start, build the bus execute environment and install bus protocol
1327 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_IO_BUS_USB
| EFI_P_PC_ENABLE
));
1328 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1329 if (EFI_ERROR (Status
)) {
1333 // Try get the Usb Bus protocol interface again
1335 Status
= gBS
->OpenProtocol (
1338 (VOID
**) &UsbBusId
,
1339 This
->DriverBindingHandle
,
1341 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1343 ASSERT (!EFI_ERROR (Status
));
1346 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1347 // usb child device will be recursively connected.
1348 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1349 // All wanted usb child devices will be remembered by the usb bus driver itself.
1350 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1352 // Save the passed in RemainingDevicePath this time
1354 if (RemainingDevicePath
!= NULL
) {
1355 if (IsDevicePathEnd (RemainingDevicePath
)) {
1357 // If RemainingDevicePath is the End of Device Path Node,
1358 // skip enumerate any device and return EFI_SUCESSS
1364 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1365 ASSERT (!EFI_ERROR (Status
));
1367 // Ensure all wanted child usb devices are fully recursively connected
1369 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1370 ASSERT (!EFI_ERROR (Status
));
1379 Stop handle the controller by this USB bus driver.
1381 @param This The USB bus driver binding protocol.
1382 @param Controller The controller to release.
1383 @param NumberOfChildren The child of USB bus that opened controller
1385 @param ChildHandleBuffer The array of child handle.
1387 @retval EFI_SUCCESS The controller or children are stopped.
1388 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1393 UsbBusControllerDriverStop (
1394 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1395 IN EFI_HANDLE Controller
,
1396 IN UINTN NumberOfChildren
,
1397 IN EFI_HANDLE
*ChildHandleBuffer
1401 USB_DEVICE
*RootHub
;
1403 USB_INTERFACE
*RootIf
;
1404 USB_INTERFACE
*UsbIf
;
1405 EFI_USB_BUS_PROTOCOL
*BusId
;
1406 EFI_USB_IO_PROTOCOL
*UsbIo
;
1410 EFI_STATUS ReturnStatus
;
1412 Status
= EFI_SUCCESS
;
1414 if (NumberOfChildren
> 0) {
1416 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1418 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1420 ReturnStatus
= EFI_SUCCESS
;
1421 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1422 Status
= gBS
->OpenProtocol (
1423 ChildHandleBuffer
[Index
],
1424 &gEfiUsbIoProtocolGuid
,
1426 This
->DriverBindingHandle
,
1428 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1431 if (EFI_ERROR (Status
)) {
1433 // It is possible that the child has already been released:
1434 // 1. For combo device, free one device will release others.
1435 // 2. If a hub is released, all devices on its down facing
1436 // ports are released also.
1441 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1442 UsbDev
= UsbIf
->Device
;
1444 ReturnStatus
= UsbRemoveDevice (UsbDev
);
1447 gBS
->RestoreTPL (OldTpl
);
1448 return ReturnStatus
;
1451 DEBUG (( EFI_D_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1454 // Locate USB_BUS for the current host controller
1456 Status
= gBS
->OpenProtocol (
1460 This
->DriverBindingHandle
,
1462 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1465 if (EFI_ERROR (Status
)) {
1469 Bus
= USB_BUS_FROM_THIS (BusId
);
1472 // Stop the root hub, then free all the devices
1474 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1476 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1478 RootHub
= Bus
->Devices
[0];
1479 RootIf
= RootHub
->Interfaces
[0];
1481 ASSERT (Bus
->MaxDevices
<= 256);
1482 ReturnStatus
= EFI_SUCCESS
;
1483 for (Index
= 1; Index
< Bus
->MaxDevices
; Index
++) {
1484 if (Bus
->Devices
[Index
] != NULL
) {
1485 Status
= UsbRemoveDevice (Bus
->Devices
[Index
]);
1486 if (EFI_ERROR (Status
)) {
1487 ReturnStatus
= Status
;
1492 gBS
->RestoreTPL (OldTpl
);
1494 if (!EFI_ERROR (ReturnStatus
)) {
1495 mUsbRootHubApi
.Release (RootIf
);
1496 gBS
->FreePool (RootIf
);
1497 gBS
->FreePool (RootHub
);
1499 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1500 ASSERT (!EFI_ERROR (Status
));
1503 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1505 gBS
->UninstallProtocolInterface (Controller
, &gEfiCallerIdGuid
, &Bus
->BusId
);
1507 if (Bus
->Usb2Hc
!= NULL
) {
1508 Status
= gBS
->CloseProtocol (
1510 &gEfiUsb2HcProtocolGuid
,
1511 This
->DriverBindingHandle
,
1516 if (Bus
->UsbHc
!= NULL
) {
1517 Status
= gBS
->CloseProtocol (
1519 &gEfiUsbHcProtocolGuid
,
1520 This
->DriverBindingHandle
,
1525 if (!EFI_ERROR (Status
)) {
1526 gBS
->CloseProtocol (
1528 &gEfiDevicePathProtocolGuid
,
1529 This
->DriverBindingHandle
,
1533 gBS
->FreePool (Bus
);