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