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