]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
Enhance the Usb bus driver to support Star with Remaining device path.
[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
844 if (EFI_ERROR (Status)) {
845 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",
846 Address, Status));
847
848 goto ON_EXIT;
849 }
850
851 Dev->Address = Address;
852
853 //
854 // Reset the current active configure, after this device
855 // is in CONFIGURED state.
856 //
857 if (Dev->ActiveConfig != NULL) {
858 Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);
859
860 if (EFI_ERROR (Status)) {
861 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",
862 Address, Status));
863 }
864 }
865
866 ON_EXIT:
867 gBS->RestoreTPL (OldTpl);
868 return Status;
869 }
870
871
872 /**
873 Install Usb Bus Protocol on host controller, and start the Usb bus
874
875 @param This The USB bus driver binding instance
876 @param Controller The controller to check
877 @param RemainingDevicePath The remaining device patch
878
879 @retval EFI_SUCCESS The controller is controlled by the usb bus
880 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus
881 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources
882
883 **/
884 EFI_STATUS
885 EFIAPI
886 UsbBusBuildProtocol (
887 IN EFI_DRIVER_BINDING_PROTOCOL *This,
888 IN EFI_HANDLE Controller,
889 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
890 )
891 {
892 USB_BUS *UsbBus;
893 USB_DEVICE *RootHub;
894 USB_INTERFACE *RootIf;
895 EFI_STATUS Status;
896 EFI_STATUS Status2;
897
898 UsbBus = AllocateZeroPool (sizeof (USB_BUS));
899
900 if (UsbBus == NULL) {
901 return EFI_OUT_OF_RESOURCES;
902 }
903
904 UsbBus->Signature = USB_BUS_SIGNATURE;
905 UsbBus->HostHandle = Controller;
906
907 Status = gBS->OpenProtocol (
908 Controller,
909 &gEfiDevicePathProtocolGuid,
910 (VOID **) &UsbBus->DevicePath,
911 This->DriverBindingHandle,
912 Controller,
913 EFI_OPEN_PROTOCOL_BY_DRIVER
914 );
915
916 if (EFI_ERROR (Status)) {
917 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));
918
919 gBS->FreePool (UsbBus);
920 return Status;
921 }
922
923 //
924 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
925 // This is for backward compatbility with EFI 1.x. In UEFI
926 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
927 // and USB_HC because EHCI driver will install both protocols
928 // (for the same reason). If we don't consume both of them,
929 // the unconsumed one may be opened by others.
930 //
931 Status = gBS->OpenProtocol (
932 Controller,
933 &gEfiUsb2HcProtocolGuid,
934 (VOID **) &(UsbBus->Usb2Hc),
935 This->DriverBindingHandle,
936 Controller,
937 EFI_OPEN_PROTOCOL_BY_DRIVER
938 );
939
940 Status2 = gBS->OpenProtocol (
941 Controller,
942 &gEfiUsbHcProtocolGuid,
943 (VOID **) &(UsbBus->UsbHc),
944 This->DriverBindingHandle,
945 Controller,
946 EFI_OPEN_PROTOCOL_BY_DRIVER
947 );
948
949 if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
950 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));
951
952 Status = EFI_DEVICE_ERROR;
953 goto CLOSE_HC;
954 }
955
956 UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
957 UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
958
959 //
960 // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.
961 //
962 Status = gBS->InstallProtocolInterface (
963 &Controller,
964 &mUsbBusProtocolGuid,
965 EFI_NATIVE_INTERFACE,
966 &UsbBus->BusId
967 );
968
969 if (EFI_ERROR (Status)) {
970 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
971 goto CLOSE_HC;
972 }
973
974 //
975 // Initial the wanted child device path list, and add first RemainingDevicePath
976 //
977 InitializeListHead (&UsbBus->WantedUsbIoDPList);
978 Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);
979 ASSERT (!EFI_ERROR (Status));
980 //
981 // Create a fake usb device for root hub
982 //
983 RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
984
985 if (RootHub == NULL) {
986 Status = EFI_OUT_OF_RESOURCES;
987 goto UNINSTALL_USBBUS;
988 }
989
990 RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
991
992 if (RootIf == NULL) {
993 gBS->FreePool (RootHub);
994 Status = EFI_OUT_OF_RESOURCES;
995 goto FREE_ROOTHUB;
996 }
997
998 RootHub->Bus = UsbBus;
999 RootHub->NumOfInterface = 1;
1000 RootHub->Interfaces[0] = RootIf;
1001 RootIf->Signature = USB_INTERFACE_SIGNATURE;
1002 RootIf->Device = RootHub;
1003 RootIf->DevicePath = UsbBus->DevicePath;
1004
1005 Status = mUsbRootHubApi.Init (RootIf);
1006
1007 if (EFI_ERROR (Status)) {
1008 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
1009 goto FREE_ROOTHUB;
1010 }
1011
1012 UsbBus->Devices[0] = RootHub;
1013
1014 DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));
1015 return EFI_SUCCESS;
1016
1017 FREE_ROOTHUB:
1018 if (RootIf != NULL) {
1019 gBS->FreePool (RootIf);
1020 }
1021 if (RootHub != NULL) {
1022 gBS->FreePool (RootHub);
1023 }
1024
1025 UNINSTALL_USBBUS:
1026 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);
1027
1028 CLOSE_HC:
1029 if (UsbBus->Usb2Hc != NULL) {
1030 gBS->CloseProtocol (
1031 Controller,
1032 &gEfiUsb2HcProtocolGuid,
1033 This->DriverBindingHandle,
1034 Controller
1035 );
1036 }
1037 if (UsbBus->UsbHc != NULL) {
1038 gBS->CloseProtocol (
1039 Controller,
1040 &gEfiUsbHcProtocolGuid,
1041 This->DriverBindingHandle,
1042 Controller
1043 );
1044 }
1045 gBS->CloseProtocol (
1046 Controller,
1047 &gEfiDevicePathProtocolGuid,
1048 This->DriverBindingHandle,
1049 Controller
1050 );
1051 gBS->FreePool (UsbBus);
1052
1053 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
1054 return Status;
1055 }
1056
1057 EFI_USB_IO_PROTOCOL mUsbIoProtocol = {
1058 UsbIoControlTransfer,
1059 UsbIoBulkTransfer,
1060 UsbIoAsyncInterruptTransfer,
1061 UsbIoSyncInterruptTransfer,
1062 UsbIoIsochronousTransfer,
1063 UsbIoAsyncIsochronousTransfer,
1064 UsbIoGetDeviceDescriptor,
1065 UsbIoGetActiveConfigDescriptor,
1066 UsbIoGetInterfaceDescriptor,
1067 UsbIoGetEndpointDescriptor,
1068 UsbIoGetStringDescriptor,
1069 UsbIoGetSupportedLanguages,
1070 UsbIoPortReset
1071 };
1072
1073
1074 EFI_STATUS
1075 EFIAPI
1076 UsbBusDriverEntryPoint (
1077 IN EFI_HANDLE ImageHandle,
1078 IN EFI_SYSTEM_TABLE *SystemTable
1079 )
1080 /*++
1081
1082 Routine Description:
1083
1084 The USB bus driver entry pointer
1085
1086 Arguments:
1087
1088 ImageHandle - The driver image handle
1089 SystemTable - The system table
1090
1091 Returns:
1092
1093 EFI_SUCCESS - The component name protocol is installed
1094 Others - Failed to init the usb driver
1095
1096 --*/
1097 {
1098 return EfiLibInstallDriverBindingComponentName2 (
1099 ImageHandle,
1100 SystemTable,
1101 &mUsbBusDriverBinding,
1102 ImageHandle,
1103 &mUsbBusComponentName,
1104 &mUsbBusComponentName2
1105 );
1106 }
1107
1108
1109 /**
1110 Check whether USB bus driver support this device
1111
1112 @param This The USB bus driver binding protocol
1113 @param Controller The controller handle to test againist
1114 @param RemainingDevicePath The remaining device path
1115
1116 @retval EFI_SUCCESS The bus supports this controller.
1117 @retval EFI_UNSUPPORTED This device isn't supported
1118
1119 **/
1120 EFI_STATUS
1121 EFIAPI
1122 UsbBusControllerDriverSupported (
1123 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1124 IN EFI_HANDLE Controller,
1125 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1126 )
1127 {
1128 EFI_DEV_PATH_PTR DevicePathNode;
1129 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1130 EFI_USB2_HC_PROTOCOL *Usb2Hc;
1131 EFI_USB_HC_PROTOCOL *UsbHc;
1132 EFI_STATUS Status;
1133
1134 //
1135 // Check whether device path is valid
1136 //
1137 if (RemainingDevicePath != NULL) {
1138 DevicePathNode.DevPath = RemainingDevicePath;
1139
1140 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||
1141 (DevicePathNode.DevPath->SubType != MSG_USB_DP &&
1142 DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP
1143 && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP
1144 )) {
1145
1146 return EFI_UNSUPPORTED;
1147 }
1148 }
1149
1150 Status = gBS->OpenProtocol (
1151 Controller,
1152 &gEfiDevicePathProtocolGuid,
1153 (VOID **) &ParentDevicePath,
1154 This->DriverBindingHandle,
1155 Controller,
1156 EFI_OPEN_PROTOCOL_BY_DRIVER
1157 );
1158
1159 if (Status == EFI_ALREADY_STARTED) {
1160 return EFI_SUCCESS;
1161 }
1162
1163 if (EFI_ERROR (Status)) {
1164 return Status;
1165 }
1166
1167 gBS->CloseProtocol (
1168 Controller,
1169 &gEfiDevicePathProtocolGuid,
1170 This->DriverBindingHandle,
1171 Controller
1172 );
1173
1174 //
1175 // Check whether USB_HC2 protocol is installed
1176 //
1177 Status = gBS->OpenProtocol (
1178 Controller,
1179 &gEfiUsb2HcProtocolGuid,
1180 (VOID **) &Usb2Hc,
1181 This->DriverBindingHandle,
1182 Controller,
1183 EFI_OPEN_PROTOCOL_BY_DRIVER
1184 );
1185
1186 if (Status == EFI_ALREADY_STARTED) {
1187 return EFI_SUCCESS;
1188 }
1189
1190 if (!EFI_ERROR (Status)) {
1191 gBS->CloseProtocol (
1192 Controller,
1193 &gEfiUsb2HcProtocolGuid,
1194 This->DriverBindingHandle,
1195 Controller
1196 );
1197
1198 return EFI_SUCCESS;
1199 }
1200
1201 //
1202 // If failed to open USB_HC2, fall back to USB_HC
1203 //
1204 Status = gBS->OpenProtocol (
1205 Controller,
1206 &gEfiUsbHcProtocolGuid,
1207 (VOID **) &UsbHc,
1208 This->DriverBindingHandle,
1209 Controller,
1210 EFI_OPEN_PROTOCOL_BY_DRIVER
1211 );
1212
1213 if (Status == EFI_ALREADY_STARTED) {
1214 return EFI_SUCCESS;
1215 }
1216
1217 if (!EFI_ERROR (Status)) {
1218 gBS->CloseProtocol (
1219 Controller,
1220 &gEfiUsbHcProtocolGuid,
1221 This->DriverBindingHandle,
1222 Controller
1223 );
1224 }
1225
1226 return Status;
1227 }
1228
1229
1230 /**
1231 Start to process the controller
1232
1233 @param This The USB bus driver binding instance
1234 @param Controller The controller to check
1235 @param RemainingDevicePath The remaining device patch
1236
1237 @retval EFI_SUCCESS The controller is controlled by the usb bus
1238 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1239 bus
1240 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources
1241
1242 **/
1243 EFI_STATUS
1244 EFIAPI
1245 UsbBusControllerDriverStart (
1246 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1247 IN EFI_HANDLE Controller,
1248 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1249 )
1250 {
1251 EFI_USB_BUS_PROTOCOL *UsbBusId;
1252 EFI_STATUS Status;
1253
1254 //
1255 // Locate the USB bus protocol, if it is found, USB bus
1256 // is already started on this controller.
1257 //
1258 Status = gBS->OpenProtocol (
1259 Controller,
1260 &mUsbBusProtocolGuid,
1261 (VOID **) &UsbBusId,
1262 This->DriverBindingHandle,
1263 Controller,
1264 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1265 );
1266
1267 if (EFI_ERROR (Status)) {
1268 //
1269 // If first start, build the bus execute enviorment and install bus protocol
1270 //
1271 Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);
1272 if (EFI_ERROR (Status)) {
1273 return Status;
1274 }
1275 //
1276 // Try get the Usb Bus protocol interface again
1277 //
1278 Status = gBS->OpenProtocol (
1279 Controller,
1280 &mUsbBusProtocolGuid,
1281 (VOID **) &UsbBusId,
1282 This->DriverBindingHandle,
1283 Controller,
1284 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1285 );
1286 ASSERT (!EFI_ERROR (Status));
1287 } else {
1288 //
1289 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1290 // usb child device will be recursively connected.
1291 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1292 // All wanted usb child devices will be remembered by the usb bus driver itself.
1293 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1294 //
1295 // Save the passed in RemainingDevicePath this time
1296 //
1297 Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);
1298 ASSERT (!EFI_ERROR (Status));
1299 //
1300 // Ensure all wanted child usb devices are fully recursively connected
1301 //
1302 Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);
1303 ASSERT (!EFI_ERROR (Status));
1304 }
1305
1306
1307 return EFI_SUCCESS;
1308 }
1309
1310
1311 /**
1312 Stop handle the controller by this USB bus driver
1313
1314 @param This The USB bus driver binding protocol
1315 @param Controller The controller to release
1316 @param NumberOfChildren The child of USB bus that opened controller
1317 BY_CHILD
1318 @param ChildHandleBuffer The array of child handle
1319
1320 @retval EFI_SUCCESS The controller or children are stopped
1321 @retval EFI_DEVICE_ERROR Failed to stop the driver
1322
1323 **/
1324 EFI_STATUS
1325 EFIAPI
1326 UsbBusControllerDriverStop (
1327 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1328 IN EFI_HANDLE Controller,
1329 IN UINTN NumberOfChildren,
1330 IN EFI_HANDLE *ChildHandleBuffer
1331 )
1332 {
1333 USB_BUS *Bus;
1334 USB_DEVICE *RootHub;
1335 USB_DEVICE *UsbDev;
1336 USB_INTERFACE *RootIf;
1337 USB_INTERFACE *UsbIf;
1338 EFI_USB_BUS_PROTOCOL *BusId;
1339 EFI_USB_IO_PROTOCOL *UsbIo;
1340 EFI_TPL OldTpl;
1341 UINTN Index;
1342 EFI_STATUS Status;
1343
1344 Status = EFI_SUCCESS;
1345
1346 if (NumberOfChildren > 0) {
1347 //
1348 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1349 //
1350 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1351
1352 for (Index = 0; Index < NumberOfChildren; Index++) {
1353 Status = gBS->OpenProtocol (
1354 ChildHandleBuffer[Index],
1355 &gEfiUsbIoProtocolGuid,
1356 (VOID **) &UsbIo,
1357 This->DriverBindingHandle,
1358 Controller,
1359 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1360 );
1361
1362 if (EFI_ERROR (Status)) {
1363 //
1364 // It is possible that the child has already been released:
1365 // 1. For combo device, free one device will release others.
1366 // 2. If a hub is released, all devices on its down facing
1367 // ports are released also.
1368 //
1369 continue;
1370 }
1371
1372 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);
1373 UsbDev = UsbIf->Device;
1374
1375 UsbRemoveDevice (UsbDev);
1376 }
1377
1378 gBS->RestoreTPL (OldTpl);
1379 return EFI_SUCCESS;
1380 }
1381
1382 DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %x\n", Controller));
1383
1384 //
1385 // Locate USB_BUS for the current host controller
1386 //
1387 Status = gBS->OpenProtocol (
1388 Controller,
1389 &mUsbBusProtocolGuid,
1390 (VOID **) &BusId,
1391 This->DriverBindingHandle,
1392 Controller,
1393 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1394 );
1395
1396 if (EFI_ERROR (Status)) {
1397 return Status;
1398 }
1399
1400 Bus = USB_BUS_FROM_THIS (BusId);
1401
1402 //
1403 // Stop the root hub, then free all the devices
1404 //
1405 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1406 //
1407 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1408 UsbHcSetState (Bus, EfiUsbHcStateHalt);
1409
1410 RootHub = Bus->Devices[0];
1411 RootIf = RootHub->Interfaces[0];
1412
1413 mUsbRootHubApi.Release (RootIf);
1414
1415 for (Index = 1; Index < USB_MAX_DEVICES; Index++) {
1416 if (Bus->Devices[Index] != NULL) {
1417 UsbRemoveDevice (Bus->Devices[Index]);
1418 }
1419 }
1420
1421 gBS->RestoreTPL (OldTpl);
1422
1423 gBS->FreePool (RootIf);
1424 gBS->FreePool (RootHub);
1425 Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
1426 ASSERT (!EFI_ERROR (Status));
1427
1428 //
1429 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1430 //
1431 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);
1432
1433 if (Bus->Usb2Hc != NULL) {
1434 gBS->CloseProtocol (
1435 Controller,
1436 &gEfiUsb2HcProtocolGuid,
1437 This->DriverBindingHandle,
1438 Controller
1439 );
1440 }
1441
1442 if (Bus->UsbHc != NULL) {
1443 gBS->CloseProtocol (
1444 Controller,
1445 &gEfiUsbHcProtocolGuid,
1446 This->DriverBindingHandle,
1447 Controller
1448 );
1449 }
1450
1451 gBS->CloseProtocol (
1452 Controller,
1453 &gEfiDevicePathProtocolGuid,
1454 This->DriverBindingHandle,
1455 Controller
1456 );
1457
1458 gBS->FreePool (Bus);
1459
1460 return Status;
1461 }
1462
1463 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {
1464 UsbBusControllerDriverSupported,
1465 UsbBusControllerDriverStart,
1466 UsbBusControllerDriverStop,
1467 0xa,
1468 NULL,
1469 NULL
1470 };