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