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