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