1 /** @file
2 
3     Usb Bus Driver Binding and Bus IO Protocol.
4 
5 Copyright (c) 2004 - 2013, 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
UsbIoControlTransfer(IN EFI_USB_IO_PROTOCOL * This,IN EFI_USB_DEVICE_REQUEST * Request,IN EFI_USB_DATA_DIRECTION Direction,IN UINT32 Timeout,IN OUT VOID * Data,OPTIONAL IN UINTN DataLength,OPTIONAL OUT UINT32 * UsbStatus)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
UsbIoBulkTransfer(IN EFI_USB_IO_PROTOCOL * This,IN UINT8 Endpoint,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN UINTN Timeout,OUT UINT32 * UsbStatus)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
UsbIoSyncInterruptTransfer(IN EFI_USB_IO_PROTOCOL * This,IN UINT8 Endpoint,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN UINTN Timeout,OUT UINT32 * UsbStatus)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
UsbIoAsyncInterruptTransfer(IN EFI_USB_IO_PROTOCOL * This,IN UINT8 Endpoint,IN BOOLEAN IsNewTransfer,IN UINTN PollInterval,OPTIONAL IN UINTN DataLength,OPTIONAL IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,OPTIONAL IN VOID * Context OPTIONAL)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
UsbIoIsochronousTransfer(IN EFI_USB_IO_PROTOCOL * This,IN UINT8 DeviceEndpoint,IN OUT VOID * Data,IN UINTN DataLength,OUT UINT32 * Status)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
UsbIoAsyncIsochronousTransfer(IN EFI_USB_IO_PROTOCOL * This,IN UINT8 DeviceEndpoint,IN OUT VOID * Data,IN UINTN DataLength,IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,IN VOID * Context OPTIONAL)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
UsbIoGetDeviceDescriptor(IN EFI_USB_IO_PROTOCOL * This,OUT EFI_USB_DEVICE_DESCRIPTOR * Descriptor)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
UsbIoGetActiveConfigDescriptor(IN EFI_USB_IO_PROTOCOL * This,OUT EFI_USB_CONFIG_DESCRIPTOR * Descriptor)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
UsbIoGetInterfaceDescriptor(IN EFI_USB_IO_PROTOCOL * This,OUT EFI_USB_INTERFACE_DESCRIPTOR * Descriptor)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
UsbIoGetEndpointDescriptor(IN EFI_USB_IO_PROTOCOL * This,IN UINT8 Index,OUT EFI_USB_ENDPOINT_DESCRIPTOR * Descriptor)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
UsbIoGetSupportedLanguages(IN EFI_USB_IO_PROTOCOL * This,OUT UINT16 ** LangIDTable,OUT UINT16 * TableSize)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
UsbIoGetStringDescriptor(IN EFI_USB_IO_PROTOCOL * This,IN UINT16 LangID,IN UINT8 StringIndex,OUT CHAR16 ** String)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
UsbIoPortReset(IN EFI_USB_IO_PROTOCOL * This)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
UsbBusBuildProtocol(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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   UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
980   UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
981 
982   //
983   // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
984   //
985   Status = gBS->InstallProtocolInterface (
986                   &Controller,
987                   &gEfiCallerIdGuid,
988                   EFI_NATIVE_INTERFACE,
989                   &UsbBus->BusId
990                   );
991 
992   if (EFI_ERROR (Status)) {
993     DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
994     goto CLOSE_HC;
995   }
996 
997   //
998   // Initial the wanted child device path list, and add first RemainingDevicePath
999   //
1000   InitializeListHead (&UsbBus->WantedUsbIoDPList);
1001   Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);
1002   ASSERT (!EFI_ERROR (Status));
1003   //
1004   // Create a fake usb device for root hub
1005   //
1006   RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
1007 
1008   if (RootHub == NULL) {
1009     Status = EFI_OUT_OF_RESOURCES;
1010     goto UNINSTALL_USBBUS;
1011   }
1012 
1013   RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
1014 
1015   if (RootIf == NULL) {
1016     FreePool (RootHub);
1017     Status = EFI_OUT_OF_RESOURCES;
1018     goto FREE_ROOTHUB;
1019   }
1020 
1021   RootHub->Bus            = UsbBus;
1022   RootHub->NumOfInterface = 1;
1023   RootHub->Interfaces[0]  = RootIf;
1024   RootHub->Tier           = 0;
1025   RootIf->Signature       = USB_INTERFACE_SIGNATURE;
1026   RootIf->Device          = RootHub;
1027   RootIf->DevicePath      = UsbBus->DevicePath;
1028 
1029   //
1030   // Report Status Code here since we will enumerate the USB devices
1031   //
1032   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1033     EFI_PROGRESS_CODE,
1034     (EFI_IO_BUS_USB | EFI_IOB_PC_DETECT),
1035     UsbBus->DevicePath
1036     );
1037 
1038   Status                  = mUsbRootHubApi.Init (RootIf);
1039 
1040   if (EFI_ERROR (Status)) {
1041     DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
1042     goto FREE_ROOTHUB;
1043   }
1044 
1045   UsbBus->Devices[0] = RootHub;
1046 
1047   DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf));
1048   return EFI_SUCCESS;
1049 
1050 FREE_ROOTHUB:
1051   if (RootIf != NULL) {
1052     FreePool (RootIf);
1053   }
1054   if (RootHub != NULL) {
1055     FreePool (RootHub);
1056   }
1057 
1058 UNINSTALL_USBBUS:
1059   gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &UsbBus->BusId);
1060 
1061 CLOSE_HC:
1062   if (UsbBus->Usb2Hc != NULL) {
1063     gBS->CloseProtocol (
1064           Controller,
1065           &gEfiUsb2HcProtocolGuid,
1066           This->DriverBindingHandle,
1067           Controller
1068           );
1069   }
1070   if (UsbBus->UsbHc != NULL) {
1071     gBS->CloseProtocol (
1072           Controller,
1073           &gEfiUsbHcProtocolGuid,
1074           This->DriverBindingHandle,
1075           Controller
1076           );
1077   }
1078   gBS->CloseProtocol (
1079          Controller,
1080          &gEfiDevicePathProtocolGuid,
1081          This->DriverBindingHandle,
1082          Controller
1083          );
1084   FreePool (UsbBus);
1085 
1086   DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
1087   return Status;
1088 }
1089 
1090 
1091 /**
1092   The USB bus driver entry pointer.
1093 
1094   @param ImageHandle       The driver image handle.
1095   @param SystemTable       The system table.
1096 
1097   @return EFI_SUCCESS      The component name protocol is installed.
1098   @return Others           Failed to init the usb driver.
1099 
1100 **/
1101 EFI_STATUS
1102 EFIAPI
UsbBusDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1103 UsbBusDriverEntryPoint (
1104   IN EFI_HANDLE           ImageHandle,
1105   IN EFI_SYSTEM_TABLE     *SystemTable
1106   )
1107 {
1108   return EfiLibInstallDriverBindingComponentName2 (
1109            ImageHandle,
1110            SystemTable,
1111            &mUsbBusDriverBinding,
1112            ImageHandle,
1113            &mUsbBusComponentName,
1114            &mUsbBusComponentName2
1115            );
1116 }
1117 
1118 
1119 /**
1120   Check whether USB bus driver support this device.
1121 
1122   @param  This                   The USB bus driver binding protocol.
1123   @param  Controller             The controller handle to check.
1124   @param  RemainingDevicePath    The remaining device path.
1125 
1126   @retval EFI_SUCCESS            The bus supports this controller.
1127   @retval EFI_UNSUPPORTED        This device isn't supported.
1128 
1129 **/
1130 EFI_STATUS
1131 EFIAPI
UsbBusControllerDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1132 UsbBusControllerDriverSupported (
1133   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1134   IN EFI_HANDLE                   Controller,
1135   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
1136   )
1137 {
1138   EFI_DEV_PATH_PTR          DevicePathNode;
1139   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;
1140   EFI_USB2_HC_PROTOCOL      *Usb2Hc;
1141   EFI_USB_HC_PROTOCOL       *UsbHc;
1142   EFI_STATUS                Status;
1143 
1144   //
1145   // Check whether device path is valid
1146   //
1147   if (RemainingDevicePath != NULL) {
1148     //
1149     // Check if RemainingDevicePath is the End of Device Path Node,
1150     // if yes, go on checking other conditions
1151     //
1152     if (!IsDevicePathEnd (RemainingDevicePath)) {
1153       //
1154       // If RemainingDevicePath isn't the End of Device Path Node,
1155       // check its validation
1156       //
1157       DevicePathNode.DevPath = RemainingDevicePath;
1158 
1159       if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||
1160           (DevicePathNode.DevPath->SubType != MSG_USB_DP &&
1161            DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP
1162            && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP
1163            )) {
1164 
1165         return EFI_UNSUPPORTED;
1166       }
1167     }
1168   }
1169 
1170   //
1171   // Check whether USB_HC2 protocol is installed
1172   //
1173   Status = gBS->OpenProtocol (
1174                   Controller,
1175                   &gEfiUsb2HcProtocolGuid,
1176                   (VOID **) &Usb2Hc,
1177                   This->DriverBindingHandle,
1178                   Controller,
1179                   EFI_OPEN_PROTOCOL_BY_DRIVER
1180                   );
1181   if (Status == EFI_ALREADY_STARTED) {
1182     return EFI_SUCCESS;
1183   }
1184 
1185   if (EFI_ERROR (Status)) {
1186     //
1187     // If failed to open USB_HC2, fall back to USB_HC
1188     //
1189     Status = gBS->OpenProtocol (
1190                     Controller,
1191                     &gEfiUsbHcProtocolGuid,
1192                     (VOID **) &UsbHc,
1193                     This->DriverBindingHandle,
1194                     Controller,
1195                     EFI_OPEN_PROTOCOL_BY_DRIVER
1196                     );
1197     if (Status == EFI_ALREADY_STARTED) {
1198       return EFI_SUCCESS;
1199     }
1200 
1201     if (EFI_ERROR (Status)) {
1202       return Status;
1203     }
1204 
1205     //
1206     // Close the USB_HC used to perform the supported test
1207     //
1208     gBS->CloseProtocol (
1209           Controller,
1210           &gEfiUsbHcProtocolGuid,
1211           This->DriverBindingHandle,
1212           Controller
1213           );
1214 
1215   } else {
1216 
1217     //
1218     // Close the USB_HC2 used to perform the supported test
1219     //
1220     gBS->CloseProtocol (
1221            Controller,
1222            &gEfiUsb2HcProtocolGuid,
1223            This->DriverBindingHandle,
1224            Controller
1225            );
1226   }
1227 
1228   //
1229   // Open the EFI Device Path protocol needed to perform the supported test
1230   //
1231   Status = gBS->OpenProtocol (
1232                   Controller,
1233                   &gEfiDevicePathProtocolGuid,
1234                   (VOID **) &ParentDevicePath,
1235                   This->DriverBindingHandle,
1236                   Controller,
1237                   EFI_OPEN_PROTOCOL_BY_DRIVER
1238                   );
1239   if (Status == EFI_ALREADY_STARTED) {
1240     return EFI_SUCCESS;
1241   }
1242 
1243   if (!EFI_ERROR (Status)) {
1244     //
1245     // Close protocol, don't use device path protocol in the Support() function
1246     //
1247     gBS->CloseProtocol (
1248           Controller,
1249           &gEfiDevicePathProtocolGuid,
1250           This->DriverBindingHandle,
1251           Controller
1252           );
1253 
1254     return EFI_SUCCESS;
1255   }
1256 
1257   return Status;
1258 }
1259 
1260 
1261 /**
1262   Start to process the controller.
1263 
1264   @param  This                   The USB bus driver binding instance.
1265   @param  Controller             The controller to check.
1266   @param  RemainingDevicePath    The remaining device patch.
1267 
1268   @retval EFI_SUCCESS            The controller is controlled by the usb bus.
1269   @retval EFI_ALREADY_STARTED    The controller is already controlled by the usb
1270                                  bus.
1271   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
1272 
1273 **/
1274 EFI_STATUS
1275 EFIAPI
UsbBusControllerDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1276 UsbBusControllerDriverStart (
1277   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1278   IN EFI_HANDLE                   Controller,
1279   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
1280   )
1281 {
1282   EFI_USB_BUS_PROTOCOL          *UsbBusId;
1283   EFI_STATUS                    Status;
1284   EFI_DEVICE_PATH_PROTOCOL      *ParentDevicePath;
1285 
1286   Status = gBS->OpenProtocol (
1287                   Controller,
1288                   &gEfiDevicePathProtocolGuid,
1289                   (VOID **) &ParentDevicePath,
1290                   This->DriverBindingHandle,
1291                   Controller,
1292                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1293                   );
1294   ASSERT_EFI_ERROR (Status);
1295 
1296   //
1297   // Report Status Code here since we will initialize the host controller
1298   //
1299   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1300     EFI_PROGRESS_CODE,
1301     (EFI_IO_BUS_USB | EFI_IOB_PC_INIT),
1302     ParentDevicePath
1303     );
1304 
1305   //
1306   // Locate the USB bus protocol, if it is found, USB bus
1307   // is already started on this controller.
1308   //
1309   Status = gBS->OpenProtocol (
1310                   Controller,
1311                   &gEfiCallerIdGuid,
1312                   (VOID **) &UsbBusId,
1313                   This->DriverBindingHandle,
1314                   Controller,
1315                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1316                   );
1317 
1318   if (EFI_ERROR (Status)) {
1319     //
1320     // If first start, build the bus execute environment and install bus protocol
1321     //
1322     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_P_PC_ENABLE));
1323     Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);
1324     if (EFI_ERROR (Status)) {
1325       return Status;
1326     }
1327     //
1328     // Try get the Usb Bus protocol interface again
1329     //
1330     Status = gBS->OpenProtocol (
1331                     Controller,
1332                     &gEfiCallerIdGuid,
1333                     (VOID **) &UsbBusId,
1334                     This->DriverBindingHandle,
1335                     Controller,
1336                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
1337                     );
1338     ASSERT (!EFI_ERROR (Status));
1339   } else {
1340     //
1341     // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1342     // usb child device will be recursively connected.
1343     // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1344     // All wanted usb child devices will be remembered by the usb bus driver itself.
1345     // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1346     //
1347     // Save the passed in RemainingDevicePath this time
1348     //
1349     if (RemainingDevicePath != NULL) {
1350       if (IsDevicePathEnd (RemainingDevicePath)) {
1351         //
1352         // If RemainingDevicePath is the End of Device Path Node,
1353         // skip enumerate any device and return EFI_SUCESSS
1354         //
1355         return EFI_SUCCESS;
1356       }
1357     }
1358 
1359     Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);
1360     ASSERT (!EFI_ERROR (Status));
1361     //
1362     // Ensure all wanted child usb devices are fully recursively connected
1363     //
1364     Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);
1365     ASSERT (!EFI_ERROR (Status));
1366   }
1367 
1368 
1369   return EFI_SUCCESS;
1370 }
1371 
1372 
1373 /**
1374   Stop handle the controller by this USB bus driver.
1375 
1376   @param  This                   The USB bus driver binding protocol.
1377   @param  Controller             The controller to release.
1378   @param  NumberOfChildren       The child of USB bus that opened controller
1379                                  BY_CHILD.
1380   @param  ChildHandleBuffer      The array of child handle.
1381 
1382   @retval EFI_SUCCESS            The controller or children are stopped.
1383   @retval EFI_DEVICE_ERROR       Failed to stop the driver.
1384 
1385 **/
1386 EFI_STATUS
1387 EFIAPI
UsbBusControllerDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1388 UsbBusControllerDriverStop (
1389   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1390   IN EFI_HANDLE                   Controller,
1391   IN UINTN                        NumberOfChildren,
1392   IN EFI_HANDLE                   *ChildHandleBuffer
1393   )
1394 {
1395   USB_BUS               *Bus;
1396   USB_DEVICE            *RootHub;
1397   USB_DEVICE            *UsbDev;
1398   USB_INTERFACE         *RootIf;
1399   USB_INTERFACE         *UsbIf;
1400   EFI_USB_BUS_PROTOCOL  *BusId;
1401   EFI_USB_IO_PROTOCOL   *UsbIo;
1402   EFI_TPL               OldTpl;
1403   UINTN                 Index;
1404   EFI_STATUS            Status;
1405   EFI_STATUS            ReturnStatus;
1406 
1407   Status  = EFI_SUCCESS;
1408 
1409   if (NumberOfChildren > 0) {
1410     //
1411     // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1412     //
1413     OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
1414 
1415     ReturnStatus = EFI_SUCCESS;
1416     for (Index = 0; Index < NumberOfChildren; Index++) {
1417       Status = gBS->OpenProtocol (
1418                       ChildHandleBuffer[Index],
1419                       &gEfiUsbIoProtocolGuid,
1420                       (VOID **) &UsbIo,
1421                       This->DriverBindingHandle,
1422                       Controller,
1423                       EFI_OPEN_PROTOCOL_GET_PROTOCOL
1424                       );
1425 
1426       if (EFI_ERROR (Status)) {
1427         //
1428         // It is possible that the child has already been released:
1429         // 1. For combo device, free one device will release others.
1430         // 2. If a hub is released, all devices on its down facing
1431         //    ports are released also.
1432         //
1433         continue;
1434       }
1435 
1436       UsbIf   = USB_INTERFACE_FROM_USBIO (UsbIo);
1437       UsbDev  = UsbIf->Device;
1438 
1439       ReturnStatus = UsbRemoveDevice (UsbDev);
1440     }
1441 
1442     gBS->RestoreTPL (OldTpl);
1443     return ReturnStatus;
1444   }
1445 
1446   DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));
1447 
1448   //
1449   // Locate USB_BUS for the current host controller
1450   //
1451   Status = gBS->OpenProtocol (
1452                   Controller,
1453                   &gEfiCallerIdGuid,
1454                   (VOID **) &BusId,
1455                   This->DriverBindingHandle,
1456                   Controller,
1457                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1458                   );
1459 
1460   if (EFI_ERROR (Status)) {
1461     return Status;
1462   }
1463 
1464   Bus = USB_BUS_FROM_THIS (BusId);
1465 
1466   //
1467   // Stop the root hub, then free all the devices
1468   //
1469   // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1470   //
1471   OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);
1472 
1473   RootHub = Bus->Devices[0];
1474   RootIf  = RootHub->Interfaces[0];
1475 
1476   ASSERT (Bus->MaxDevices <= 256);
1477   ReturnStatus = EFI_SUCCESS;
1478   for (Index = 1; Index < Bus->MaxDevices; Index++) {
1479     if (Bus->Devices[Index] != NULL) {
1480       Status = UsbRemoveDevice (Bus->Devices[Index]);
1481       if (EFI_ERROR (Status)) {
1482         ReturnStatus = Status;
1483       }
1484     }
1485   }
1486 
1487   gBS->RestoreTPL (OldTpl);
1488 
1489   if (!EFI_ERROR (ReturnStatus)) {
1490     mUsbRootHubApi.Release (RootIf);
1491     gBS->FreePool   (RootIf);
1492     gBS->FreePool   (RootHub);
1493 
1494     Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
1495     ASSERT (!EFI_ERROR (Status));
1496 
1497     //
1498     // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1499     //
1500     gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &Bus->BusId);
1501 
1502     if (Bus->Usb2Hc != NULL) {
1503       Status = gBS->CloseProtocol (
1504                       Controller,
1505                       &gEfiUsb2HcProtocolGuid,
1506                       This->DriverBindingHandle,
1507                       Controller
1508                       );
1509     }
1510 
1511     if (Bus->UsbHc != NULL) {
1512       Status = gBS->CloseProtocol (
1513                       Controller,
1514                       &gEfiUsbHcProtocolGuid,
1515                       This->DriverBindingHandle,
1516                       Controller
1517                       );
1518     }
1519 
1520     if (!EFI_ERROR (Status)) {
1521       gBS->CloseProtocol (
1522              Controller,
1523              &gEfiDevicePathProtocolGuid,
1524              This->DriverBindingHandle,
1525              Controller
1526              );
1527 
1528       gBS->FreePool (Bus);
1529     }
1530   }
1531   return Status;
1532 }
1533