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