3 Usb Bus Driver Binding and Bus IO Protocol.
5 Copyright (c) 2004 - 2007, Intel Corporation
6 All rights reserved. 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
,
50 USB_IO function to execute a control transfer. This
51 function will execute the USB transfer. If transfer
52 successes, it will sync the internal state of USB bus
55 @param This The USB_IO instance
56 @param Request The control transfer request
57 @param Direction Direction for data stage
58 @param Timeout The time to wait before timeout
59 @param Data The buffer holding the data
60 @param DataLength Then length of the data
61 @param UsbStatus USB result
63 @retval EFI_INVALID_PARAMETER The parameters are invalid
64 @retval EFI_SUCCESS The control transfer succeeded.
65 @retval Others Failed to execute the transfer
70 UsbIoControlTransfer (
71 IN EFI_USB_IO_PROTOCOL
*This
,
72 IN EFI_USB_DEVICE_REQUEST
*Request
,
73 IN EFI_USB_DATA_DIRECTION Direction
,
75 IN OUT VOID
*Data
, OPTIONAL
76 IN UINTN DataLength
, OPTIONAL
82 USB_ENDPOINT_DESC
*EpDesc
;
86 if (UsbStatus
== NULL
) {
87 return EFI_INVALID_PARAMETER
;
90 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
92 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
95 Status
= UsbHcControlTransfer (
109 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
111 // Clear TT buffer when CTRL/BULK split transaction failes
112 // Clear the TRANSLATOR TT buffer, not parent's buffer
114 ASSERT (Dev
->Translator
.TranslatorHubAddress
< USB_MAX_DEVICES
);
115 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
116 UsbHubCtrlClearTTBuffer (
117 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
118 Dev
->Translator
.TranslatorPortNumber
,
129 // Some control transfer will change the device's internal
130 // status, such as Set_Configuration and Set_Interface.
131 // We must synchronize the bus driver's status with that in
132 // device. We ignore the Set_Descriptor request because it's
133 // hardly used by any device, especially in pre-boot environment
137 // Reset the endpoint toggle when endpoint stall is cleared
139 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
140 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
141 USB_TARGET_ENDPOINT
)) &&
142 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
144 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
146 if (EpDesc
!= NULL
) {
152 // Select a new configuration. This is a dangerous action. Upper driver
153 // should stop use its current UsbIo after calling this driver. The old
154 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
155 // ReinstallProtocol since interfaces in different configuration may be
156 // completely irrelevant.
158 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
159 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
160 USB_TARGET_DEVICE
))) {
162 // Don't re-create the USB interfaces if configuration isn't changed.
164 if ((Dev
->ActiveConfig
!= NULL
) &&
165 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
169 DEBUG ((EFI_D_INFO
, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
171 if (Dev
->ActiveConfig
!= NULL
) {
172 UsbRemoveConfig (Dev
);
175 if (Request
->Value
!= 0) {
176 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
180 // Exit now, Old USB_IO is invalid now
186 // A new alternative setting is selected for the interface.
187 // No need to reinstall UsbIo in this case because only
188 // underlying communication endpoints are changed. Functionality
189 // should remains the same.
191 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
192 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
193 USB_TARGET_INTERFACE
)) &&
194 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
196 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
198 if (!EFI_ERROR (Status
)) {
199 ASSERT (UsbIf
->IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
200 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
205 gBS
->RestoreTPL (OldTpl
);
211 Execute a bulk transfer to the device endpoint.
213 @param This The USB IO instance.
214 @param Endpoint The device endpoint.
215 @param Data The data to transfer.
216 @param DataLength The length of the data to transfer.
217 @param Timeout Time to wait before timeout.
218 @param UsbStatus The result of USB transfer.
220 @retval EFI_SUCCESS The bulk transfer is OK.
221 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
222 @retval Others Failed to execute transfer, reason returned in
229 IN EFI_USB_IO_PROTOCOL
*This
,
232 IN OUT UINTN
*DataLength
,
234 OUT UINT32
*UsbStatus
238 USB_INTERFACE
*UsbIf
;
239 USB_ENDPOINT_DESC
*EpDesc
;
245 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
246 (UsbStatus
== NULL
)) {
248 return EFI_INVALID_PARAMETER
;
251 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
253 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
256 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
258 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
259 Status
= EFI_INVALID_PARAMETER
;
264 Toggle
= EpDesc
->Toggle
;
265 Status
= UsbHcBulkTransfer (
270 EpDesc
->Desc
.MaxPacketSize
,
280 EpDesc
->Toggle
= Toggle
;
282 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
284 // Clear TT buffer when CTRL/BULK split transaction failes.
285 // Clear the TRANSLATOR TT buffer, not parent's buffer
287 ASSERT (Dev
->Translator
.TranslatorHubAddress
< USB_MAX_DEVICES
);
288 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
289 UsbHubCtrlClearTTBuffer (
290 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
291 Dev
->Translator
.TranslatorPortNumber
,
300 gBS
->RestoreTPL (OldTpl
);
306 Execute a synchronous interrupt transfer.
308 @param This The USB IO instance.
309 @param Endpoint The device endpoint.
310 @param Data The data to transfer.
311 @param DataLength The length of the data to transfer.
312 @param Timeout Time to wait before timeout.
313 @param UsbStatus The result of USB transfer.
315 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
316 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
317 @retval Others Failed to execute transfer, reason returned in
323 UsbIoSyncInterruptTransfer (
324 IN EFI_USB_IO_PROTOCOL
*This
,
327 IN OUT UINTN
*DataLength
,
329 OUT UINT32
*UsbStatus
333 USB_INTERFACE
*UsbIf
;
334 USB_ENDPOINT_DESC
*EpDesc
;
339 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
340 (UsbStatus
== NULL
)) {
342 return EFI_INVALID_PARAMETER
;
345 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
347 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
350 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
352 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
353 Status
= EFI_INVALID_PARAMETER
;
357 Toggle
= EpDesc
->Toggle
;
358 Status
= UsbHcSyncInterruptTransfer (
363 EpDesc
->Desc
.MaxPacketSize
,
372 EpDesc
->Toggle
= Toggle
;
375 gBS
->RestoreTPL (OldTpl
);
381 Queue a new asynchronous interrupt transfer, or remove the old
382 request if (IsNewTransfer == FALSE).
384 @param This The USB_IO instance.
385 @param Endpoint The device endpoint.
386 @param IsNewTransfer Whether this is a new request, if it's old, remove
388 @param PollInterval The interval to poll the transfer result, (in ms).
389 @param DataLength The length of perodic data transfer.
390 @param Callback The function to call periodicaly when transfer is
392 @param Context The context to the callback.
394 @retval EFI_SUCCESS New transfer is queued or old request is removed.
395 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
396 @retval Others Failed to queue the new request or remove the old
402 UsbIoAsyncInterruptTransfer (
403 IN EFI_USB_IO_PROTOCOL
*This
,
405 IN BOOLEAN IsNewTransfer
,
406 IN UINTN PollInterval
, OPTIONAL
407 IN UINTN DataLength
, OPTIONAL
408 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
409 IN VOID
*Context OPTIONAL
413 USB_INTERFACE
*UsbIf
;
414 USB_ENDPOINT_DESC
*EpDesc
;
419 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
420 return EFI_INVALID_PARAMETER
;
423 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
424 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
427 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
429 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
430 Status
= EFI_INVALID_PARAMETER
;
434 Toggle
= EpDesc
->Toggle
;
435 Status
= UsbHcAsyncInterruptTransfer (
440 EpDesc
->Desc
.MaxPacketSize
,
450 EpDesc
->Toggle
= Toggle
;
453 gBS
->RestoreTPL (OldTpl
);
459 Execute a synchronous isochronous transfer.
461 @param This The USB IO instance.
462 @param DeviceEndpoint The device endpoint.
463 @param Data The data to transfer.
464 @param DataLength The length of the data to transfer.
465 @param UsbStatus The result of USB transfer.
467 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
472 UsbIoIsochronousTransfer (
473 IN EFI_USB_IO_PROTOCOL
*This
,
474 IN UINT8 DeviceEndpoint
,
480 return EFI_UNSUPPORTED
;
485 Queue an asynchronous isochronous transfer.
487 @param This The USB_IO instance.
488 @param DeviceEndpoint The device endpoint.
489 @param Data The data to transfer.
490 @param DataLength The length of perodic data transfer.
491 @param IsochronousCallBack The function to call periodicaly when transfer is
493 @param Context The context to the callback.
495 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
500 UsbIoAsyncIsochronousTransfer (
501 IN EFI_USB_IO_PROTOCOL
*This
,
502 IN UINT8 DeviceEndpoint
,
505 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
506 IN VOID
*Context OPTIONAL
509 return EFI_UNSUPPORTED
;
514 Retrieve the device descriptor of the device.
516 @param This The USB IO instance.
517 @param Descriptor The variable to receive the device descriptor.
519 @retval EFI_SUCCESS The device descriptor is returned.
520 @retval EFI_INVALID_PARAMETER The parameter is invalid.
525 UsbIoGetDeviceDescriptor (
526 IN EFI_USB_IO_PROTOCOL
*This
,
527 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
531 USB_INTERFACE
*UsbIf
;
534 if (Descriptor
== NULL
) {
535 return EFI_INVALID_PARAMETER
;
538 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
540 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
543 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
545 gBS
->RestoreTPL (OldTpl
);
551 Return the configuration descriptor of the current active configuration.
553 @param This The USB IO instance.
554 @param Descriptor The USB configuration descriptor.
556 @retval EFI_SUCCESS The active configuration descriptor is returned.
557 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
558 @retval EFI_NOT_FOUND Currently no active configuration is selected.
563 UsbIoGetActiveConfigDescriptor (
564 IN EFI_USB_IO_PROTOCOL
*This
,
565 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
569 USB_INTERFACE
*UsbIf
;
573 if (Descriptor
== NULL
) {
574 return EFI_INVALID_PARAMETER
;
577 Status
= EFI_SUCCESS
;
578 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
580 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
583 if (Dev
->ActiveConfig
== NULL
) {
584 Status
= EFI_NOT_FOUND
;
588 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
591 gBS
->RestoreTPL (OldTpl
);
597 Retrieve the active interface setting descriptor for this USB IO instance.
599 @param This The USB IO instance.
600 @param Descriptor The variable to receive active interface setting.
602 @retval EFI_SUCCESS The active interface setting is returned.
603 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
608 UsbIoGetInterfaceDescriptor (
609 IN EFI_USB_IO_PROTOCOL
*This
,
610 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
613 USB_INTERFACE
*UsbIf
;
616 if (Descriptor
== NULL
) {
617 return EFI_INVALID_PARAMETER
;
620 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
622 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
623 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
625 gBS
->RestoreTPL (OldTpl
);
631 Retrieve the endpoint descriptor from this interface setting.
633 @param This The USB IO instance.
634 @param Index The index (start from zero) of the endpoint to
636 @param Descriptor The variable to receive the descriptor.
638 @retval EFI_SUCCESS The endpoint descriptor is returned.
639 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
644 UsbIoGetEndpointDescriptor (
645 IN EFI_USB_IO_PROTOCOL
*This
,
647 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
650 USB_INTERFACE
*UsbIf
;
653 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
655 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
657 if ((Descriptor
== NULL
) || (Index
> 15)) {
658 gBS
->RestoreTPL (OldTpl
);
659 return EFI_INVALID_PARAMETER
;
662 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
663 gBS
->RestoreTPL (OldTpl
);
664 return EFI_NOT_FOUND
;
669 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
670 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
673 gBS
->RestoreTPL (OldTpl
);
679 Retrieve the supported language ID table from the device.
681 @param This The USB IO instance.
682 @param LangIDTable The table to return the language IDs.
683 @param TableSize The number of supported languanges.
685 @retval EFI_SUCCESS The language ID is return.
690 UsbIoGetSupportedLanguages (
691 IN EFI_USB_IO_PROTOCOL
*This
,
692 OUT UINT16
**LangIDTable
,
693 OUT UINT16
*TableSize
697 USB_INTERFACE
*UsbIf
;
700 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
702 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
705 *LangIDTable
= Dev
->LangId
;
706 *TableSize
= Dev
->TotalLangId
;
708 gBS
->RestoreTPL (OldTpl
);
714 Retrieve an indexed string in the language of LangID.
716 @param This The USB IO instance.
717 @param LangID The language ID of the string to retrieve.
718 @param StringIndex The index of the string.
719 @param String The variable to receive the string.
721 @retval EFI_SUCCESS The string is returned.
722 @retval EFI_NOT_FOUND No such string existed.
727 UsbIoGetStringDescriptor (
728 IN EFI_USB_IO_PROTOCOL
*This
,
730 IN UINT8 StringIndex
,
735 USB_INTERFACE
*UsbIf
;
736 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
742 if ((StringIndex
== 0) || (LangID
== 0)) {
743 return EFI_NOT_FOUND
;
746 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
748 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
752 // Check whether language ID is supported
754 Status
= EFI_NOT_FOUND
;
756 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
757 ASSERT (Index
< USB_MAX_LANG_ID
);
758 if (Dev
->LangId
[Index
] == LangID
) {
763 if (Index
== Dev
->TotalLangId
) {
768 // Retrieve the string descriptor then allocate a buffer
769 // to hold the string itself.
771 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
773 if (StrDesc
== NULL
) {
777 if (StrDesc
->Length
<= 2) {
781 Buf
= AllocateZeroPool (StrDesc
->Length
);
784 Status
= EFI_OUT_OF_RESOURCES
;
788 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
789 *String
= (CHAR16
*) Buf
;
790 Status
= EFI_SUCCESS
;
793 gBS
->FreePool (StrDesc
);
796 gBS
->RestoreTPL (OldTpl
);
802 Reset the device, then if that succeeds, reconfigure the
803 device with its address and current active configuration.
805 @param This The USB IO instance.
807 @retval EFI_SUCCESS The device is reset and configured.
808 @retval Others Failed to reset the device.
814 IN EFI_USB_IO_PROTOCOL
*This
817 USB_INTERFACE
*UsbIf
;
818 USB_INTERFACE
*HubIf
;
824 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
826 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
830 Status
= EFI_INVALID_PARAMETER
;
834 HubIf
= Dev
->ParentIf
;
835 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
837 if (EFI_ERROR (Status
)) {
838 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
839 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
845 // Reset the device to its current address. The device now has a
846 // address of ZERO, so need to set Dev->Address to zero first for
847 // host to communicate with the device
849 Address
= Dev
->Address
;
851 Status
= UsbSetAddress (Dev
, Address
);
852 Dev
->Address
= Address
;
854 if (EFI_ERROR (Status
)) {
855 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set address for device %d - %r\n",
861 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
863 DEBUG (( EFI_D_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address
));
866 // Reset the current active configure, after this device
867 // is in CONFIGURED state.
869 if (Dev
->ActiveConfig
!= NULL
) {
870 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
872 if (EFI_ERROR (Status
)) {
873 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set configure for device %d - %r\n",
879 gBS
->RestoreTPL (OldTpl
);
885 Install Usb Bus Protocol on host controller, and start the Usb bus.
887 @param This The USB bus driver binding instance.
888 @param Controller The controller to check.
889 @param RemainingDevicePath The remaining device patch.
891 @retval EFI_SUCCESS The controller is controlled by the usb bus.
892 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
893 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
898 UsbBusBuildProtocol (
899 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
900 IN EFI_HANDLE Controller
,
901 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
906 USB_INTERFACE
*RootIf
;
910 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
912 if (UsbBus
== NULL
) {
913 return EFI_OUT_OF_RESOURCES
;
916 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
917 UsbBus
->HostHandle
= Controller
;
919 Status
= gBS
->OpenProtocol (
921 &gEfiDevicePathProtocolGuid
,
922 (VOID
**) &UsbBus
->DevicePath
,
923 This
->DriverBindingHandle
,
925 EFI_OPEN_PROTOCOL_BY_DRIVER
928 if (EFI_ERROR (Status
)) {
929 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open device path %r\n", Status
));
936 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
937 // This is for backward compatibility with EFI 1.x. In UEFI
938 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
939 // and USB_HC because EHCI driver will install both protocols
940 // (for the same reason). If we don't consume both of them,
941 // the unconsumed one may be opened by others.
943 Status
= gBS
->OpenProtocol (
945 &gEfiUsb2HcProtocolGuid
,
946 (VOID
**) &(UsbBus
->Usb2Hc
),
947 This
->DriverBindingHandle
,
949 EFI_OPEN_PROTOCOL_BY_DRIVER
952 Status2
= gBS
->OpenProtocol (
954 &gEfiUsbHcProtocolGuid
,
955 (VOID
**) &(UsbBus
->UsbHc
),
956 This
->DriverBindingHandle
,
958 EFI_OPEN_PROTOCOL_BY_DRIVER
961 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
962 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
964 Status
= EFI_DEVICE_ERROR
;
968 UsbHcReset (UsbBus
, EFI_USB_HC_RESET_GLOBAL
);
969 UsbHcSetState (UsbBus
, EfiUsbHcStateOperational
);
972 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
974 Status
= gBS
->InstallProtocolInterface (
976 &mUsbBusProtocolGuid
,
977 EFI_NATIVE_INTERFACE
,
981 if (EFI_ERROR (Status
)) {
982 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to install bus protocol %r\n", Status
));
987 // Initial the wanted child device path list, and add first RemainingDevicePath
989 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
990 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
991 ASSERT (!EFI_ERROR (Status
));
993 // Create a fake usb device for root hub
995 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
997 if (RootHub
== NULL
) {
998 Status
= EFI_OUT_OF_RESOURCES
;
999 goto UNINSTALL_USBBUS
;
1002 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1004 if (RootIf
== NULL
) {
1006 Status
= EFI_OUT_OF_RESOURCES
;
1010 RootHub
->Bus
= UsbBus
;
1011 RootHub
->NumOfInterface
= 1;
1012 RootHub
->Interfaces
[0] = RootIf
;
1013 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1014 RootIf
->Device
= RootHub
;
1015 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1017 Status
= mUsbRootHubApi
.Init (RootIf
);
1019 if (EFI_ERROR (Status
)) {
1020 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to init root hub %r\n", Status
));
1024 UsbBus
->Devices
[0] = RootHub
;
1026 DEBUG ((EFI_D_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1030 if (RootIf
!= NULL
) {
1033 if (RootHub
!= NULL
) {
1038 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &UsbBus
->BusId
);
1041 if (UsbBus
->Usb2Hc
!= NULL
) {
1042 gBS
->CloseProtocol (
1044 &gEfiUsb2HcProtocolGuid
,
1045 This
->DriverBindingHandle
,
1049 if (UsbBus
->UsbHc
!= NULL
) {
1050 gBS
->CloseProtocol (
1052 &gEfiUsbHcProtocolGuid
,
1053 This
->DriverBindingHandle
,
1057 gBS
->CloseProtocol (
1059 &gEfiDevicePathProtocolGuid
,
1060 This
->DriverBindingHandle
,
1065 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to start bus driver %r\n", Status
));
1071 The USB bus driver entry pointer.
1073 @param ImageHandle The driver image handle.
1074 @param SystemTable The system table.
1076 @return EFI_SUCCESS The component name protocol is installed.
1077 @return Others Failed to init the usb driver.
1082 UsbBusDriverEntryPoint (
1083 IN EFI_HANDLE ImageHandle
,
1084 IN EFI_SYSTEM_TABLE
*SystemTable
1087 return EfiLibInstallDriverBindingComponentName2 (
1090 &mUsbBusDriverBinding
,
1092 &mUsbBusComponentName
,
1093 &mUsbBusComponentName2
1099 Check whether USB bus driver support this device.
1101 @param This The USB bus driver binding protocol.
1102 @param Controller The controller handle to check.
1103 @param RemainingDevicePath The remaining device path.
1105 @retval EFI_SUCCESS The bus supports this controller.
1106 @retval EFI_UNSUPPORTED This device isn't supported.
1111 UsbBusControllerDriverSupported (
1112 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1113 IN EFI_HANDLE Controller
,
1114 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1117 EFI_DEV_PATH_PTR DevicePathNode
;
1118 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1119 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1120 EFI_USB_HC_PROTOCOL
*UsbHc
;
1124 // Check whether device path is valid
1126 if (RemainingDevicePath
!= NULL
) {
1127 DevicePathNode
.DevPath
= RemainingDevicePath
;
1129 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1130 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
&&
1131 DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
1132 && DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
1135 return EFI_UNSUPPORTED
;
1139 Status
= gBS
->OpenProtocol (
1141 &gEfiDevicePathProtocolGuid
,
1142 (VOID
**) &ParentDevicePath
,
1143 This
->DriverBindingHandle
,
1145 EFI_OPEN_PROTOCOL_BY_DRIVER
1148 if (Status
== EFI_ALREADY_STARTED
) {
1152 if (EFI_ERROR (Status
)) {
1156 gBS
->CloseProtocol (
1158 &gEfiDevicePathProtocolGuid
,
1159 This
->DriverBindingHandle
,
1164 // Check whether USB_HC2 protocol is installed
1166 Status
= gBS
->OpenProtocol (
1168 &gEfiUsb2HcProtocolGuid
,
1170 This
->DriverBindingHandle
,
1172 EFI_OPEN_PROTOCOL_BY_DRIVER
1175 if (Status
== EFI_ALREADY_STARTED
) {
1179 if (!EFI_ERROR (Status
)) {
1180 gBS
->CloseProtocol (
1182 &gEfiUsb2HcProtocolGuid
,
1183 This
->DriverBindingHandle
,
1191 // If failed to open USB_HC2, fall back to USB_HC
1193 Status
= gBS
->OpenProtocol (
1195 &gEfiUsbHcProtocolGuid
,
1197 This
->DriverBindingHandle
,
1199 EFI_OPEN_PROTOCOL_BY_DRIVER
1202 if (Status
== EFI_ALREADY_STARTED
) {
1206 if (!EFI_ERROR (Status
)) {
1207 gBS
->CloseProtocol (
1209 &gEfiUsbHcProtocolGuid
,
1210 This
->DriverBindingHandle
,
1220 Start to process the controller.
1222 @param This The USB bus driver binding instance.
1223 @param Controller The controller to check.
1224 @param RemainingDevicePath The remaining device patch.
1226 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1227 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1229 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1234 UsbBusControllerDriverStart (
1235 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1236 IN EFI_HANDLE Controller
,
1237 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1240 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1244 // Locate the USB bus protocol, if it is found, USB bus
1245 // is already started on this controller.
1247 Status
= gBS
->OpenProtocol (
1249 &mUsbBusProtocolGuid
,
1250 (VOID
**) &UsbBusId
,
1251 This
->DriverBindingHandle
,
1253 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1256 if (EFI_ERROR (Status
)) {
1258 // If first start, build the bus execute environment and install bus protocol
1260 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1261 if (EFI_ERROR (Status
)) {
1265 // Try get the Usb Bus protocol interface again
1267 Status
= gBS
->OpenProtocol (
1269 &mUsbBusProtocolGuid
,
1270 (VOID
**) &UsbBusId
,
1271 This
->DriverBindingHandle
,
1273 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1275 ASSERT (!EFI_ERROR (Status
));
1278 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1279 // usb child device will be recursively connected.
1280 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1281 // All wanted usb child devices will be remembered by the usb bus driver itself.
1282 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1284 // Save the passed in RemainingDevicePath this time
1286 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1287 ASSERT (!EFI_ERROR (Status
));
1289 // Ensure all wanted child usb devices are fully recursively connected
1291 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1292 ASSERT (!EFI_ERROR (Status
));
1301 Stop handle the controller by this USB bus driver.
1303 @param This The USB bus driver binding protocol.
1304 @param Controller The controller to release.
1305 @param NumberOfChildren The child of USB bus that opened controller
1307 @param ChildHandleBuffer The array of child handle.
1309 @retval EFI_SUCCESS The controller or children are stopped.
1310 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1315 UsbBusControllerDriverStop (
1316 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1317 IN EFI_HANDLE Controller
,
1318 IN UINTN NumberOfChildren
,
1319 IN EFI_HANDLE
*ChildHandleBuffer
1323 USB_DEVICE
*RootHub
;
1325 USB_INTERFACE
*RootIf
;
1326 USB_INTERFACE
*UsbIf
;
1327 EFI_USB_BUS_PROTOCOL
*BusId
;
1328 EFI_USB_IO_PROTOCOL
*UsbIo
;
1333 Status
= EFI_SUCCESS
;
1335 if (NumberOfChildren
> 0) {
1337 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1339 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1341 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1342 Status
= gBS
->OpenProtocol (
1343 ChildHandleBuffer
[Index
],
1344 &gEfiUsbIoProtocolGuid
,
1346 This
->DriverBindingHandle
,
1348 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1351 if (EFI_ERROR (Status
)) {
1353 // It is possible that the child has already been released:
1354 // 1. For combo device, free one device will release others.
1355 // 2. If a hub is released, all devices on its down facing
1356 // ports are released also.
1361 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1362 UsbDev
= UsbIf
->Device
;
1364 UsbRemoveDevice (UsbDev
);
1367 gBS
->RestoreTPL (OldTpl
);
1371 DEBUG (( EFI_D_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1374 // Locate USB_BUS for the current host controller
1376 Status
= gBS
->OpenProtocol (
1378 &mUsbBusProtocolGuid
,
1380 This
->DriverBindingHandle
,
1382 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1385 if (EFI_ERROR (Status
)) {
1389 Bus
= USB_BUS_FROM_THIS (BusId
);
1392 // Stop the root hub, then free all the devices
1394 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1396 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1397 UsbHcSetState (Bus
, EfiUsbHcStateHalt
);
1399 RootHub
= Bus
->Devices
[0];
1400 RootIf
= RootHub
->Interfaces
[0];
1402 mUsbRootHubApi
.Release (RootIf
);
1404 for (Index
= 1; Index
< USB_MAX_DEVICES
; Index
++) {
1405 if (Bus
->Devices
[Index
] != NULL
) {
1406 UsbRemoveDevice (Bus
->Devices
[Index
]);
1410 gBS
->RestoreTPL (OldTpl
);
1412 gBS
->FreePool (RootIf
);
1413 gBS
->FreePool (RootHub
);
1414 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1415 ASSERT (!EFI_ERROR (Status
));
1418 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1420 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &Bus
->BusId
);
1422 if (Bus
->Usb2Hc
!= NULL
) {
1423 gBS
->CloseProtocol (
1425 &gEfiUsb2HcProtocolGuid
,
1426 This
->DriverBindingHandle
,
1431 if (Bus
->UsbHc
!= NULL
) {
1432 gBS
->CloseProtocol (
1434 &gEfiUsbHcProtocolGuid
,
1435 This
->DriverBindingHandle
,
1440 gBS
->CloseProtocol (
1442 &gEfiDevicePathProtocolGuid
,
1443 This
->DriverBindingHandle
,
1447 gBS
->FreePool (Bus
);