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