1 /** @file
2 
3     Wrapper function for usb host controller interface.
4 
5 Copyright (c) 2007 - 2010, 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 
17 #include "UsbBus.h"
18 
19 //
20 // if RemainingDevicePath== NULL, then all Usb child devices in this bus are wanted.
21 // Use a shor form Usb class Device Path, which could match any usb device, in WantedUsbIoDPList to indicate all Usb devices
22 // are wanted Usb devices
23 //
24 USB_CLASS_FORMAT_DEVICE_PATH mAllUsbClassDevicePath = {
25   {
26     {
27       MESSAGING_DEVICE_PATH,
28       MSG_USB_CLASS_DP,
29       {
30         (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
31         (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
32       }
33     },
34     0xffff, // VendorId
35     0xffff, // ProductId
36     0xff,   // DeviceClass
37     0xff,   // DeviceSubClass
38     0xff    // DeviceProtocol
39   },
40 
41   {
42     END_DEVICE_PATH_TYPE,
43     END_ENTIRE_DEVICE_PATH_SUBTYPE,
44     {
45       END_DEVICE_PATH_LENGTH,
46       0
47     }
48   }
49 };
50 
51 
52 /**
53   Get the capability of the host controller.
54 
55   @param  UsbBus           The usb driver.
56   @param  MaxSpeed         The maximum speed this host controller supports.
57   @param  NumOfPort        The number of the root hub port.
58   @param  Is64BitCapable   Whether this controller support 64 bit addressing.
59 
60   @retval EFI_SUCCESS      The host controller capability is returned.
61   @retval Others           Failed to retrieve the host controller capability.
62 
63 **/
64 EFI_STATUS
UsbHcGetCapability(IN USB_BUS * UsbBus,OUT UINT8 * MaxSpeed,OUT UINT8 * NumOfPort,OUT UINT8 * Is64BitCapable)65 UsbHcGetCapability (
66   IN  USB_BUS             *UsbBus,
67   OUT UINT8               *MaxSpeed,
68   OUT UINT8               *NumOfPort,
69   OUT UINT8               *Is64BitCapable
70   )
71 {
72   EFI_STATUS              Status;
73 
74   if (UsbBus->Usb2Hc != NULL) {
75     Status = UsbBus->Usb2Hc->GetCapability (
76                               UsbBus->Usb2Hc,
77                               MaxSpeed,
78                               NumOfPort,
79                               Is64BitCapable
80                               );
81 
82   } else {
83     Status = UsbBus->UsbHc->GetRootHubPortNumber (UsbBus->UsbHc, NumOfPort);
84 
85     *MaxSpeed       = EFI_USB_SPEED_FULL;
86     *Is64BitCapable = (UINT8) FALSE;
87   }
88 
89   return Status;
90 }
91 
92 
93 /**
94   Reset the host controller.
95 
96   @param  UsbBus                The usb bus driver.
97   @param  Attributes            The reset type, only global reset is used by this driver.
98 
99   @retval EFI_SUCCESS           The reset operation succeeded.
100   @retval EFI_INVALID_PARAMETER Attributes is not valid.
101   @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is
102                                 not currently supported by the host controller.
103   @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.
104 **/
105 EFI_STATUS
UsbHcReset(IN USB_BUS * UsbBus,IN UINT16 Attributes)106 UsbHcReset (
107   IN USB_BUS              *UsbBus,
108   IN UINT16               Attributes
109   )
110 {
111   EFI_STATUS              Status;
112 
113   if (UsbBus->Usb2Hc != NULL) {
114     Status = UsbBus->Usb2Hc->Reset (UsbBus->Usb2Hc, Attributes);
115   } else {
116     Status = UsbBus->UsbHc->Reset (UsbBus->UsbHc, Attributes);
117   }
118 
119   return Status;
120 }
121 
122 
123 /**
124   Get the current operation state of the host controller.
125 
126   @param  UsbBus           The USB bus driver.
127   @param  State            The host controller operation state.
128 
129   @retval EFI_SUCCESS      The operation state is returned in State.
130   @retval Others           Failed to get the host controller state.
131 
132 **/
133 EFI_STATUS
UsbHcGetState(IN USB_BUS * UsbBus,OUT EFI_USB_HC_STATE * State)134 UsbHcGetState (
135   IN  USB_BUS             *UsbBus,
136   OUT EFI_USB_HC_STATE    *State
137   )
138 {
139   EFI_STATUS              Status;
140 
141   if (UsbBus->Usb2Hc != NULL) {
142     Status = UsbBus->Usb2Hc->GetState (UsbBus->Usb2Hc, State);
143   } else {
144     Status = UsbBus->UsbHc->GetState (UsbBus->UsbHc, State);
145   }
146 
147   return Status;
148 }
149 
150 
151 /**
152   Set the host controller operation state.
153 
154   @param  UsbBus           The USB bus driver.
155   @param  State            The state to set.
156 
157   @retval EFI_SUCCESS      The host controller is now working at State.
158   @retval Others           Failed to set operation state.
159 
160 **/
161 EFI_STATUS
UsbHcSetState(IN USB_BUS * UsbBus,IN EFI_USB_HC_STATE State)162 UsbHcSetState (
163   IN USB_BUS              *UsbBus,
164   IN EFI_USB_HC_STATE     State
165   )
166 {
167   EFI_STATUS              Status;
168 
169   if (UsbBus->Usb2Hc != NULL) {
170     Status = UsbBus->Usb2Hc->SetState (UsbBus->Usb2Hc, State);
171   } else {
172     Status = UsbBus->UsbHc->SetState (UsbBus->UsbHc, State);
173   }
174 
175   return Status;
176 }
177 
178 
179 /**
180   Get the root hub port state.
181 
182   @param  UsbBus           The USB bus driver.
183   @param  PortIndex        The index of port.
184   @param  PortStatus       The variable to save port state.
185 
186   @retval EFI_SUCCESS      The root port state is returned in.
187   @retval Others           Failed to get the root hub port state.
188 
189 **/
190 EFI_STATUS
UsbHcGetRootHubPortStatus(IN USB_BUS * UsbBus,IN UINT8 PortIndex,OUT EFI_USB_PORT_STATUS * PortStatus)191 UsbHcGetRootHubPortStatus (
192   IN  USB_BUS             *UsbBus,
193   IN  UINT8               PortIndex,
194   OUT EFI_USB_PORT_STATUS *PortStatus
195   )
196 {
197   EFI_STATUS              Status;
198 
199   if (UsbBus->Usb2Hc != NULL) {
200     Status = UsbBus->Usb2Hc->GetRootHubPortStatus (UsbBus->Usb2Hc, PortIndex, PortStatus);
201   } else {
202     Status = UsbBus->UsbHc->GetRootHubPortStatus (UsbBus->UsbHc, PortIndex, PortStatus);
203   }
204 
205   return Status;
206 }
207 
208 
209 /**
210   Set the root hub port feature.
211 
212   @param  UsbBus           The USB bus driver.
213   @param  PortIndex        The port index.
214   @param  Feature          The port feature to set.
215 
216   @retval EFI_SUCCESS      The port feature is set.
217   @retval Others           Failed to set port feature.
218 
219 **/
220 EFI_STATUS
UsbHcSetRootHubPortFeature(IN USB_BUS * UsbBus,IN UINT8 PortIndex,IN EFI_USB_PORT_FEATURE Feature)221 UsbHcSetRootHubPortFeature (
222   IN USB_BUS              *UsbBus,
223   IN UINT8                PortIndex,
224   IN EFI_USB_PORT_FEATURE Feature
225   )
226 {
227   EFI_STATUS              Status;
228 
229 
230   if (UsbBus->Usb2Hc != NULL) {
231     Status = UsbBus->Usb2Hc->SetRootHubPortFeature (UsbBus->Usb2Hc, PortIndex, Feature);
232   } else {
233     Status = UsbBus->UsbHc->SetRootHubPortFeature (UsbBus->UsbHc, PortIndex, Feature);
234   }
235 
236   return Status;
237 }
238 
239 
240 /**
241   Clear the root hub port feature.
242 
243   @param  UsbBus           The USB bus driver.
244   @param  PortIndex        The port index.
245   @param  Feature          The port feature to clear.
246 
247   @retval EFI_SUCCESS      The port feature is clear.
248   @retval Others           Failed to clear port feature.
249 
250 **/
251 EFI_STATUS
UsbHcClearRootHubPortFeature(IN USB_BUS * UsbBus,IN UINT8 PortIndex,IN EFI_USB_PORT_FEATURE Feature)252 UsbHcClearRootHubPortFeature (
253   IN USB_BUS              *UsbBus,
254   IN UINT8                PortIndex,
255   IN EFI_USB_PORT_FEATURE Feature
256   )
257 {
258   EFI_STATUS              Status;
259 
260   if (UsbBus->Usb2Hc != NULL) {
261     Status = UsbBus->Usb2Hc->ClearRootHubPortFeature (UsbBus->Usb2Hc, PortIndex, Feature);
262   } else {
263     Status = UsbBus->UsbHc->ClearRootHubPortFeature (UsbBus->UsbHc, PortIndex, Feature);
264   }
265 
266   return Status;
267 }
268 
269 
270 /**
271   Execute a control transfer to the device.
272 
273   @param  UsbBus           The USB bus driver.
274   @param  DevAddr          The device address.
275   @param  DevSpeed         The device speed.
276   @param  MaxPacket        Maximum packet size of endpoint 0.
277   @param  Request          The control transfer request.
278   @param  Direction        The direction of data stage.
279   @param  Data             The buffer holding data.
280   @param  DataLength       The length of the data.
281   @param  TimeOut          Timeout (in ms) to wait until timeout.
282   @param  Translator       The transaction translator for low/full speed device.
283   @param  UsbResult        The result of transfer.
284 
285   @retval EFI_SUCCESS      The control transfer finished without error.
286   @retval Others           The control transfer failed, reason returned in UsbReslt.
287 
288 **/
289 EFI_STATUS
UsbHcControlTransfer(IN USB_BUS * UsbBus,IN UINT8 DevAddr,IN UINT8 DevSpeed,IN UINTN MaxPacket,IN EFI_USB_DEVICE_REQUEST * Request,IN EFI_USB_DATA_DIRECTION Direction,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * UsbResult)290 UsbHcControlTransfer (
291   IN  USB_BUS                             *UsbBus,
292   IN  UINT8                               DevAddr,
293   IN  UINT8                               DevSpeed,
294   IN  UINTN                               MaxPacket,
295   IN  EFI_USB_DEVICE_REQUEST              *Request,
296   IN  EFI_USB_DATA_DIRECTION              Direction,
297   IN  OUT VOID                            *Data,
298   IN  OUT UINTN                           *DataLength,
299   IN  UINTN                               TimeOut,
300   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
301   OUT UINT32                              *UsbResult
302   )
303 {
304   EFI_STATUS              Status;
305   BOOLEAN                 IsSlowDevice;
306 
307   if (UsbBus->Usb2Hc != NULL) {
308     Status = UsbBus->Usb2Hc->ControlTransfer (
309                                UsbBus->Usb2Hc,
310                                DevAddr,
311                                DevSpeed,
312                                MaxPacket,
313                                Request,
314                                Direction,
315                                Data,
316                                DataLength,
317                                TimeOut,
318                                Translator,
319                                UsbResult
320                                );
321 
322   } else {
323     IsSlowDevice = (BOOLEAN)(EFI_USB_SPEED_LOW == DevSpeed);
324     Status = UsbBus->UsbHc->ControlTransfer (
325                               UsbBus->UsbHc,
326                               DevAddr,
327                               IsSlowDevice,
328                               (UINT8) MaxPacket,
329                               Request,
330                               Direction,
331                               Data,
332                               DataLength,
333                               TimeOut,
334                               UsbResult
335                               );
336   }
337 
338   return Status;
339 }
340 
341 
342 /**
343   Execute a bulk transfer to the device's endpoint.
344 
345   @param  UsbBus           The USB bus driver.
346   @param  DevAddr          The target device address.
347   @param  EpAddr           The target endpoint address, with direction encoded in
348                            bit 7.
349   @param  DevSpeed         The device's speed.
350   @param  MaxPacket        The endpoint's max packet size.
351   @param  BufferNum        The number of data buffer.
352   @param  Data             Array of pointers to data buffer.
353   @param  DataLength       The length of data buffer.
354   @param  DataToggle       On input, the initial data toggle to use, also  return
355                            the next toggle on output.
356   @param  TimeOut          The time to wait until timeout.
357   @param  Translator       The transaction translator for low/full speed device.
358   @param  UsbResult        The result of USB execution.
359 
360   @retval EFI_SUCCESS      The bulk transfer is finished without error.
361   @retval Others           Failed to execute bulk transfer, result in UsbResult.
362 
363 **/
364 EFI_STATUS
UsbHcBulkTransfer(IN USB_BUS * UsbBus,IN UINT8 DevAddr,IN UINT8 EpAddr,IN UINT8 DevSpeed,IN UINTN MaxPacket,IN UINT8 BufferNum,IN OUT VOID * Data[EFI_USB_MAX_BULK_BUFFER_NUM],IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * UsbResult)365 UsbHcBulkTransfer (
366   IN  USB_BUS                             *UsbBus,
367   IN  UINT8                               DevAddr,
368   IN  UINT8                               EpAddr,
369   IN  UINT8                               DevSpeed,
370   IN  UINTN                               MaxPacket,
371   IN  UINT8                               BufferNum,
372   IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
373   IN  OUT UINTN                           *DataLength,
374   IN  OUT UINT8                           *DataToggle,
375   IN  UINTN                               TimeOut,
376   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
377   OUT UINT32                              *UsbResult
378   )
379 {
380   EFI_STATUS              Status;
381 
382   if (UsbBus->Usb2Hc != NULL) {
383     Status = UsbBus->Usb2Hc->BulkTransfer (
384                                UsbBus->Usb2Hc,
385                                DevAddr,
386                                EpAddr,
387                                DevSpeed,
388                                MaxPacket,
389                                BufferNum,
390                                Data,
391                                DataLength,
392                                DataToggle,
393                                TimeOut,
394                                Translator,
395                                UsbResult
396                                );
397   } else {
398     Status = UsbBus->UsbHc->BulkTransfer (
399                               UsbBus->UsbHc,
400                               DevAddr,
401                               EpAddr,
402                               (UINT8) MaxPacket,
403                               *Data,
404                               DataLength,
405                               DataToggle,
406                               TimeOut,
407                               UsbResult
408                               );
409   }
410 
411   return Status;
412 }
413 
414 
415 /**
416   Queue or cancel an asynchronous interrupt transfer.
417 
418   @param  UsbBus           The USB bus driver.
419   @param  DevAddr          The target device address.
420   @param  EpAddr           The target endpoint address, with direction encoded in
421                            bit 7.
422   @param  DevSpeed         The device's speed.
423   @param  MaxPacket        The endpoint's max packet size.
424   @param  IsNewTransfer    Whether this is a new request. If not, cancel the old
425                            request.
426   @param  DataToggle       Data toggle to use on input, next toggle on output.
427   @param  PollingInterval  The interval to poll the interrupt transfer (in ms).
428   @param  DataLength       The length of periodical data receive.
429   @param  Translator       The transaction translator for low/full speed device.
430   @param  Callback         Function to call when data is received.
431   @param  Context          The context to the callback.
432 
433   @retval EFI_SUCCESS      The asynchronous transfer is queued.
434   @retval Others           Failed to queue the transfer.
435 
436 **/
437 EFI_STATUS
UsbHcAsyncInterruptTransfer(IN USB_BUS * UsbBus,IN UINT8 DevAddr,IN UINT8 EpAddr,IN UINT8 DevSpeed,IN UINTN MaxPacket,IN BOOLEAN IsNewTransfer,IN OUT UINT8 * DataToggle,IN UINTN PollingInterval,IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,IN VOID * Context OPTIONAL)438 UsbHcAsyncInterruptTransfer (
439   IN  USB_BUS                             *UsbBus,
440   IN  UINT8                               DevAddr,
441   IN  UINT8                               EpAddr,
442   IN  UINT8                               DevSpeed,
443   IN  UINTN                               MaxPacket,
444   IN  BOOLEAN                             IsNewTransfer,
445   IN OUT UINT8                            *DataToggle,
446   IN  UINTN                               PollingInterval,
447   IN  UINTN                               DataLength,
448   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
449   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     Callback,
450   IN  VOID                                *Context OPTIONAL
451   )
452 {
453   EFI_STATUS              Status;
454   BOOLEAN                 IsSlowDevice;
455 
456   if (UsbBus->Usb2Hc != NULL) {
457     Status = UsbBus->Usb2Hc->AsyncInterruptTransfer (
458                                UsbBus->Usb2Hc,
459                                DevAddr,
460                                EpAddr,
461                                DevSpeed,
462                                MaxPacket,
463                                IsNewTransfer,
464                                DataToggle,
465                                PollingInterval,
466                                DataLength,
467                                Translator,
468                                Callback,
469                                Context
470                                );
471   } else {
472     IsSlowDevice = (BOOLEAN)(EFI_USB_SPEED_LOW == DevSpeed);
473 
474     Status = UsbBus->UsbHc->AsyncInterruptTransfer (
475                               UsbBus->UsbHc,
476                               DevAddr,
477                               EpAddr,
478                               IsSlowDevice,
479                               (UINT8) MaxPacket,
480                               IsNewTransfer,
481                               DataToggle,
482                               PollingInterval,
483                               DataLength,
484                               Callback,
485                               Context
486                               );
487   }
488 
489   return Status;
490 }
491 
492 
493 /**
494   Execute a synchronous interrupt transfer to the target endpoint.
495 
496   @param  UsbBus           The USB bus driver.
497   @param  DevAddr          The target device address.
498   @param  EpAddr           The target endpoint address, with direction encoded in
499                            bit 7.
500   @param  DevSpeed         The device's speed.
501   @param  MaxPacket        The endpoint's max packet size.
502   @param  Data             Pointer to data buffer.
503   @param  DataLength       The length of data buffer.
504   @param  DataToggle       On input, the initial data toggle to use, also  return
505                            the next toggle on output.
506   @param  TimeOut          The time to wait until timeout.
507   @param  Translator       The transaction translator for low/full speed device.
508   @param  UsbResult        The result of USB execution.
509 
510   @retval EFI_SUCCESS      The synchronous interrupt transfer is OK.
511   @retval Others           Failed to execute the synchronous interrupt transfer.
512 
513 **/
514 EFI_STATUS
UsbHcSyncInterruptTransfer(IN USB_BUS * UsbBus,IN UINT8 DevAddr,IN UINT8 EpAddr,IN UINT8 DevSpeed,IN UINTN MaxPacket,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * UsbResult)515 UsbHcSyncInterruptTransfer (
516   IN  USB_BUS                             *UsbBus,
517   IN  UINT8                               DevAddr,
518   IN  UINT8                               EpAddr,
519   IN  UINT8                               DevSpeed,
520   IN  UINTN                               MaxPacket,
521   IN OUT VOID                             *Data,
522   IN OUT UINTN                            *DataLength,
523   IN OUT UINT8                            *DataToggle,
524   IN  UINTN                               TimeOut,
525   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
526   OUT UINT32                              *UsbResult
527   )
528 {
529   EFI_STATUS              Status;
530   BOOLEAN                 IsSlowDevice;
531 
532   if (UsbBus->Usb2Hc != NULL) {
533     Status = UsbBus->Usb2Hc->SyncInterruptTransfer (
534                                UsbBus->Usb2Hc,
535                                DevAddr,
536                                EpAddr,
537                                DevSpeed,
538                                MaxPacket,
539                                Data,
540                                DataLength,
541                                DataToggle,
542                                TimeOut,
543                                Translator,
544                                UsbResult
545                                );
546   } else {
547     IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DevSpeed) ? TRUE : FALSE);
548     Status = UsbBus->UsbHc->SyncInterruptTransfer (
549                               UsbBus->UsbHc,
550                               DevAddr,
551                               EpAddr,
552                               IsSlowDevice,
553                               (UINT8) MaxPacket,
554                               Data,
555                               DataLength,
556                               DataToggle,
557                               TimeOut,
558                               UsbResult
559                               );
560   }
561 
562   return Status;
563 }
564 
565 
566 /**
567   Execute a synchronous Isochronous USB transfer.
568 
569   @param  UsbBus           The USB bus driver.
570   @param  DevAddr          The target device address.
571   @param  EpAddr           The target endpoint address, with direction encoded in
572                            bit 7.
573   @param  DevSpeed         The device's speed.
574   @param  MaxPacket        The endpoint's max packet size.
575   @param  BufferNum        The number of data buffer.
576   @param  Data             Array of pointers to data buffer.
577   @param  DataLength       The length of data buffer.
578   @param  Translator       The transaction translator for low/full speed device.
579   @param  UsbResult        The result of USB execution.
580 
581   @retval EFI_UNSUPPORTED  The isochronous transfer isn't supported now.
582 
583 **/
584 EFI_STATUS
UsbHcIsochronousTransfer(IN USB_BUS * UsbBus,IN UINT8 DevAddr,IN UINT8 EpAddr,IN UINT8 DevSpeed,IN UINTN MaxPacket,IN UINT8 BufferNum,IN OUT VOID * Data[EFI_USB_MAX_ISO_BUFFER_NUM],IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * UsbResult)585 UsbHcIsochronousTransfer (
586   IN  USB_BUS                             *UsbBus,
587   IN  UINT8                               DevAddr,
588   IN  UINT8                               EpAddr,
589   IN  UINT8                               DevSpeed,
590   IN  UINTN                               MaxPacket,
591   IN  UINT8                               BufferNum,
592   IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
593   IN  UINTN                               DataLength,
594   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
595   OUT UINT32                              *UsbResult
596   )
597 {
598   return EFI_UNSUPPORTED;
599 }
600 
601 
602 /**
603   Queue an asynchronous isochronous transfer.
604 
605   @param  UsbBus           The USB bus driver.
606   @param  DevAddr          The target device address.
607   @param  EpAddr           The target endpoint address, with direction encoded in
608                            bit 7.
609   @param  DevSpeed         The device's speed.
610   @param  MaxPacket        The endpoint's max packet size.
611   @param  BufferNum        The number of data buffer.
612   @param  Data             Array of pointers to data buffer.
613   @param  DataLength       The length of data buffer.
614   @param  Translator       The transaction translator for low/full speed device.
615   @param  Callback         The function to call when data is transferred.
616   @param  Context          The context to the callback function.
617 
618   @retval EFI_UNSUPPORTED  The asynchronous isochronous transfer isn't supported.
619 
620 **/
621 EFI_STATUS
UsbHcAsyncIsochronousTransfer(IN USB_BUS * UsbBus,IN UINT8 DevAddr,IN UINT8 EpAddr,IN UINT8 DevSpeed,IN UINTN MaxPacket,IN UINT8 BufferNum,IN OUT VOID * Data[EFI_USB_MAX_ISO_BUFFER_NUM],IN UINTN DataLength,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,IN VOID * Context)622 UsbHcAsyncIsochronousTransfer (
623   IN  USB_BUS                             *UsbBus,
624   IN  UINT8                               DevAddr,
625   IN  UINT8                               EpAddr,
626   IN  UINT8                               DevSpeed,
627   IN  UINTN                               MaxPacket,
628   IN  UINT8                               BufferNum,
629   IN OUT VOID                             *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
630   IN  UINTN                               DataLength,
631   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
632   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     Callback,
633   IN  VOID                                *Context
634   )
635 {
636   return EFI_UNSUPPORTED;
637 }
638 
639 
640 /**
641   Open the USB host controller protocol BY_CHILD.
642 
643   @param  Bus              The USB bus driver.
644   @param  Child            The child handle.
645 
646   @return The open protocol return.
647 
648 **/
649 EFI_STATUS
UsbOpenHostProtoByChild(IN USB_BUS * Bus,IN EFI_HANDLE Child)650 UsbOpenHostProtoByChild (
651   IN USB_BUS              *Bus,
652   IN EFI_HANDLE           Child
653   )
654 {
655   EFI_USB_HC_PROTOCOL     *UsbHc;
656   EFI_USB2_HC_PROTOCOL    *Usb2Hc;
657   EFI_STATUS              Status;
658 
659   if (Bus->Usb2Hc != NULL) {
660     Status = gBS->OpenProtocol (
661                     Bus->HostHandle,
662                     &gEfiUsb2HcProtocolGuid,
663                     (VOID **) &Usb2Hc,
664                     mUsbBusDriverBinding.DriverBindingHandle,
665                     Child,
666                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
667                     );
668 
669   } else {
670     Status = gBS->OpenProtocol (
671                     Bus->HostHandle,
672                     &gEfiUsbHcProtocolGuid,
673                     (VOID **) &UsbHc,
674                     mUsbBusDriverBinding.DriverBindingHandle,
675                     Child,
676                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
677                     );
678   }
679 
680   return Status;
681 }
682 
683 
684 /**
685   Close the USB host controller protocol BY_CHILD.
686 
687   @param  Bus              The USB bus driver.
688   @param  Child            The child handle.
689 
690 **/
691 VOID
UsbCloseHostProtoByChild(IN USB_BUS * Bus,IN EFI_HANDLE Child)692 UsbCloseHostProtoByChild (
693   IN USB_BUS              *Bus,
694   IN EFI_HANDLE           Child
695   )
696 {
697   if (Bus->Usb2Hc != NULL) {
698     gBS->CloseProtocol (
699            Bus->HostHandle,
700            &gEfiUsb2HcProtocolGuid,
701            mUsbBusDriverBinding.DriverBindingHandle,
702            Child
703            );
704 
705   } else {
706     gBS->CloseProtocol (
707            Bus->HostHandle,
708            &gEfiUsbHcProtocolGuid,
709            mUsbBusDriverBinding.DriverBindingHandle,
710            Child
711            );
712   }
713 }
714 
715 
716 /**
717   return the current TPL, copied from the EDKII glue lib.
718 
719   @param  VOID.
720 
721   @return Current TPL.
722 
723 **/
724 EFI_TPL
UsbGetCurrentTpl(VOID)725 UsbGetCurrentTpl (
726   VOID
727   )
728 {
729   EFI_TPL                 Tpl;
730 
731   Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
732   gBS->RestoreTPL (Tpl);
733 
734   return Tpl;
735 }
736 
737 /**
738   Create a new device path which only contain the first Usb part of the DevicePath.
739 
740   @param DevicePath  A full device path which contain the usb nodes.
741 
742   @return            A new device path which only contain the Usb part of the DevicePath.
743 
744 **/
745 EFI_DEVICE_PATH_PROTOCOL *
746 EFIAPI
GetUsbDPFromFullDP(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)747 GetUsbDPFromFullDP (
748   IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath
749   )
750 {
751   EFI_DEVICE_PATH_PROTOCOL    *UsbDevicePathPtr;
752   EFI_DEVICE_PATH_PROTOCOL    *UsbDevicePathBeginPtr;
753   EFI_DEVICE_PATH_PROTOCOL    *UsbDevicePathEndPtr;
754   UINTN                       Size;
755 
756   //
757   // Get the Usb part first Begin node in full device path
758   //
759   UsbDevicePathBeginPtr = DevicePath;
760   while ( (!IsDevicePathEnd (UsbDevicePathBeginPtr))&&
761          ((UsbDevicePathBeginPtr->Type != MESSAGING_DEVICE_PATH) ||
762          (UsbDevicePathBeginPtr->SubType != MSG_USB_DP &&
763           UsbDevicePathBeginPtr->SubType != MSG_USB_CLASS_DP
764           && UsbDevicePathBeginPtr->SubType != MSG_USB_WWID_DP
765           ))) {
766 
767     UsbDevicePathBeginPtr = NextDevicePathNode(UsbDevicePathBeginPtr);
768   }
769 
770   //
771   // Get the Usb part first End node in full device path
772   //
773   UsbDevicePathEndPtr = UsbDevicePathBeginPtr;
774   while ((!IsDevicePathEnd (UsbDevicePathEndPtr))&&
775          (UsbDevicePathEndPtr->Type == MESSAGING_DEVICE_PATH) &&
776          (UsbDevicePathEndPtr->SubType == MSG_USB_DP ||
777           UsbDevicePathEndPtr->SubType == MSG_USB_CLASS_DP
778           || UsbDevicePathEndPtr->SubType == MSG_USB_WWID_DP
779           )) {
780 
781     UsbDevicePathEndPtr = NextDevicePathNode(UsbDevicePathEndPtr);
782   }
783 
784   Size  = GetDevicePathSize (UsbDevicePathBeginPtr);
785   Size -= GetDevicePathSize (UsbDevicePathEndPtr);
786   if (Size ==0){
787     //
788     // The passed in DevicePath does not contain the usb nodes
789     //
790     return NULL;
791   }
792 
793   //
794   // Create a new device path which only contain the above Usb part
795   //
796   UsbDevicePathPtr = AllocateZeroPool (Size + sizeof (EFI_DEVICE_PATH_PROTOCOL));
797   ASSERT (UsbDevicePathPtr != NULL);
798   CopyMem (UsbDevicePathPtr, UsbDevicePathBeginPtr, Size);
799   //
800   // Append end device path node
801   //
802   UsbDevicePathEndPtr = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) UsbDevicePathPtr + Size);
803   SetDevicePathEndNode (UsbDevicePathEndPtr);
804   return UsbDevicePathPtr;
805 }
806 
807 /**
808   Check whether a usb device path is in a DEVICE_PATH_LIST_ITEM list.
809 
810   @param UsbDP       a usb device path of DEVICE_PATH_LIST_ITEM.
811   @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list.
812 
813   @retval TRUE       there is a DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP.
814   @retval FALSE      there is no DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP.
815 
816 **/
817 BOOLEAN
818 EFIAPI
SearchUsbDPInList(IN EFI_DEVICE_PATH_PROTOCOL * UsbDP,IN LIST_ENTRY * UsbIoDPList)819 SearchUsbDPInList (
820   IN EFI_DEVICE_PATH_PROTOCOL     *UsbDP,
821   IN LIST_ENTRY                   *UsbIoDPList
822   )
823 {
824   LIST_ENTRY                  *ListIndex;
825   DEVICE_PATH_LIST_ITEM       *ListItem;
826   BOOLEAN                     Found;
827   UINTN                       UsbDpDevicePathSize;
828 
829   //
830   // Check that UsbDP and UsbIoDPList are valid
831   //
832   if ((UsbIoDPList == NULL) || (UsbDP == NULL)) {
833     return FALSE;
834   }
835 
836   Found = FALSE;
837   ListIndex = UsbIoDPList->ForwardLink;
838   while (ListIndex != UsbIoDPList){
839     ListItem = CR(ListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);
840     //
841     // Compare DEVICE_PATH_LIST_ITEM.DevicePath[]
842     //
843     ASSERT (ListItem->DevicePath != NULL);
844 
845     UsbDpDevicePathSize  = GetDevicePathSize (UsbDP);
846     if (UsbDpDevicePathSize == GetDevicePathSize (ListItem->DevicePath)) {
847       if ((CompareMem (UsbDP, ListItem->DevicePath, UsbDpDevicePathSize)) == 0) {
848         Found = TRUE;
849         break;
850       }
851     }
852     ListIndex =  ListIndex->ForwardLink;
853   }
854 
855   return Found;
856 }
857 
858 /**
859   Add a usb device path into the DEVICE_PATH_LIST_ITEM list.
860 
861   @param UsbDP                   a usb device path of DEVICE_PATH_LIST_ITEM.
862   @param UsbIoDPList             a DEVICE_PATH_LIST_ITEM list.
863 
864   @retval EFI_INVALID_PARAMETER  If parameters are invalid, return this value.
865   @retval EFI_SUCCESS            If Add operation is successful, return this value.
866 
867 **/
868 EFI_STATUS
869 EFIAPI
AddUsbDPToList(IN EFI_DEVICE_PATH_PROTOCOL * UsbDP,IN LIST_ENTRY * UsbIoDPList)870 AddUsbDPToList (
871   IN EFI_DEVICE_PATH_PROTOCOL     *UsbDP,
872   IN LIST_ENTRY                   *UsbIoDPList
873   )
874 {
875   DEVICE_PATH_LIST_ITEM       *ListItem;
876 
877   //
878   // Check that UsbDP and UsbIoDPList are valid
879   //
880   if ((UsbIoDPList == NULL) || (UsbDP == NULL)) {
881     return EFI_INVALID_PARAMETER;
882   }
883 
884   if (SearchUsbDPInList (UsbDP, UsbIoDPList)){
885     return EFI_SUCCESS;
886   }
887 
888   //
889   // Prepare the usbio device path DEVICE_PATH_LIST_ITEM structure.
890   //
891   ListItem = AllocateZeroPool (sizeof (DEVICE_PATH_LIST_ITEM));
892   ASSERT (ListItem != NULL);
893   ListItem->Signature = DEVICE_PATH_LIST_ITEM_SIGNATURE;
894   ListItem->DevicePath = DuplicateDevicePath (UsbDP);
895 
896   InsertTailList (UsbIoDPList, &ListItem->Link);
897 
898   return EFI_SUCCESS;
899 }
900 
901 /**
902   Check whether usb device, whose interface is UsbIf, matches the usb class which indicated by
903   UsbClassDevicePathPtr whose is a short form usb class device path.
904 
905   @param UsbClassDevicePathPtr    a short form usb class device path.
906   @param UsbIf                    a usb device interface.
907 
908   @retval TRUE                    the usb device match the usb class.
909   @retval FALSE                   the usb device does not match the usb class.
910 
911 **/
912 BOOLEAN
913 EFIAPI
MatchUsbClass(IN USB_CLASS_DEVICE_PATH * UsbClassDevicePathPtr,IN USB_INTERFACE * UsbIf)914 MatchUsbClass (
915   IN USB_CLASS_DEVICE_PATH      *UsbClassDevicePathPtr,
916   IN USB_INTERFACE              *UsbIf
917   )
918 {
919   USB_INTERFACE_DESC            *IfDesc;
920   EFI_USB_INTERFACE_DESCRIPTOR  *ActIfDesc;
921   EFI_USB_DEVICE_DESCRIPTOR     *DevDesc;
922 
923 
924   if ((UsbClassDevicePathPtr->Header.Type != MESSAGING_DEVICE_PATH) ||
925       (UsbClassDevicePathPtr->Header.SubType != MSG_USB_CLASS_DP)){
926     ASSERT (0);
927     return FALSE;
928   }
929 
930   IfDesc       = UsbIf->IfDesc;
931   ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);
932   ActIfDesc    = &(IfDesc->Settings[IfDesc->ActiveIndex]->Desc);
933   DevDesc      = &(UsbIf->Device->DevDesc->Desc);
934 
935   //
936   // If connect class policy, determine whether to create device handle by the five fields
937   // in class device path node.
938   //
939   // In addtion, hub interface is always matched for this policy.
940   //
941   if ((ActIfDesc->InterfaceClass == USB_HUB_CLASS_CODE) &&
942       (ActIfDesc->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {
943     return TRUE;
944   }
945 
946   //
947   // If vendor id or product id is 0xffff, they will be ignored.
948   //
949   if ((UsbClassDevicePathPtr->VendorId == 0xffff || UsbClassDevicePathPtr->VendorId == DevDesc->IdVendor) &&
950       (UsbClassDevicePathPtr->ProductId == 0xffff || UsbClassDevicePathPtr->ProductId == DevDesc->IdProduct)) {
951 
952     //
953     // If Class in Device Descriptor is set to 0, the counterparts in interface should be checked.
954     //
955     if (DevDesc->DeviceClass == 0) {
956       if ((UsbClassDevicePathPtr->DeviceClass == ActIfDesc->InterfaceClass ||
957                                           UsbClassDevicePathPtr->DeviceClass == 0xff) &&
958           (UsbClassDevicePathPtr->DeviceSubClass == ActIfDesc->InterfaceSubClass ||
959                                        UsbClassDevicePathPtr->DeviceSubClass == 0xff) &&
960           (UsbClassDevicePathPtr->DeviceProtocol == ActIfDesc->InterfaceProtocol ||
961                                        UsbClassDevicePathPtr->DeviceProtocol == 0xff)) {
962         return TRUE;
963       }
964 
965     } else if ((UsbClassDevicePathPtr->DeviceClass == DevDesc->DeviceClass ||
966                                          UsbClassDevicePathPtr->DeviceClass == 0xff) &&
967                (UsbClassDevicePathPtr->DeviceSubClass == DevDesc->DeviceSubClass ||
968                                       UsbClassDevicePathPtr->DeviceSubClass == 0xff) &&
969                (UsbClassDevicePathPtr->DeviceProtocol == DevDesc->DeviceProtocol ||
970                                       UsbClassDevicePathPtr->DeviceProtocol == 0xff)) {
971 
972       return TRUE;
973     }
974   }
975 
976   return FALSE;
977 }
978 
979 /**
980   Check whether usb device, whose interface is UsbIf, matches the usb WWID requirement which indicated by
981   UsbWWIDDevicePathPtr whose is a short form usb WWID device path.
982 
983   @param UsbWWIDDevicePathPtr    a short form usb WWID device path.
984   @param UsbIf                   a usb device interface.
985 
986   @retval TRUE                   the usb device match the usb WWID requirement.
987   @retval FALSE                  the usb device does not match the usb WWID requirement.
988 
989 **/
990 BOOLEAN
MatchUsbWwid(IN USB_WWID_DEVICE_PATH * UsbWWIDDevicePathPtr,IN USB_INTERFACE * UsbIf)991 MatchUsbWwid (
992   IN USB_WWID_DEVICE_PATH       *UsbWWIDDevicePathPtr,
993   IN USB_INTERFACE              *UsbIf
994   )
995 {
996   USB_INTERFACE_DESC            *IfDesc;
997   EFI_USB_INTERFACE_DESCRIPTOR  *ActIfDesc;
998   EFI_USB_DEVICE_DESCRIPTOR     *DevDesc;
999   EFI_USB_STRING_DESCRIPTOR     *StrDesc;
1000   UINT16                        Index;
1001   CHAR16                        *CompareStr;
1002   UINTN                         CompareLen;
1003   UINTN                         Length;
1004 
1005   if ((UsbWWIDDevicePathPtr->Header.Type != MESSAGING_DEVICE_PATH) ||
1006      (UsbWWIDDevicePathPtr->Header.SubType != MSG_USB_WWID_DP )){
1007     ASSERT (0);
1008     return FALSE;
1009   }
1010 
1011   IfDesc       = UsbIf->IfDesc;
1012   ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);
1013   ActIfDesc    = &(IfDesc->Settings[IfDesc->ActiveIndex]->Desc);
1014   DevDesc      = &(UsbIf->Device->DevDesc->Desc);
1015 
1016   //
1017   // In addition, Hub interface is always matched for this policy.
1018   //
1019   if ((ActIfDesc->InterfaceClass == USB_HUB_CLASS_CODE) &&
1020       (ActIfDesc->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {
1021     return TRUE;
1022   }
1023 
1024   //
1025   // Check Vendor Id, Product Id and Interface Number.
1026   //
1027   if ((DevDesc->IdVendor != UsbWWIDDevicePathPtr->VendorId) ||
1028       (DevDesc->IdProduct != UsbWWIDDevicePathPtr->ProductId) ||
1029       (ActIfDesc->InterfaceNumber != UsbWWIDDevicePathPtr->InterfaceNumber)) {
1030     return FALSE;
1031   }
1032 
1033   //
1034   // Check SerialNumber.
1035   //
1036   if (DevDesc->StrSerialNumber == 0) {
1037     return FALSE;
1038   }
1039 
1040   //
1041   // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.
1042   //
1043   CompareStr = (CHAR16 *) (UINTN) (UsbWWIDDevicePathPtr + 1);
1044   CompareLen = (DevicePathNodeLength (UsbWWIDDevicePathPtr) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);
1045   if (CompareStr[CompareLen - 1] == L'\0') {
1046     CompareLen--;
1047   }
1048 
1049   //
1050   // Compare serial number in each supported language.
1051   //
1052   for (Index = 0; Index < UsbIf->Device->TotalLangId; Index++) {
1053     StrDesc = UsbGetOneString (UsbIf->Device, DevDesc->StrSerialNumber, UsbIf->Device->LangId[Index]);
1054     if (StrDesc == NULL) {
1055       continue;
1056     }
1057 
1058     Length = (StrDesc->Length - 2) / sizeof (CHAR16);
1059     if ((Length >= CompareLen) &&
1060         (CompareMem (StrDesc->String + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0)) {
1061       return TRUE;
1062     }
1063   }
1064 
1065   return FALSE;
1066 }
1067 
1068 /**
1069   Free a DEVICE_PATH_LIST_ITEM list.
1070 
1071   @param  UsbIoDPList            a DEVICE_PATH_LIST_ITEM list pointer.
1072 
1073   @retval EFI_INVALID_PARAMETER  If parameters are invalid, return this value.
1074   @retval EFI_SUCCESS            If free operation is successful, return this value.
1075 
1076 **/
1077 EFI_STATUS
1078 EFIAPI
UsbBusFreeUsbDPList(IN LIST_ENTRY * UsbIoDPList)1079 UsbBusFreeUsbDPList (
1080   IN LIST_ENTRY          *UsbIoDPList
1081   )
1082 {
1083   LIST_ENTRY                  *ListIndex;
1084   DEVICE_PATH_LIST_ITEM       *ListItem;
1085 
1086   //
1087   // Check that ControllerHandle is a valid handle
1088   //
1089   if (UsbIoDPList == NULL) {
1090     return EFI_INVALID_PARAMETER;
1091   }
1092 
1093   ListIndex = UsbIoDPList->ForwardLink;
1094   while (ListIndex != UsbIoDPList){
1095     ListItem = CR(ListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);
1096     //
1097     // Free DEVICE_PATH_LIST_ITEM.DevicePath[]
1098     //
1099     if (ListItem->DevicePath != NULL){
1100       FreePool(ListItem->DevicePath);
1101     }
1102     //
1103     // Free DEVICE_PATH_LIST_ITEM itself
1104     //
1105     ListIndex =  ListIndex->ForwardLink;
1106     RemoveEntryList (&ListItem->Link);
1107     FreePool (ListItem);
1108   }
1109 
1110   InitializeListHead (UsbIoDPList);
1111   return EFI_SUCCESS;
1112 }
1113 
1114 /**
1115   Store a wanted usb child device info (its Usb part of device path) which is indicated by
1116   RemainingDevicePath in a Usb bus which  is indicated by UsbBusId.
1117 
1118   @param  UsbBusId               Point to EFI_USB_BUS_PROTOCOL interface.
1119   @param  RemainingDevicePath    The remaining device patch.
1120 
1121   @retval EFI_SUCCESS            Add operation is successful.
1122   @retval EFI_INVALID_PARAMETER  The parameters are invalid.
1123 
1124 **/
1125 EFI_STATUS
1126 EFIAPI
UsbBusAddWantedUsbIoDP(IN EFI_USB_BUS_PROTOCOL * UsbBusId,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1127 UsbBusAddWantedUsbIoDP (
1128   IN EFI_USB_BUS_PROTOCOL         *UsbBusId,
1129   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
1130   )
1131 {
1132   USB_BUS                       *Bus;
1133   EFI_STATUS                    Status;
1134   EFI_DEVICE_PATH_PROTOCOL      *DevicePathPtr;
1135 
1136   //
1137   // Check whether remaining device path is valid
1138   //
1139   if (RemainingDevicePath != NULL && !IsDevicePathEnd (RemainingDevicePath)) {
1140     if ((RemainingDevicePath->Type    != MESSAGING_DEVICE_PATH) ||
1141         (RemainingDevicePath->SubType != MSG_USB_DP &&
1142          RemainingDevicePath->SubType != MSG_USB_CLASS_DP
1143          && RemainingDevicePath->SubType != MSG_USB_WWID_DP
1144          )) {
1145       return EFI_INVALID_PARAMETER;
1146     }
1147   }
1148 
1149   if (UsbBusId == NULL){
1150     return EFI_INVALID_PARAMETER;
1151   }
1152 
1153   Bus = USB_BUS_FROM_THIS (UsbBusId);
1154 
1155   if (RemainingDevicePath == NULL) {
1156     //
1157     // RemainingDevicePath == NULL means all Usb devices in this bus are wanted.
1158     // Here use a Usb class Device Path in WantedUsbIoDPList to indicate all Usb devices
1159     // are wanted Usb devices
1160     //
1161     Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
1162     ASSERT (!EFI_ERROR (Status));
1163     DevicePathPtr = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) &mAllUsbClassDevicePath);
1164   } else if (!IsDevicePathEnd (RemainingDevicePath)) {
1165     //
1166     // If RemainingDevicePath isn't the End of Device Path Node,
1167     // Create new Usb device path according to the usb part in remaining device path
1168     //
1169     DevicePathPtr = GetUsbDPFromFullDP (RemainingDevicePath);
1170   } else {
1171     //
1172     // If RemainingDevicePath is the End of Device Path Node,
1173     // skip enumerate any device and return EFI_SUCESSS
1174     //
1175     return EFI_SUCCESS;
1176   }
1177 
1178   ASSERT (DevicePathPtr != NULL);
1179   Status = AddUsbDPToList (DevicePathPtr, &Bus->WantedUsbIoDPList);
1180   ASSERT (!EFI_ERROR (Status));
1181   FreePool (DevicePathPtr);
1182   return EFI_SUCCESS;
1183 }
1184 
1185 /**
1186   Check whether a usb child device is the wanted device in a bus.
1187 
1188   @param  Bus     The Usb bus's private data pointer.
1189   @param  UsbIf   The usb child device inferface.
1190 
1191   @retval True    If a usb child device is the wanted device in a bus.
1192   @retval False   If a usb child device is *NOT* the wanted device in a bus.
1193 
1194 **/
1195 BOOLEAN
1196 EFIAPI
UsbBusIsWantedUsbIO(IN USB_BUS * Bus,IN USB_INTERFACE * UsbIf)1197 UsbBusIsWantedUsbIO (
1198   IN USB_BUS                 *Bus,
1199   IN USB_INTERFACE           *UsbIf
1200   )
1201 {
1202   EFI_DEVICE_PATH_PROTOCOL      *DevicePathPtr;
1203   LIST_ENTRY                    *WantedUsbIoDPListPtr;
1204   LIST_ENTRY                    *WantedListIndex;
1205   DEVICE_PATH_LIST_ITEM         *WantedListItem;
1206   BOOLEAN                       DoConvert;
1207   UINTN                         FirstDevicePathSize;
1208 
1209   //
1210   // Check whether passed in parameters are valid
1211   //
1212   if ((UsbIf == NULL) || (Bus == NULL)) {
1213     return FALSE;
1214   }
1215   //
1216   // Check whether UsbIf is Hub
1217   //
1218   if (UsbIf->IsHub) {
1219     return TRUE;
1220   }
1221 
1222   //
1223   // Check whether all Usb devices in this bus are wanted
1224   //
1225   if (SearchUsbDPInList ((EFI_DEVICE_PATH_PROTOCOL *)&mAllUsbClassDevicePath, &Bus->WantedUsbIoDPList)){
1226     return TRUE;
1227   }
1228 
1229   //
1230   // Check whether the Usb device match any item in WantedUsbIoDPList
1231   //
1232   WantedUsbIoDPListPtr = &Bus->WantedUsbIoDPList;
1233   //
1234   // Create new Usb device path according to the usb part in UsbIo full device path
1235   //
1236   DevicePathPtr = GetUsbDPFromFullDP (UsbIf->DevicePath);
1237   ASSERT (DevicePathPtr != NULL);
1238 
1239   DoConvert = FALSE;
1240   WantedListIndex = WantedUsbIoDPListPtr->ForwardLink;
1241   while (WantedListIndex != WantedUsbIoDPListPtr){
1242     WantedListItem = CR(WantedListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);
1243     ASSERT (WantedListItem->DevicePath->Type == MESSAGING_DEVICE_PATH);
1244     switch (WantedListItem->DevicePath->SubType) {
1245     case MSG_USB_DP:
1246       FirstDevicePathSize = GetDevicePathSize (WantedListItem->DevicePath);
1247       if (FirstDevicePathSize == GetDevicePathSize (DevicePathPtr)) {
1248         if (CompareMem (
1249               WantedListItem->DevicePath,
1250               DevicePathPtr,
1251               GetDevicePathSize (DevicePathPtr)) == 0
1252             ) {
1253           DoConvert = TRUE;
1254         }
1255       }
1256       break;
1257     case MSG_USB_CLASS_DP:
1258       if (MatchUsbClass((USB_CLASS_DEVICE_PATH *)WantedListItem->DevicePath, UsbIf)) {
1259         DoConvert = TRUE;
1260       }
1261       break;
1262    case MSG_USB_WWID_DP:
1263       if (MatchUsbWwid((USB_WWID_DEVICE_PATH *)WantedListItem->DevicePath, UsbIf)) {
1264         DoConvert = TRUE;
1265       }
1266       break;
1267     default:
1268       ASSERT (0);
1269       break;
1270     }
1271 
1272     if (DoConvert) {
1273       break;
1274     }
1275 
1276     WantedListIndex =  WantedListIndex->ForwardLink;
1277   }
1278   gBS->FreePool (DevicePathPtr);
1279 
1280   //
1281   // Check whether the new Usb device path is wanted
1282   //
1283   if (DoConvert){
1284     return TRUE;
1285   } else {
1286     return FALSE;
1287   }
1288 }
1289 
1290 /**
1291   Recursively connnect every wanted usb child device to ensure they all fully connected.
1292   Check all the child Usb IO handles in this bus, recursively connecte if it is wanted usb child device.
1293 
1294   @param  UsbBusId                  Point to EFI_USB_BUS_PROTOCOL interface.
1295 
1296   @retval EFI_SUCCESS               Connect is done successfully.
1297   @retval EFI_INVALID_PARAMETER     The parameter is invalid.
1298 
1299 **/
1300 EFI_STATUS
1301 EFIAPI
UsbBusRecursivelyConnectWantedUsbIo(IN EFI_USB_BUS_PROTOCOL * UsbBusId)1302 UsbBusRecursivelyConnectWantedUsbIo (
1303   IN EFI_USB_BUS_PROTOCOL         *UsbBusId
1304   )
1305 {
1306   USB_BUS                       *Bus;
1307   EFI_STATUS                    Status;
1308   UINTN                         Index;
1309   EFI_USB_IO_PROTOCOL           *UsbIo;
1310   USB_INTERFACE                 *UsbIf;
1311   UINTN                         UsbIoHandleCount;
1312   EFI_HANDLE                    *UsbIoBuffer;
1313   EFI_DEVICE_PATH_PROTOCOL      *UsbIoDevicePath;
1314 
1315   if (UsbBusId == NULL){
1316     return EFI_INVALID_PARAMETER;
1317   }
1318 
1319   Bus = USB_BUS_FROM_THIS (UsbBusId);
1320 
1321   //
1322   // Get all Usb IO handles in system
1323   //
1324   UsbIoHandleCount = 0;
1325   Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer);
1326   if (Status == EFI_NOT_FOUND || UsbIoHandleCount == 0) {
1327     return EFI_SUCCESS;
1328   }
1329   ASSERT (!EFI_ERROR (Status));
1330 
1331   for (Index = 0; Index < UsbIoHandleCount; Index++) {
1332     //
1333     // Check whether the USB IO handle is a child of this bus
1334     // Note: The usb child handle maybe invalid because of hot plugged out during the loop
1335     //
1336     UsbIoDevicePath = NULL;
1337     Status = gBS->HandleProtocol (UsbIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &UsbIoDevicePath);
1338     if (EFI_ERROR (Status) || UsbIoDevicePath == NULL) {
1339       continue;
1340     }
1341     if (CompareMem (
1342             UsbIoDevicePath,
1343             Bus->DevicePath,
1344             (GetDevicePathSize (Bus->DevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL))
1345             ) != 0) {
1346       continue;
1347     }
1348 
1349     //
1350     // Get the child Usb IO interface
1351     //
1352     Status = gBS->HandleProtocol(
1353                      UsbIoBuffer[Index],
1354                      &gEfiUsbIoProtocolGuid,
1355                      (VOID **) &UsbIo
1356                      );
1357     if (EFI_ERROR (Status)) {
1358       continue;
1359     }
1360     UsbIf   = USB_INTERFACE_FROM_USBIO (UsbIo);
1361 
1362     if (UsbBusIsWantedUsbIO (Bus, UsbIf)) {
1363       if (!UsbIf->IsManaged) {
1364         //
1365         // Recursively connect the wanted Usb Io handle
1366         //
1367         DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d\n", (UINT32)UsbGetCurrentTpl ()));
1368         Status            = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
1369         UsbIf->IsManaged  = (BOOLEAN)!EFI_ERROR (Status);
1370         DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl()));
1371       }
1372     }
1373   }
1374 
1375   return EFI_SUCCESS;
1376 }
1377 
1378