3 Usb Bus Driver Binding and Bus IO Protocol.
5 Copyright (c) 2004 - 2011, 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.
19 // USB_BUS_PROTOCOL is only used to locate USB_BUS
21 EFI_GUID mUsbBusProtocolGuid
= EFI_USB_BUS_PROTOCOL_GUID
;
23 EFI_USB_IO_PROTOCOL mUsbIoProtocol
= {
26 UsbIoAsyncInterruptTransfer
,
27 UsbIoSyncInterruptTransfer
,
28 UsbIoIsochronousTransfer
,
29 UsbIoAsyncIsochronousTransfer
,
30 UsbIoGetDeviceDescriptor
,
31 UsbIoGetActiveConfigDescriptor
,
32 UsbIoGetInterfaceDescriptor
,
33 UsbIoGetEndpointDescriptor
,
34 UsbIoGetStringDescriptor
,
35 UsbIoGetSupportedLanguages
,
39 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding
= {
40 UsbBusControllerDriverSupported
,
41 UsbBusControllerDriverStart
,
42 UsbBusControllerDriverStop
,
48 UINT16 mMaxUsbDeviceNum
= USB_MAX_DEVICES
;
51 USB_IO function to execute a control transfer. This
52 function will execute the USB transfer. If transfer
53 successes, it will sync the internal state of USB bus
56 @param This The USB_IO instance
57 @param Request The control transfer request
58 @param Direction Direction for data stage
59 @param Timeout The time to wait before timeout
60 @param Data The buffer holding the data
61 @param DataLength Then length of the data
62 @param UsbStatus USB result
64 @retval EFI_INVALID_PARAMETER The parameters are invalid
65 @retval EFI_SUCCESS The control transfer succeeded.
66 @retval Others Failed to execute the transfer
71 UsbIoControlTransfer (
72 IN EFI_USB_IO_PROTOCOL
*This
,
73 IN EFI_USB_DEVICE_REQUEST
*Request
,
74 IN EFI_USB_DATA_DIRECTION Direction
,
76 IN OUT VOID
*Data
, OPTIONAL
77 IN UINTN DataLength
, OPTIONAL
83 USB_ENDPOINT_DESC
*EpDesc
;
87 if (UsbStatus
== NULL
) {
88 return EFI_INVALID_PARAMETER
;
91 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
93 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
96 Status
= UsbHcControlTransfer (
110 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
112 // Clear TT buffer when CTRL/BULK split transaction failes
113 // Clear the TRANSLATOR TT buffer, not parent's buffer
115 ASSERT (Dev
->Translator
.TranslatorHubAddress
< mMaxUsbDeviceNum
);
116 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
117 UsbHubCtrlClearTTBuffer (
118 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
119 Dev
->Translator
.TranslatorPortNumber
,
130 // Some control transfer will change the device's internal
131 // status, such as Set_Configuration and Set_Interface.
132 // We must synchronize the bus driver's status with that in
133 // device. We ignore the Set_Descriptor request because it's
134 // hardly used by any device, especially in pre-boot environment
138 // Reset the endpoint toggle when endpoint stall is cleared
140 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
141 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
142 USB_TARGET_ENDPOINT
)) &&
143 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
145 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
147 if (EpDesc
!= NULL
) {
153 // Select a new configuration. This is a dangerous action. Upper driver
154 // should stop use its current UsbIo after calling this driver. The old
155 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
156 // ReinstallProtocol since interfaces in different configuration may be
157 // completely irrelevant.
159 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
160 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
161 USB_TARGET_DEVICE
))) {
163 // Don't re-create the USB interfaces if configuration isn't changed.
165 if ((Dev
->ActiveConfig
!= NULL
) &&
166 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
170 DEBUG ((EFI_D_INFO
, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
172 if (Dev
->ActiveConfig
!= NULL
) {
173 UsbRemoveConfig (Dev
);
176 if (Request
->Value
!= 0) {
177 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
181 // Exit now, Old USB_IO is invalid now
187 // A new alternative setting is selected for the interface.
188 // No need to reinstall UsbIo in this case because only
189 // underlying communication endpoints are changed. Functionality
190 // should remains the same.
192 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
193 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
194 USB_TARGET_INTERFACE
)) &&
195 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
197 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
199 if (!EFI_ERROR (Status
)) {
200 ASSERT (UsbIf
->IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
201 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
206 gBS
->RestoreTPL (OldTpl
);
212 Execute a bulk transfer to the device endpoint.
214 @param This The USB IO instance.
215 @param Endpoint The device endpoint.
216 @param Data The data to transfer.
217 @param DataLength The length of the data to transfer.
218 @param Timeout Time to wait before timeout.
219 @param UsbStatus The result of USB transfer.
221 @retval EFI_SUCCESS The bulk transfer is OK.
222 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
223 @retval Others Failed to execute transfer, reason returned in
230 IN EFI_USB_IO_PROTOCOL
*This
,
233 IN OUT UINTN
*DataLength
,
235 OUT UINT32
*UsbStatus
239 USB_INTERFACE
*UsbIf
;
240 USB_ENDPOINT_DESC
*EpDesc
;
246 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
247 (UsbStatus
== NULL
)) {
249 return EFI_INVALID_PARAMETER
;
252 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
254 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
257 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
259 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
260 Status
= EFI_INVALID_PARAMETER
;
265 Toggle
= EpDesc
->Toggle
;
266 Status
= UsbHcBulkTransfer (
271 EpDesc
->Desc
.MaxPacketSize
,
281 EpDesc
->Toggle
= Toggle
;
283 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
285 // Clear TT buffer when CTRL/BULK split transaction failes.
286 // Clear the TRANSLATOR TT buffer, not parent's buffer
288 ASSERT (Dev
->Translator
.TranslatorHubAddress
< mMaxUsbDeviceNum
);
289 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
290 UsbHubCtrlClearTTBuffer (
291 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
292 Dev
->Translator
.TranslatorPortNumber
,
301 gBS
->RestoreTPL (OldTpl
);
307 Execute a synchronous interrupt transfer.
309 @param This The USB IO instance.
310 @param Endpoint The device endpoint.
311 @param Data The data to transfer.
312 @param DataLength The length of the data to transfer.
313 @param Timeout Time to wait before timeout.
314 @param UsbStatus The result of USB transfer.
316 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
317 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
318 @retval Others Failed to execute transfer, reason returned in
324 UsbIoSyncInterruptTransfer (
325 IN EFI_USB_IO_PROTOCOL
*This
,
328 IN OUT UINTN
*DataLength
,
330 OUT UINT32
*UsbStatus
334 USB_INTERFACE
*UsbIf
;
335 USB_ENDPOINT_DESC
*EpDesc
;
340 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
341 (UsbStatus
== NULL
)) {
343 return EFI_INVALID_PARAMETER
;
346 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
348 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
351 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
353 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
354 Status
= EFI_INVALID_PARAMETER
;
358 Toggle
= EpDesc
->Toggle
;
359 Status
= UsbHcSyncInterruptTransfer (
364 EpDesc
->Desc
.MaxPacketSize
,
373 EpDesc
->Toggle
= Toggle
;
376 gBS
->RestoreTPL (OldTpl
);
382 Queue a new asynchronous interrupt transfer, or remove the old
383 request if (IsNewTransfer == FALSE).
385 @param This The USB_IO instance.
386 @param Endpoint The device endpoint.
387 @param IsNewTransfer Whether this is a new request, if it's old, remove
389 @param PollInterval The interval to poll the transfer result, (in ms).
390 @param DataLength The length of perodic data transfer.
391 @param Callback The function to call periodicaly when transfer is
393 @param Context The context to the callback.
395 @retval EFI_SUCCESS New transfer is queued or old request is removed.
396 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
397 @retval Others Failed to queue the new request or remove the old
403 UsbIoAsyncInterruptTransfer (
404 IN EFI_USB_IO_PROTOCOL
*This
,
406 IN BOOLEAN IsNewTransfer
,
407 IN UINTN PollInterval
, OPTIONAL
408 IN UINTN DataLength
, OPTIONAL
409 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
410 IN VOID
*Context OPTIONAL
414 USB_INTERFACE
*UsbIf
;
415 USB_ENDPOINT_DESC
*EpDesc
;
420 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
421 return EFI_INVALID_PARAMETER
;
424 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
425 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
428 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
430 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
431 Status
= EFI_INVALID_PARAMETER
;
435 Toggle
= EpDesc
->Toggle
;
436 Status
= UsbHcAsyncInterruptTransfer (
441 EpDesc
->Desc
.MaxPacketSize
,
451 EpDesc
->Toggle
= Toggle
;
454 gBS
->RestoreTPL (OldTpl
);
460 Execute a synchronous isochronous transfer.
462 @param This The USB IO instance.
463 @param DeviceEndpoint The device endpoint.
464 @param Data The data to transfer.
465 @param DataLength The length of the data to transfer.
466 @param UsbStatus The result of USB transfer.
468 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
473 UsbIoIsochronousTransfer (
474 IN EFI_USB_IO_PROTOCOL
*This
,
475 IN UINT8 DeviceEndpoint
,
481 return EFI_UNSUPPORTED
;
486 Queue an asynchronous isochronous transfer.
488 @param This The USB_IO instance.
489 @param DeviceEndpoint The device endpoint.
490 @param Data The data to transfer.
491 @param DataLength The length of perodic data transfer.
492 @param IsochronousCallBack The function to call periodicaly when transfer is
494 @param Context The context to the callback.
496 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
501 UsbIoAsyncIsochronousTransfer (
502 IN EFI_USB_IO_PROTOCOL
*This
,
503 IN UINT8 DeviceEndpoint
,
506 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
507 IN VOID
*Context OPTIONAL
510 return EFI_UNSUPPORTED
;
515 Retrieve the device descriptor of the device.
517 @param This The USB IO instance.
518 @param Descriptor The variable to receive the device descriptor.
520 @retval EFI_SUCCESS The device descriptor is returned.
521 @retval EFI_INVALID_PARAMETER The parameter is invalid.
526 UsbIoGetDeviceDescriptor (
527 IN EFI_USB_IO_PROTOCOL
*This
,
528 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
532 USB_INTERFACE
*UsbIf
;
535 if (Descriptor
== NULL
) {
536 return EFI_INVALID_PARAMETER
;
539 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
541 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
544 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
546 gBS
->RestoreTPL (OldTpl
);
552 Return the configuration descriptor of the current active configuration.
554 @param This The USB IO instance.
555 @param Descriptor The USB configuration descriptor.
557 @retval EFI_SUCCESS The active configuration descriptor is returned.
558 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
559 @retval EFI_NOT_FOUND Currently no active configuration is selected.
564 UsbIoGetActiveConfigDescriptor (
565 IN EFI_USB_IO_PROTOCOL
*This
,
566 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
570 USB_INTERFACE
*UsbIf
;
574 if (Descriptor
== NULL
) {
575 return EFI_INVALID_PARAMETER
;
578 Status
= EFI_SUCCESS
;
579 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
581 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
584 if (Dev
->ActiveConfig
== NULL
) {
585 Status
= EFI_NOT_FOUND
;
589 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
592 gBS
->RestoreTPL (OldTpl
);
598 Retrieve the active interface setting descriptor for this USB IO instance.
600 @param This The USB IO instance.
601 @param Descriptor The variable to receive active interface setting.
603 @retval EFI_SUCCESS The active interface setting is returned.
604 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
609 UsbIoGetInterfaceDescriptor (
610 IN EFI_USB_IO_PROTOCOL
*This
,
611 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
614 USB_INTERFACE
*UsbIf
;
617 if (Descriptor
== NULL
) {
618 return EFI_INVALID_PARAMETER
;
621 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
623 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
624 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
626 gBS
->RestoreTPL (OldTpl
);
632 Retrieve the endpoint descriptor from this interface setting.
634 @param This The USB IO instance.
635 @param Index The index (start from zero) of the endpoint to
637 @param Descriptor The variable to receive the descriptor.
639 @retval EFI_SUCCESS The endpoint descriptor is returned.
640 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
645 UsbIoGetEndpointDescriptor (
646 IN EFI_USB_IO_PROTOCOL
*This
,
648 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
651 USB_INTERFACE
*UsbIf
;
654 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
656 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
658 if ((Descriptor
== NULL
) || (Index
> 15)) {
659 gBS
->RestoreTPL (OldTpl
);
660 return EFI_INVALID_PARAMETER
;
663 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
664 gBS
->RestoreTPL (OldTpl
);
665 return EFI_NOT_FOUND
;
670 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
671 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
674 gBS
->RestoreTPL (OldTpl
);
680 Retrieve the supported language ID table from the device.
682 @param This The USB IO instance.
683 @param LangIDTable The table to return the language IDs.
684 @param TableSize The size, in bytes, of the table LangIDTable.
686 @retval EFI_SUCCESS The language ID is return.
691 UsbIoGetSupportedLanguages (
692 IN EFI_USB_IO_PROTOCOL
*This
,
693 OUT UINT16
**LangIDTable
,
694 OUT UINT16
*TableSize
698 USB_INTERFACE
*UsbIf
;
701 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
703 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
706 *LangIDTable
= Dev
->LangId
;
707 *TableSize
= (UINT16
) (Dev
->TotalLangId
* sizeof (UINT16
));
709 gBS
->RestoreTPL (OldTpl
);
715 Retrieve an indexed string in the language of LangID.
717 @param This The USB IO instance.
718 @param LangID The language ID of the string to retrieve.
719 @param StringIndex The index of the string.
720 @param String The variable to receive the string.
722 @retval EFI_SUCCESS The string is returned.
723 @retval EFI_NOT_FOUND No such string existed.
728 UsbIoGetStringDescriptor (
729 IN EFI_USB_IO_PROTOCOL
*This
,
731 IN UINT8 StringIndex
,
736 USB_INTERFACE
*UsbIf
;
737 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
743 if ((StringIndex
== 0) || (LangID
== 0)) {
744 return EFI_NOT_FOUND
;
747 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
749 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
753 // Check whether language ID is supported
755 Status
= EFI_NOT_FOUND
;
757 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
758 ASSERT (Index
< USB_MAX_LANG_ID
);
759 if (Dev
->LangId
[Index
] == LangID
) {
764 if (Index
== Dev
->TotalLangId
) {
769 // Retrieve the string descriptor then allocate a buffer
770 // to hold the string itself.
772 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
774 if (StrDesc
== NULL
) {
778 if (StrDesc
->Length
<= 2) {
782 Buf
= AllocateZeroPool (StrDesc
->Length
);
785 Status
= EFI_OUT_OF_RESOURCES
;
789 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
790 *String
= (CHAR16
*) Buf
;
791 Status
= EFI_SUCCESS
;
794 gBS
->FreePool (StrDesc
);
797 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
)) {
839 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
840 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
846 // Reset the device to its current address. The device now has a
847 // address of ZERO, so need to set Dev->Address to zero first for
848 // host to communicate with the device
850 Address
= Dev
->Address
;
852 Status
= UsbSetAddress (Dev
, Address
);
854 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
856 if (EFI_ERROR (Status
)) {
857 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set address for device %d - %r\n",
863 Dev
->Address
= Address
;
865 DEBUG (( EFI_D_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address
));
868 // Reset the current active configure, after this device
869 // is in CONFIGURED state.
871 if (Dev
->ActiveConfig
!= NULL
) {
872 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
874 if (EFI_ERROR (Status
)) {
875 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set configure for device %d - %r\n",
881 gBS
->RestoreTPL (OldTpl
);
887 Install Usb Bus Protocol on host controller, and start the Usb bus.
889 @param This The USB bus driver binding instance.
890 @param Controller The controller to check.
891 @param RemainingDevicePath The remaining device patch.
893 @retval EFI_SUCCESS The controller is controlled by the usb bus.
894 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
895 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
900 UsbBusBuildProtocol (
901 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
902 IN EFI_HANDLE Controller
,
903 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
908 USB_INTERFACE
*RootIf
;
912 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
914 if (UsbBus
== NULL
) {
915 return EFI_OUT_OF_RESOURCES
;
918 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
919 UsbBus
->HostHandle
= Controller
;
921 Status
= gBS
->OpenProtocol (
923 &gEfiDevicePathProtocolGuid
,
924 (VOID
**) &UsbBus
->DevicePath
,
925 This
->DriverBindingHandle
,
927 EFI_OPEN_PROTOCOL_BY_DRIVER
930 if (EFI_ERROR (Status
)) {
931 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open device path %r\n", Status
));
938 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
939 // This is for backward compatibility with EFI 1.x. In UEFI
940 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
941 // and USB_HC because EHCI driver will install both protocols
942 // (for the same reason). If we don't consume both of them,
943 // the unconsumed one may be opened by others.
945 Status
= gBS
->OpenProtocol (
947 &gEfiUsb2HcProtocolGuid
,
948 (VOID
**) &(UsbBus
->Usb2Hc
),
949 This
->DriverBindingHandle
,
951 EFI_OPEN_PROTOCOL_BY_DRIVER
954 Status2
= gBS
->OpenProtocol (
956 &gEfiUsbHcProtocolGuid
,
957 (VOID
**) &(UsbBus
->UsbHc
),
958 This
->DriverBindingHandle
,
960 EFI_OPEN_PROTOCOL_BY_DRIVER
963 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
964 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
966 Status
= EFI_DEVICE_ERROR
;
970 if (!EFI_ERROR (Status
)) {
971 if (UsbBus
->Usb2Hc
->MajorRevision
== 0x3) {
973 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
974 // Then its max supported devices are 256.
976 mMaxUsbDeviceNum
= 256;
980 UsbHcReset (UsbBus
, EFI_USB_HC_RESET_GLOBAL
);
981 UsbHcSetState (UsbBus
, EfiUsbHcStateOperational
);
984 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
986 Status
= gBS
->InstallProtocolInterface (
988 &mUsbBusProtocolGuid
,
989 EFI_NATIVE_INTERFACE
,
993 if (EFI_ERROR (Status
)) {
994 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to install bus protocol %r\n", Status
));
999 // Initial the wanted child device path list, and add first RemainingDevicePath
1001 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
1002 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
1003 ASSERT (!EFI_ERROR (Status
));
1005 // Create a fake usb device for root hub
1007 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
1009 if (RootHub
== NULL
) {
1010 Status
= EFI_OUT_OF_RESOURCES
;
1011 goto UNINSTALL_USBBUS
;
1014 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1016 if (RootIf
== NULL
) {
1018 Status
= EFI_OUT_OF_RESOURCES
;
1022 RootHub
->Bus
= UsbBus
;
1023 RootHub
->NumOfInterface
= 1;
1024 RootHub
->Interfaces
[0] = RootIf
;
1026 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1027 RootIf
->Device
= RootHub
;
1028 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1030 Status
= mUsbRootHubApi
.Init (RootIf
);
1032 if (EFI_ERROR (Status
)) {
1033 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to init root hub %r\n", Status
));
1037 UsbBus
->Devices
[0] = RootHub
;
1039 DEBUG ((EFI_D_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1043 if (RootIf
!= NULL
) {
1046 if (RootHub
!= NULL
) {
1051 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &UsbBus
->BusId
);
1054 if (UsbBus
->Usb2Hc
!= NULL
) {
1055 gBS
->CloseProtocol (
1057 &gEfiUsb2HcProtocolGuid
,
1058 This
->DriverBindingHandle
,
1062 if (UsbBus
->UsbHc
!= NULL
) {
1063 gBS
->CloseProtocol (
1065 &gEfiUsbHcProtocolGuid
,
1066 This
->DriverBindingHandle
,
1070 gBS
->CloseProtocol (
1072 &gEfiDevicePathProtocolGuid
,
1073 This
->DriverBindingHandle
,
1078 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to start bus driver %r\n", Status
));
1084 The USB bus driver entry pointer.
1086 @param ImageHandle The driver image handle.
1087 @param SystemTable The system table.
1089 @return EFI_SUCCESS The component name protocol is installed.
1090 @return Others Failed to init the usb driver.
1095 UsbBusDriverEntryPoint (
1096 IN EFI_HANDLE ImageHandle
,
1097 IN EFI_SYSTEM_TABLE
*SystemTable
1100 return EfiLibInstallDriverBindingComponentName2 (
1103 &mUsbBusDriverBinding
,
1105 &mUsbBusComponentName
,
1106 &mUsbBusComponentName2
1112 Check whether USB bus driver support this device.
1114 @param This The USB bus driver binding protocol.
1115 @param Controller The controller handle to check.
1116 @param RemainingDevicePath The remaining device path.
1118 @retval EFI_SUCCESS The bus supports this controller.
1119 @retval EFI_UNSUPPORTED This device isn't supported.
1124 UsbBusControllerDriverSupported (
1125 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1126 IN EFI_HANDLE Controller
,
1127 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1130 EFI_DEV_PATH_PTR DevicePathNode
;
1131 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1132 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1133 EFI_USB_HC_PROTOCOL
*UsbHc
;
1137 // Check whether device path is valid
1139 if (RemainingDevicePath
!= NULL
) {
1141 // Check if RemainingDevicePath is the End of Device Path Node,
1142 // if yes, go on checking other conditions
1144 if (!IsDevicePathEnd (RemainingDevicePath
)) {
1146 // If RemainingDevicePath isn't the End of Device Path Node,
1147 // check its validation
1149 DevicePathNode
.DevPath
= RemainingDevicePath
;
1151 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1152 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
&&
1153 DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
1154 && DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
1157 return EFI_UNSUPPORTED
;
1163 // Check whether USB_HC2 protocol is installed
1165 Status
= gBS
->OpenProtocol (
1167 &gEfiUsb2HcProtocolGuid
,
1169 This
->DriverBindingHandle
,
1171 EFI_OPEN_PROTOCOL_BY_DRIVER
1173 if (Status
== EFI_ALREADY_STARTED
) {
1177 if (EFI_ERROR (Status
)) {
1179 // If failed to open USB_HC2, fall back to USB_HC
1181 Status
= gBS
->OpenProtocol (
1183 &gEfiUsbHcProtocolGuid
,
1185 This
->DriverBindingHandle
,
1187 EFI_OPEN_PROTOCOL_BY_DRIVER
1189 if (Status
== EFI_ALREADY_STARTED
) {
1193 if (EFI_ERROR (Status
)) {
1198 // Close the USB_HC used to perform the supported test
1200 gBS
->CloseProtocol (
1202 &gEfiUsbHcProtocolGuid
,
1203 This
->DriverBindingHandle
,
1210 // Close the USB_HC2 used to perform the supported test
1212 gBS
->CloseProtocol (
1214 &gEfiUsb2HcProtocolGuid
,
1215 This
->DriverBindingHandle
,
1221 // Open the EFI Device Path protocol needed to perform the supported test
1223 Status
= gBS
->OpenProtocol (
1225 &gEfiDevicePathProtocolGuid
,
1226 (VOID
**) &ParentDevicePath
,
1227 This
->DriverBindingHandle
,
1229 EFI_OPEN_PROTOCOL_BY_DRIVER
1231 if (Status
== EFI_ALREADY_STARTED
) {
1235 if (!EFI_ERROR (Status
)) {
1237 // Close protocol, don't use device path protocol in the Support() function
1239 gBS
->CloseProtocol (
1241 &gEfiDevicePathProtocolGuid
,
1242 This
->DriverBindingHandle
,
1254 Start to process the controller.
1256 @param This The USB bus driver binding instance.
1257 @param Controller The controller to check.
1258 @param RemainingDevicePath The remaining device patch.
1260 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1261 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1263 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1268 UsbBusControllerDriverStart (
1269 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1270 IN EFI_HANDLE Controller
,
1271 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1274 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1278 // Locate the USB bus protocol, if it is found, USB bus
1279 // is already started on this controller.
1281 Status
= gBS
->OpenProtocol (
1283 &mUsbBusProtocolGuid
,
1284 (VOID
**) &UsbBusId
,
1285 This
->DriverBindingHandle
,
1287 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1290 if (EFI_ERROR (Status
)) {
1292 // If first start, build the bus execute environment and install bus protocol
1294 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_IO_BUS_USB
| EFI_P_PC_ENABLE
));
1295 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1296 if (EFI_ERROR (Status
)) {
1300 // Try get the Usb Bus protocol interface again
1302 Status
= gBS
->OpenProtocol (
1304 &mUsbBusProtocolGuid
,
1305 (VOID
**) &UsbBusId
,
1306 This
->DriverBindingHandle
,
1308 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1310 ASSERT (!EFI_ERROR (Status
));
1313 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1314 // usb child device will be recursively connected.
1315 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1316 // All wanted usb child devices will be remembered by the usb bus driver itself.
1317 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1319 // Save the passed in RemainingDevicePath this time
1321 if (RemainingDevicePath
!= NULL
) {
1322 if (IsDevicePathEnd (RemainingDevicePath
)) {
1324 // If RemainingDevicePath is the End of Device Path Node,
1325 // skip enumerate any device and return EFI_SUCESSS
1331 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1332 ASSERT (!EFI_ERROR (Status
));
1334 // Ensure all wanted child usb devices are fully recursively connected
1336 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1337 ASSERT (!EFI_ERROR (Status
));
1346 Stop handle the controller by this USB bus driver.
1348 @param This The USB bus driver binding protocol.
1349 @param Controller The controller to release.
1350 @param NumberOfChildren The child of USB bus that opened controller
1352 @param ChildHandleBuffer The array of child handle.
1354 @retval EFI_SUCCESS The controller or children are stopped.
1355 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1360 UsbBusControllerDriverStop (
1361 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1362 IN EFI_HANDLE Controller
,
1363 IN UINTN NumberOfChildren
,
1364 IN EFI_HANDLE
*ChildHandleBuffer
1368 USB_DEVICE
*RootHub
;
1370 USB_INTERFACE
*RootIf
;
1371 USB_INTERFACE
*UsbIf
;
1372 EFI_USB_BUS_PROTOCOL
*BusId
;
1373 EFI_USB_IO_PROTOCOL
*UsbIo
;
1378 Status
= EFI_SUCCESS
;
1380 if (NumberOfChildren
> 0) {
1382 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1384 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1386 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1387 Status
= gBS
->OpenProtocol (
1388 ChildHandleBuffer
[Index
],
1389 &gEfiUsbIoProtocolGuid
,
1391 This
->DriverBindingHandle
,
1393 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1396 if (EFI_ERROR (Status
)) {
1398 // It is possible that the child has already been released:
1399 // 1. For combo device, free one device will release others.
1400 // 2. If a hub is released, all devices on its down facing
1401 // ports are released also.
1406 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1407 UsbDev
= UsbIf
->Device
;
1409 UsbRemoveDevice (UsbDev
);
1412 gBS
->RestoreTPL (OldTpl
);
1416 DEBUG (( EFI_D_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1419 // Locate USB_BUS for the current host controller
1421 Status
= gBS
->OpenProtocol (
1423 &mUsbBusProtocolGuid
,
1425 This
->DriverBindingHandle
,
1427 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1430 if (EFI_ERROR (Status
)) {
1434 Bus
= USB_BUS_FROM_THIS (BusId
);
1437 // Stop the root hub, then free all the devices
1439 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1441 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1442 UsbHcSetState (Bus
, EfiUsbHcStateHalt
);
1444 RootHub
= Bus
->Devices
[0];
1445 RootIf
= RootHub
->Interfaces
[0];
1447 mUsbRootHubApi
.Release (RootIf
);
1449 for (Index
= 1; Index
< mMaxUsbDeviceNum
; Index
++) {
1450 if (Bus
->Devices
[Index
] != NULL
) {
1451 UsbRemoveDevice (Bus
->Devices
[Index
]);
1455 gBS
->RestoreTPL (OldTpl
);
1457 gBS
->FreePool (RootIf
);
1458 gBS
->FreePool (RootHub
);
1459 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1460 ASSERT (!EFI_ERROR (Status
));
1463 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1465 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &Bus
->BusId
);
1467 if (Bus
->Usb2Hc
!= NULL
) {
1468 gBS
->CloseProtocol (
1470 &gEfiUsb2HcProtocolGuid
,
1471 This
->DriverBindingHandle
,
1476 if (Bus
->UsbHc
!= NULL
) {
1477 gBS
->CloseProtocol (
1479 &gEfiUsbHcProtocolGuid
,
1480 This
->DriverBindingHandle
,
1485 gBS
->CloseProtocol (
1487 &gEfiDevicePathProtocolGuid
,
1488 This
->DriverBindingHandle
,
1492 gBS
->FreePool (Bus
);