]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
Check Library usage and fix some typo.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbBus.c
1 /** @file
2
3 Usb Bus Driver Binding and Bus IO Protocol.
4
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
10
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.
13
14 **/
15
16 #include "UsbBus.h"
17
18 //
19 // USB_BUS_PROTOCOL is only used to locate USB_BUS
20 //
21 EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;
22
23 EFI_USB_IO_PROTOCOL mUsbIoProtocol = {
24 UsbIoControlTransfer,
25 UsbIoBulkTransfer,
26 UsbIoAsyncInterruptTransfer,
27 UsbIoSyncInterruptTransfer,
28 UsbIoIsochronousTransfer,
29 UsbIoAsyncIsochronousTransfer,
30 UsbIoGetDeviceDescriptor,
31 UsbIoGetActiveConfigDescriptor,
32 UsbIoGetInterfaceDescriptor,
33 UsbIoGetEndpointDescriptor,
34 UsbIoGetStringDescriptor,
35 UsbIoGetSupportedLanguages,
36 UsbIoPortReset
37 };
38
39 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {
40 UsbBusControllerDriverSupported,
41 UsbBusControllerDriverStart,
42 UsbBusControllerDriverStop,
43 0xa,
44 NULL,
45 NULL
46 };
47
48
49 /**
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
53 with device state.
54
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
62
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
66
67 **/
68 EFI_STATUS
69 EFIAPI
70 UsbIoControlTransfer (
71 IN EFI_USB_IO_PROTOCOL *This,
72 IN EFI_USB_DEVICE_REQUEST *Request,
73 IN EFI_USB_DATA_DIRECTION Direction,
74 IN UINT32 Timeout,
75 IN OUT VOID *Data, OPTIONAL
76 IN UINTN DataLength, OPTIONAL
77 OUT UINT32 *UsbStatus
78 )
79 {
80 USB_DEVICE *Dev;
81 USB_INTERFACE *UsbIf;
82 USB_ENDPOINT_DESC *EpDesc;
83 EFI_TPL OldTpl;
84 EFI_STATUS Status;
85
86 if (UsbStatus == NULL) {
87 return EFI_INVALID_PARAMETER;
88 }
89
90 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
91
92 UsbIf = USB_INTERFACE_FROM_USBIO (This);
93 Dev = UsbIf->Device;
94
95 Status = UsbHcControlTransfer (
96 Dev->Bus,
97 Dev->Address,
98 Dev->Speed,
99 Dev->MaxPacket0,
100 Request,
101 Direction,
102 Data,
103 &DataLength,
104 (UINTN) Timeout,
105 &Dev->Translator,
106 UsbStatus
107 );
108
109 if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {
110 //
111 // Clear TT buffer when CTRL/BULK split transaction failes
112 // Clear the TRANSLATOR TT buffer, not parent's buffer
113 //
114 if (Dev->Translator.TranslatorHubAddress != 0) {
115 UsbHubCtrlClearTTBuffer (
116 Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],
117 Dev->Translator.TranslatorPortNumber,
118 Dev->Address,
119 0,
120 USB_ENDPOINT_CONTROL
121 );
122 }
123
124 goto ON_EXIT;
125 }
126
127 //
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
133 //
134
135 //
136 // Reset the endpoint toggle when endpoint stall is cleared
137 //
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)) {
142
143 EpDesc = UsbGetEndpointDesc (UsbIf, (UINT8) Request->Index);
144
145 if (EpDesc != NULL) {
146 EpDesc->Toggle = 0;
147 }
148 }
149
150 //
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.
156 //
157 if ((Request->Request == USB_REQ_SET_CONFIG) &&
158 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,
159 USB_TARGET_DEVICE))) {
160 //
161 // Don't re-create the USB interfaces if configuration isn't changed.
162 //
163 if ((Dev->ActiveConfig != NULL) &&
164 (Request->Value == Dev->ActiveConfig->Desc.ConfigurationValue)) {
165
166 goto ON_EXIT;
167 }
168 DEBUG ((EFI_D_INFO, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
169
170 if (Dev->ActiveConfig != NULL) {
171 UsbRemoveConfig (Dev);
172 }
173
174 if (Request->Value != 0) {
175 Status = UsbSelectConfig (Dev, (UINT8) Request->Value);
176 }
177
178 //
179 // Exit now, Old USB_IO is invalid now
180 //
181 goto ON_EXIT;
182 }
183
184 //
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.
189 //
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)) {
194
195 Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);
196
197 if (!EFI_ERROR (Status)) {
198 UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];
199 }
200 }
201
202 ON_EXIT:
203 gBS->RestoreTPL (OldTpl);
204 return Status;
205 }
206
207
208 /**
209 Execute a bulk transfer to the device endpoint.
210
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.
217
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
221 UsbStatus.
222
223 **/
224 EFI_STATUS
225 EFIAPI
226 UsbIoBulkTransfer (
227 IN EFI_USB_IO_PROTOCOL *This,
228 IN UINT8 Endpoint,
229 IN OUT VOID *Data,
230 IN OUT UINTN *DataLength,
231 IN UINTN Timeout,
232 OUT UINT32 *UsbStatus
233 )
234 {
235 USB_DEVICE *Dev;
236 USB_INTERFACE *UsbIf;
237 USB_ENDPOINT_DESC *EpDesc;
238 UINT8 BufNum;
239 UINT8 Toggle;
240 EFI_TPL OldTpl;
241 EFI_STATUS Status;
242
243 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||
244 (UsbStatus == NULL)) {
245
246 return EFI_INVALID_PARAMETER;
247 }
248
249 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
250
251 UsbIf = USB_INTERFACE_FROM_USBIO (This);
252 Dev = UsbIf->Device;
253
254 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);
255
256 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_BULK)) {
257 Status = EFI_INVALID_PARAMETER;
258 goto ON_EXIT;
259 }
260
261 BufNum = 1;
262 Toggle = EpDesc->Toggle;
263 Status = UsbHcBulkTransfer (
264 Dev->Bus,
265 Dev->Address,
266 Endpoint,
267 Dev->Speed,
268 EpDesc->Desc.MaxPacketSize,
269 BufNum,
270 &Data,
271 DataLength,
272 &Toggle,
273 Timeout,
274 &Dev->Translator,
275 UsbStatus
276 );
277
278 EpDesc->Toggle = Toggle;
279
280 if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {
281 //
282 // Clear TT buffer when CTRL/BULK split transaction failes.
283 // Clear the TRANSLATOR TT buffer, not parent's buffer
284 //
285 if (Dev->Translator.TranslatorHubAddress != 0) {
286 UsbHubCtrlClearTTBuffer (
287 Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],
288 Dev->Translator.TranslatorPortNumber,
289 Dev->Address,
290 0,
291 USB_ENDPOINT_BULK
292 );
293 }
294 }
295
296 ON_EXIT:
297 gBS->RestoreTPL (OldTpl);
298 return Status;
299 }
300
301
302 /**
303 Execute a synchronous interrupt transfer.
304
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.
311
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
315 UsbStatus.
316
317 **/
318 EFI_STATUS
319 EFIAPI
320 UsbIoSyncInterruptTransfer (
321 IN EFI_USB_IO_PROTOCOL *This,
322 IN UINT8 Endpoint,
323 IN OUT VOID *Data,
324 IN OUT UINTN *DataLength,
325 IN UINTN Timeout,
326 OUT UINT32 *UsbStatus
327 )
328 {
329 USB_DEVICE *Dev;
330 USB_INTERFACE *UsbIf;
331 USB_ENDPOINT_DESC *EpDesc;
332 EFI_TPL OldTpl;
333 UINT8 Toggle;
334 EFI_STATUS Status;
335
336 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||
337 (UsbStatus == NULL)) {
338
339 return EFI_INVALID_PARAMETER;
340 }
341
342 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
343
344 UsbIf = USB_INTERFACE_FROM_USBIO (This);
345 Dev = UsbIf->Device;
346
347 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);
348
349 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {
350 Status = EFI_INVALID_PARAMETER;
351 goto ON_EXIT;
352 }
353
354 Toggle = EpDesc->Toggle;
355 Status = UsbHcSyncInterruptTransfer (
356 Dev->Bus,
357 Dev->Address,
358 Endpoint,
359 Dev->Speed,
360 EpDesc->Desc.MaxPacketSize,
361 Data,
362 DataLength,
363 &Toggle,
364 Timeout,
365 &Dev->Translator,
366 UsbStatus
367 );
368
369 EpDesc->Toggle = Toggle;
370
371 ON_EXIT:
372 gBS->RestoreTPL (OldTpl);
373 return Status;
374 }
375
376
377 /**
378 Queue a new asynchronous interrupt transfer, or remove the old
379 request if (IsNewTransfer == FALSE).
380
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
384 the request.
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
388 ready.
389 @param Context The context to the callback.
390
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
394 request.
395
396 **/
397 EFI_STATUS
398 EFIAPI
399 UsbIoAsyncInterruptTransfer (
400 IN EFI_USB_IO_PROTOCOL *This,
401 IN UINT8 Endpoint,
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
407 )
408 {
409 USB_DEVICE *Dev;
410 USB_INTERFACE *UsbIf;
411 USB_ENDPOINT_DESC *EpDesc;
412 EFI_TPL OldTpl;
413 UINT8 Toggle;
414 EFI_STATUS Status;
415
416 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR (Endpoint) > 15)) {
417 return EFI_INVALID_PARAMETER;
418 }
419
420 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
421 UsbIf = USB_INTERFACE_FROM_USBIO (This);
422 Dev = UsbIf->Device;
423
424 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);
425
426 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {
427 Status = EFI_INVALID_PARAMETER;
428 goto ON_EXIT;
429 }
430
431 Toggle = EpDesc->Toggle;
432 Status = UsbHcAsyncInterruptTransfer (
433 Dev->Bus,
434 Dev->Address,
435 Endpoint,
436 Dev->Speed,
437 EpDesc->Desc.MaxPacketSize,
438 IsNewTransfer,
439 &Toggle,
440 PollInterval,
441 DataLength,
442 &Dev->Translator,
443 Callback,
444 Context
445 );
446
447 EpDesc->Toggle = Toggle;
448
449 ON_EXIT:
450 gBS->RestoreTPL (OldTpl);
451 return Status;
452 }
453
454
455 /**
456 Execute a synchronous isochronous transfer.
457
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.
463
464 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
465
466 **/
467 EFI_STATUS
468 EFIAPI
469 UsbIoIsochronousTransfer (
470 IN EFI_USB_IO_PROTOCOL *This,
471 IN UINT8 DeviceEndpoint,
472 IN OUT VOID *Data,
473 IN UINTN DataLength,
474 OUT UINT32 *Status
475 )
476 {
477 return EFI_UNSUPPORTED;
478 }
479
480
481 /**
482 Queue an asynchronous isochronous transfer.
483
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
489 ready.
490 @param Context The context to the callback.
491
492 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
493
494 **/
495 EFI_STATUS
496 EFIAPI
497 UsbIoAsyncIsochronousTransfer (
498 IN EFI_USB_IO_PROTOCOL *This,
499 IN UINT8 DeviceEndpoint,
500 IN OUT VOID *Data,
501 IN UINTN DataLength,
502 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
503 IN VOID *Context OPTIONAL
504 )
505 {
506 return EFI_UNSUPPORTED;
507 }
508
509
510 /**
511 Retrieve the device descriptor of the device.
512
513 @param This The USB IO instance.
514 @param Descriptor The variable to receive the device descriptor.
515
516 @retval EFI_SUCCESS The device descriptor is returned.
517 @retval EFI_INVALID_PARAMETER The parameter is invalid.
518
519 **/
520 EFI_STATUS
521 EFIAPI
522 UsbIoGetDeviceDescriptor (
523 IN EFI_USB_IO_PROTOCOL *This,
524 OUT EFI_USB_DEVICE_DESCRIPTOR *Descriptor
525 )
526 {
527 USB_DEVICE *Dev;
528 USB_INTERFACE *UsbIf;
529 EFI_TPL OldTpl;
530
531 if (Descriptor == NULL) {
532 return EFI_INVALID_PARAMETER;
533 }
534
535 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
536
537 UsbIf = USB_INTERFACE_FROM_USBIO (This);
538 Dev = UsbIf->Device;
539
540 CopyMem (Descriptor, &Dev->DevDesc->Desc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
541
542 gBS->RestoreTPL (OldTpl);
543 return EFI_SUCCESS;
544 }
545
546
547 /**
548 Return the configuration descriptor of the current active configuration.
549
550 @param This The USB IO instance.
551 @param Descriptor The USB configuration descriptor.
552
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.
556
557 **/
558 EFI_STATUS
559 EFIAPI
560 UsbIoGetActiveConfigDescriptor (
561 IN EFI_USB_IO_PROTOCOL *This,
562 OUT EFI_USB_CONFIG_DESCRIPTOR *Descriptor
563 )
564 {
565 USB_DEVICE *Dev;
566 USB_INTERFACE *UsbIf;
567 EFI_STATUS Status;
568 EFI_TPL OldTpl;
569
570 if (Descriptor == NULL) {
571 return EFI_INVALID_PARAMETER;
572 }
573
574 Status = EFI_SUCCESS;
575 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
576
577 UsbIf = USB_INTERFACE_FROM_USBIO (This);
578 Dev = UsbIf->Device;
579
580 if (Dev->ActiveConfig == NULL) {
581 Status = EFI_NOT_FOUND;
582 goto ON_EXIT;
583 }
584
585 CopyMem (Descriptor, &(Dev->ActiveConfig->Desc), sizeof (EFI_USB_CONFIG_DESCRIPTOR));
586
587 ON_EXIT:
588 gBS->RestoreTPL (OldTpl);
589 return Status;
590 }
591
592
593 /**
594 Retrieve the active interface setting descriptor for this USB IO instance.
595
596 @param This The USB IO instance.
597 @param Descriptor The variable to receive active interface setting.
598
599 @retval EFI_SUCCESS The active interface setting is returned.
600 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
601
602 **/
603 EFI_STATUS
604 EFIAPI
605 UsbIoGetInterfaceDescriptor (
606 IN EFI_USB_IO_PROTOCOL *This,
607 OUT EFI_USB_INTERFACE_DESCRIPTOR *Descriptor
608 )
609 {
610 USB_INTERFACE *UsbIf;
611 EFI_TPL OldTpl;
612
613 if (Descriptor == NULL) {
614 return EFI_INVALID_PARAMETER;
615 }
616
617 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
618
619 UsbIf = USB_INTERFACE_FROM_USBIO (This);
620 CopyMem (Descriptor, &(UsbIf->IfSetting->Desc), sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
621
622 gBS->RestoreTPL (OldTpl);
623 return EFI_SUCCESS;
624 }
625
626
627 /**
628 Retrieve the endpoint descriptor from this interface setting.
629
630 @param This The USB IO instance.
631 @param Index The index (start from zero) of the endpoint to
632 retrieve.
633 @param Descriptor The variable to receive the descriptor.
634
635 @retval EFI_SUCCESS The endpoint descriptor is returned.
636 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
637
638 **/
639 EFI_STATUS
640 EFIAPI
641 UsbIoGetEndpointDescriptor (
642 IN EFI_USB_IO_PROTOCOL *This,
643 IN UINT8 Index,
644 OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor
645 )
646 {
647 USB_INTERFACE *UsbIf;
648 EFI_TPL OldTpl;
649
650 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
651
652 UsbIf = USB_INTERFACE_FROM_USBIO (This);
653
654 if ((Descriptor == NULL) || (Index > 15)) {
655 gBS->RestoreTPL (OldTpl);
656 return EFI_INVALID_PARAMETER;
657 }
658
659 if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {
660 gBS->RestoreTPL (OldTpl);
661 return EFI_NOT_FOUND;
662 }
663
664 CopyMem (
665 Descriptor,
666 &(UsbIf->IfSetting->Endpoints[Index]->Desc),
667 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
668 );
669
670 gBS->RestoreTPL (OldTpl);
671 return EFI_SUCCESS;
672 }
673
674
675 /**
676 Retrieve the supported language ID table from the device.
677
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.
681
682 @retval EFI_SUCCESS The language ID is return.
683
684 **/
685 EFI_STATUS
686 EFIAPI
687 UsbIoGetSupportedLanguages (
688 IN EFI_USB_IO_PROTOCOL *This,
689 OUT UINT16 **LangIDTable,
690 OUT UINT16 *TableSize
691 )
692 {
693 USB_DEVICE *Dev;
694 USB_INTERFACE *UsbIf;
695 EFI_TPL OldTpl;
696
697 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
698
699 UsbIf = USB_INTERFACE_FROM_USBIO (This);
700 Dev = UsbIf->Device;
701
702 *LangIDTable = Dev->LangId;
703 *TableSize = Dev->TotalLangId;
704
705 gBS->RestoreTPL (OldTpl);
706 return EFI_SUCCESS;
707 }
708
709
710 /**
711 Retrieve an indexed string in the language of LangID.
712
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.
717
718 @retval EFI_SUCCESS The string is returned.
719 @retval EFI_NOT_FOUND No such string existed.
720
721 **/
722 EFI_STATUS
723 EFIAPI
724 UsbIoGetStringDescriptor (
725 IN EFI_USB_IO_PROTOCOL *This,
726 IN UINT16 LangID,
727 IN UINT8 StringIndex,
728 OUT CHAR16 **String
729 )
730 {
731 USB_DEVICE *Dev;
732 USB_INTERFACE *UsbIf;
733 EFI_USB_STRING_DESCRIPTOR *StrDesc;
734 EFI_TPL OldTpl;
735 UINT8 *Buf;
736 UINT8 Index;
737 EFI_STATUS Status;
738
739 if ((StringIndex == 0) || (LangID == 0)) {
740 return EFI_NOT_FOUND;
741 }
742
743 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
744
745 UsbIf = USB_INTERFACE_FROM_USBIO (This);
746 Dev = UsbIf->Device;
747
748 //
749 // Check whether language ID is supported
750 //
751 Status = EFI_NOT_FOUND;
752
753 for (Index = 0; Index < Dev->TotalLangId; Index++) {
754 if (Dev->LangId[Index] == LangID) {
755 break;
756 }
757 }
758
759 if (Index == Dev->TotalLangId) {
760 goto ON_EXIT;
761 }
762
763 //
764 // Retrieve the string descriptor then allocate a buffer
765 // to hold the string itself.
766 //
767 StrDesc = UsbGetOneString (Dev, StringIndex, LangID);
768
769 if (StrDesc == NULL) {
770 goto ON_EXIT;
771 }
772
773 if (StrDesc->Length <= 2) {
774 goto FREE_STR;
775 }
776
777 Buf = AllocateZeroPool (StrDesc->Length);
778
779 if (Buf == NULL) {
780 Status = EFI_OUT_OF_RESOURCES;
781 goto FREE_STR;
782 }
783
784 CopyMem (Buf, StrDesc->String, StrDesc->Length - 2);
785 *String = (CHAR16 *) Buf;
786 Status = EFI_SUCCESS;
787
788 FREE_STR:
789 gBS->FreePool (StrDesc);
790
791 ON_EXIT:
792 gBS->RestoreTPL (OldTpl);
793 return Status;
794 }
795
796
797 /**
798 Reset the device, then if that succeeds, reconfigure the
799 device with its address and current active configuration.
800
801 @param This The USB IO instance.
802
803 @retval EFI_SUCCESS The device is reset and configured.
804 @retval Others Failed to reset the device.
805
806 **/
807 EFI_STATUS
808 EFIAPI
809 UsbIoPortReset (
810 IN EFI_USB_IO_PROTOCOL *This
811 )
812 {
813 USB_INTERFACE *UsbIf;
814 USB_INTERFACE *HubIf;
815 USB_DEVICE *Dev;
816 UINT8 Address;
817 EFI_TPL OldTpl;
818 EFI_STATUS Status;
819
820 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
821
822 UsbIf = USB_INTERFACE_FROM_USBIO (This);
823 Dev = UsbIf->Device;
824
825 if (UsbIf->IsHub) {
826 Status = EFI_INVALID_PARAMETER;
827 goto ON_EXIT;
828 }
829
830 HubIf = Dev->ParentIf;
831 Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);
832
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));
836
837 goto ON_EXIT;
838 }
839
840 //
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
844 //
845 Address = Dev->Address;
846 Dev->Address = 0;
847 Status = UsbSetAddress (Dev, Address);
848 Dev->Address = Address;
849
850 if (EFI_ERROR (Status)) {
851 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",
852 Address, Status));
853
854 goto ON_EXIT;
855 }
856
857 gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
858
859 DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address));
860
861 //
862 // Reset the current active configure, after this device
863 // is in CONFIGURED state.
864 //
865 if (Dev->ActiveConfig != NULL) {
866 Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);
867
868 if (EFI_ERROR (Status)) {
869 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",
870 Address, Status));
871 }
872 }
873
874 ON_EXIT:
875 gBS->RestoreTPL (OldTpl);
876 return Status;
877 }
878
879
880 /**
881 Install Usb Bus Protocol on host controller, and start the Usb bus.
882
883 @param This The USB bus driver binding instance.
884 @param Controller The controller to check.
885 @param RemainingDevicePath The remaining device patch.
886
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.
890
891 **/
892 EFI_STATUS
893 EFIAPI
894 UsbBusBuildProtocol (
895 IN EFI_DRIVER_BINDING_PROTOCOL *This,
896 IN EFI_HANDLE Controller,
897 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
898 )
899 {
900 USB_BUS *UsbBus;
901 USB_DEVICE *RootHub;
902 USB_INTERFACE *RootIf;
903 EFI_STATUS Status;
904 EFI_STATUS Status2;
905
906 UsbBus = AllocateZeroPool (sizeof (USB_BUS));
907
908 if (UsbBus == NULL) {
909 return EFI_OUT_OF_RESOURCES;
910 }
911
912 UsbBus->Signature = USB_BUS_SIGNATURE;
913 UsbBus->HostHandle = Controller;
914
915 Status = gBS->OpenProtocol (
916 Controller,
917 &gEfiDevicePathProtocolGuid,
918 (VOID **) &UsbBus->DevicePath,
919 This->DriverBindingHandle,
920 Controller,
921 EFI_OPEN_PROTOCOL_BY_DRIVER
922 );
923
924 if (EFI_ERROR (Status)) {
925 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));
926
927 FreePool (UsbBus);
928 return Status;
929 }
930
931 //
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.
938 //
939 Status = gBS->OpenProtocol (
940 Controller,
941 &gEfiUsb2HcProtocolGuid,
942 (VOID **) &(UsbBus->Usb2Hc),
943 This->DriverBindingHandle,
944 Controller,
945 EFI_OPEN_PROTOCOL_BY_DRIVER
946 );
947
948 Status2 = gBS->OpenProtocol (
949 Controller,
950 &gEfiUsbHcProtocolGuid,
951 (VOID **) &(UsbBus->UsbHc),
952 This->DriverBindingHandle,
953 Controller,
954 EFI_OPEN_PROTOCOL_BY_DRIVER
955 );
956
957 if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
958 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));
959
960 Status = EFI_DEVICE_ERROR;
961 goto CLOSE_HC;
962 }
963
964 UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
965 UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
966
967 //
968 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
969 //
970 Status = gBS->InstallProtocolInterface (
971 &Controller,
972 &mUsbBusProtocolGuid,
973 EFI_NATIVE_INTERFACE,
974 &UsbBus->BusId
975 );
976
977 if (EFI_ERROR (Status)) {
978 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
979 goto CLOSE_HC;
980 }
981
982 //
983 // Initial the wanted child device path list, and add first RemainingDevicePath
984 //
985 InitializeListHead (&UsbBus->WantedUsbIoDPList);
986 Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);
987 ASSERT (!EFI_ERROR (Status));
988 //
989 // Create a fake usb device for root hub
990 //
991 RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
992
993 if (RootHub == NULL) {
994 Status = EFI_OUT_OF_RESOURCES;
995 goto UNINSTALL_USBBUS;
996 }
997
998 RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
999
1000 if (RootIf == NULL) {
1001 FreePool (RootHub);
1002 Status = EFI_OUT_OF_RESOURCES;
1003 goto FREE_ROOTHUB;
1004 }
1005
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;
1012
1013 Status = mUsbRootHubApi.Init (RootIf);
1014
1015 if (EFI_ERROR (Status)) {
1016 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
1017 goto FREE_ROOTHUB;
1018 }
1019
1020 UsbBus->Devices[0] = RootHub;
1021
1022 DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf));
1023 return EFI_SUCCESS;
1024
1025 FREE_ROOTHUB:
1026 if (RootIf != NULL) {
1027 FreePool (RootIf);
1028 }
1029 if (RootHub != NULL) {
1030 FreePool (RootHub);
1031 }
1032
1033 UNINSTALL_USBBUS:
1034 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);
1035
1036 CLOSE_HC:
1037 if (UsbBus->Usb2Hc != NULL) {
1038 gBS->CloseProtocol (
1039 Controller,
1040 &gEfiUsb2HcProtocolGuid,
1041 This->DriverBindingHandle,
1042 Controller
1043 );
1044 }
1045 if (UsbBus->UsbHc != NULL) {
1046 gBS->CloseProtocol (
1047 Controller,
1048 &gEfiUsbHcProtocolGuid,
1049 This->DriverBindingHandle,
1050 Controller
1051 );
1052 }
1053 gBS->CloseProtocol (
1054 Controller,
1055 &gEfiDevicePathProtocolGuid,
1056 This->DriverBindingHandle,
1057 Controller
1058 );
1059 FreePool (UsbBus);
1060
1061 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
1062 return Status;
1063 }
1064
1065
1066 /**
1067 The USB bus driver entry pointer.
1068
1069 @param ImageHandle The driver image handle.
1070 @param SystemTable The system table.
1071
1072 @return EFI_SUCCESS The component name protocol is installed.
1073 @return Others Failed to init the usb driver.
1074
1075 **/
1076 EFI_STATUS
1077 EFIAPI
1078 UsbBusDriverEntryPoint (
1079 IN EFI_HANDLE ImageHandle,
1080 IN EFI_SYSTEM_TABLE *SystemTable
1081 )
1082 {
1083 return EfiLibInstallDriverBindingComponentName2 (
1084 ImageHandle,
1085 SystemTable,
1086 &mUsbBusDriverBinding,
1087 ImageHandle,
1088 &mUsbBusComponentName,
1089 &mUsbBusComponentName2
1090 );
1091 }
1092
1093
1094 /**
1095 Check whether USB bus driver support this device.
1096
1097 @param This The USB bus driver binding protocol.
1098 @param Controller The controller handle to check.
1099 @param RemainingDevicePath The remaining device path.
1100
1101 @retval EFI_SUCCESS The bus supports this controller.
1102 @retval EFI_UNSUPPORTED This device isn't supported.
1103
1104 **/
1105 EFI_STATUS
1106 EFIAPI
1107 UsbBusControllerDriverSupported (
1108 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1109 IN EFI_HANDLE Controller,
1110 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1111 )
1112 {
1113 EFI_DEV_PATH_PTR DevicePathNode;
1114 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1115 EFI_USB2_HC_PROTOCOL *Usb2Hc;
1116 EFI_USB_HC_PROTOCOL *UsbHc;
1117 EFI_STATUS Status;
1118
1119 //
1120 // Check whether device path is valid
1121 //
1122 if (RemainingDevicePath != NULL) {
1123 DevicePathNode.DevPath = RemainingDevicePath;
1124
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
1129 )) {
1130
1131 return EFI_UNSUPPORTED;
1132 }
1133 }
1134
1135 Status = gBS->OpenProtocol (
1136 Controller,
1137 &gEfiDevicePathProtocolGuid,
1138 (VOID **) &ParentDevicePath,
1139 This->DriverBindingHandle,
1140 Controller,
1141 EFI_OPEN_PROTOCOL_BY_DRIVER
1142 );
1143
1144 if (Status == EFI_ALREADY_STARTED) {
1145 return EFI_SUCCESS;
1146 }
1147
1148 if (EFI_ERROR (Status)) {
1149 return Status;
1150 }
1151
1152 gBS->CloseProtocol (
1153 Controller,
1154 &gEfiDevicePathProtocolGuid,
1155 This->DriverBindingHandle,
1156 Controller
1157 );
1158
1159 //
1160 // Check whether USB_HC2 protocol is installed
1161 //
1162 Status = gBS->OpenProtocol (
1163 Controller,
1164 &gEfiUsb2HcProtocolGuid,
1165 (VOID **) &Usb2Hc,
1166 This->DriverBindingHandle,
1167 Controller,
1168 EFI_OPEN_PROTOCOL_BY_DRIVER
1169 );
1170
1171 if (Status == EFI_ALREADY_STARTED) {
1172 return EFI_SUCCESS;
1173 }
1174
1175 if (!EFI_ERROR (Status)) {
1176 gBS->CloseProtocol (
1177 Controller,
1178 &gEfiUsb2HcProtocolGuid,
1179 This->DriverBindingHandle,
1180 Controller
1181 );
1182
1183 return EFI_SUCCESS;
1184 }
1185
1186 //
1187 // If failed to open USB_HC2, fall back to USB_HC
1188 //
1189 Status = gBS->OpenProtocol (
1190 Controller,
1191 &gEfiUsbHcProtocolGuid,
1192 (VOID **) &UsbHc,
1193 This->DriverBindingHandle,
1194 Controller,
1195 EFI_OPEN_PROTOCOL_BY_DRIVER
1196 );
1197
1198 if (Status == EFI_ALREADY_STARTED) {
1199 return EFI_SUCCESS;
1200 }
1201
1202 if (!EFI_ERROR (Status)) {
1203 gBS->CloseProtocol (
1204 Controller,
1205 &gEfiUsbHcProtocolGuid,
1206 This->DriverBindingHandle,
1207 Controller
1208 );
1209 }
1210
1211 return Status;
1212 }
1213
1214
1215 /**
1216 Start to process the controller.
1217
1218 @param This The USB bus driver binding instance.
1219 @param Controller The controller to check.
1220 @param RemainingDevicePath The remaining device patch.
1221
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
1224 bus.
1225 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1226
1227 **/
1228 EFI_STATUS
1229 EFIAPI
1230 UsbBusControllerDriverStart (
1231 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1232 IN EFI_HANDLE Controller,
1233 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1234 )
1235 {
1236 EFI_USB_BUS_PROTOCOL *UsbBusId;
1237 EFI_STATUS Status;
1238
1239 //
1240 // Locate the USB bus protocol, if it is found, USB bus
1241 // is already started on this controller.
1242 //
1243 Status = gBS->OpenProtocol (
1244 Controller,
1245 &mUsbBusProtocolGuid,
1246 (VOID **) &UsbBusId,
1247 This->DriverBindingHandle,
1248 Controller,
1249 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1250 );
1251
1252 if (EFI_ERROR (Status)) {
1253 //
1254 // If first start, build the bus execute environment and install bus protocol
1255 //
1256 Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);
1257 if (EFI_ERROR (Status)) {
1258 return Status;
1259 }
1260 //
1261 // Try get the Usb Bus protocol interface again
1262 //
1263 Status = gBS->OpenProtocol (
1264 Controller,
1265 &mUsbBusProtocolGuid,
1266 (VOID **) &UsbBusId,
1267 This->DriverBindingHandle,
1268 Controller,
1269 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1270 );
1271 ASSERT (!EFI_ERROR (Status));
1272 } else {
1273 //
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.
1279 //
1280 // Save the passed in RemainingDevicePath this time
1281 //
1282 Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);
1283 ASSERT (!EFI_ERROR (Status));
1284 //
1285 // Ensure all wanted child usb devices are fully recursively connected
1286 //
1287 Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);
1288 ASSERT (!EFI_ERROR (Status));
1289 }
1290
1291
1292 return EFI_SUCCESS;
1293 }
1294
1295
1296 /**
1297 Stop handle the controller by this USB bus driver.
1298
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
1302 BY_CHILD.
1303 @param ChildHandleBuffer The array of child handle.
1304
1305 @retval EFI_SUCCESS The controller or children are stopped.
1306 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1307
1308 **/
1309 EFI_STATUS
1310 EFIAPI
1311 UsbBusControllerDriverStop (
1312 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1313 IN EFI_HANDLE Controller,
1314 IN UINTN NumberOfChildren,
1315 IN EFI_HANDLE *ChildHandleBuffer
1316 )
1317 {
1318 USB_BUS *Bus;
1319 USB_DEVICE *RootHub;
1320 USB_DEVICE *UsbDev;
1321 USB_INTERFACE *RootIf;
1322 USB_INTERFACE *UsbIf;
1323 EFI_USB_BUS_PROTOCOL *BusId;
1324 EFI_USB_IO_PROTOCOL *UsbIo;
1325 EFI_TPL OldTpl;
1326 UINTN Index;
1327 EFI_STATUS Status;
1328
1329 Status = EFI_SUCCESS;
1330
1331 if (NumberOfChildren > 0) {
1332 //
1333 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1334 //
1335 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1336
1337 for (Index = 0; Index < NumberOfChildren; Index++) {
1338 Status = gBS->OpenProtocol (
1339 ChildHandleBuffer[Index],
1340 &gEfiUsbIoProtocolGuid,
1341 (VOID **) &UsbIo,
1342 This->DriverBindingHandle,
1343 Controller,
1344 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1345 );
1346
1347 if (EFI_ERROR (Status)) {
1348 //
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.
1353 //
1354 continue;
1355 }
1356
1357 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);
1358 UsbDev = UsbIf->Device;
1359
1360 UsbRemoveDevice (UsbDev);
1361 }
1362
1363 gBS->RestoreTPL (OldTpl);
1364 return EFI_SUCCESS;
1365 }
1366
1367 DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));
1368
1369 //
1370 // Locate USB_BUS for the current host controller
1371 //
1372 Status = gBS->OpenProtocol (
1373 Controller,
1374 &mUsbBusProtocolGuid,
1375 (VOID **) &BusId,
1376 This->DriverBindingHandle,
1377 Controller,
1378 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1379 );
1380
1381 if (EFI_ERROR (Status)) {
1382 return Status;
1383 }
1384
1385 Bus = USB_BUS_FROM_THIS (BusId);
1386
1387 //
1388 // Stop the root hub, then free all the devices
1389 //
1390 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1391 //
1392 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1393 UsbHcSetState (Bus, EfiUsbHcStateHalt);
1394
1395 RootHub = Bus->Devices[0];
1396 RootIf = RootHub->Interfaces[0];
1397
1398 mUsbRootHubApi.Release (RootIf);
1399
1400 for (Index = 1; Index < USB_MAX_DEVICES; Index++) {
1401 if (Bus->Devices[Index] != NULL) {
1402 UsbRemoveDevice (Bus->Devices[Index]);
1403 }
1404 }
1405
1406 gBS->RestoreTPL (OldTpl);
1407
1408 gBS->FreePool (RootIf);
1409 gBS->FreePool (RootHub);
1410 Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
1411 ASSERT (!EFI_ERROR (Status));
1412
1413 //
1414 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1415 //
1416 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);
1417
1418 if (Bus->Usb2Hc != NULL) {
1419 gBS->CloseProtocol (
1420 Controller,
1421 &gEfiUsb2HcProtocolGuid,
1422 This->DriverBindingHandle,
1423 Controller
1424 );
1425 }
1426
1427 if (Bus->UsbHc != NULL) {
1428 gBS->CloseProtocol (
1429 Controller,
1430 &gEfiUsbHcProtocolGuid,
1431 This->DriverBindingHandle,
1432 Controller
1433 );
1434 }
1435
1436 gBS->CloseProtocol (
1437 Controller,
1438 &gEfiDevicePathProtocolGuid,
1439 This->DriverBindingHandle,
1440 Controller
1441 );
1442
1443 gBS->FreePool (Bus);
1444
1445 return Status;
1446 }