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