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