3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Usb Bus Driver Binding and Bus IO Protocol
28 // USB_BUS_PROTOCOL is only used to locate USB_BUS
30 EFI_GUID mUsbBusProtocolGuid
= EFI_USB_BUS_PROTOCOL_GUID
;
34 USB_IO function to execute a control transfer. This
35 function will execute the USB transfer. If transfer
36 successes, it will sync the internal state of USB bus
39 @param This The USB_IO instance
40 @param Request The control transfer request
41 @param Direction Direction for data stage
42 @param Timeout The time to wait before timeout
43 @param Data The buffer holding the data
44 @param DataLength Then length of the data
45 @param UsbStatus USB result
47 @retval EFI_INVALID_PARAMETER The parameters are invalid
48 @retval EFI_SUCCESS The control transfer succeded.
49 @retval Others Failed to execute the transfer
55 UsbIoControlTransfer (
56 IN EFI_USB_IO_PROTOCOL
*This
,
57 IN EFI_USB_DEVICE_REQUEST
*Request
,
58 IN EFI_USB_DATA_DIRECTION Direction
,
60 IN OUT VOID
*Data
, OPTIONAL
61 IN UINTN DataLength
, OPTIONAL
67 USB_ENDPOINT_DESC
*EpDesc
;
71 if (UsbStatus
== NULL
) {
72 return EFI_INVALID_PARAMETER
;
75 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
77 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
80 Status
= UsbHcControlTransfer (
94 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
96 // Clear TT buffer when CTRL/BULK split transaction failes
97 // Clear the TRANSLATOR TT buffer, not parent's buffer
99 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
100 UsbHubCtrlClearTTBuffer (
101 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
102 Dev
->Translator
.TranslatorPortNumber
,
113 // Some control transfer will change the device's internal
114 // status, such as Set_Configuration and Set_Interface.
115 // We must synchronize the bus driver's status with that in
116 // device. We ignore the Set_Descriptor request because it's
117 // hardly used by any device, especially in pre-boot environment
121 // Reset the endpoint toggle when endpoint stall is cleared
123 if ((Request
->Request
== USB_REQ_CLEAR_FEATURE
) &&
124 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
125 USB_TARGET_ENDPOINT
)) &&
126 (Request
->Value
== USB_FEATURE_ENDPOINT_HALT
)) {
128 EpDesc
= UsbGetEndpointDesc (UsbIf
, (UINT8
) Request
->Index
);
130 if (EpDesc
!= NULL
) {
136 // Select a new configuration. This is a dangerous action. Upper driver
137 // should stop use its current UsbIo after calling this driver. The old
138 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
139 // ReinstallProtocol since interfaces in different configuration may be
140 // completely irrellvant.
142 if ((Request
->Request
== USB_REQ_SET_CONFIG
) &&
143 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
144 USB_TARGET_DEVICE
))) {
146 // Don't re-create the USB interfaces if configuration isn't changed.
148 if ((Dev
->ActiveConfig
!= NULL
) &&
149 (Request
->Value
== Dev
->ActiveConfig
->Desc
.ConfigurationValue
)) {
154 USB_DEBUG (("UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
156 if (Dev
->ActiveConfig
!= NULL
) {
157 UsbRemoveConfig (Dev
);
160 if (Request
->Value
!= 0) {
161 Status
= UsbSelectConfig (Dev
, (UINT8
) Request
->Value
);
165 // Exit now, Old USB_IO is invalid now
171 // A new alternative setting is selected for the interface.
172 // No need to reinstall UsbIo in this case because only
173 // underlying communication endpoints are changed. Functionality
174 // should remains the same.
176 if ((Request
->Request
== USB_REQ_SET_INTERFACE
) &&
177 (Request
->RequestType
== USB_REQUEST_TYPE (EfiUsbNoData
, USB_REQ_TYPE_STANDARD
,
178 USB_TARGET_INTERFACE
)) &&
179 (Request
->Index
== UsbIf
->IfSetting
->Desc
.InterfaceNumber
)) {
181 Status
= UsbSelectSetting (UsbIf
->IfDesc
, (UINT8
) Request
->Value
);
183 if (!EFI_ERROR (Status
)) {
184 UsbIf
->IfSetting
= UsbIf
->IfDesc
->Settings
[UsbIf
->IfDesc
->ActiveIndex
];
189 gBS
->RestoreTPL (OldTpl
);
195 Execute a bulk transfer to the device endpoint
197 @param This The USB IO instance
198 @param Endpoint The device endpoint
199 @param Data The data to transfer
200 @param DataLength The length of the data to transfer
201 @param Timeout Time to wait before timeout
202 @param UsbStatus The result of USB transfer
204 @retval EFI_SUCCESS The bulk transfer is OK
205 @retval EFI_INVALID_PARAMETER Some parameters are invalid
206 @retval Others Failed to execute transfer, reason returned in
214 IN EFI_USB_IO_PROTOCOL
*This
,
217 IN OUT UINTN
*DataLength
,
219 OUT UINT32
*UsbStatus
223 USB_INTERFACE
*UsbIf
;
224 USB_ENDPOINT_DESC
*EpDesc
;
230 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
231 (UsbStatus
== NULL
)) {
233 return EFI_INVALID_PARAMETER
;
236 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
238 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
241 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
243 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_BULK
)) {
244 Status
= EFI_INVALID_PARAMETER
;
249 Toggle
= EpDesc
->Toggle
;
250 Status
= UsbHcBulkTransfer (
255 EpDesc
->Desc
.MaxPacketSize
,
265 EpDesc
->Toggle
= Toggle
;
267 if (EFI_ERROR (Status
) || (*UsbStatus
!= EFI_USB_NOERROR
)) {
269 // Clear TT buffer when CTRL/BULK split transaction failes.
270 // Clear the TRANSLATOR TT buffer, not parent's buffer
272 if (Dev
->Translator
.TranslatorHubAddress
!= 0) {
273 UsbHubCtrlClearTTBuffer (
274 Dev
->Bus
->Devices
[Dev
->Translator
.TranslatorHubAddress
],
275 Dev
->Translator
.TranslatorPortNumber
,
284 gBS
->RestoreTPL (OldTpl
);
290 Execute a synchronous interrupt transfer
292 @param This The USB IO instance
293 @param Endpoint The device endpoint
294 @param Data The data to transfer
295 @param DataLength The length of the data to transfer
296 @param Timeout Time to wait before timeout
297 @param UsbStatus The result of USB transfer
299 @retval EFI_SUCCESS The synchronous interrupt transfer is OK
300 @retval EFI_INVALID_PARAMETER Some parameters are invalid
301 @retval Others Failed to execute transfer, reason returned in
308 UsbIoSyncInterruptTransfer (
309 IN EFI_USB_IO_PROTOCOL
*This
,
312 IN OUT UINTN
*DataLength
,
314 OUT UINT32
*UsbStatus
318 USB_INTERFACE
*UsbIf
;
319 USB_ENDPOINT_DESC
*EpDesc
;
324 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR(Endpoint
) > 15) ||
325 (UsbStatus
== NULL
)) {
327 return EFI_INVALID_PARAMETER
;
330 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
332 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
335 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
337 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
338 Status
= EFI_INVALID_PARAMETER
;
342 Toggle
= EpDesc
->Toggle
;
343 Status
= UsbHcSyncInterruptTransfer (
348 EpDesc
->Desc
.MaxPacketSize
,
357 EpDesc
->Toggle
= Toggle
;
360 gBS
->RestoreTPL (OldTpl
);
366 Queue a new asynchronous interrupt transfer, or remove the old
367 request if (IsNewTransfer == FALSE)
369 @param This The USB_IO instance
370 @param Endpoint The device endpoint
371 @param IsNewTransfer Whether this is a new request, if it's old, remove
373 @param PollInterval The interval to poll the transfer result, (in ms)
374 @param DataLength The length of perodic data transfer
375 @param Callback The function to call periodicaly when transfer is
377 @param Context The context to the callback
379 @retval EFI_SUCCESS New transfer is queued or old request is removed
380 @retval EFI_INVALID_PARAMETER Some parameters are invalid
381 @retval Others Failed to queue the new request or remove the old
388 UsbIoAsyncInterruptTransfer (
389 IN EFI_USB_IO_PROTOCOL
*This
,
391 IN BOOLEAN IsNewTransfer
,
392 IN UINTN PollInterval
, OPTIONAL
393 IN UINTN DataLength
, OPTIONAL
394 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
, OPTIONAL
395 IN VOID
*Context OPTIONAL
399 USB_INTERFACE
*UsbIf
;
400 USB_ENDPOINT_DESC
*EpDesc
;
405 if ((USB_ENDPOINT_ADDR (Endpoint
) == 0) || (USB_ENDPOINT_ADDR (Endpoint
) > 15)) {
406 return EFI_INVALID_PARAMETER
;
409 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
410 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
413 EpDesc
= UsbGetEndpointDesc (UsbIf
, Endpoint
);
415 if ((EpDesc
== NULL
) || (USB_ENDPOINT_TYPE (&EpDesc
->Desc
) != USB_ENDPOINT_INTERRUPT
)) {
416 Status
= EFI_INVALID_PARAMETER
;
420 Toggle
= EpDesc
->Toggle
;
421 Status
= UsbHcAsyncInterruptTransfer (
426 EpDesc
->Desc
.MaxPacketSize
,
436 EpDesc
->Toggle
= Toggle
;
439 gBS
->RestoreTPL (OldTpl
);
445 Execute a synchronous isochronous transfer
447 @param This The USB IO instance
448 @param DeviceEndpoint The device endpoint
449 @param Data The data to transfer
450 @param DataLength The length of the data to transfer
451 @param UsbStatus The result of USB transfer
453 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported
459 UsbIoIsochronousTransfer (
460 IN EFI_USB_IO_PROTOCOL
*This
,
461 IN UINT8 DeviceEndpoint
,
467 return EFI_UNSUPPORTED
;
472 Queue an asynchronous isochronous transfer
474 @param This The USB_IO instance
475 @param DeviceEndpoint The device endpoint
476 @param DataLength The length of perodic data transfer
477 @param IsochronousCallBack The function to call periodicaly when transfer is
479 @param Context The context to the callback
481 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported
487 UsbIoAsyncIsochronousTransfer (
488 IN EFI_USB_IO_PROTOCOL
*This
,
489 IN UINT8 DeviceEndpoint
,
492 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
493 IN VOID
*Context OPTIONAL
496 return EFI_UNSUPPORTED
;
501 Retrieve the device descriptor of the device
503 @param This The USB IO instance
504 @param Descriptor The variable to receive the device descriptor
506 @retval EFI_SUCCESS The device descriptor is returned
507 @retval EFI_INVALID_PARAMETER The parameter is invalid
513 UsbIoGetDeviceDescriptor (
514 IN EFI_USB_IO_PROTOCOL
*This
,
515 OUT EFI_USB_DEVICE_DESCRIPTOR
*Descriptor
519 USB_INTERFACE
*UsbIf
;
522 if (Descriptor
== NULL
) {
523 return EFI_INVALID_PARAMETER
;
526 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
528 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
531 CopyMem (Descriptor
, &Dev
->DevDesc
->Desc
, sizeof (EFI_USB_DEVICE_DESCRIPTOR
));
533 gBS
->RestoreTPL (OldTpl
);
539 Return the configuration descriptor of the current active configuration
541 @param This The USB IO instance
542 @param Descriptor The USB configuration descriptor
544 @retval EFI_SUCCESS The active configuration descriptor is returned
545 @retval EFI_INVALID_PARAMETER Some parameter is invalid
546 @retval EFI_NOT_FOUND Currently no active configuration is selected.
552 UsbIoGetActiveConfigDescriptor (
553 IN EFI_USB_IO_PROTOCOL
*This
,
554 OUT EFI_USB_CONFIG_DESCRIPTOR
*Descriptor
558 USB_INTERFACE
*UsbIf
;
562 if (Descriptor
== NULL
) {
563 return EFI_INVALID_PARAMETER
;
566 Status
= EFI_SUCCESS
;
567 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
569 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
572 if (Dev
->ActiveConfig
== NULL
) {
573 Status
= EFI_NOT_FOUND
;
577 CopyMem (Descriptor
, &(Dev
->ActiveConfig
->Desc
), sizeof (EFI_USB_CONFIG_DESCRIPTOR
));
580 gBS
->RestoreTPL (OldTpl
);
586 Retrieve the active interface setting descriptor for this USB IO instance
588 @param This The USB IO instance
589 @param Descriptor The variable to receive active interface setting
591 @retval EFI_SUCCESS The active interface setting is returned
592 @retval EFI_INVALID_PARAMETER Some parameter is invalid
598 UsbIoGetInterfaceDescriptor (
599 IN EFI_USB_IO_PROTOCOL
*This
,
600 OUT EFI_USB_INTERFACE_DESCRIPTOR
*Descriptor
603 USB_INTERFACE
*UsbIf
;
606 if (Descriptor
== NULL
) {
607 return EFI_INVALID_PARAMETER
;
610 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
612 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
613 CopyMem (Descriptor
, &(UsbIf
->IfSetting
->Desc
), sizeof (EFI_USB_INTERFACE_DESCRIPTOR
));
615 gBS
->RestoreTPL (OldTpl
);
621 Retrieve the endpoint descriptor from this interface setting
623 @param This The USB IO instance
624 @param Index The index (start from zero) of the endpoint to
626 @param Descriptor The variable to receive the descriptor
628 @retval EFI_SUCCESS The endpoint descriptor is returned
629 @retval EFI_INVALID_PARAMETER Some parameter is invalid
635 UsbIoGetEndpointDescriptor (
636 IN EFI_USB_IO_PROTOCOL
*This
,
638 OUT EFI_USB_ENDPOINT_DESCRIPTOR
*Descriptor
641 USB_INTERFACE
*UsbIf
;
644 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
646 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
648 if ((Descriptor
== NULL
) || (Index
> 15)) {
649 gBS
->RestoreTPL (OldTpl
);
650 return EFI_INVALID_PARAMETER
;
653 if (Index
>= UsbIf
->IfSetting
->Desc
.NumEndpoints
) {
654 gBS
->RestoreTPL (OldTpl
);
655 return EFI_NOT_FOUND
;
660 &(UsbIf
->IfSetting
->Endpoints
[Index
]->Desc
),
661 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR
)
664 gBS
->RestoreTPL (OldTpl
);
670 Retrieve the supported language ID table from the device
672 @param This The USB IO instance
673 @param LangIDTable The table to return the language IDs
674 @param TableSize The number of supported languanges
676 @retval EFI_SUCCESS The language ID is return
682 UsbIoGetSupportedLanguages (
683 IN EFI_USB_IO_PROTOCOL
*This
,
684 OUT UINT16
**LangIDTable
,
685 OUT UINT16
*TableSize
689 USB_INTERFACE
*UsbIf
;
692 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
694 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
697 *LangIDTable
= Dev
->LangId
;
698 *TableSize
= Dev
->TotalLangId
;
700 gBS
->RestoreTPL (OldTpl
);
706 Retrieve an indexed string in the language of LangID
708 @param This The USB IO instance
709 @param LangID The language ID of the string to retrieve
710 @param StringIndex The index of the string
711 @param String The variable to receive the string
713 @retval EFI_SUCCESS The string is returned
714 @retval EFI_NOT_FOUND No such string existed
720 UsbIoGetStringDescriptor (
721 IN EFI_USB_IO_PROTOCOL
*This
,
723 IN UINT8 StringIndex
,
728 USB_INTERFACE
*UsbIf
;
729 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
735 if ((StringIndex
== 0) || (LangID
== 0)) {
736 return EFI_NOT_FOUND
;
739 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
741 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
745 // Check whether language ID is supported
747 Status
= EFI_NOT_FOUND
;
749 for (Index
= 0; Index
< Dev
->TotalLangId
; Index
++) {
750 if (Dev
->LangId
[Index
] == LangID
) {
755 if (Index
== Dev
->TotalLangId
) {
760 // Retrieve the string descriptor then allocate a buffer
761 // to hold the string itself.
763 StrDesc
= UsbGetOneString (Dev
, StringIndex
, LangID
);
765 if (StrDesc
== NULL
) {
769 if (StrDesc
->Length
<= 2) {
773 Buf
= AllocateZeroPool (StrDesc
->Length
);
776 Status
= EFI_OUT_OF_RESOURCES
;
780 CopyMem (Buf
, StrDesc
->String
, StrDesc
->Length
- 2);
781 *String
= (CHAR16
*) Buf
;
782 Status
= EFI_SUCCESS
;
785 gBS
->FreePool (StrDesc
);
788 gBS
->RestoreTPL (OldTpl
);
794 Reset the device, then if that succeeds, reconfigure the
795 device with its address and current active configuration.
797 @param This The USB IO instance
799 @retval EFI_SUCCESS The device is reset and configured
800 @retval Others Failed to reset the device
806 IN EFI_USB_IO_PROTOCOL
*This
809 USB_INTERFACE
*UsbIf
;
810 USB_INTERFACE
*HubIf
;
816 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
818 UsbIf
= USB_INTERFACE_FROM_USBIO (This
);
821 if (UsbIf
->IsHub
== TRUE
) {
822 Status
= EFI_INVALID_PARAMETER
;
826 HubIf
= Dev
->ParentIf
;
827 Status
= HubIf
->HubApi
->ResetPort (HubIf
, Dev
->ParentPort
);
829 if (EFI_ERROR (Status
)) {
830 USB_ERROR (("UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
831 Dev
->ParentPort
, Dev
->ParentAddr
, Status
));
837 // Reset the device to its current address. The device now has a
838 // address of ZERO, so need to set Dev->Address to zero first for
839 // host to communicate with the device
841 Address
= Dev
->Address
;
843 Status
= UsbSetAddress (Dev
, Address
);
845 if (EFI_ERROR (Status
)) {
846 USB_ERROR (("UsbIoPortReset: failed to set address for device %d - %r\n",
852 Dev
->Address
= Address
;
855 // Reset the current active configure, after this device
856 // is in CONFIGURED state.
858 if (Dev
->ActiveConfig
!= NULL
) {
859 Status
= UsbSetConfig (Dev
, Dev
->ActiveConfig
->Desc
.ConfigurationValue
);
861 if (EFI_ERROR (Status
)) {
862 USB_ERROR (("UsbIoPortReset: failed to set configure for device %d - %r\n",
868 gBS
->RestoreTPL (OldTpl
);
872 EFI_USB_IO_PROTOCOL mUsbIoProtocol
= {
873 UsbIoControlTransfer
,
875 UsbIoAsyncInterruptTransfer
,
876 UsbIoSyncInterruptTransfer
,
877 UsbIoIsochronousTransfer
,
878 UsbIoAsyncIsochronousTransfer
,
879 UsbIoGetDeviceDescriptor
,
880 UsbIoGetActiveConfigDescriptor
,
881 UsbIoGetInterfaceDescriptor
,
882 UsbIoGetEndpointDescriptor
,
883 UsbIoGetStringDescriptor
,
884 UsbIoGetSupportedLanguages
,
891 UsbBusDriverEntryPoint (
892 IN EFI_HANDLE ImageHandle
,
893 IN EFI_SYSTEM_TABLE
*SystemTable
899 The USB bus driver entry pointer
903 ImageHandle - The driver image handle
904 SystemTable - The system table
908 EFI_SUCCESS - The component name protocol is installed
909 Others - Failed to init the usb driver
913 return EfiLibInstallAllDriverProtocols (
916 &mUsbBusDriverBinding
,
918 &mUsbBusComponentName
,
926 Check whether USB bus driver support this device
928 @param This The USB bus driver binding protocol
929 @param Controller The controller handle to test againist
930 @param RemainingDevicePath The remaining device path
932 @retval EFI_SUCCESS The bus supports this controller.
933 @retval EFI_UNSUPPORTED This device isn't supported
938 UsbBusControllerDriverSupported (
939 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
940 IN EFI_HANDLE Controller
,
941 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
944 EFI_DEV_PATH_PTR DevicePathNode
;
945 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
946 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
947 EFI_USB_HC_PROTOCOL
*UsbHc
;
951 // Check whether device path is valid
953 if (RemainingDevicePath
!= NULL
) {
954 DevicePathNode
.DevPath
= RemainingDevicePath
;
956 if ((DevicePathNode
.DevPath
->Type
!= MESSAGING_DEVICE_PATH
) ||
957 (DevicePathNode
.DevPath
->SubType
!= MSG_USB_DP
) ||
958 (DevicePathNodeLength (DevicePathNode
.DevPath
) != sizeof (USB_DEVICE_PATH
))) {
960 return EFI_UNSUPPORTED
;
964 Status
= gBS
->OpenProtocol (
966 &gEfiDevicePathProtocolGuid
,
967 (VOID
**) &ParentDevicePath
,
968 This
->DriverBindingHandle
,
970 EFI_OPEN_PROTOCOL_BY_DRIVER
973 if (Status
== EFI_ALREADY_STARTED
) {
977 if (EFI_ERROR (Status
)) {
983 &gEfiDevicePathProtocolGuid
,
984 This
->DriverBindingHandle
,
989 // Check whether USB_HC2 protocol is installed
991 Status
= gBS
->OpenProtocol (
993 &gEfiUsb2HcProtocolGuid
,
995 This
->DriverBindingHandle
,
997 EFI_OPEN_PROTOCOL_BY_DRIVER
1000 if (Status
== EFI_ALREADY_STARTED
) {
1004 if (!EFI_ERROR (Status
)) {
1005 gBS
->CloseProtocol (
1007 &gEfiUsb2HcProtocolGuid
,
1008 This
->DriverBindingHandle
,
1016 // If failed to open USB_HC2, fall back to USB_HC
1018 Status
= gBS
->OpenProtocol (
1020 &gEfiUsbHcProtocolGuid
,
1022 This
->DriverBindingHandle
,
1024 EFI_OPEN_PROTOCOL_BY_DRIVER
1027 if (Status
== EFI_ALREADY_STARTED
) {
1031 if (!EFI_ERROR (Status
)) {
1032 gBS
->CloseProtocol (
1034 &gEfiUsbHcProtocolGuid
,
1035 This
->DriverBindingHandle
,
1045 Start to process the controller
1047 @param This The USB bus driver binding instance
1048 @param Controller The controller to check
1049 @param RemainingDevicePath The remaining device patch
1051 @retval EFI_SUCCESS The controller is controlled by the usb bus
1052 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1054 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources
1059 UsbBusControllerDriverStart (
1060 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1061 IN EFI_HANDLE Controller
,
1062 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1066 USB_DEVICE
*RootHub
;
1067 USB_INTERFACE
*RootIf
;
1068 EFI_USB_BUS_PROTOCOL
*UsbBusId
;
1073 // Locate the USB bus protocol, if it is found, USB bus
1074 // is already started on this controller.
1076 Status
= gBS
->OpenProtocol (
1078 &mUsbBusProtocolGuid
,
1079 (VOID
**) &UsbBusId
,
1080 This
->DriverBindingHandle
,
1082 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1085 if (!EFI_ERROR (Status
)) {
1086 return EFI_ALREADY_STARTED
;
1089 UsbBus
= AllocateZeroPool (sizeof (USB_BUS
));
1091 if (UsbBus
== NULL
) {
1092 return EFI_OUT_OF_RESOURCES
;
1095 UsbBus
->Signature
= USB_BUS_SIGNATURE
;
1096 UsbBus
->HostHandle
= Controller
;
1098 Status
= gBS
->OpenProtocol (
1100 &gEfiDevicePathProtocolGuid
,
1101 (VOID
**) &UsbBus
->DevicePath
,
1102 This
->DriverBindingHandle
,
1104 EFI_OPEN_PROTOCOL_BY_DRIVER
1107 if (EFI_ERROR (Status
)) {
1108 USB_ERROR (("UsbBusStart: Failed to open device path %r\n", Status
));
1110 gBS
->FreePool (UsbBus
);
1115 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
1116 // This is for backward compatbility with EFI 1.x. In UEFI
1117 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
1118 // and USB_HC because EHCI driver will install both protocols
1119 // (for the same reason). If we don't consume both of them,
1120 // the unconsumed one may be opened by others.
1122 Status
= gBS
->OpenProtocol (
1124 &gEfiUsb2HcProtocolGuid
,
1125 (VOID
**) &(UsbBus
->Usb2Hc
),
1126 This
->DriverBindingHandle
,
1128 EFI_OPEN_PROTOCOL_BY_DRIVER
1131 Status2
= gBS
->OpenProtocol (
1133 &gEfiUsbHcProtocolGuid
,
1134 (VOID
**) &(UsbBus
->UsbHc
),
1135 This
->DriverBindingHandle
,
1137 EFI_OPEN_PROTOCOL_BY_DRIVER
1140 if (EFI_ERROR (Status
) && EFI_ERROR (Status2
)) {
1141 USB_ERROR (("UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status
));
1143 Status
= EFI_DEVICE_ERROR
;
1148 // Create a fake usb device for root hub
1150 RootHub
= AllocateZeroPool (sizeof (USB_DEVICE
));
1152 if (RootHub
== NULL
) {
1153 Status
= EFI_OUT_OF_RESOURCES
;
1157 RootIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
1159 if (RootIf
== NULL
) {
1160 gBS
->FreePool (RootHub
);
1161 Status
= EFI_OUT_OF_RESOURCES
;
1165 RootHub
->Bus
= UsbBus
;
1166 RootHub
->NumOfInterface
= 1;
1167 RootHub
->Interfaces
[0] = RootIf
;
1168 RootIf
->Signature
= USB_INTERFACE_SIGNATURE
;
1169 RootIf
->Device
= RootHub
;
1170 RootIf
->DevicePath
= UsbBus
->DevicePath
;
1172 Status
= mUsbRootHubApi
.Init (RootIf
);
1174 if (EFI_ERROR (Status
)) {
1175 USB_ERROR (("UsbBusStart: Failed to init root hub %r\n", Status
));
1179 UsbBus
->Devices
[0] = RootHub
;
1182 // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.
1184 Status
= gBS
->InstallProtocolInterface (
1186 &mUsbBusProtocolGuid
,
1187 EFI_NATIVE_INTERFACE
,
1191 if (EFI_ERROR (Status
)) {
1192 USB_ERROR (("UsbBusStart: Failed to install bus protocol %r\n", Status
));
1194 mUsbRootHubApi
.Release (RootIf
);
1198 UsbHcReset (UsbBus
, EFI_USB_HC_RESET_GLOBAL
);
1199 UsbHcSetState (UsbBus
, EfiUsbHcStateOperational
);
1201 USB_DEBUG (("UsbBusStart: usb bus started on %x, root hub %x\n", Controller
, RootIf
));
1205 gBS
->FreePool (RootIf
);
1206 gBS
->FreePool (RootHub
);
1209 if (UsbBus
->Usb2Hc
!= NULL
) {
1210 gBS
->CloseProtocol (
1212 &gEfiUsb2HcProtocolGuid
,
1213 This
->DriverBindingHandle
,
1218 if (UsbBus
->UsbHc
!= NULL
) {
1219 gBS
->CloseProtocol (
1221 &gEfiUsbHcProtocolGuid
,
1222 This
->DriverBindingHandle
,
1227 gBS
->CloseProtocol (
1229 &gEfiDevicePathProtocolGuid
,
1230 This
->DriverBindingHandle
,
1234 gBS
->FreePool (UsbBus
);
1236 USB_ERROR (("UsbBusStart: Failed to start bus driver %r\n", Status
));
1242 Stop handle the controller by this USB bus driver
1244 @param This The USB bus driver binding protocol
1245 @param Controller The controller to release
1246 @param NumberOfChildren The child of USB bus that opened controller
1248 @param ChildHandleBuffer The array of child handle
1250 @retval EFI_SUCCESS The controller or children are stopped
1251 @retval EFI_DEVICE_ERROR Failed to stop the driver
1256 UsbBusControllerDriverStop (
1257 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1258 IN EFI_HANDLE Controller
,
1259 IN UINTN NumberOfChildren
,
1260 IN EFI_HANDLE
*ChildHandleBuffer
1264 USB_DEVICE
*RootHub
;
1266 USB_INTERFACE
*RootIf
;
1267 USB_INTERFACE
*UsbIf
;
1268 EFI_USB_BUS_PROTOCOL
*BusId
;
1269 EFI_USB_IO_PROTOCOL
*UsbIo
;
1274 Status
= EFI_SUCCESS
;
1276 if (NumberOfChildren
> 0) {
1277 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
1279 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1280 Status
= gBS
->OpenProtocol (
1281 ChildHandleBuffer
[Index
],
1282 &gEfiUsbIoProtocolGuid
,
1284 This
->DriverBindingHandle
,
1286 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1289 if (EFI_ERROR (Status
)) {
1291 // It is possible that the child has already been released:
1292 // 1. For combo device, free one device will release others.
1293 // 2. If a hub is released, all devices on its down facing
1294 // ports are released also.
1299 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1300 UsbDev
= UsbIf
->Device
;
1302 UsbRemoveDevice (UsbDev
);
1305 gBS
->RestoreTPL (OldTpl
);
1309 USB_DEBUG (("UsbBusStop: usb bus stopped on %x\n", Controller
));
1312 // Locate USB_BUS for the current host controller
1314 Status
= gBS
->OpenProtocol (
1316 &mUsbBusProtocolGuid
,
1318 This
->DriverBindingHandle
,
1320 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1323 if (EFI_ERROR (Status
)) {
1327 Bus
= USB_BUS_FROM_THIS (BusId
);
1330 // Stop the root hub, then free all the devices
1332 OldTpl
= gBS
->RaiseTPL (USB_BUS_TPL
);
1333 UsbHcSetState (Bus
, EfiUsbHcStateHalt
);
1335 RootHub
= Bus
->Devices
[0];
1336 RootIf
= RootHub
->Interfaces
[0];
1338 mUsbRootHubApi
.Release (RootIf
);
1340 for (Index
= 1; Index
< USB_MAX_DEVICES
; Index
++) {
1341 if (Bus
->Devices
[Index
] != NULL
) {
1342 UsbRemoveDevice (Bus
->Devices
[Index
]);
1346 gBS
->RestoreTPL (OldTpl
);
1348 gBS
->FreePool (RootIf
);
1349 gBS
->FreePool (RootHub
);
1352 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1354 gBS
->UninstallProtocolInterface (Controller
, &mUsbBusProtocolGuid
, &Bus
->BusId
);
1356 if (Bus
->Usb2Hc
!= NULL
) {
1357 gBS
->CloseProtocol (
1359 &gEfiUsb2HcProtocolGuid
,
1360 This
->DriverBindingHandle
,
1365 if (Bus
->UsbHc
!= NULL
) {
1366 gBS
->CloseProtocol (
1368 &gEfiUsbHcProtocolGuid
,
1369 This
->DriverBindingHandle
,
1374 gBS
->CloseProtocol (
1376 &gEfiDevicePathProtocolGuid
,
1377 This
->DriverBindingHandle
,
1381 gBS
->FreePool (Bus
);
1386 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding
= {
1387 UsbBusControllerDriverSupported
,
1388 UsbBusControllerDriverStart
,
1389 UsbBusControllerDriverStop
,