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