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 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 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
203 gBS
->RestoreTPL (OldTpl
);
209 Execute a bulk transfer to the device endpoint.
211 @param This The USB IO instance.
212 @param Endpoint The device endpoint.
213 @param Data The data to transfer.
214 @param DataLength The length of the data to transfer.
215 @param Timeout Time to wait before timeout.
216 @param UsbStatus The result of USB transfer.
218 @retval EFI_SUCCESS The bulk transfer is OK.
219 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
220 @retval Others Failed to execute transfer, reason returned in
227 IN EFI_USB_IO_PROTOCOL
*This
,
230 IN OUT UINTN
*DataLength
,
232 OUT UINT32
*UsbStatus
236 USB_INTERFACE
*UsbIf
;
237 USB_ENDPOINT_DESC
*EpDesc
;
243 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
244 (UsbStatus
== NULL
)) {
246 return EFI_INVALID_PARAMETER
;
249 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
251 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
254 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
256 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
257 Status
= EFI_INVALID_PARAMETER
;
262 Toggle
= EpDesc
->Toggle
;
263 Status
= UsbHcBulkTransfer (
268 EpDesc
->Desc
.MaxPacketSize
,
278 EpDesc
->Toggle
= Toggle
;
280 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
282 // Clear TT buffer when CTRL/BULK split transaction failes.
283 // Clear the TRANSLATOR TT buffer, not parent's buffer
285 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
286 UsbHubCtrlClearTTBuffer (
287 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
288 Dev
->Translator
.TranslatorPortNumber
,
297 gBS
->RestoreTPL (OldTpl
);
303 Execute a synchronous interrupt transfer.
305 @param This The USB IO instance.
306 @param Endpoint The device endpoint.
307 @param Data The data to transfer.
308 @param DataLength The length of the data to transfer.
309 @param Timeout Time to wait before timeout.
310 @param UsbStatus The result of USB transfer.
312 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
313 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
314 @retval Others Failed to execute transfer, reason returned in
320 UsbIoSyncInterruptTransfer (
321 IN EFI_USB_IO_PROTOCOL
*This
,
324 IN OUT UINTN
*DataLength
,
326 OUT UINT32
*UsbStatus
330 USB_INTERFACE
*UsbIf
;
331 USB_ENDPOINT_DESC
*EpDesc
;
336 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
337 (UsbStatus
== NULL
)) {
339 return EFI_INVALID_PARAMETER
;
342 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
344 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
347 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
349 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
350 Status
= EFI_INVALID_PARAMETER
;
354 Toggle
= EpDesc
->Toggle
;
355 Status
= UsbHcSyncInterruptTransfer (
360 EpDesc
->Desc
.MaxPacketSize
,
369 EpDesc
->Toggle
= Toggle
;
372 gBS
->RestoreTPL (OldTpl
);
378 Queue a new asynchronous interrupt transfer, or remove the old
379 request if (IsNewTransfer == FALSE).
381 @param This The USB_IO instance.
382 @param Endpoint The device endpoint.
383 @param IsNewTransfer Whether this is a new request, if it's old, remove
385 @param PollInterval The interval to poll the transfer result, (in ms).
386 @param DataLength The length of perodic data transfer.
387 @param Callback The function to call periodicaly when transfer is
389 @param Context The context to the callback.
391 @retval EFI_SUCCESS New transfer is queued or old request is removed.
392 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
393 @retval Others Failed to queue the new request or remove the old
399 UsbIoAsyncInterruptTransfer (
400 IN EFI_USB_IO_PROTOCOL
*This
,
402 IN BOOLEAN IsNewTransfer
,
403 IN UINTN PollInterval
, OPTIONAL
404 IN UINTN DataLength
, OPTIONAL
405 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
406 IN VOID
*Context OPTIONAL
410 USB_INTERFACE
*UsbIf
;
411 USB_ENDPOINT_DESC
*EpDesc
;
416 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
417 return EFI_INVALID_PARAMETER
;
420 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
421 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
424 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
426 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
427 Status
= EFI_INVALID_PARAMETER
;
431 Toggle
= EpDesc
->Toggle
;
432 Status
= UsbHcAsyncInterruptTransfer (
437 EpDesc
->Desc
.MaxPacketSize
,
447 EpDesc
->Toggle
= Toggle
;
450 gBS
->RestoreTPL (OldTpl
);
456 Execute a synchronous isochronous transfer.
458 @param This The USB IO instance.
459 @param DeviceEndpoint The device endpoint.
460 @param Data The data to transfer.
461 @param DataLength The length of the data to transfer.
462 @param UsbStatus The result of USB transfer.
464 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
469 UsbIoIsochronousTransfer (
470 IN EFI_USB_IO_PROTOCOL
*This
,
471 IN UINT8 DeviceEndpoint
,
477 return EFI_UNSUPPORTED
;
482 Queue an asynchronous isochronous transfer.
484 @param This The USB_IO instance.
485 @param DeviceEndpoint The device endpoint.
486 @param Data The data to transfer.
487 @param DataLength The length of perodic data transfer.
488 @param IsochronousCallBack The function to call periodicaly when transfer is
490 @param Context The context to the callback.
492 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
497 UsbIoAsyncIsochronousTransfer (
498 IN EFI_USB_IO_PROTOCOL
*This
,
499 IN UINT8 DeviceEndpoint
,
502 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
503 IN VOID
*Context OPTIONAL
506 return EFI_UNSUPPORTED
;
511 Retrieve the device descriptor of the device.
513 @param This The USB IO instance.
514 @param Descriptor The variable to receive the device descriptor.
516 @retval EFI_SUCCESS The device descriptor is returned.
517 @retval EFI_INVALID_PARAMETER The parameter is invalid.
522 UsbIoGetDeviceDescriptor (
523 IN EFI_USB_IO_PROTOCOL
*This
,
524 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
528 USB_INTERFACE
*UsbIf
;
531 if (Descriptor
== NULL
) {
532 return EFI_INVALID_PARAMETER
;
535 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
537 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
540 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
542 gBS
->RestoreTPL (OldTpl
);
548 Return the configuration descriptor of the current active configuration.
550 @param This The USB IO instance.
551 @param Descriptor The USB configuration descriptor.
553 @retval EFI_SUCCESS The active configuration descriptor is returned.
554 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
555 @retval EFI_NOT_FOUND Currently no active configuration is selected.
560 UsbIoGetActiveConfigDescriptor (
561 IN EFI_USB_IO_PROTOCOL
*This
,
562 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
566 USB_INTERFACE
*UsbIf
;
570 if (Descriptor
== NULL
) {
571 return EFI_INVALID_PARAMETER
;
574 Status
= EFI_SUCCESS
;
575 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
577 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
580 if (Dev
->ActiveConfig
== NULL
) {
581 Status
= EFI_NOT_FOUND
;
585 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
588 gBS
->RestoreTPL (OldTpl
);
594 Retrieve the active interface setting descriptor for this USB IO instance.
596 @param This The USB IO instance.
597 @param Descriptor The variable to receive active interface setting.
599 @retval EFI_SUCCESS The active interface setting is returned.
600 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
605 UsbIoGetInterfaceDescriptor (
606 IN EFI_USB_IO_PROTOCOL
*This
,
607 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
610 USB_INTERFACE
*UsbIf
;
613 if (Descriptor
== NULL
) {
614 return EFI_INVALID_PARAMETER
;
617 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
619 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
620 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
622 gBS
->RestoreTPL (OldTpl
);
628 Retrieve the endpoint descriptor from this interface setting.
630 @param This The USB IO instance.
631 @param Index The index (start from zero) of the endpoint to
633 @param Descriptor The variable to receive the descriptor.
635 @retval EFI_SUCCESS The endpoint descriptor is returned.
636 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
641 UsbIoGetEndpointDescriptor (
642 IN EFI_USB_IO_PROTOCOL
*This
,
644 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
647 USB_INTERFACE
*UsbIf
;
650 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
652 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
654 if ((Descriptor
== NULL
) || (Index
> 15)) {
655 gBS
->RestoreTPL (OldTpl
);
656 return EFI_INVALID_PARAMETER
;
659 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
660 gBS
->RestoreTPL (OldTpl
);
661 return EFI_NOT_FOUND
;
666 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
667 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
670 gBS
->RestoreTPL (OldTpl
);
676 Retrieve the supported language ID table from the device.
678 @param This The USB IO instance.
679 @param LangIDTable The table to return the language IDs.
680 @param TableSize The number of supported languanges.
682 @retval EFI_SUCCESS The language ID is return.
687 UsbIoGetSupportedLanguages (
688 IN EFI_USB_IO_PROTOCOL
*This
,
689 OUT UINT16
**LangIDTable
,
690 OUT UINT16
*TableSize
694 USB_INTERFACE
*UsbIf
;
697 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
699 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
702 *LangIDTable
= Dev
->LangId
;
703 *TableSize
= Dev
->TotalLangId
;
705 gBS
->RestoreTPL (OldTpl
);
711 Retrieve an indexed string in the language of LangID.
713 @param This The USB IO instance.
714 @param LangID The language ID of the string to retrieve.
715 @param StringIndex The index of the string.
716 @param String The variable to receive the string.
718 @retval EFI_SUCCESS The string is returned.
719 @retval EFI_NOT_FOUND No such string existed.
724 UsbIoGetStringDescriptor (
725 IN EFI_USB_IO_PROTOCOL
*This
,
727 IN UINT8 StringIndex
,
732 USB_INTERFACE
*UsbIf
;
733 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
739 if ((StringIndex
== 0) || (LangID
== 0)) {
740 return EFI_NOT_FOUND
;
743 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
745 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
749 // Check whether language ID is supported
751 Status
= EFI_NOT_FOUND
;
753 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
754 if (Dev
->LangId
[Index
] == LangID
) {
759 if (Index
== Dev
->TotalLangId
) {
764 // Retrieve the string descriptor then allocate a buffer
765 // to hold the string itself.
767 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
769 if (StrDesc
== NULL
) {
773 if (StrDesc
->Length
<= 2) {
777 Buf
= AllocateZeroPool (StrDesc
->Length
);
780 Status
= EFI_OUT_OF_RESOURCES
;
784 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
785 *String
= (CHAR16
*) Buf
;
786 Status
= EFI_SUCCESS
;
789 gBS
->FreePool (StrDesc
);
792 gBS
->RestoreTPL (OldTpl
);
798 Reset the device, then if that succeeds, reconfigure the
799 device with its address and current active configuration.
801 @param This The USB IO instance.
803 @retval EFI_SUCCESS The device is reset and configured.
804 @retval Others Failed to reset the device.
810 IN EFI_USB_IO_PROTOCOL
*This
813 USB_INTERFACE
*UsbIf
;
814 USB_INTERFACE
*HubIf
;
820 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
822 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
826 Status
= EFI_INVALID_PARAMETER
;
830 HubIf
= Dev
->ParentIf
;
831 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
833 if (EFI_ERROR (Status
)) {
834 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
835 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
841 // Reset the device to its current address. The device now has a
842 // address of ZERO, so need to set Dev->Address to zero first for
843 // host to communicate with the device
845 Address
= Dev
->Address
;
847 Status
= UsbSetAddress (Dev
, Address
);
848 Dev
->Address
= Address
;
850 if (EFI_ERROR (Status
)) {
851 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set address for device %d - %r\n",
857 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
859 DEBUG (( EFI_D_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address
));
862 // Reset the current active configure, after this device
863 // is in CONFIGURED state.
865 if (Dev
->ActiveConfig
!= NULL
) {
866 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
868 if (EFI_ERROR (Status
)) {
869 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set configure for device %d - %r\n",
875 gBS
->RestoreTPL (OldTpl
);
881 Install Usb Bus Protocol on host controller, and start the Usb bus.
883 @param This The USB bus driver binding instance.
884 @param Controller The controller to check.
885 @param RemainingDevicePath The remaining device patch.
887 @retval EFI_SUCCESS The controller is controlled by the usb bus.
888 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
889 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
894 UsbBusBuildProtocol (
895 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
896 IN EFI_HANDLE Controller
,
897 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
902 USB_INTERFACE
*RootIf
;
906 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
908 if (UsbBus
== NULL
) {
909 return EFI_OUT_OF_RESOURCES
;
912 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
913 UsbBus
->HostHandle
= Controller
;
915 Status
= gBS
->OpenProtocol (
917 &gEfiDevicePathProtocolGuid
,
918 (VOID
**) &UsbBus
->DevicePath
,
919 This
->DriverBindingHandle
,
921 EFI_OPEN_PROTOCOL_BY_DRIVER
924 if (EFI_ERROR (Status
)) {
925 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open device path %r\n", Status
));
932 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
933 // This is for backward compatibility with EFI 1.x. In UEFI
934 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
935 // and USB_HC because EHCI driver will install both protocols
936 // (for the same reason). If we don't consume both of them,
937 // the unconsumed one may be opened by others.
939 Status
= gBS
->OpenProtocol (
941 &gEfiUsb2HcProtocolGuid
,
942 (VOID
**) &(UsbBus
->Usb2Hc
),
943 This
->DriverBindingHandle
,
945 EFI_OPEN_PROTOCOL_BY_DRIVER
948 Status2
= gBS
->OpenProtocol (
950 &gEfiUsbHcProtocolGuid
,
951 (VOID
**) &(UsbBus
->UsbHc
),
952 This
->DriverBindingHandle
,
954 EFI_OPEN_PROTOCOL_BY_DRIVER
957 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
958 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
960 Status
= EFI_DEVICE_ERROR
;
964 UsbHcReset (UsbBus
, EFI_USB_HC_RESET_GLOBAL
);
965 UsbHcSetState (UsbBus
, EfiUsbHcStateOperational
);
968 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
970 Status
= gBS
->InstallProtocolInterface (
972 &mUsbBusProtocolGuid
,
973 EFI_NATIVE_INTERFACE
,
977 if (EFI_ERROR (Status
)) {
978 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to install bus protocol %r\n", Status
));
983 // Initial the wanted child device path list, and add first RemainingDevicePath
985 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
986 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
987 ASSERT (!EFI_ERROR (Status
));
989 // Create a fake usb device for root hub
991 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
993 if (RootHub
== NULL
) {
994 Status
= EFI_OUT_OF_RESOURCES
;
995 goto UNINSTALL_USBBUS
;
998 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1000 if (RootIf
== NULL
) {
1002 Status
= EFI_OUT_OF_RESOURCES
;
1006 RootHub
->Bus
= UsbBus
;
1007 RootHub
->NumOfInterface
= 1;
1008 RootHub
->Interfaces
[0] = RootIf
;
1009 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1010 RootIf
->Device
= RootHub
;
1011 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1013 Status
= mUsbRootHubApi
.Init (RootIf
);
1015 if (EFI_ERROR (Status
)) {
1016 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to init root hub %r\n", Status
));
1020 UsbBus
->Devices
[0] = RootHub
;
1022 DEBUG ((EFI_D_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1026 if (RootIf
!= NULL
) {
1029 if (RootHub
!= NULL
) {
1034 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &UsbBus
->BusId
);
1037 if (UsbBus
->Usb2Hc
!= NULL
) {
1038 gBS
->CloseProtocol (
1040 &gEfiUsb2HcProtocolGuid
,
1041 This
->DriverBindingHandle
,
1045 if (UsbBus
->UsbHc
!= NULL
) {
1046 gBS
->CloseProtocol (
1048 &gEfiUsbHcProtocolGuid
,
1049 This
->DriverBindingHandle
,
1053 gBS
->CloseProtocol (
1055 &gEfiDevicePathProtocolGuid
,
1056 This
->DriverBindingHandle
,
1061 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to start bus driver %r\n", Status
));
1067 The USB bus driver entry pointer.
1069 @param ImageHandle The driver image handle.
1070 @param SystemTable The system table.
1072 @return EFI_SUCCESS The component name protocol is installed.
1073 @return Others Failed to init the usb driver.
1078 UsbBusDriverEntryPoint (
1079 IN EFI_HANDLE ImageHandle
,
1080 IN EFI_SYSTEM_TABLE
*SystemTable
1083 return EfiLibInstallDriverBindingComponentName2 (
1086 &mUsbBusDriverBinding
,
1088 &mUsbBusComponentName
,
1089 &mUsbBusComponentName2
1095 Check whether USB bus driver support this device.
1097 @param This The USB bus driver binding protocol.
1098 @param Controller The controller handle to check.
1099 @param RemainingDevicePath The remaining device path.
1101 @retval EFI_SUCCESS The bus supports this controller.
1102 @retval EFI_UNSUPPORTED This device isn't supported.
1107 UsbBusControllerDriverSupported (
1108 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1109 IN EFI_HANDLE Controller
,
1110 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1113 EFI_DEV_PATH_PTR DevicePathNode
;
1114 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1115 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1116 EFI_USB_HC_PROTOCOL
*UsbHc
;
1120 // Check whether device path is valid
1122 if (RemainingDevicePath
!= NULL
) {
1123 DevicePathNode
.DevPath
= RemainingDevicePath
;
1125 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1126 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
&&
1127 DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
1128 && DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
1131 return EFI_UNSUPPORTED
;
1135 Status
= gBS
->OpenProtocol (
1137 &gEfiDevicePathProtocolGuid
,
1138 (VOID
**) &ParentDevicePath
,
1139 This
->DriverBindingHandle
,
1141 EFI_OPEN_PROTOCOL_BY_DRIVER
1144 if (Status
== EFI_ALREADY_STARTED
) {
1148 if (EFI_ERROR (Status
)) {
1152 gBS
->CloseProtocol (
1154 &gEfiDevicePathProtocolGuid
,
1155 This
->DriverBindingHandle
,
1160 // Check whether USB_HC2 protocol is installed
1162 Status
= gBS
->OpenProtocol (
1164 &gEfiUsb2HcProtocolGuid
,
1166 This
->DriverBindingHandle
,
1168 EFI_OPEN_PROTOCOL_BY_DRIVER
1171 if (Status
== EFI_ALREADY_STARTED
) {
1175 if (!EFI_ERROR (Status
)) {
1176 gBS
->CloseProtocol (
1178 &gEfiUsb2HcProtocolGuid
,
1179 This
->DriverBindingHandle
,
1187 // If failed to open USB_HC2, fall back to USB_HC
1189 Status
= gBS
->OpenProtocol (
1191 &gEfiUsbHcProtocolGuid
,
1193 This
->DriverBindingHandle
,
1195 EFI_OPEN_PROTOCOL_BY_DRIVER
1198 if (Status
== EFI_ALREADY_STARTED
) {
1202 if (!EFI_ERROR (Status
)) {
1203 gBS
->CloseProtocol (
1205 &gEfiUsbHcProtocolGuid
,
1206 This
->DriverBindingHandle
,
1216 Start to process the controller.
1218 @param This The USB bus driver binding instance.
1219 @param Controller The controller to check.
1220 @param RemainingDevicePath The remaining device patch.
1222 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1223 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1225 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1230 UsbBusControllerDriverStart (
1231 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1232 IN EFI_HANDLE Controller
,
1233 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1236 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1240 // Locate the USB bus protocol, if it is found, USB bus
1241 // is already started on this controller.
1243 Status
= gBS
->OpenProtocol (
1245 &mUsbBusProtocolGuid
,
1246 (VOID
**) &UsbBusId
,
1247 This
->DriverBindingHandle
,
1249 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1252 if (EFI_ERROR (Status
)) {
1254 // If first start, build the bus execute environment and install bus protocol
1256 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1257 if (EFI_ERROR (Status
)) {
1261 // Try get the Usb Bus protocol interface again
1263 Status
= gBS
->OpenProtocol (
1265 &mUsbBusProtocolGuid
,
1266 (VOID
**) &UsbBusId
,
1267 This
->DriverBindingHandle
,
1269 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1271 ASSERT (!EFI_ERROR (Status
));
1274 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1275 // usb child device will be recursively connected.
1276 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1277 // All wanted usb child devices will be remembered by the usb bus driver itself.
1278 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1280 // Save the passed in RemainingDevicePath this time
1282 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1283 ASSERT (!EFI_ERROR (Status
));
1285 // Ensure all wanted child usb devices are fully recursively connected
1287 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1288 ASSERT (!EFI_ERROR (Status
));
1297 Stop handle the controller by this USB bus driver.
1299 @param This The USB bus driver binding protocol.
1300 @param Controller The controller to release.
1301 @param NumberOfChildren The child of USB bus that opened controller
1303 @param ChildHandleBuffer The array of child handle.
1305 @retval EFI_SUCCESS The controller or children are stopped.
1306 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1311 UsbBusControllerDriverStop (
1312 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1313 IN EFI_HANDLE Controller
,
1314 IN UINTN NumberOfChildren
,
1315 IN EFI_HANDLE
*ChildHandleBuffer
1319 USB_DEVICE
*RootHub
;
1321 USB_INTERFACE
*RootIf
;
1322 USB_INTERFACE
*UsbIf
;
1323 EFI_USB_BUS_PROTOCOL
*BusId
;
1324 EFI_USB_IO_PROTOCOL
*UsbIo
;
1329 Status
= EFI_SUCCESS
;
1331 if (NumberOfChildren
> 0) {
1333 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1335 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1337 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1338 Status
= gBS
->OpenProtocol (
1339 ChildHandleBuffer
[Index
],
1340 &gEfiUsbIoProtocolGuid
,
1342 This
->DriverBindingHandle
,
1344 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1347 if (EFI_ERROR (Status
)) {
1349 // It is possible that the child has already been released:
1350 // 1. For combo device, free one device will release others.
1351 // 2. If a hub is released, all devices on its down facing
1352 // ports are released also.
1357 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1358 UsbDev
= UsbIf
->Device
;
1360 UsbRemoveDevice (UsbDev
);
1363 gBS
->RestoreTPL (OldTpl
);
1367 DEBUG (( EFI_D_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1370 // Locate USB_BUS for the current host controller
1372 Status
= gBS
->OpenProtocol (
1374 &mUsbBusProtocolGuid
,
1376 This
->DriverBindingHandle
,
1378 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1381 if (EFI_ERROR (Status
)) {
1385 Bus
= USB_BUS_FROM_THIS (BusId
);
1388 // Stop the root hub, then free all the devices
1390 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1392 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1393 UsbHcSetState (Bus
, EfiUsbHcStateHalt
);
1395 RootHub
= Bus
->Devices
[0];
1396 RootIf
= RootHub
->Interfaces
[0];
1398 mUsbRootHubApi
.Release (RootIf
);
1400 for (Index
= 1; Index
< USB_MAX_DEVICES
; Index
++) {
1401 if (Bus
->Devices
[Index
] != NULL
) {
1402 UsbRemoveDevice (Bus
->Devices
[Index
]);
1406 gBS
->RestoreTPL (OldTpl
);
1408 gBS
->FreePool (RootIf
);
1409 gBS
->FreePool (RootHub
);
1410 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1411 ASSERT (!EFI_ERROR (Status
));
1414 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1416 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &Bus
->BusId
);
1418 if (Bus
->Usb2Hc
!= NULL
) {
1419 gBS
->CloseProtocol (
1421 &gEfiUsb2HcProtocolGuid
,
1422 This
->DriverBindingHandle
,
1427 if (Bus
->UsbHc
!= NULL
) {
1428 gBS
->CloseProtocol (
1430 &gEfiUsbHcProtocolGuid
,
1431 This
->DriverBindingHandle
,
1436 gBS
->CloseProtocol (
1438 &gEfiDevicePathProtocolGuid
,
1439 This
->DriverBindingHandle
,
1443 gBS
->FreePool (Bus
);