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
;
25 USB_IO function to execute a control transfer. This
26 function will execute the USB transfer. If transfer
27 successes, it will sync the internal state of USB bus
30 @param This The USB_IO instance
31 @param Request The control transfer request
32 @param Direction Direction for data stage
33 @param Timeout The time to wait before timeout
34 @param Data The buffer holding the data
35 @param DataLength Then length of the data
36 @param UsbStatus USB result
38 @retval EFI_INVALID_PARAMETER The parameters are invalid
39 @retval EFI_SUCCESS The control transfer succeded.
40 @retval Others Failed to execute the transfer
45 UsbIoControlTransfer (
46 IN EFI_USB_IO_PROTOCOL
*This
,
47 IN EFI_USB_DEVICE_REQUEST
*Request
,
48 IN EFI_USB_DATA_DIRECTION Direction
,
50 IN OUT VOID
*Data
, OPTIONAL
51 IN UINTN DataLength
, OPTIONAL
57 USB_ENDPOINT_DESC
*EpDesc
;
61 if (UsbStatus
== NULL
) {
62 return EFI_INVALID_PARAMETER
;
65 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
67 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
70 Status
= UsbHcControlTransfer (
84 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
86 // Clear TT buffer when CTRL/BULK split transaction failes
87 // Clear the TRANSLATOR TT buffer, not parent's buffer
89 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
90 UsbHubCtrlClearTTBuffer (
91 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
92 Dev
->Translator
.TranslatorPortNumber
,
103 // Some control transfer will change the device's internal
104 // status, such as Set_Configuration and Set_Interface.
105 // We must synchronize the bus driver's status with that in
106 // device. We ignore the Set_Descriptor request because it's
107 // hardly used by any device, especially in pre-boot environment
111 // Reset the endpoint toggle when endpoint stall is cleared
113 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
114 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
115 USB_TARGET_ENDPOINT
)) &&
116 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
118 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
120 if (EpDesc
!= NULL
) {
126 // Select a new configuration. This is a dangerous action. Upper driver
127 // should stop use its current UsbIo after calling this driver. The old
128 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
129 // ReinstallProtocol since interfaces in different configuration may be
130 // completely irrellvant.
132 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
133 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
134 USB_TARGET_DEVICE
))) {
136 // Don't re-create the USB interfaces if configuration isn't changed.
138 if ((Dev
->ActiveConfig
!= NULL
) &&
139 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
143 DEBUG ((EFI_D_INFO
, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
145 if (Dev
->ActiveConfig
!= NULL
) {
146 UsbRemoveConfig (Dev
);
149 if (Request
->Value
!= 0) {
150 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
154 // Exit now, Old USB_IO is invalid now
160 // A new alternative setting is selected for the interface.
161 // No need to reinstall UsbIo in this case because only
162 // underlying communication endpoints are changed. Functionality
163 // should remains the same.
165 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
166 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
167 USB_TARGET_INTERFACE
)) &&
168 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
170 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
172 if (!EFI_ERROR (Status
)) {
173 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
178 gBS
->RestoreTPL (OldTpl
);
184 Execute a bulk transfer to the device endpoint.
186 @param This The USB IO instance.
187 @param Endpoint The device endpoint.
188 @param Data The data to transfer.
189 @param DataLength The length of the data to transfer.
190 @param Timeout Time to wait before timeout.
191 @param UsbStatus The result of USB transfer.
193 @retval EFI_SUCCESS The bulk transfer is OK.
194 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
195 @retval Others Failed to execute transfer, reason returned in
202 IN EFI_USB_IO_PROTOCOL
*This
,
205 IN OUT UINTN
*DataLength
,
207 OUT UINT32
*UsbStatus
211 USB_INTERFACE
*UsbIf
;
212 USB_ENDPOINT_DESC
*EpDesc
;
218 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
219 (UsbStatus
== NULL
)) {
221 return EFI_INVALID_PARAMETER
;
224 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
226 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
229 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
231 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
232 Status
= EFI_INVALID_PARAMETER
;
237 Toggle
= EpDesc
->Toggle
;
238 Status
= UsbHcBulkTransfer (
243 EpDesc
->Desc
.MaxPacketSize
,
253 EpDesc
->Toggle
= Toggle
;
255 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
257 // Clear TT buffer when CTRL/BULK split transaction failes.
258 // Clear the TRANSLATOR TT buffer, not parent's buffer
260 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
261 UsbHubCtrlClearTTBuffer (
262 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
263 Dev
->Translator
.TranslatorPortNumber
,
272 gBS
->RestoreTPL (OldTpl
);
278 Execute a synchronous interrupt transfer.
280 @param This The USB IO instance.
281 @param Endpoint The device endpoint.
282 @param Data The data to transfer.
283 @param DataLength The length of the data to transfer.
284 @param Timeout Time to wait before timeout.
285 @param UsbStatus The result of USB transfer.
287 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
288 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
289 @retval Others Failed to execute transfer, reason returned in
295 UsbIoSyncInterruptTransfer (
296 IN EFI_USB_IO_PROTOCOL
*This
,
299 IN OUT UINTN
*DataLength
,
301 OUT UINT32
*UsbStatus
305 USB_INTERFACE
*UsbIf
;
306 USB_ENDPOINT_DESC
*EpDesc
;
311 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
312 (UsbStatus
== NULL
)) {
314 return EFI_INVALID_PARAMETER
;
317 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
319 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
322 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
324 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
325 Status
= EFI_INVALID_PARAMETER
;
329 Toggle
= EpDesc
->Toggle
;
330 Status
= UsbHcSyncInterruptTransfer (
335 EpDesc
->Desc
.MaxPacketSize
,
344 EpDesc
->Toggle
= Toggle
;
347 gBS
->RestoreTPL (OldTpl
);
353 Queue a new asynchronous interrupt transfer, or remove the old
354 request if (IsNewTransfer == FALSE).
356 @param This The USB_IO instance.
357 @param Endpoint The device endpoint.
358 @param IsNewTransfer Whether this is a new request, if it's old, remove
360 @param PollInterval The interval to poll the transfer result, (in ms).
361 @param DataLength The length of perodic data transfer.
362 @param Callback The function to call periodicaly when transfer is
364 @param Context The context to the callback.
366 @retval EFI_SUCCESS New transfer is queued or old request is removed.
367 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
368 @retval Others Failed to queue the new request or remove the old
374 UsbIoAsyncInterruptTransfer (
375 IN EFI_USB_IO_PROTOCOL
*This
,
377 IN BOOLEAN IsNewTransfer
,
378 IN UINTN PollInterval
, OPTIONAL
379 IN UINTN DataLength
, OPTIONAL
380 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
381 IN VOID
*Context OPTIONAL
385 USB_INTERFACE
*UsbIf
;
386 USB_ENDPOINT_DESC
*EpDesc
;
391 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
392 return EFI_INVALID_PARAMETER
;
395 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
396 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
399 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
401 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
402 Status
= EFI_INVALID_PARAMETER
;
406 Toggle
= EpDesc
->Toggle
;
407 Status
= UsbHcAsyncInterruptTransfer (
412 EpDesc
->Desc
.MaxPacketSize
,
422 EpDesc
->Toggle
= Toggle
;
425 gBS
->RestoreTPL (OldTpl
);
431 Execute a synchronous isochronous transfer.
433 @param This The USB IO instance.
434 @param DeviceEndpoint The device endpoint.
435 @param Data The data to transfer.
436 @param DataLength The length of the data to transfer.
437 @param UsbStatus The result of USB transfer.
439 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
444 UsbIoIsochronousTransfer (
445 IN EFI_USB_IO_PROTOCOL
*This
,
446 IN UINT8 DeviceEndpoint
,
452 return EFI_UNSUPPORTED
;
457 Queue an asynchronous isochronous transfer.
459 @param This The USB_IO instance.
460 @param DeviceEndpoint The device endpoint.
461 @param Data The data to transfer.
462 @param DataLength The length of perodic data transfer.
463 @param IsochronousCallBack The function to call periodicaly when transfer is
465 @param Context The context to the callback.
467 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
472 UsbIoAsyncIsochronousTransfer (
473 IN EFI_USB_IO_PROTOCOL
*This
,
474 IN UINT8 DeviceEndpoint
,
477 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
478 IN VOID
*Context OPTIONAL
481 return EFI_UNSUPPORTED
;
486 Retrieve the device descriptor of the device.
488 @param This The USB IO instance.
489 @param Descriptor The variable to receive the device descriptor.
491 @retval EFI_SUCCESS The device descriptor is returned.
492 @retval EFI_INVALID_PARAMETER The parameter is invalid.
497 UsbIoGetDeviceDescriptor (
498 IN EFI_USB_IO_PROTOCOL
*This
,
499 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
503 USB_INTERFACE
*UsbIf
;
506 if (Descriptor
== NULL
) {
507 return EFI_INVALID_PARAMETER
;
510 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
512 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
515 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
517 gBS
->RestoreTPL (OldTpl
);
523 Return the configuration descriptor of the current active configuration.
525 @param This The USB IO instance.
526 @param Descriptor The USB configuration descriptor.
528 @retval EFI_SUCCESS The active configuration descriptor is returned.
529 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
530 @retval EFI_NOT_FOUND Currently no active configuration is selected.
535 UsbIoGetActiveConfigDescriptor (
536 IN EFI_USB_IO_PROTOCOL
*This
,
537 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
541 USB_INTERFACE
*UsbIf
;
545 if (Descriptor
== NULL
) {
546 return EFI_INVALID_PARAMETER
;
549 Status
= EFI_SUCCESS
;
550 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
552 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
555 if (Dev
->ActiveConfig
== NULL
) {
556 Status
= EFI_NOT_FOUND
;
560 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
563 gBS
->RestoreTPL (OldTpl
);
569 Retrieve the active interface setting descriptor for this USB IO instance.
571 @param This The USB IO instance.
572 @param Descriptor The variable to receive active interface setting.
574 @retval EFI_SUCCESS The active interface setting is returned.
575 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
580 UsbIoGetInterfaceDescriptor (
581 IN EFI_USB_IO_PROTOCOL
*This
,
582 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
585 USB_INTERFACE
*UsbIf
;
588 if (Descriptor
== NULL
) {
589 return EFI_INVALID_PARAMETER
;
592 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
594 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
595 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
597 gBS
->RestoreTPL (OldTpl
);
603 Retrieve the endpoint descriptor from this interface setting.
605 @param This The USB IO instance.
606 @param Index The index (start from zero) of the endpoint to
608 @param Descriptor The variable to receive the descriptor.
610 @retval EFI_SUCCESS The endpoint descriptor is returned.
611 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
616 UsbIoGetEndpointDescriptor (
617 IN EFI_USB_IO_PROTOCOL
*This
,
619 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
622 USB_INTERFACE
*UsbIf
;
625 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
627 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
629 if ((Descriptor
== NULL
) || (Index
> 15)) {
630 gBS
->RestoreTPL (OldTpl
);
631 return EFI_INVALID_PARAMETER
;
634 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
635 gBS
->RestoreTPL (OldTpl
);
636 return EFI_NOT_FOUND
;
641 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
642 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
645 gBS
->RestoreTPL (OldTpl
);
651 Retrieve the supported language ID table from the device.
653 @param This The USB IO instance.
654 @param LangIDTable The table to return the language IDs.
655 @param TableSize The number of supported languanges.
657 @retval EFI_SUCCESS The language ID is return.
662 UsbIoGetSupportedLanguages (
663 IN EFI_USB_IO_PROTOCOL
*This
,
664 OUT UINT16
**LangIDTable
,
665 OUT UINT16
*TableSize
669 USB_INTERFACE
*UsbIf
;
672 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
674 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
677 *LangIDTable
= Dev
->LangId
;
678 *TableSize
= Dev
->TotalLangId
;
680 gBS
->RestoreTPL (OldTpl
);
686 Retrieve an indexed string in the language of LangID.
688 @param This The USB IO instance.
689 @param LangID The language ID of the string to retrieve.
690 @param StringIndex The index of the string.
691 @param String The variable to receive the string.
693 @retval EFI_SUCCESS The string is returned.
694 @retval EFI_NOT_FOUND No such string existed.
699 UsbIoGetStringDescriptor (
700 IN EFI_USB_IO_PROTOCOL
*This
,
702 IN UINT8 StringIndex
,
707 USB_INTERFACE
*UsbIf
;
708 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
714 if ((StringIndex
== 0) || (LangID
== 0)) {
715 return EFI_NOT_FOUND
;
718 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
720 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
724 // Check whether language ID is supported
726 Status
= EFI_NOT_FOUND
;
728 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
729 if (Dev
->LangId
[Index
] == LangID
) {
734 if (Index
== Dev
->TotalLangId
) {
739 // Retrieve the string descriptor then allocate a buffer
740 // to hold the string itself.
742 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
744 if (StrDesc
== NULL
) {
748 if (StrDesc
->Length
<= 2) {
752 Buf
= AllocateZeroPool (StrDesc
->Length
);
755 Status
= EFI_OUT_OF_RESOURCES
;
759 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
760 *String
= (CHAR16
*) Buf
;
761 Status
= EFI_SUCCESS
;
764 gBS
->FreePool (StrDesc
);
767 gBS
->RestoreTPL (OldTpl
);
773 Reset the device, then if that succeeds, reconfigure the
774 device with its address and current active configuration.
776 @param This The USB IO instance.
778 @retval EFI_SUCCESS The device is reset and configured.
779 @retval Others Failed to reset the device.
785 IN EFI_USB_IO_PROTOCOL
*This
788 USB_INTERFACE
*UsbIf
;
789 USB_INTERFACE
*HubIf
;
795 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
797 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
801 Status
= EFI_INVALID_PARAMETER
;
805 HubIf
= Dev
->ParentIf
;
806 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
808 if (EFI_ERROR (Status
)) {
809 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
810 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
816 // Reset the device to its current address. The device now has a
817 // address of ZERO, so need to set Dev->Address to zero first for
818 // host to communicate with the device
820 Address
= Dev
->Address
;
822 Status
= UsbSetAddress (Dev
, Address
);
823 Dev
->Address
= Address
;
825 if (EFI_ERROR (Status
)) {
826 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set address for device %d - %r\n",
832 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
834 DEBUG (( EFI_D_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address
));
837 // Reset the current active configure, after this device
838 // is in CONFIGURED state.
840 if (Dev
->ActiveConfig
!= NULL
) {
841 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
843 if (EFI_ERROR (Status
)) {
844 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set configure for device %d - %r\n",
850 gBS
->RestoreTPL (OldTpl
);
856 Install Usb Bus Protocol on host controller, and start the Usb bus.
858 @param This The USB bus driver binding instance.
859 @param Controller The controller to check.
860 @param RemainingDevicePath The remaining device patch.
862 @retval EFI_SUCCESS The controller is controlled by the usb bus.
863 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
864 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
869 UsbBusBuildProtocol (
870 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
871 IN EFI_HANDLE Controller
,
872 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
877 USB_INTERFACE
*RootIf
;
881 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
883 if (UsbBus
== NULL
) {
884 return EFI_OUT_OF_RESOURCES
;
887 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
888 UsbBus
->HostHandle
= Controller
;
890 Status
= gBS
->OpenProtocol (
892 &gEfiDevicePathProtocolGuid
,
893 (VOID
**) &UsbBus
->DevicePath
,
894 This
->DriverBindingHandle
,
896 EFI_OPEN_PROTOCOL_BY_DRIVER
899 if (EFI_ERROR (Status
)) {
900 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open device path %r\n", Status
));
902 gBS
->FreePool (UsbBus
);
907 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
908 // This is for backward compatbility with EFI 1.x. In UEFI
909 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
910 // and USB_HC because EHCI driver will install both protocols
911 // (for the same reason). If we don't consume both of them,
912 // the unconsumed one may be opened by others.
914 Status
= gBS
->OpenProtocol (
916 &gEfiUsb2HcProtocolGuid
,
917 (VOID
**) &(UsbBus
->Usb2Hc
),
918 This
->DriverBindingHandle
,
920 EFI_OPEN_PROTOCOL_BY_DRIVER
923 Status2
= gBS
->OpenProtocol (
925 &gEfiUsbHcProtocolGuid
,
926 (VOID
**) &(UsbBus
->UsbHc
),
927 This
->DriverBindingHandle
,
929 EFI_OPEN_PROTOCOL_BY_DRIVER
932 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
933 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
935 Status
= EFI_DEVICE_ERROR
;
939 UsbHcReset (UsbBus
, EFI_USB_HC_RESET_GLOBAL
);
940 UsbHcSetState (UsbBus
, EfiUsbHcStateOperational
);
943 // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.
945 Status
= gBS
->InstallProtocolInterface (
947 &mUsbBusProtocolGuid
,
948 EFI_NATIVE_INTERFACE
,
952 if (EFI_ERROR (Status
)) {
953 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to install bus protocol %r\n", Status
));
958 // Initial the wanted child device path list, and add first RemainingDevicePath
960 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
961 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
962 ASSERT (!EFI_ERROR (Status
));
964 // Create a fake usb device for root hub
966 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
968 if (RootHub
== NULL
) {
969 Status
= EFI_OUT_OF_RESOURCES
;
970 goto UNINSTALL_USBBUS
;
973 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
975 if (RootIf
== NULL
) {
976 gBS
->FreePool (RootHub
);
977 Status
= EFI_OUT_OF_RESOURCES
;
981 RootHub
->Bus
= UsbBus
;
982 RootHub
->NumOfInterface
= 1;
983 RootHub
->Interfaces
[0] = RootIf
;
984 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
985 RootIf
->Device
= RootHub
;
986 RootIf
->DevicePath
= UsbBus
->DevicePath
;
988 Status
= mUsbRootHubApi
.Init (RootIf
);
990 if (EFI_ERROR (Status
)) {
991 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to init root hub %r\n", Status
));
995 UsbBus
->Devices
[0] = RootHub
;
997 DEBUG ((EFI_D_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1001 if (RootIf
!= NULL
) {
1002 gBS
->FreePool (RootIf
);
1004 if (RootHub
!= NULL
) {
1005 gBS
->FreePool (RootHub
);
1009 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &UsbBus
->BusId
);
1012 if (UsbBus
->Usb2Hc
!= NULL
) {
1013 gBS
->CloseProtocol (
1015 &gEfiUsb2HcProtocolGuid
,
1016 This
->DriverBindingHandle
,
1020 if (UsbBus
->UsbHc
!= NULL
) {
1021 gBS
->CloseProtocol (
1023 &gEfiUsbHcProtocolGuid
,
1024 This
->DriverBindingHandle
,
1028 gBS
->CloseProtocol (
1030 &gEfiDevicePathProtocolGuid
,
1031 This
->DriverBindingHandle
,
1034 gBS
->FreePool (UsbBus
);
1036 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to start bus driver %r\n", Status
));
1040 EFI_USB_IO_PROTOCOL mUsbIoProtocol
= {
1041 UsbIoControlTransfer
,
1043 UsbIoAsyncInterruptTransfer
,
1044 UsbIoSyncInterruptTransfer
,
1045 UsbIoIsochronousTransfer
,
1046 UsbIoAsyncIsochronousTransfer
,
1047 UsbIoGetDeviceDescriptor
,
1048 UsbIoGetActiveConfigDescriptor
,
1049 UsbIoGetInterfaceDescriptor
,
1050 UsbIoGetEndpointDescriptor
,
1051 UsbIoGetStringDescriptor
,
1052 UsbIoGetSupportedLanguages
,
1058 The USB bus driver entry pointer.
1060 @param ImageHandle The driver image handle.
1061 @param SystemTable The system table.
1063 @return EFI_SUCCESS The component name protocol is installed.
1064 @return Others Failed to init the usb driver.
1069 UsbBusDriverEntryPoint (
1070 IN EFI_HANDLE ImageHandle
,
1071 IN EFI_SYSTEM_TABLE
*SystemTable
1074 return EfiLibInstallDriverBindingComponentName2 (
1077 &mUsbBusDriverBinding
,
1079 &mUsbBusComponentName
,
1080 &mUsbBusComponentName2
1086 Check whether USB bus driver support this device.
1088 @param This The USB bus driver binding protocol.
1089 @param Controller The controller handle to check.
1090 @param RemainingDevicePath The remaining device path.
1092 @retval EFI_SUCCESS The bus supports this controller.
1093 @retval EFI_UNSUPPORTED This device isn't supported.
1098 UsbBusControllerDriverSupported (
1099 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1100 IN EFI_HANDLE Controller
,
1101 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1104 EFI_DEV_PATH_PTR DevicePathNode
;
1105 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1106 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1107 EFI_USB_HC_PROTOCOL
*UsbHc
;
1111 // Check whether device path is valid
1113 if (RemainingDevicePath
!= NULL
) {
1114 DevicePathNode
.DevPath
= RemainingDevicePath
;
1116 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1117 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
&&
1118 DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
1119 && DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
1122 return EFI_UNSUPPORTED
;
1126 Status
= gBS
->OpenProtocol (
1128 &gEfiDevicePathProtocolGuid
,
1129 (VOID
**) &ParentDevicePath
,
1130 This
->DriverBindingHandle
,
1132 EFI_OPEN_PROTOCOL_BY_DRIVER
1135 if (Status
== EFI_ALREADY_STARTED
) {
1139 if (EFI_ERROR (Status
)) {
1143 gBS
->CloseProtocol (
1145 &gEfiDevicePathProtocolGuid
,
1146 This
->DriverBindingHandle
,
1151 // Check whether USB_HC2 protocol is installed
1153 Status
= gBS
->OpenProtocol (
1155 &gEfiUsb2HcProtocolGuid
,
1157 This
->DriverBindingHandle
,
1159 EFI_OPEN_PROTOCOL_BY_DRIVER
1162 if (Status
== EFI_ALREADY_STARTED
) {
1166 if (!EFI_ERROR (Status
)) {
1167 gBS
->CloseProtocol (
1169 &gEfiUsb2HcProtocolGuid
,
1170 This
->DriverBindingHandle
,
1178 // If failed to open USB_HC2, fall back to USB_HC
1180 Status
= gBS
->OpenProtocol (
1182 &gEfiUsbHcProtocolGuid
,
1184 This
->DriverBindingHandle
,
1186 EFI_OPEN_PROTOCOL_BY_DRIVER
1189 if (Status
== EFI_ALREADY_STARTED
) {
1193 if (!EFI_ERROR (Status
)) {
1194 gBS
->CloseProtocol (
1196 &gEfiUsbHcProtocolGuid
,
1197 This
->DriverBindingHandle
,
1207 Start to process the controller.
1209 @param This The USB bus driver binding instance.
1210 @param Controller The controller to check.
1211 @param RemainingDevicePath The remaining device patch.
1213 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1214 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1216 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1221 UsbBusControllerDriverStart (
1222 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1223 IN EFI_HANDLE Controller
,
1224 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1227 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1231 // Locate the USB bus protocol, if it is found, USB bus
1232 // is already started on this controller.
1234 Status
= gBS
->OpenProtocol (
1236 &mUsbBusProtocolGuid
,
1237 (VOID
**) &UsbBusId
,
1238 This
->DriverBindingHandle
,
1240 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1243 if (EFI_ERROR (Status
)) {
1245 // If first start, build the bus execute enviorment and install bus protocol
1247 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1248 if (EFI_ERROR (Status
)) {
1252 // Try get the Usb Bus protocol interface again
1254 Status
= gBS
->OpenProtocol (
1256 &mUsbBusProtocolGuid
,
1257 (VOID
**) &UsbBusId
,
1258 This
->DriverBindingHandle
,
1260 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1262 ASSERT (!EFI_ERROR (Status
));
1265 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1266 // usb child device will be recursively connected.
1267 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1268 // All wanted usb child devices will be remembered by the usb bus driver itself.
1269 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1271 // Save the passed in RemainingDevicePath this time
1273 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1274 ASSERT (!EFI_ERROR (Status
));
1276 // Ensure all wanted child usb devices are fully recursively connected
1278 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1279 ASSERT (!EFI_ERROR (Status
));
1288 Stop handle the controller by this USB bus driver.
1290 @param This The USB bus driver binding protocol.
1291 @param Controller The controller to release.
1292 @param NumberOfChildren The child of USB bus that opened controller
1294 @param ChildHandleBuffer The array of child handle.
1296 @retval EFI_SUCCESS The controller or children are stopped.
1297 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1302 UsbBusControllerDriverStop (
1303 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1304 IN EFI_HANDLE Controller
,
1305 IN UINTN NumberOfChildren
,
1306 IN EFI_HANDLE
*ChildHandleBuffer
1310 USB_DEVICE
*RootHub
;
1312 USB_INTERFACE
*RootIf
;
1313 USB_INTERFACE
*UsbIf
;
1314 EFI_USB_BUS_PROTOCOL
*BusId
;
1315 EFI_USB_IO_PROTOCOL
*UsbIo
;
1320 Status
= EFI_SUCCESS
;
1322 if (NumberOfChildren
> 0) {
1324 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1326 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1328 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1329 Status
= gBS
->OpenProtocol (
1330 ChildHandleBuffer
[Index
],
1331 &gEfiUsbIoProtocolGuid
,
1333 This
->DriverBindingHandle
,
1335 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1338 if (EFI_ERROR (Status
)) {
1340 // It is possible that the child has already been released:
1341 // 1. For combo device, free one device will release others.
1342 // 2. If a hub is released, all devices on its down facing
1343 // ports are released also.
1348 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1349 UsbDev
= UsbIf
->Device
;
1351 UsbRemoveDevice (UsbDev
);
1354 gBS
->RestoreTPL (OldTpl
);
1358 DEBUG (( EFI_D_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1361 // Locate USB_BUS for the current host controller
1363 Status
= gBS
->OpenProtocol (
1365 &mUsbBusProtocolGuid
,
1367 This
->DriverBindingHandle
,
1369 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1372 if (EFI_ERROR (Status
)) {
1376 Bus
= USB_BUS_FROM_THIS (BusId
);
1379 // Stop the root hub, then free all the devices
1381 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1383 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1384 UsbHcSetState (Bus
, EfiUsbHcStateHalt
);
1386 RootHub
= Bus
->Devices
[0];
1387 RootIf
= RootHub
->Interfaces
[0];
1389 mUsbRootHubApi
.Release (RootIf
);
1391 for (Index
= 1; Index
< USB_MAX_DEVICES
; Index
++) {
1392 if (Bus
->Devices
[Index
] != NULL
) {
1393 UsbRemoveDevice (Bus
->Devices
[Index
]);
1397 gBS
->RestoreTPL (OldTpl
);
1399 gBS
->FreePool (RootIf
);
1400 gBS
->FreePool (RootHub
);
1401 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1402 ASSERT (!EFI_ERROR (Status
));
1405 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1407 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &Bus
->BusId
);
1409 if (Bus
->Usb2Hc
!= NULL
) {
1410 gBS
->CloseProtocol (
1412 &gEfiUsb2HcProtocolGuid
,
1413 This
->DriverBindingHandle
,
1418 if (Bus
->UsbHc
!= NULL
) {
1419 gBS
->CloseProtocol (
1421 &gEfiUsbHcProtocolGuid
,
1422 This
->DriverBindingHandle
,
1427 gBS
->CloseProtocol (
1429 &gEfiDevicePathProtocolGuid
,
1430 This
->DriverBindingHandle
,
1434 gBS
->FreePool (Bus
);
1439 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding
= {
1440 UsbBusControllerDriverSupported
,
1441 UsbBusControllerDriverStart
,
1442 UsbBusControllerDriverStop
,