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