3 Usb Bus Driver Binding and Bus IO Protocol.
5 Copyright (c) 2004 - 2018, 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.
18 EFI_USB_IO_PROTOCOL mUsbIoProtocol
= {
21 UsbIoAsyncInterruptTransfer
,
22 UsbIoSyncInterruptTransfer
,
23 UsbIoIsochronousTransfer
,
24 UsbIoAsyncIsochronousTransfer
,
25 UsbIoGetDeviceDescriptor
,
26 UsbIoGetActiveConfigDescriptor
,
27 UsbIoGetInterfaceDescriptor
,
28 UsbIoGetEndpointDescriptor
,
29 UsbIoGetStringDescriptor
,
30 UsbIoGetSupportedLanguages
,
34 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding
= {
35 UsbBusControllerDriverSupported
,
36 UsbBusControllerDriverStart
,
37 UsbBusControllerDriverStop
,
44 USB_IO function to execute a control transfer. This
45 function will execute the USB transfer. If transfer
46 successes, it will sync the internal state of USB bus
49 @param This The USB_IO instance
50 @param Request The control transfer request
51 @param Direction Direction for data stage
52 @param Timeout The time to wait before timeout
53 @param Data The buffer holding the data
54 @param DataLength Then length of the data
55 @param UsbStatus USB result
57 @retval EFI_INVALID_PARAMETER The parameters are invalid
58 @retval EFI_SUCCESS The control transfer succeeded.
59 @retval Others Failed to execute the transfer
64 UsbIoControlTransfer (
65 IN EFI_USB_IO_PROTOCOL
*This
,
66 IN EFI_USB_DEVICE_REQUEST
*Request
,
67 IN EFI_USB_DATA_DIRECTION Direction
,
69 IN OUT VOID
*Data
, OPTIONAL
70 IN UINTN DataLength
, OPTIONAL
76 USB_ENDPOINT_DESC
*EpDesc
;
79 UINTN RequestedDataLength
;
81 if (UsbStatus
== NULL
) {
82 return EFI_INVALID_PARAMETER
;
85 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
87 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
90 RequestedDataLength
= DataLength
;
91 Status
= UsbHcControlTransfer (
105 // If the request completed sucessfully and the Direction of the request is
106 // EfiUsbDataIn or EfiUsbDataOut, then make sure the actual number of bytes
107 // transfered is the same as the number of bytes requested. If a different
108 // number of bytes were transfered, then return EFI_DEVICE_ERROR.
110 if (!EFI_ERROR (Status
)) {
111 if (Direction
!= EfiUsbNoData
&& DataLength
!= RequestedDataLength
) {
112 Status
= EFI_DEVICE_ERROR
;
117 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
119 // Clear TT buffer when CTRL/BULK split transaction failes
120 // Clear the TRANSLATOR TT buffer, not parent's buffer
122 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
123 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
124 UsbHubCtrlClearTTBuffer (
125 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
126 Dev
->Translator
.TranslatorPortNumber
,
137 // Some control transfer will change the device's internal
138 // status, such as Set_Configuration and Set_Interface.
139 // We must synchronize the bus driver's status with that in
140 // device. We ignore the Set_Descriptor request because it's
141 // hardly used by any device, especially in pre-boot environment
145 // Reset the endpoint toggle when endpoint stall is cleared
147 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
148 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
149 USB_TARGET_ENDPOINT
)) &&
150 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
152 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
154 if (EpDesc
!= NULL
) {
160 // Select a new configuration. This is a dangerous action. Upper driver
161 // should stop use its current UsbIo after calling this driver. The old
162 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
163 // ReinstallProtocol since interfaces in different configuration may be
164 // completely irrelevant.
166 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
167 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
168 USB_TARGET_DEVICE
))) {
170 // Don't re-create the USB interfaces if configuration isn't changed.
172 if ((Dev
->ActiveConfig
!= NULL
) &&
173 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
177 DEBUG ((EFI_D_INFO
, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
179 if (Dev
->ActiveConfig
!= NULL
) {
180 UsbRemoveConfig (Dev
);
183 if (Request
->Value
!= 0) {
184 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
188 // Exit now, Old USB_IO is invalid now
194 // A new alternative setting is selected for the interface.
195 // No need to reinstall UsbIo in this case because only
196 // underlying communication endpoints are changed. Functionality
197 // should remains the same.
199 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
200 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
201 USB_TARGET_INTERFACE
)) &&
202 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
204 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
206 if (!EFI_ERROR (Status
)) {
207 ASSERT (UsbIf
->IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
208 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
213 gBS
->RestoreTPL (OldTpl
);
219 Execute a bulk transfer to the device endpoint.
221 @param This The USB IO instance.
222 @param Endpoint The device endpoint.
223 @param Data The data to transfer.
224 @param DataLength The length of the data to transfer.
225 @param Timeout Time to wait before timeout.
226 @param UsbStatus The result of USB transfer.
228 @retval EFI_SUCCESS The bulk transfer is OK.
229 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
230 @retval Others Failed to execute transfer, reason returned in
237 IN EFI_USB_IO_PROTOCOL
*This
,
240 IN OUT UINTN
*DataLength
,
242 OUT UINT32
*UsbStatus
246 USB_INTERFACE
*UsbIf
;
247 USB_ENDPOINT_DESC
*EpDesc
;
253 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
254 (UsbStatus
== NULL
)) {
256 return EFI_INVALID_PARAMETER
;
259 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
261 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
264 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
266 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
267 Status
= EFI_INVALID_PARAMETER
;
272 Toggle
= EpDesc
->Toggle
;
273 Status
= UsbHcBulkTransfer (
278 EpDesc
->Desc
.MaxPacketSize
,
288 EpDesc
->Toggle
= Toggle
;
290 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
292 // Clear TT buffer when CTRL/BULK split transaction failes.
293 // Clear the TRANSLATOR TT buffer, not parent's buffer
295 ASSERT (Dev
->Translator
.TranslatorHubAddress
< Dev
->Bus
->MaxDevices
);
296 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
297 UsbHubCtrlClearTTBuffer (
298 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
299 Dev
->Translator
.TranslatorPortNumber
,
308 gBS
->RestoreTPL (OldTpl
);
314 Execute a synchronous interrupt transfer.
316 @param This The USB IO instance.
317 @param Endpoint The device endpoint.
318 @param Data The data to transfer.
319 @param DataLength The length of the data to transfer.
320 @param Timeout Time to wait before timeout.
321 @param UsbStatus The result of USB transfer.
323 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
324 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
325 @retval Others Failed to execute transfer, reason returned in
331 UsbIoSyncInterruptTransfer (
332 IN EFI_USB_IO_PROTOCOL
*This
,
335 IN OUT UINTN
*DataLength
,
337 OUT UINT32
*UsbStatus
341 USB_INTERFACE
*UsbIf
;
342 USB_ENDPOINT_DESC
*EpDesc
;
347 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
348 (UsbStatus
== NULL
)) {
350 return EFI_INVALID_PARAMETER
;
353 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
355 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
358 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
360 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
361 Status
= EFI_INVALID_PARAMETER
;
365 Toggle
= EpDesc
->Toggle
;
366 Status
= UsbHcSyncInterruptTransfer (
371 EpDesc
->Desc
.MaxPacketSize
,
380 EpDesc
->Toggle
= Toggle
;
383 gBS
->RestoreTPL (OldTpl
);
389 Queue a new asynchronous interrupt transfer, or remove the old
390 request if (IsNewTransfer == FALSE).
392 @param This The USB_IO instance.
393 @param Endpoint The device endpoint.
394 @param IsNewTransfer Whether this is a new request, if it's old, remove
396 @param PollInterval The interval to poll the transfer result, (in ms).
397 @param DataLength The length of perodic data transfer.
398 @param Callback The function to call periodicaly when transfer is
400 @param Context The context to the callback.
402 @retval EFI_SUCCESS New transfer is queued or old request is removed.
403 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
404 @retval Others Failed to queue the new request or remove the old
410 UsbIoAsyncInterruptTransfer (
411 IN EFI_USB_IO_PROTOCOL
*This
,
413 IN BOOLEAN IsNewTransfer
,
414 IN UINTN PollInterval
, OPTIONAL
415 IN UINTN DataLength
, OPTIONAL
416 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
417 IN VOID
*Context OPTIONAL
421 USB_INTERFACE
*UsbIf
;
422 USB_ENDPOINT_DESC
*EpDesc
;
427 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
428 return EFI_INVALID_PARAMETER
;
431 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
432 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
435 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
437 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
438 Status
= EFI_INVALID_PARAMETER
;
442 Toggle
= EpDesc
->Toggle
;
443 Status
= UsbHcAsyncInterruptTransfer (
448 EpDesc
->Desc
.MaxPacketSize
,
458 EpDesc
->Toggle
= Toggle
;
461 gBS
->RestoreTPL (OldTpl
);
467 Execute a synchronous isochronous transfer.
469 @param This The USB IO instance.
470 @param DeviceEndpoint The device endpoint.
471 @param Data The data to transfer.
472 @param DataLength The length of the data to transfer.
473 @param UsbStatus The result of USB transfer.
475 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
480 UsbIoIsochronousTransfer (
481 IN EFI_USB_IO_PROTOCOL
*This
,
482 IN UINT8 DeviceEndpoint
,
488 return EFI_UNSUPPORTED
;
493 Queue an asynchronous isochronous transfer.
495 @param This The USB_IO instance.
496 @param DeviceEndpoint The device endpoint.
497 @param Data The data to transfer.
498 @param DataLength The length of perodic data transfer.
499 @param IsochronousCallBack The function to call periodicaly when transfer is
501 @param Context The context to the callback.
503 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
508 UsbIoAsyncIsochronousTransfer (
509 IN EFI_USB_IO_PROTOCOL
*This
,
510 IN UINT8 DeviceEndpoint
,
513 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
514 IN VOID
*Context OPTIONAL
517 return EFI_UNSUPPORTED
;
522 Retrieve the device descriptor of the device.
524 @param This The USB IO instance.
525 @param Descriptor The variable to receive the device descriptor.
527 @retval EFI_SUCCESS The device descriptor is returned.
528 @retval EFI_INVALID_PARAMETER The parameter is invalid.
533 UsbIoGetDeviceDescriptor (
534 IN EFI_USB_IO_PROTOCOL
*This
,
535 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
539 USB_INTERFACE
*UsbIf
;
542 if (Descriptor
== NULL
) {
543 return EFI_INVALID_PARAMETER
;
546 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
548 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
551 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
553 gBS
->RestoreTPL (OldTpl
);
559 Return the configuration descriptor of the current active configuration.
561 @param This The USB IO instance.
562 @param Descriptor The USB configuration descriptor.
564 @retval EFI_SUCCESS The active configuration descriptor is returned.
565 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
566 @retval EFI_NOT_FOUND Currently no active configuration is selected.
571 UsbIoGetActiveConfigDescriptor (
572 IN EFI_USB_IO_PROTOCOL
*This
,
573 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
577 USB_INTERFACE
*UsbIf
;
581 if (Descriptor
== NULL
) {
582 return EFI_INVALID_PARAMETER
;
585 Status
= EFI_SUCCESS
;
586 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
588 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
591 if (Dev
->ActiveConfig
== NULL
) {
592 Status
= EFI_NOT_FOUND
;
596 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
599 gBS
->RestoreTPL (OldTpl
);
605 Retrieve the active interface setting descriptor for this USB IO instance.
607 @param This The USB IO instance.
608 @param Descriptor The variable to receive active interface setting.
610 @retval EFI_SUCCESS The active interface setting is returned.
611 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
616 UsbIoGetInterfaceDescriptor (
617 IN EFI_USB_IO_PROTOCOL
*This
,
618 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
621 USB_INTERFACE
*UsbIf
;
624 if (Descriptor
== NULL
) {
625 return EFI_INVALID_PARAMETER
;
628 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
630 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
631 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
633 gBS
->RestoreTPL (OldTpl
);
639 Retrieve the endpoint descriptor from this interface setting.
641 @param This The USB IO instance.
642 @param Index The index (start from zero) of the endpoint to
644 @param Descriptor The variable to receive the descriptor.
646 @retval EFI_SUCCESS The endpoint descriptor is returned.
647 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
652 UsbIoGetEndpointDescriptor (
653 IN EFI_USB_IO_PROTOCOL
*This
,
655 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
658 USB_INTERFACE
*UsbIf
;
661 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
663 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
665 if ((Descriptor
== NULL
) || (Index
> 15)) {
666 gBS
->RestoreTPL (OldTpl
);
667 return EFI_INVALID_PARAMETER
;
670 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
671 gBS
->RestoreTPL (OldTpl
);
672 return EFI_NOT_FOUND
;
677 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
678 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
681 gBS
->RestoreTPL (OldTpl
);
687 Retrieve the supported language ID table from the device.
689 @param This The USB IO instance.
690 @param LangIDTable The table to return the language IDs.
691 @param TableSize The size, in bytes, of the table LangIDTable.
693 @retval EFI_SUCCESS The language ID is return.
698 UsbIoGetSupportedLanguages (
699 IN EFI_USB_IO_PROTOCOL
*This
,
700 OUT UINT16
**LangIDTable
,
701 OUT UINT16
*TableSize
705 USB_INTERFACE
*UsbIf
;
708 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
710 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
713 *LangIDTable
= Dev
->LangId
;
714 *TableSize
= (UINT16
) (Dev
->TotalLangId
* sizeof (UINT16
));
716 gBS
->RestoreTPL (OldTpl
);
722 Retrieve an indexed string in the language of LangID.
724 @param This The USB IO instance.
725 @param LangID The language ID of the string to retrieve.
726 @param StringIndex The index of the string.
727 @param String The variable to receive the string.
729 @retval EFI_SUCCESS The string is returned.
730 @retval EFI_NOT_FOUND No such string existed.
735 UsbIoGetStringDescriptor (
736 IN EFI_USB_IO_PROTOCOL
*This
,
738 IN UINT8 StringIndex
,
743 USB_INTERFACE
*UsbIf
;
744 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
750 if ((StringIndex
== 0) || (LangID
== 0)) {
751 return EFI_NOT_FOUND
;
754 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
756 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
760 // Check whether language ID is supported
762 Status
= EFI_NOT_FOUND
;
764 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
765 ASSERT (Index
< USB_MAX_LANG_ID
);
766 if (Dev
->LangId
[Index
] == LangID
) {
771 if (Index
== Dev
->TotalLangId
) {
776 // Retrieve the string descriptor then allocate a buffer
777 // to hold the string itself.
779 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
781 if (StrDesc
== NULL
) {
785 if (StrDesc
->Length
<= 2) {
789 Buf
= AllocateZeroPool (StrDesc
->Length
);
792 Status
= EFI_OUT_OF_RESOURCES
;
796 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
797 *String
= (CHAR16
*) Buf
;
798 Status
= EFI_SUCCESS
;
801 gBS
->FreePool (StrDesc
);
804 gBS
->RestoreTPL (OldTpl
);
810 Reset the device, then if that succeeds, reconfigure the
811 device with its address and current active configuration.
813 @param This The USB IO instance.
815 @retval EFI_SUCCESS The device is reset and configured.
816 @retval Others Failed to reset the device.
822 IN EFI_USB_IO_PROTOCOL
*This
825 USB_INTERFACE
*UsbIf
;
826 USB_INTERFACE
*HubIf
;
832 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
834 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
838 Status
= EFI_INVALID_PARAMETER
;
842 HubIf
= Dev
->ParentIf
;
843 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
845 if (EFI_ERROR (Status
)) {
846 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
847 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
852 HubIf
->HubApi
->ClearPortChange (HubIf
, Dev
->ParentPort
);
855 // Reset the device to its current address. The device now has an address
856 // of ZERO after port reset, so need to set Dev->Address to the device again for
857 // host to communicate with it.
859 DevAddress
= Dev
->Address
;
861 Status
= UsbSetAddress (Dev
, DevAddress
);
862 Dev
->Address
= DevAddress
;
864 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
866 if (EFI_ERROR (Status
)) {
868 // It may fail due to device disconnection or other reasons.
870 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set address for device %d - %r\n",
871 Dev
->Address
, Status
));
876 DEBUG (( EFI_D_INFO
, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev
->Address
));
879 // Reset the current active configure, after this device
880 // is in CONFIGURED state.
882 if (Dev
->ActiveConfig
!= NULL
) {
883 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
885 if (EFI_ERROR (Status
)) {
886 DEBUG (( EFI_D_ERROR
, "UsbIoPortReset: failed to set configure for device %d - %r\n",
887 Dev
->Address
, Status
));
892 gBS
->RestoreTPL (OldTpl
);
898 Install Usb Bus Protocol on host controller, and start the Usb bus.
900 @param This The USB bus driver binding instance.
901 @param Controller The controller to check.
902 @param RemainingDevicePath The remaining device patch.
904 @retval EFI_SUCCESS The controller is controlled by the usb bus.
905 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
906 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
911 UsbBusBuildProtocol (
912 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
913 IN EFI_HANDLE Controller
,
914 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
919 USB_INTERFACE
*RootIf
;
923 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
925 if (UsbBus
== NULL
) {
926 return EFI_OUT_OF_RESOURCES
;
929 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
930 UsbBus
->HostHandle
= Controller
;
931 UsbBus
->MaxDevices
= USB_MAX_DEVICES
;
933 Status
= gBS
->OpenProtocol (
935 &gEfiDevicePathProtocolGuid
,
936 (VOID
**) &UsbBus
->DevicePath
,
937 This
->DriverBindingHandle
,
939 EFI_OPEN_PROTOCOL_BY_DRIVER
942 if (EFI_ERROR (Status
)) {
943 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open device path %r\n", Status
));
950 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
951 // This is for backward compatibility with EFI 1.x. In UEFI
952 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
953 // and USB_HC because EHCI driver will install both protocols
954 // (for the same reason). If we don't consume both of them,
955 // the unconsumed one may be opened by others.
957 Status
= gBS
->OpenProtocol (
959 &gEfiUsb2HcProtocolGuid
,
960 (VOID
**) &(UsbBus
->Usb2Hc
),
961 This
->DriverBindingHandle
,
963 EFI_OPEN_PROTOCOL_BY_DRIVER
966 Status2
= gBS
->OpenProtocol (
968 &gEfiUsbHcProtocolGuid
,
969 (VOID
**) &(UsbBus
->UsbHc
),
970 This
->DriverBindingHandle
,
972 EFI_OPEN_PROTOCOL_BY_DRIVER
975 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
976 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
978 Status
= EFI_DEVICE_ERROR
;
982 if (!EFI_ERROR (Status
)) {
984 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
985 // Then its max supported devices are 256. Otherwise it's 128.
987 ASSERT (UsbBus
->Usb2Hc
!= NULL
);
988 if (UsbBus
->Usb2Hc
->MajorRevision
== 0x3) {
989 UsbBus
->MaxDevices
= 256;
994 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
996 Status
= gBS
->InstallProtocolInterface (
999 EFI_NATIVE_INTERFACE
,
1003 if (EFI_ERROR (Status
)) {
1004 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to install bus protocol %r\n", Status
));
1009 // Initial the wanted child device path list, and add first RemainingDevicePath
1011 InitializeListHead (&UsbBus
->WantedUsbIoDPList
);
1012 Status
= UsbBusAddWantedUsbIoDP (&UsbBus
->BusId
, RemainingDevicePath
);
1013 ASSERT (!EFI_ERROR (Status
));
1015 // Create a fake usb device for root hub
1017 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
1019 if (RootHub
== NULL
) {
1020 Status
= EFI_OUT_OF_RESOURCES
;
1021 goto UNINSTALL_USBBUS
;
1024 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1026 if (RootIf
== NULL
) {
1028 Status
= EFI_OUT_OF_RESOURCES
;
1032 RootHub
->Bus
= UsbBus
;
1033 RootHub
->NumOfInterface
= 1;
1034 RootHub
->Interfaces
[0] = RootIf
;
1036 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1037 RootIf
->Device
= RootHub
;
1038 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1041 // Report Status Code here since we will enumerate the USB devices
1043 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1045 (EFI_IO_BUS_USB
| EFI_IOB_PC_DETECT
),
1049 Status
= mUsbRootHubApi
.Init (RootIf
);
1051 if (EFI_ERROR (Status
)) {
1052 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to init root hub %r\n", Status
));
1056 UsbBus
->Devices
[0] = RootHub
;
1058 DEBUG ((EFI_D_INFO
, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller
, RootIf
));
1062 if (RootIf
!= NULL
) {
1065 if (RootHub
!= NULL
) {
1070 gBS
->UninstallProtocolInterface (Controller
, &gEfiCallerIdGuid
, &UsbBus
->BusId
);
1073 if (UsbBus
->Usb2Hc
!= NULL
) {
1074 gBS
->CloseProtocol (
1076 &gEfiUsb2HcProtocolGuid
,
1077 This
->DriverBindingHandle
,
1081 if (UsbBus
->UsbHc
!= NULL
) {
1082 gBS
->CloseProtocol (
1084 &gEfiUsbHcProtocolGuid
,
1085 This
->DriverBindingHandle
,
1089 gBS
->CloseProtocol (
1091 &gEfiDevicePathProtocolGuid
,
1092 This
->DriverBindingHandle
,
1097 DEBUG ((EFI_D_ERROR
, "UsbBusStart: Failed to start bus driver %r\n", Status
));
1103 The USB bus driver entry pointer.
1105 @param ImageHandle The driver image handle.
1106 @param SystemTable The system table.
1108 @return EFI_SUCCESS The component name protocol is installed.
1109 @return Others Failed to init the usb driver.
1114 UsbBusDriverEntryPoint (
1115 IN EFI_HANDLE ImageHandle
,
1116 IN EFI_SYSTEM_TABLE
*SystemTable
1119 return EfiLibInstallDriverBindingComponentName2 (
1122 &mUsbBusDriverBinding
,
1124 &mUsbBusComponentName
,
1125 &mUsbBusComponentName2
1131 Check whether USB bus driver support this device.
1133 @param This The USB bus driver binding protocol.
1134 @param Controller The controller handle to check.
1135 @param RemainingDevicePath The remaining device path.
1137 @retval EFI_SUCCESS The bus supports this controller.
1138 @retval EFI_UNSUPPORTED This device isn't supported.
1143 UsbBusControllerDriverSupported (
1144 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1145 IN EFI_HANDLE Controller
,
1146 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1149 EFI_DEV_PATH_PTR DevicePathNode
;
1150 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1151 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
1152 EFI_USB_HC_PROTOCOL
*UsbHc
;
1156 // Check whether device path is valid
1158 if (RemainingDevicePath
!= NULL
) {
1160 // Check if RemainingDevicePath is the End of Device Path Node,
1161 // if yes, go on checking other conditions
1163 if (!IsDevicePathEnd (RemainingDevicePath
)) {
1165 // If RemainingDevicePath isn't the End of Device Path Node,
1166 // check its validation
1168 DevicePathNode
.DevPath
= RemainingDevicePath
;
1170 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1171 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
&&
1172 DevicePathNode
.DevPath
->SubType
!= MSG_USB_CLASS_DP
1173 && DevicePathNode
.DevPath
->SubType
!= MSG_USB_WWID_DP
1176 return EFI_UNSUPPORTED
;
1182 // Check whether USB_HC2 protocol is installed
1184 Status
= gBS
->OpenProtocol (
1186 &gEfiUsb2HcProtocolGuid
,
1188 This
->DriverBindingHandle
,
1190 EFI_OPEN_PROTOCOL_BY_DRIVER
1192 if (Status
== EFI_ALREADY_STARTED
) {
1196 if (EFI_ERROR (Status
)) {
1198 // If failed to open USB_HC2, fall back to USB_HC
1200 Status
= gBS
->OpenProtocol (
1202 &gEfiUsbHcProtocolGuid
,
1204 This
->DriverBindingHandle
,
1206 EFI_OPEN_PROTOCOL_BY_DRIVER
1208 if (Status
== EFI_ALREADY_STARTED
) {
1212 if (EFI_ERROR (Status
)) {
1217 // Close the USB_HC used to perform the supported test
1219 gBS
->CloseProtocol (
1221 &gEfiUsbHcProtocolGuid
,
1222 This
->DriverBindingHandle
,
1229 // Close the USB_HC2 used to perform the supported test
1231 gBS
->CloseProtocol (
1233 &gEfiUsb2HcProtocolGuid
,
1234 This
->DriverBindingHandle
,
1240 // Open the EFI Device Path protocol needed to perform the supported test
1242 Status
= gBS
->OpenProtocol (
1244 &gEfiDevicePathProtocolGuid
,
1245 (VOID
**) &ParentDevicePath
,
1246 This
->DriverBindingHandle
,
1248 EFI_OPEN_PROTOCOL_BY_DRIVER
1250 if (Status
== EFI_ALREADY_STARTED
) {
1254 if (!EFI_ERROR (Status
)) {
1256 // Close protocol, don't use device path protocol in the Support() function
1258 gBS
->CloseProtocol (
1260 &gEfiDevicePathProtocolGuid
,
1261 This
->DriverBindingHandle
,
1273 Start to process the controller.
1275 @param This The USB bus driver binding instance.
1276 @param Controller The controller to check.
1277 @param RemainingDevicePath The remaining device patch.
1279 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1280 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1282 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1287 UsbBusControllerDriverStart (
1288 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1289 IN EFI_HANDLE Controller
,
1290 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1293 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1295 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1297 Status
= gBS
->OpenProtocol (
1299 &gEfiDevicePathProtocolGuid
,
1300 (VOID
**) &ParentDevicePath
,
1301 This
->DriverBindingHandle
,
1303 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1305 ASSERT_EFI_ERROR (Status
);
1308 // Report Status Code here since we will initialize the host controller
1310 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1312 (EFI_IO_BUS_USB
| EFI_IOB_PC_INIT
),
1317 // Locate the USB bus protocol, if it is found, USB bus
1318 // is already started on this controller.
1320 Status
= gBS
->OpenProtocol (
1323 (VOID
**) &UsbBusId
,
1324 This
->DriverBindingHandle
,
1326 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1329 if (EFI_ERROR (Status
)) {
1331 // If first start, build the bus execute environment and install bus protocol
1333 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_IO_BUS_USB
| EFI_P_PC_ENABLE
));
1334 Status
= UsbBusBuildProtocol (This
, Controller
, RemainingDevicePath
);
1335 if (EFI_ERROR (Status
)) {
1339 // Try get the Usb Bus protocol interface again
1341 Status
= gBS
->OpenProtocol (
1344 (VOID
**) &UsbBusId
,
1345 This
->DriverBindingHandle
,
1347 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1349 ASSERT (!EFI_ERROR (Status
));
1352 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1353 // usb child device will be recursively connected.
1354 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1355 // All wanted usb child devices will be remembered by the usb bus driver itself.
1356 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1358 // Save the passed in RemainingDevicePath this time
1360 if (RemainingDevicePath
!= NULL
) {
1361 if (IsDevicePathEnd (RemainingDevicePath
)) {
1363 // If RemainingDevicePath is the End of Device Path Node,
1364 // skip enumerate any device and return EFI_SUCESSS
1370 Status
= UsbBusAddWantedUsbIoDP (UsbBusId
, RemainingDevicePath
);
1371 ASSERT (!EFI_ERROR (Status
));
1373 // Ensure all wanted child usb devices are fully recursively connected
1375 Status
= UsbBusRecursivelyConnectWantedUsbIo (UsbBusId
);
1376 ASSERT (!EFI_ERROR (Status
));
1385 Stop handle the controller by this USB bus driver.
1387 @param This The USB bus driver binding protocol.
1388 @param Controller The controller to release.
1389 @param NumberOfChildren The child of USB bus that opened controller
1391 @param ChildHandleBuffer The array of child handle.
1393 @retval EFI_SUCCESS The controller or children are stopped.
1394 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1399 UsbBusControllerDriverStop (
1400 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1401 IN EFI_HANDLE Controller
,
1402 IN UINTN NumberOfChildren
,
1403 IN EFI_HANDLE
*ChildHandleBuffer
1407 USB_DEVICE
*RootHub
;
1409 USB_INTERFACE
*RootIf
;
1410 USB_INTERFACE
*UsbIf
;
1411 EFI_USB_BUS_PROTOCOL
*BusId
;
1412 EFI_USB_IO_PROTOCOL
*UsbIo
;
1416 EFI_STATUS ReturnStatus
;
1418 Status
= EFI_SUCCESS
;
1420 if (NumberOfChildren
> 0) {
1422 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1424 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1426 ReturnStatus
= EFI_SUCCESS
;
1427 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1428 Status
= gBS
->OpenProtocol (
1429 ChildHandleBuffer
[Index
],
1430 &gEfiUsbIoProtocolGuid
,
1432 This
->DriverBindingHandle
,
1434 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1437 if (EFI_ERROR (Status
)) {
1439 // It is possible that the child has already been released:
1440 // 1. For combo device, free one device will release others.
1441 // 2. If a hub is released, all devices on its down facing
1442 // ports are released also.
1447 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1448 UsbDev
= UsbIf
->Device
;
1450 ReturnStatus
= UsbRemoveDevice (UsbDev
);
1453 gBS
->RestoreTPL (OldTpl
);
1454 return ReturnStatus
;
1457 DEBUG (( EFI_D_INFO
, "UsbBusStop: usb bus stopped on %p\n", Controller
));
1460 // Locate USB_BUS for the current host controller
1462 Status
= gBS
->OpenProtocol (
1466 This
->DriverBindingHandle
,
1468 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1471 if (EFI_ERROR (Status
)) {
1475 Bus
= USB_BUS_FROM_THIS (BusId
);
1478 // Stop the root hub, then free all the devices
1480 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1482 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1484 RootHub
= Bus
->Devices
[0];
1485 RootIf
= RootHub
->Interfaces
[0];
1487 ASSERT (Bus
->MaxDevices
<= 256);
1488 ReturnStatus
= EFI_SUCCESS
;
1489 for (Index
= 1; Index
< Bus
->MaxDevices
; Index
++) {
1490 if (Bus
->Devices
[Index
] != NULL
) {
1491 Status
= UsbRemoveDevice (Bus
->Devices
[Index
]);
1492 if (EFI_ERROR (Status
)) {
1493 ReturnStatus
= Status
;
1498 gBS
->RestoreTPL (OldTpl
);
1500 if (!EFI_ERROR (ReturnStatus
)) {
1501 mUsbRootHubApi
.Release (RootIf
);
1502 gBS
->FreePool (RootIf
);
1503 gBS
->FreePool (RootHub
);
1505 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1506 ASSERT (!EFI_ERROR (Status
));
1509 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1511 gBS
->UninstallProtocolInterface (Controller
, &gEfiCallerIdGuid
, &Bus
->BusId
);
1513 if (Bus
->Usb2Hc
!= NULL
) {
1514 Status
= gBS
->CloseProtocol (
1516 &gEfiUsb2HcProtocolGuid
,
1517 This
->DriverBindingHandle
,
1522 if (Bus
->UsbHc
!= NULL
) {
1523 Status
= gBS
->CloseProtocol (
1525 &gEfiUsbHcProtocolGuid
,
1526 This
->DriverBindingHandle
,
1531 if (!EFI_ERROR (Status
)) {
1532 gBS
->CloseProtocol (
1534 &gEfiDevicePathProtocolGuid
,
1535 This
->DriverBindingHandle
,
1539 gBS
->FreePool (Bus
);