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
,
49 USB_IO function to execute a control transfer. This
50 function will execute the USB transfer. If transfer
51 successes, it will sync the internal state of USB bus
54 @param This The USB_IO instance
55 @param Request The control transfer request
56 @param Direction Direction for data stage
57 @param Timeout The time to wait before timeout
58 @param Data The buffer holding the data
59 @param DataLength Then length of the data
60 @param UsbStatus USB result
62 @retval EFI_INVALID_PARAMETER The parameters are invalid
63 @retval EFI_SUCCESS The control transfer succeeded.
64 @retval Others Failed to execute the transfer
69 UsbIoControlTransfer (
70 IN EFI_USB_IO_PROTOCOL
*This
,
71 IN EFI_USB_DEVICE_REQUEST
*Request
,
72 IN EFI_USB_DATA_DIRECTION Direction
,
74 IN OUT VOID
*Data
, OPTIONAL
75 IN UINTN DataLength
, OPTIONAL
81 USB_ENDPOINT_DESC
*EpDesc
;
85 if (UsbStatus
== NULL
) {
86 return EFI_INVALID_PARAMETER
;
89 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
91 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
94 Status
= UsbHcControlTransfer (
108 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
110 // Clear TT buffer when CTRL/BULK split transaction failes
111 // Clear the TRANSLATOR TT buffer, not parent's buffer
113 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
114 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
115 UsbHubCtrlClearTTBuffer (
116 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
117 Dev
->Translator
.TranslatorPortNumber
,
128 // Some control transfer will change the device's internal
129 // status, such as Set_Configuration and Set_Interface.
130 // We must synchronize the bus driver's status with that in
131 // device. We ignore the Set_Descriptor request because it's
132 // hardly used by any device, especially in pre-boot environment
136 // Reset the endpoint toggle when endpoint stall is cleared
138 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
139 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
140 USB_TARGET_ENDPOINT
)) &&
141 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
143 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
145 if (EpDesc
!= NULL
) {
151 // Select a new configuration. This is a dangerous action. Upper driver
152 // should stop use its current UsbIo after calling this driver. The old
153 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
154 // ReinstallProtocol since interfaces in different configuration may be
155 // completely irrelevant.
157 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
158 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
159 USB_TARGET_DEVICE
))) {
161 // Don't re-create the USB interfaces if configuration isn't changed.
163 if ((Dev
->ActiveConfig
!= NULL
) &&
164 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
168 DEBUG ((EFI_D_INFO
, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
170 if (Dev
->ActiveConfig
!= NULL
) {
171 UsbRemoveConfig (Dev
);
174 if (Request
->Value
!= 0) {
175 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
179 // Exit now, Old USB_IO is invalid now
185 // A new alternative setting is selected for the interface.
186 // No need to reinstall UsbIo in this case because only
187 // underlying communication endpoints are changed. Functionality
188 // should remains the same.
190 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
191 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
192 USB_TARGET_INTERFACE
)) &&
193 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
195 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
197 if (!EFI_ERROR (Status
)) {
198 ASSERT (UsbIf
->IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
199 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
204 gBS
->RestoreTPL (OldTpl
);
210 Execute a bulk transfer to the device endpoint.
212 @param This The USB IO instance.
213 @param Endpoint The device endpoint.
214 @param Data The data to transfer.
215 @param DataLength The length of the data to transfer.
216 @param Timeout Time to wait before timeout.
217 @param UsbStatus The result of USB transfer.
219 @retval EFI_SUCCESS The bulk transfer is OK.
220 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
221 @retval Others Failed to execute transfer, reason returned in
228 IN EFI_USB_IO_PROTOCOL
*This
,
231 IN OUT UINTN
*DataLength
,
233 OUT UINT32
*UsbStatus
237 USB_INTERFACE
*UsbIf
;
238 USB_ENDPOINT_DESC
*EpDesc
;
244 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
245 (UsbStatus
== NULL
)) {
247 return EFI_INVALID_PARAMETER
;
250 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
252 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
255 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
257 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
258 Status
= EFI_INVALID_PARAMETER
;
263 Toggle
= EpDesc
->Toggle
;
264 Status
= UsbHcBulkTransfer (
269 EpDesc
->Desc
.MaxPacketSize
,
279 EpDesc
->Toggle
= Toggle
;
281 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
283 // Clear TT buffer when CTRL/BULK split transaction failes.
284 // Clear the TRANSLATOR TT buffer, not parent's buffer
286 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
287 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
288 UsbHubCtrlClearTTBuffer (
289 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
290 Dev
->Translator
.TranslatorPortNumber
,
299 gBS
->RestoreTPL (OldTpl
);
305 Execute a synchronous interrupt transfer.
307 @param This The USB IO instance.
308 @param Endpoint The device endpoint.
309 @param Data The data to transfer.
310 @param DataLength The length of the data to transfer.
311 @param Timeout Time to wait before timeout.
312 @param UsbStatus The result of USB transfer.
314 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
315 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
316 @retval Others Failed to execute transfer, reason returned in
322 UsbIoSyncInterruptTransfer (
323 IN EFI_USB_IO_PROTOCOL
*This
,
326 IN OUT UINTN
*DataLength
,
328 OUT UINT32
*UsbStatus
332 USB_INTERFACE
*UsbIf
;
333 USB_ENDPOINT_DESC
*EpDesc
;
338 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
339 (UsbStatus
== NULL
)) {
341 return EFI_INVALID_PARAMETER
;
344 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
346 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
349 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
351 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
352 Status
= EFI_INVALID_PARAMETER
;
356 Toggle
= EpDesc
->Toggle
;
357 Status
= UsbHcSyncInterruptTransfer (
362 EpDesc
->Desc
.MaxPacketSize
,
371 EpDesc
->Toggle
= Toggle
;
374 gBS
->RestoreTPL (OldTpl
);
380 Queue a new asynchronous interrupt transfer, or remove the old
381 request if (IsNewTransfer == FALSE).
383 @param This The USB_IO instance.
384 @param Endpoint The device endpoint.
385 @param IsNewTransfer Whether this is a new request, if it's old, remove
387 @param PollInterval The interval to poll the transfer result, (in ms).
388 @param DataLength The length of perodic data transfer.
389 @param Callback The function to call periodicaly when transfer is
391 @param Context The context to the callback.
393 @retval EFI_SUCCESS New transfer is queued or old request is removed.
394 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
395 @retval Others Failed to queue the new request or remove the old
401 UsbIoAsyncInterruptTransfer (
402 IN EFI_USB_IO_PROTOCOL
*This
,
404 IN BOOLEAN IsNewTransfer
,
405 IN UINTN PollInterval
, OPTIONAL
406 IN UINTN DataLength
, OPTIONAL
407 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
408 IN VOID
*Context OPTIONAL
412 USB_INTERFACE
*UsbIf
;
413 USB_ENDPOINT_DESC
*EpDesc
;
418 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
419 return EFI_INVALID_PARAMETER
;
422 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
423 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
426 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
428 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
429 Status
= EFI_INVALID_PARAMETER
;
433 Toggle
= EpDesc
->Toggle
;
434 Status
= UsbHcAsyncInterruptTransfer (
439 EpDesc
->Desc
.MaxPacketSize
,
449 EpDesc
->Toggle
= Toggle
;
452 gBS
->RestoreTPL (OldTpl
);
458 Execute a synchronous isochronous transfer.
460 @param This The USB IO instance.
461 @param DeviceEndpoint The device endpoint.
462 @param Data The data to transfer.
463 @param DataLength The length of the data to transfer.
464 @param UsbStatus The result of USB transfer.
466 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
471 UsbIoIsochronousTransfer (
472 IN EFI_USB_IO_PROTOCOL
*This
,
473 IN UINT8 DeviceEndpoint
,
479 return EFI_UNSUPPORTED
;
484 Queue an asynchronous isochronous transfer.
486 @param This The USB_IO instance.
487 @param DeviceEndpoint The device endpoint.
488 @param Data The data to transfer.
489 @param DataLength The length of perodic data transfer.
490 @param IsochronousCallBack The function to call periodicaly when transfer is
492 @param Context The context to the callback.
494 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
499 UsbIoAsyncIsochronousTransfer (
500 IN EFI_USB_IO_PROTOCOL
*This
,
501 IN UINT8 DeviceEndpoint
,
504 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
505 IN VOID
*Context OPTIONAL
508 return EFI_UNSUPPORTED
;
513 Retrieve the device descriptor of the device.
515 @param This The USB IO instance.
516 @param Descriptor The variable to receive the device descriptor.
518 @retval EFI_SUCCESS The device descriptor is returned.
519 @retval EFI_INVALID_PARAMETER The parameter is invalid.
524 UsbIoGetDeviceDescriptor (
525 IN EFI_USB_IO_PROTOCOL
*This
,
526 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
530 USB_INTERFACE
*UsbIf
;
533 if (Descriptor
== NULL
) {
534 return EFI_INVALID_PARAMETER
;
537 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
539 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
542 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
544 gBS
->RestoreTPL (OldTpl
);
550 Return the configuration descriptor of the current active configuration.
552 @param This The USB IO instance.
553 @param Descriptor The USB configuration descriptor.
555 @retval EFI_SUCCESS The active configuration descriptor is returned.
556 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
557 @retval EFI_NOT_FOUND Currently no active configuration is selected.
562 UsbIoGetActiveConfigDescriptor (
563 IN EFI_USB_IO_PROTOCOL
*This
,
564 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
568 USB_INTERFACE
*UsbIf
;
572 if (Descriptor
== NULL
) {
573 return EFI_INVALID_PARAMETER
;
576 Status
= EFI_SUCCESS
;
577 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
579 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
582 if (Dev
->ActiveConfig
== NULL
) {
583 Status
= EFI_NOT_FOUND
;
587 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
590 gBS
->RestoreTPL (OldTpl
);
596 Retrieve the active interface setting descriptor for this USB IO instance.
598 @param This The USB IO instance.
599 @param Descriptor The variable to receive active interface setting.
601 @retval EFI_SUCCESS The active interface setting is returned.
602 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
607 UsbIoGetInterfaceDescriptor (
608 IN EFI_USB_IO_PROTOCOL
*This
,
609 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
612 USB_INTERFACE
*UsbIf
;
615 if (Descriptor
== NULL
) {
616 return EFI_INVALID_PARAMETER
;
619 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
621 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
622 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
624 gBS
->RestoreTPL (OldTpl
);
630 Retrieve the endpoint descriptor from this interface setting.
632 @param This The USB IO instance.
633 @param Index The index (start from zero) of the endpoint to
635 @param Descriptor The variable to receive the descriptor.
637 @retval EFI_SUCCESS The endpoint descriptor is returned.
638 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
643 UsbIoGetEndpointDescriptor (
644 IN EFI_USB_IO_PROTOCOL
*This
,
646 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
649 USB_INTERFACE
*UsbIf
;
652 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
654 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
656 if ((Descriptor
== NULL
) || (Index
> 15)) {
657 gBS
->RestoreTPL (OldTpl
);
658 return EFI_INVALID_PARAMETER
;
661 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
662 gBS
->RestoreTPL (OldTpl
);
663 return EFI_NOT_FOUND
;
668 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
669 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
672 gBS
->RestoreTPL (OldTpl
);
678 Retrieve the supported language ID table from the device.
680 @param This The USB IO instance.
681 @param LangIDTable The table to return the language IDs.
682 @param TableSize The size, in bytes, of the table LangIDTable.
684 @retval EFI_SUCCESS The language ID is return.
689 UsbIoGetSupportedLanguages (
690 IN EFI_USB_IO_PROTOCOL
*This
,
691 OUT UINT16
**LangIDTable
,
692 OUT UINT16
*TableSize
696 USB_INTERFACE
*UsbIf
;
699 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
701 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
704 *LangIDTable
= Dev
->LangId
;
705 *TableSize
= (UINT16
) (Dev
->TotalLangId
* sizeof (UINT16
));
707 gBS
->RestoreTPL (OldTpl
);
713 Retrieve an indexed string in the language of LangID.
715 @param This The USB IO instance.
716 @param LangID The language ID of the string to retrieve.
717 @param StringIndex The index of the string.
718 @param String The variable to receive the string.
720 @retval EFI_SUCCESS The string is returned.
721 @retval EFI_NOT_FOUND No such string existed.
726 UsbIoGetStringDescriptor (
727 IN EFI_USB_IO_PROTOCOL
*This
,
729 IN UINT8 StringIndex
,
734 USB_INTERFACE
*UsbIf
;
735 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
741 if ((StringIndex
== 0) || (LangID
== 0)) {
742 return EFI_NOT_FOUND
;
745 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
747 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
751 // Check whether language ID is supported
753 Status
= EFI_NOT_FOUND
;
755 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
756 ASSERT (Index
< USB_MAX_LANG_ID
);
757 if (Dev
->LangId
[Index
] == LangID
) {
762 if (Index
== Dev
->TotalLangId
) {
767 // Retrieve the string descriptor then allocate a buffer
768 // to hold the string itself.
770 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
772 if (StrDesc
== NULL
) {
776 if (StrDesc
->Length
<= 2) {
780 Buf
= AllocateZeroPool (StrDesc
->Length
);
783 Status
= EFI_OUT_OF_RESOURCES
;
787 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
788 *String
= (CHAR16
*) Buf
;
789 Status
= EFI_SUCCESS
;
792 gBS
->FreePool (StrDesc
);
795 gBS
->RestoreTPL (OldTpl
);
801 Reset the device, then if that succeeds, reconfigure the
802 device with its address and current active configuration.
804 @param This The USB IO instance.
806 @retval EFI_SUCCESS The device is reset and configured.
807 @retval Others Failed to reset the device.
813 IN EFI_USB_IO_PROTOCOL
*This
816 USB_INTERFACE
*UsbIf
;
817 USB_INTERFACE
*HubIf
;
822 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
824 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
828 Status
= EFI_INVALID_PARAMETER
;
832 HubIf
= Dev
->ParentIf
;
833 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
835 if (EFI_ERROR (Status
)) {
836 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
837 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
843 // Reset the device to its current address. The device now has an address
844 // of ZERO after port reset, so need to set Dev->Address to the device again for
845 // host to communicate with it.
847 Status
= UsbSetAddress (Dev
, Dev
->Address
);
849 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
851 if (EFI_ERROR (Status
)) {
853 // It may fail due to device disconnection or other reasons.
855 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set address for device %d - %r\n",
856 Dev
->Address
, Status
));
861 DEBUG (( EFI_D_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev
->Address
));
864 // Reset the current active configure, after this device
865 // is in CONFIGURED state.
867 if (Dev
->ActiveConfig
!= NULL
) {
868 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
870 if (EFI_ERROR (Status
)) {
871 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set configure for device %d - %r\n",
872 Dev
->Address
, Status
));
877 gBS
->RestoreTPL (OldTpl
);
883 Install Usb Bus Protocol on host controller, and start the Usb bus.
885 @param This The USB bus driver binding instance.
886 @param Controller The controller to check.
887 @param RemainingDevicePath The remaining device patch.
889 @retval EFI_SUCCESS The controller is controlled by the usb bus.
890 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
891 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
896 UsbBusBuildProtocol (
897 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
898 IN EFI_HANDLE Controller
,
899 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
904 USB_INTERFACE
*RootIf
;
908 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
910 if (UsbBus
== NULL
) {
911 return EFI_OUT_OF_RESOURCES
;
914 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
915 UsbBus
->HostHandle
= Controller
;
916 UsbBus
->MaxDevices
= USB_MAX_DEVICES
;
918 Status
= gBS
->OpenProtocol (
920 &gEfiDevicePathProtocolGuid
,
921 (VOID
**) &UsbBus
->DevicePath
,
922 This
->DriverBindingHandle
,
924 EFI_OPEN_PROTOCOL_BY_DRIVER
927 if (EFI_ERROR (Status
)) {
928 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open device path %r\n", Status
));
935 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
936 // This is for backward compatibility with EFI 1.x. In UEFI
937 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
938 // and USB_HC because EHCI driver will install both protocols
939 // (for the same reason). If we don't consume both of them,
940 // the unconsumed one may be opened by others.
942 Status
= gBS
->OpenProtocol (
944 &gEfiUsb2HcProtocolGuid
,
945 (VOID
**) &(UsbBus
->Usb2Hc
),
946 This
->DriverBindingHandle
,
948 EFI_OPEN_PROTOCOL_BY_DRIVER
951 Status2
= gBS
->OpenProtocol (
953 &gEfiUsbHcProtocolGuid
,
954 (VOID
**) &(UsbBus
->UsbHc
),
955 This
->DriverBindingHandle
,
957 EFI_OPEN_PROTOCOL_BY_DRIVER
960 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
961 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
963 Status
= EFI_DEVICE_ERROR
;
967 if (!EFI_ERROR (Status
)) {
969 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
970 // Then its max supported devices are 256. Otherwise it's 128.
972 if (UsbBus
->Usb2Hc
->MajorRevision
== 0x3) {
973 UsbBus
->MaxDevices
= 256;
977 UsbHcReset (UsbBus
, EFI_USB_HC_RESET_GLOBAL
);
978 UsbHcSetState (UsbBus
, EfiUsbHcStateOperational
);
981 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
983 Status
= gBS
->InstallProtocolInterface (
985 &mUsbBusProtocolGuid
,
986 EFI_NATIVE_INTERFACE
,
990 if (EFI_ERROR (Status
)) {
991 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to install bus protocol %r\n", Status
));
996 // Initial the wanted child device path list, and add first RemainingDevicePath
998 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
999 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
1000 ASSERT (!EFI_ERROR (Status
));
1002 // Create a fake usb device for root hub
1004 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
1006 if (RootHub
== NULL
) {
1007 Status
= EFI_OUT_OF_RESOURCES
;
1008 goto UNINSTALL_USBBUS
;
1011 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1013 if (RootIf
== NULL
) {
1015 Status
= EFI_OUT_OF_RESOURCES
;
1019 RootHub
->Bus
= UsbBus
;
1020 RootHub
->NumOfInterface
= 1;
1021 RootHub
->Interfaces
[0] = RootIf
;
1023 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1024 RootIf
->Device
= RootHub
;
1025 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1027 Status
= mUsbRootHubApi
.Init (RootIf
);
1029 if (EFI_ERROR (Status
)) {
1030 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to init root hub %r\n", Status
));
1034 UsbBus
->Devices
[0] = RootHub
;
1036 DEBUG ((EFI_D_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1040 if (RootIf
!= NULL
) {
1043 if (RootHub
!= NULL
) {
1048 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &UsbBus
->BusId
);
1051 if (UsbBus
->Usb2Hc
!= NULL
) {
1052 gBS
->CloseProtocol (
1054 &gEfiUsb2HcProtocolGuid
,
1055 This
->DriverBindingHandle
,
1059 if (UsbBus
->UsbHc
!= NULL
) {
1060 gBS
->CloseProtocol (
1062 &gEfiUsbHcProtocolGuid
,
1063 This
->DriverBindingHandle
,
1067 gBS
->CloseProtocol (
1069 &gEfiDevicePathProtocolGuid
,
1070 This
->DriverBindingHandle
,
1075 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to start bus driver %r\n", Status
));
1081 The USB bus driver entry pointer.
1083 @param ImageHandle The driver image handle.
1084 @param SystemTable The system table.
1086 @return EFI_SUCCESS The component name protocol is installed.
1087 @return Others Failed to init the usb driver.
1092 UsbBusDriverEntryPoint (
1093 IN EFI_HANDLE ImageHandle
,
1094 IN EFI_SYSTEM_TABLE
*SystemTable
1097 return EfiLibInstallDriverBindingComponentName2 (
1100 &mUsbBusDriverBinding
,
1102 &mUsbBusComponentName
,
1103 &mUsbBusComponentName2
1109 Check whether USB bus driver support this device.
1111 @param This The USB bus driver binding protocol.
1112 @param Controller The controller handle to check.
1113 @param RemainingDevicePath The remaining device path.
1115 @retval EFI_SUCCESS The bus supports this controller.
1116 @retval EFI_UNSUPPORTED This device isn't supported.
1121 UsbBusControllerDriverSupported (
1122 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1123 IN EFI_HANDLE Controller
,
1124 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1127 EFI_DEV_PATH_PTR DevicePathNode
;
1128 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1129 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1130 EFI_USB_HC_PROTOCOL
*UsbHc
;
1134 // Check whether device path is valid
1136 if (RemainingDevicePath
!= NULL
) {
1138 // Check if RemainingDevicePath is the End of Device Path Node,
1139 // if yes, go on checking other conditions
1141 if (!IsDevicePathEnd (RemainingDevicePath
)) {
1143 // If RemainingDevicePath isn't the End of Device Path Node,
1144 // check its validation
1146 DevicePathNode
.DevPath
= RemainingDevicePath
;
1148 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1149 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
&&
1150 DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
1151 && DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
1154 return EFI_UNSUPPORTED
;
1160 // Check whether USB_HC2 protocol is installed
1162 Status
= gBS
->OpenProtocol (
1164 &gEfiUsb2HcProtocolGuid
,
1166 This
->DriverBindingHandle
,
1168 EFI_OPEN_PROTOCOL_BY_DRIVER
1170 if (Status
== EFI_ALREADY_STARTED
) {
1174 if (EFI_ERROR (Status
)) {
1176 // If failed to open USB_HC2, fall back to USB_HC
1178 Status
= gBS
->OpenProtocol (
1180 &gEfiUsbHcProtocolGuid
,
1182 This
->DriverBindingHandle
,
1184 EFI_OPEN_PROTOCOL_BY_DRIVER
1186 if (Status
== EFI_ALREADY_STARTED
) {
1190 if (EFI_ERROR (Status
)) {
1195 // Close the USB_HC used to perform the supported test
1197 gBS
->CloseProtocol (
1199 &gEfiUsbHcProtocolGuid
,
1200 This
->DriverBindingHandle
,
1207 // Close the USB_HC2 used to perform the supported test
1209 gBS
->CloseProtocol (
1211 &gEfiUsb2HcProtocolGuid
,
1212 This
->DriverBindingHandle
,
1218 // Open the EFI Device Path protocol needed to perform the supported test
1220 Status
= gBS
->OpenProtocol (
1222 &gEfiDevicePathProtocolGuid
,
1223 (VOID
**) &ParentDevicePath
,
1224 This
->DriverBindingHandle
,
1226 EFI_OPEN_PROTOCOL_BY_DRIVER
1228 if (Status
== EFI_ALREADY_STARTED
) {
1232 if (!EFI_ERROR (Status
)) {
1234 // Close protocol, don't use device path protocol in the Support() function
1236 gBS
->CloseProtocol (
1238 &gEfiDevicePathProtocolGuid
,
1239 This
->DriverBindingHandle
,
1251 Start to process the controller.
1253 @param This The USB bus driver binding instance.
1254 @param Controller The controller to check.
1255 @param RemainingDevicePath The remaining device patch.
1257 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1258 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1260 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1265 UsbBusControllerDriverStart (
1266 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1267 IN EFI_HANDLE Controller
,
1268 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1271 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1275 // Locate the USB bus protocol, if it is found, USB bus
1276 // is already started on this controller.
1278 Status
= gBS
->OpenProtocol (
1280 &mUsbBusProtocolGuid
,
1281 (VOID
**) &UsbBusId
,
1282 This
->DriverBindingHandle
,
1284 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1287 if (EFI_ERROR (Status
)) {
1289 // If first start, build the bus execute environment and install bus protocol
1291 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_IO_BUS_USB
| EFI_P_PC_ENABLE
));
1292 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1293 if (EFI_ERROR (Status
)) {
1297 // Try get the Usb Bus protocol interface again
1299 Status
= gBS
->OpenProtocol (
1301 &mUsbBusProtocolGuid
,
1302 (VOID
**) &UsbBusId
,
1303 This
->DriverBindingHandle
,
1305 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1307 ASSERT (!EFI_ERROR (Status
));
1310 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1311 // usb child device will be recursively connected.
1312 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1313 // All wanted usb child devices will be remembered by the usb bus driver itself.
1314 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1316 // Save the passed in RemainingDevicePath this time
1318 if (RemainingDevicePath
!= NULL
) {
1319 if (IsDevicePathEnd (RemainingDevicePath
)) {
1321 // If RemainingDevicePath is the End of Device Path Node,
1322 // skip enumerate any device and return EFI_SUCESSS
1328 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1329 ASSERT (!EFI_ERROR (Status
));
1331 // Ensure all wanted child usb devices are fully recursively connected
1333 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1334 ASSERT (!EFI_ERROR (Status
));
1343 Stop handle the controller by this USB bus driver.
1345 @param This The USB bus driver binding protocol.
1346 @param Controller The controller to release.
1347 @param NumberOfChildren The child of USB bus that opened controller
1349 @param ChildHandleBuffer The array of child handle.
1351 @retval EFI_SUCCESS The controller or children are stopped.
1352 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1357 UsbBusControllerDriverStop (
1358 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1359 IN EFI_HANDLE Controller
,
1360 IN UINTN NumberOfChildren
,
1361 IN EFI_HANDLE
*ChildHandleBuffer
1365 USB_DEVICE
*RootHub
;
1367 USB_INTERFACE
*RootIf
;
1368 USB_INTERFACE
*UsbIf
;
1369 EFI_USB_BUS_PROTOCOL
*BusId
;
1370 EFI_USB_IO_PROTOCOL
*UsbIo
;
1375 Status
= EFI_SUCCESS
;
1377 if (NumberOfChildren
> 0) {
1379 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1381 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1383 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1384 Status
= gBS
->OpenProtocol (
1385 ChildHandleBuffer
[Index
],
1386 &gEfiUsbIoProtocolGuid
,
1388 This
->DriverBindingHandle
,
1390 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1393 if (EFI_ERROR (Status
)) {
1395 // It is possible that the child has already been released:
1396 // 1. For combo device, free one device will release others.
1397 // 2. If a hub is released, all devices on its down facing
1398 // ports are released also.
1403 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1404 UsbDev
= UsbIf
->Device
;
1406 UsbRemoveDevice (UsbDev
);
1409 gBS
->RestoreTPL (OldTpl
);
1413 DEBUG (( EFI_D_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1416 // Locate USB_BUS for the current host controller
1418 Status
= gBS
->OpenProtocol (
1420 &mUsbBusProtocolGuid
,
1422 This
->DriverBindingHandle
,
1424 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1427 if (EFI_ERROR (Status
)) {
1431 Bus
= USB_BUS_FROM_THIS (BusId
);
1434 // Stop the root hub, then free all the devices
1436 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1438 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1439 UsbHcSetState (Bus
, EfiUsbHcStateHalt
);
1441 RootHub
= Bus
->Devices
[0];
1442 RootIf
= RootHub
->Interfaces
[0];
1444 mUsbRootHubApi
.Release (RootIf
);
1446 ASSERT (Bus
->MaxDevices
<= 256);
1447 for (Index
= 1; Index
< Bus
->MaxDevices
; Index
++) {
1448 if (Bus
->Devices
[Index
] != NULL
) {
1449 UsbRemoveDevice (Bus
->Devices
[Index
]);
1453 gBS
->RestoreTPL (OldTpl
);
1455 gBS
->FreePool (RootIf
);
1456 gBS
->FreePool (RootHub
);
1457 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1458 ASSERT (!EFI_ERROR (Status
));
1461 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1463 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &Bus
->BusId
);
1465 if (Bus
->Usb2Hc
!= NULL
) {
1466 gBS
->CloseProtocol (
1468 &gEfiUsb2HcProtocolGuid
,
1469 This
->DriverBindingHandle
,
1474 if (Bus
->UsbHc
!= NULL
) {
1475 gBS
->CloseProtocol (
1477 &gEfiUsbHcProtocolGuid
,
1478 This
->DriverBindingHandle
,
1483 gBS
->CloseProtocol (
1485 &gEfiDevicePathProtocolGuid
,
1486 This
->DriverBindingHandle
,
1490 gBS
->FreePool (Bus
);