]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
78220222f6ed68953afebd86b68f9b5663db9146
[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 - 2016, 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 UINT8 DevAddress;
817
818 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
819
820 UsbIf = USB_INTERFACE_FROM_USBIO (This);
821 Dev = UsbIf->Device;
822
823 if (UsbIf->IsHub) {
824 Status = EFI_INVALID_PARAMETER;
825 goto ON_EXIT;
826 }
827
828 HubIf = Dev->ParentIf;
829 Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);
830
831 if (EFI_ERROR (Status)) {
832 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
833 Dev->ParentPort, Dev->ParentAddr, Status));
834
835 goto ON_EXIT;
836 }
837
838 HubIf->HubApi->ClearPortChange (HubIf, Dev->ParentPort);
839
840 //
841 // Reset the device to its current address. The device now has an address
842 // of ZERO after port reset, so need to set Dev->Address to the device again for
843 // host to communicate with it.
844 //
845 DevAddress = Dev->Address;
846 Dev->Address = 0;
847 Status = UsbSetAddress (Dev, DevAddress);
848 Dev->Address = DevAddress;
849
850 gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
851
852 if (EFI_ERROR (Status)) {
853 //
854 // It may fail due to device disconnection or other reasons.
855 //
856 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",
857 Dev->Address, Status));
858
859 goto ON_EXIT;
860 }
861
862 DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev->Address));
863
864 //
865 // Reset the current active configure, after this device
866 // is in CONFIGURED state.
867 //
868 if (Dev->ActiveConfig != NULL) {
869 Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);
870
871 if (EFI_ERROR (Status)) {
872 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",
873 Dev->Address, Status));
874 }
875 }
876
877 ON_EXIT:
878 gBS->RestoreTPL (OldTpl);
879 return Status;
880 }
881
882
883 /**
884 Install Usb Bus Protocol on host controller, and start the Usb bus.
885
886 @param This The USB bus driver binding instance.
887 @param Controller The controller to check.
888 @param RemainingDevicePath The remaining device patch.
889
890 @retval EFI_SUCCESS The controller is controlled by the usb bus.
891 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
892 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
893
894 **/
895 EFI_STATUS
896 EFIAPI
897 UsbBusBuildProtocol (
898 IN EFI_DRIVER_BINDING_PROTOCOL *This,
899 IN EFI_HANDLE Controller,
900 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
901 )
902 {
903 USB_BUS *UsbBus;
904 USB_DEVICE *RootHub;
905 USB_INTERFACE *RootIf;
906 EFI_STATUS Status;
907 EFI_STATUS Status2;
908
909 UsbBus = AllocateZeroPool (sizeof (USB_BUS));
910
911 if (UsbBus == NULL) {
912 return EFI_OUT_OF_RESOURCES;
913 }
914
915 UsbBus->Signature = USB_BUS_SIGNATURE;
916 UsbBus->HostHandle = Controller;
917 UsbBus->MaxDevices = USB_MAX_DEVICES;
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 if (!EFI_ERROR (Status)) {
969 //
970 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
971 // Then its max supported devices are 256. Otherwise it's 128.
972 //
973 ASSERT (UsbBus->Usb2Hc != NULL);
974 if (UsbBus->Usb2Hc->MajorRevision == 0x3) {
975 UsbBus->MaxDevices = 256;
976 }
977 }
978
979 //
980 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
981 //
982 Status = gBS->InstallProtocolInterface (
983 &Controller,
984 &gEfiCallerIdGuid,
985 EFI_NATIVE_INTERFACE,
986 &UsbBus->BusId
987 );
988
989 if (EFI_ERROR (Status)) {
990 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
991 goto CLOSE_HC;
992 }
993
994 //
995 // Initial the wanted child device path list, and add first RemainingDevicePath
996 //
997 InitializeListHead (&UsbBus->WantedUsbIoDPList);
998 Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);
999 ASSERT (!EFI_ERROR (Status));
1000 //
1001 // Create a fake usb device for root hub
1002 //
1003 RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
1004
1005 if (RootHub == NULL) {
1006 Status = EFI_OUT_OF_RESOURCES;
1007 goto UNINSTALL_USBBUS;
1008 }
1009
1010 RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
1011
1012 if (RootIf == NULL) {
1013 FreePool (RootHub);
1014 Status = EFI_OUT_OF_RESOURCES;
1015 goto FREE_ROOTHUB;
1016 }
1017
1018 RootHub->Bus = UsbBus;
1019 RootHub->NumOfInterface = 1;
1020 RootHub->Interfaces[0] = RootIf;
1021 RootHub->Tier = 0;
1022 RootIf->Signature = USB_INTERFACE_SIGNATURE;
1023 RootIf->Device = RootHub;
1024 RootIf->DevicePath = UsbBus->DevicePath;
1025
1026 //
1027 // Report Status Code here since we will enumerate the USB devices
1028 //
1029 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1030 EFI_PROGRESS_CODE,
1031 (EFI_IO_BUS_USB | EFI_IOB_PC_DETECT),
1032 UsbBus->DevicePath
1033 );
1034
1035 Status = mUsbRootHubApi.Init (RootIf);
1036
1037 if (EFI_ERROR (Status)) {
1038 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
1039 goto FREE_ROOTHUB;
1040 }
1041
1042 UsbBus->Devices[0] = RootHub;
1043
1044 DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf));
1045 return EFI_SUCCESS;
1046
1047 FREE_ROOTHUB:
1048 if (RootIf != NULL) {
1049 FreePool (RootIf);
1050 }
1051 if (RootHub != NULL) {
1052 FreePool (RootHub);
1053 }
1054
1055 UNINSTALL_USBBUS:
1056 gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &UsbBus->BusId);
1057
1058 CLOSE_HC:
1059 if (UsbBus->Usb2Hc != NULL) {
1060 gBS->CloseProtocol (
1061 Controller,
1062 &gEfiUsb2HcProtocolGuid,
1063 This->DriverBindingHandle,
1064 Controller
1065 );
1066 }
1067 if (UsbBus->UsbHc != NULL) {
1068 gBS->CloseProtocol (
1069 Controller,
1070 &gEfiUsbHcProtocolGuid,
1071 This->DriverBindingHandle,
1072 Controller
1073 );
1074 }
1075 gBS->CloseProtocol (
1076 Controller,
1077 &gEfiDevicePathProtocolGuid,
1078 This->DriverBindingHandle,
1079 Controller
1080 );
1081 FreePool (UsbBus);
1082
1083 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
1084 return Status;
1085 }
1086
1087
1088 /**
1089 The USB bus driver entry pointer.
1090
1091 @param ImageHandle The driver image handle.
1092 @param SystemTable The system table.
1093
1094 @return EFI_SUCCESS The component name protocol is installed.
1095 @return Others Failed to init the usb driver.
1096
1097 **/
1098 EFI_STATUS
1099 EFIAPI
1100 UsbBusDriverEntryPoint (
1101 IN EFI_HANDLE ImageHandle,
1102 IN EFI_SYSTEM_TABLE *SystemTable
1103 )
1104 {
1105 return EfiLibInstallDriverBindingComponentName2 (
1106 ImageHandle,
1107 SystemTable,
1108 &mUsbBusDriverBinding,
1109 ImageHandle,
1110 &mUsbBusComponentName,
1111 &mUsbBusComponentName2
1112 );
1113 }
1114
1115
1116 /**
1117 Check whether USB bus driver support this device.
1118
1119 @param This The USB bus driver binding protocol.
1120 @param Controller The controller handle to check.
1121 @param RemainingDevicePath The remaining device path.
1122
1123 @retval EFI_SUCCESS The bus supports this controller.
1124 @retval EFI_UNSUPPORTED This device isn't supported.
1125
1126 **/
1127 EFI_STATUS
1128 EFIAPI
1129 UsbBusControllerDriverSupported (
1130 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1131 IN EFI_HANDLE Controller,
1132 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1133 )
1134 {
1135 EFI_DEV_PATH_PTR DevicePathNode;
1136 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1137 EFI_USB2_HC_PROTOCOL *Usb2Hc;
1138 EFI_USB_HC_PROTOCOL *UsbHc;
1139 EFI_STATUS Status;
1140
1141 //
1142 // Check whether device path is valid
1143 //
1144 if (RemainingDevicePath != NULL) {
1145 //
1146 // Check if RemainingDevicePath is the End of Device Path Node,
1147 // if yes, go on checking other conditions
1148 //
1149 if (!IsDevicePathEnd (RemainingDevicePath)) {
1150 //
1151 // If RemainingDevicePath isn't the End of Device Path Node,
1152 // check its validation
1153 //
1154 DevicePathNode.DevPath = RemainingDevicePath;
1155
1156 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||
1157 (DevicePathNode.DevPath->SubType != MSG_USB_DP &&
1158 DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP
1159 && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP
1160 )) {
1161
1162 return EFI_UNSUPPORTED;
1163 }
1164 }
1165 }
1166
1167 //
1168 // Check whether USB_HC2 protocol is installed
1169 //
1170 Status = gBS->OpenProtocol (
1171 Controller,
1172 &gEfiUsb2HcProtocolGuid,
1173 (VOID **) &Usb2Hc,
1174 This->DriverBindingHandle,
1175 Controller,
1176 EFI_OPEN_PROTOCOL_BY_DRIVER
1177 );
1178 if (Status == EFI_ALREADY_STARTED) {
1179 return EFI_SUCCESS;
1180 }
1181
1182 if (EFI_ERROR (Status)) {
1183 //
1184 // If failed to open USB_HC2, fall back to USB_HC
1185 //
1186 Status = gBS->OpenProtocol (
1187 Controller,
1188 &gEfiUsbHcProtocolGuid,
1189 (VOID **) &UsbHc,
1190 This->DriverBindingHandle,
1191 Controller,
1192 EFI_OPEN_PROTOCOL_BY_DRIVER
1193 );
1194 if (Status == EFI_ALREADY_STARTED) {
1195 return EFI_SUCCESS;
1196 }
1197
1198 if (EFI_ERROR (Status)) {
1199 return Status;
1200 }
1201
1202 //
1203 // Close the USB_HC used to perform the supported test
1204 //
1205 gBS->CloseProtocol (
1206 Controller,
1207 &gEfiUsbHcProtocolGuid,
1208 This->DriverBindingHandle,
1209 Controller
1210 );
1211
1212 } else {
1213
1214 //
1215 // Close the USB_HC2 used to perform the supported test
1216 //
1217 gBS->CloseProtocol (
1218 Controller,
1219 &gEfiUsb2HcProtocolGuid,
1220 This->DriverBindingHandle,
1221 Controller
1222 );
1223 }
1224
1225 //
1226 // Open the EFI Device Path protocol needed to perform the supported test
1227 //
1228 Status = gBS->OpenProtocol (
1229 Controller,
1230 &gEfiDevicePathProtocolGuid,
1231 (VOID **) &ParentDevicePath,
1232 This->DriverBindingHandle,
1233 Controller,
1234 EFI_OPEN_PROTOCOL_BY_DRIVER
1235 );
1236 if (Status == EFI_ALREADY_STARTED) {
1237 return EFI_SUCCESS;
1238 }
1239
1240 if (!EFI_ERROR (Status)) {
1241 //
1242 // Close protocol, don't use device path protocol in the Support() function
1243 //
1244 gBS->CloseProtocol (
1245 Controller,
1246 &gEfiDevicePathProtocolGuid,
1247 This->DriverBindingHandle,
1248 Controller
1249 );
1250
1251 return EFI_SUCCESS;
1252 }
1253
1254 return Status;
1255 }
1256
1257
1258 /**
1259 Start to process the controller.
1260
1261 @param This The USB bus driver binding instance.
1262 @param Controller The controller to check.
1263 @param RemainingDevicePath The remaining device patch.
1264
1265 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1266 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1267 bus.
1268 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1269
1270 **/
1271 EFI_STATUS
1272 EFIAPI
1273 UsbBusControllerDriverStart (
1274 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1275 IN EFI_HANDLE Controller,
1276 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1277 )
1278 {
1279 EFI_USB_BUS_PROTOCOL *UsbBusId;
1280 EFI_STATUS Status;
1281 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1282
1283 Status = gBS->OpenProtocol (
1284 Controller,
1285 &gEfiDevicePathProtocolGuid,
1286 (VOID **) &ParentDevicePath,
1287 This->DriverBindingHandle,
1288 Controller,
1289 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1290 );
1291 ASSERT_EFI_ERROR (Status);
1292
1293 //
1294 // Report Status Code here since we will initialize the host controller
1295 //
1296 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1297 EFI_PROGRESS_CODE,
1298 (EFI_IO_BUS_USB | EFI_IOB_PC_INIT),
1299 ParentDevicePath
1300 );
1301
1302 //
1303 // Locate the USB bus protocol, if it is found, USB bus
1304 // is already started on this controller.
1305 //
1306 Status = gBS->OpenProtocol (
1307 Controller,
1308 &gEfiCallerIdGuid,
1309 (VOID **) &UsbBusId,
1310 This->DriverBindingHandle,
1311 Controller,
1312 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1313 );
1314
1315 if (EFI_ERROR (Status)) {
1316 //
1317 // If first start, build the bus execute environment and install bus protocol
1318 //
1319 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_P_PC_ENABLE));
1320 Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);
1321 if (EFI_ERROR (Status)) {
1322 return Status;
1323 }
1324 //
1325 // Try get the Usb Bus protocol interface again
1326 //
1327 Status = gBS->OpenProtocol (
1328 Controller,
1329 &gEfiCallerIdGuid,
1330 (VOID **) &UsbBusId,
1331 This->DriverBindingHandle,
1332 Controller,
1333 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1334 );
1335 ASSERT (!EFI_ERROR (Status));
1336 } else {
1337 //
1338 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1339 // usb child device will be recursively connected.
1340 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1341 // All wanted usb child devices will be remembered by the usb bus driver itself.
1342 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1343 //
1344 // Save the passed in RemainingDevicePath this time
1345 //
1346 if (RemainingDevicePath != NULL) {
1347 if (IsDevicePathEnd (RemainingDevicePath)) {
1348 //
1349 // If RemainingDevicePath is the End of Device Path Node,
1350 // skip enumerate any device and return EFI_SUCESSS
1351 //
1352 return EFI_SUCCESS;
1353 }
1354 }
1355
1356 Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);
1357 ASSERT (!EFI_ERROR (Status));
1358 //
1359 // Ensure all wanted child usb devices are fully recursively connected
1360 //
1361 Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);
1362 ASSERT (!EFI_ERROR (Status));
1363 }
1364
1365
1366 return EFI_SUCCESS;
1367 }
1368
1369
1370 /**
1371 Stop handle the controller by this USB bus driver.
1372
1373 @param This The USB bus driver binding protocol.
1374 @param Controller The controller to release.
1375 @param NumberOfChildren The child of USB bus that opened controller
1376 BY_CHILD.
1377 @param ChildHandleBuffer The array of child handle.
1378
1379 @retval EFI_SUCCESS The controller or children are stopped.
1380 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1381
1382 **/
1383 EFI_STATUS
1384 EFIAPI
1385 UsbBusControllerDriverStop (
1386 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1387 IN EFI_HANDLE Controller,
1388 IN UINTN NumberOfChildren,
1389 IN EFI_HANDLE *ChildHandleBuffer
1390 )
1391 {
1392 USB_BUS *Bus;
1393 USB_DEVICE *RootHub;
1394 USB_DEVICE *UsbDev;
1395 USB_INTERFACE *RootIf;
1396 USB_INTERFACE *UsbIf;
1397 EFI_USB_BUS_PROTOCOL *BusId;
1398 EFI_USB_IO_PROTOCOL *UsbIo;
1399 EFI_TPL OldTpl;
1400 UINTN Index;
1401 EFI_STATUS Status;
1402 EFI_STATUS ReturnStatus;
1403
1404 Status = EFI_SUCCESS;
1405
1406 if (NumberOfChildren > 0) {
1407 //
1408 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1409 //
1410 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1411
1412 ReturnStatus = EFI_SUCCESS;
1413 for (Index = 0; Index < NumberOfChildren; Index++) {
1414 Status = gBS->OpenProtocol (
1415 ChildHandleBuffer[Index],
1416 &gEfiUsbIoProtocolGuid,
1417 (VOID **) &UsbIo,
1418 This->DriverBindingHandle,
1419 Controller,
1420 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1421 );
1422
1423 if (EFI_ERROR (Status)) {
1424 //
1425 // It is possible that the child has already been released:
1426 // 1. For combo device, free one device will release others.
1427 // 2. If a hub is released, all devices on its down facing
1428 // ports are released also.
1429 //
1430 continue;
1431 }
1432
1433 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);
1434 UsbDev = UsbIf->Device;
1435
1436 ReturnStatus = UsbRemoveDevice (UsbDev);
1437 }
1438
1439 gBS->RestoreTPL (OldTpl);
1440 return ReturnStatus;
1441 }
1442
1443 DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));
1444
1445 //
1446 // Locate USB_BUS for the current host controller
1447 //
1448 Status = gBS->OpenProtocol (
1449 Controller,
1450 &gEfiCallerIdGuid,
1451 (VOID **) &BusId,
1452 This->DriverBindingHandle,
1453 Controller,
1454 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1455 );
1456
1457 if (EFI_ERROR (Status)) {
1458 return Status;
1459 }
1460
1461 Bus = USB_BUS_FROM_THIS (BusId);
1462
1463 //
1464 // Stop the root hub, then free all the devices
1465 //
1466 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1467 //
1468 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1469
1470 RootHub = Bus->Devices[0];
1471 RootIf = RootHub->Interfaces[0];
1472
1473 ASSERT (Bus->MaxDevices <= 256);
1474 ReturnStatus = EFI_SUCCESS;
1475 for (Index = 1; Index < Bus->MaxDevices; Index++) {
1476 if (Bus->Devices[Index] != NULL) {
1477 Status = UsbRemoveDevice (Bus->Devices[Index]);
1478 if (EFI_ERROR (Status)) {
1479 ReturnStatus = Status;
1480 }
1481 }
1482 }
1483
1484 gBS->RestoreTPL (OldTpl);
1485
1486 if (!EFI_ERROR (ReturnStatus)) {
1487 mUsbRootHubApi.Release (RootIf);
1488 gBS->FreePool (RootIf);
1489 gBS->FreePool (RootHub);
1490
1491 Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
1492 ASSERT (!EFI_ERROR (Status));
1493
1494 //
1495 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1496 //
1497 gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &Bus->BusId);
1498
1499 if (Bus->Usb2Hc != NULL) {
1500 Status = gBS->CloseProtocol (
1501 Controller,
1502 &gEfiUsb2HcProtocolGuid,
1503 This->DriverBindingHandle,
1504 Controller
1505 );
1506 }
1507
1508 if (Bus->UsbHc != NULL) {
1509 Status = gBS->CloseProtocol (
1510 Controller,
1511 &gEfiUsbHcProtocolGuid,
1512 This->DriverBindingHandle,
1513 Controller
1514 );
1515 }
1516
1517 if (!EFI_ERROR (Status)) {
1518 gBS->CloseProtocol (
1519 Controller,
1520 &gEfiDevicePathProtocolGuid,
1521 This->DriverBindingHandle,
1522 Controller
1523 );
1524
1525 gBS->FreePool (Bus);
1526 }
1527 }
1528 return Status;
1529 }