]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c
MdeModulePkg: Apply uncrustify changes
[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
e237e7ae 10#include "UsbBus.h"\r
11\r
ecb575d9 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
1436aea4 17USB_CLASS_FORMAT_DEVICE_PATH mAllUsbClassDevicePath = {\r
ecb575d9 18 {\r
19 {\r
20 MESSAGING_DEVICE_PATH,\r
21 MSG_USB_CLASS_DP,\r
faff3b47 22 {\r
1436aea4
MK
23 (UINT8)(sizeof (USB_CLASS_DEVICE_PATH)),\r
24 (UINT8)((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)\r
faff3b47 25 }\r
ecb575d9 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
faff3b47 37 {\r
38 END_DEVICE_PATH_LENGTH,\r
39 0\r
40 }\r
ecb575d9 41 }\r
42};\r
43\r
e237e7ae 44/**\r
8616fc4c 45 Get the capability of the host controller.\r
e237e7ae 46\r
8616fc4c 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
e237e7ae 51\r
8616fc4c 52 @retval EFI_SUCCESS The host controller capability is returned.\r
e237e7ae 53 @retval Others Failed to retrieve the host controller capability.\r
54\r
55**/\r
56EFI_STATUS\r
57UsbHcGetCapability (\r
1436aea4
MK
58 IN USB_BUS *UsbBus,\r
59 OUT UINT8 *MaxSpeed,\r
60 OUT UINT8 *NumOfPort,\r
61 OUT UINT8 *Is64BitCapable\r
e237e7ae 62 )\r
63{\r
1436aea4 64 EFI_STATUS Status;\r
e237e7ae 65\r
66 if (UsbBus->Usb2Hc != NULL) {\r
67 Status = UsbBus->Usb2Hc->GetCapability (\r
1436aea4
MK
68 UsbBus->Usb2Hc,\r
69 MaxSpeed,\r
70 NumOfPort,\r
71 Is64BitCapable\r
72 );\r
e237e7ae 73 } else {\r
74 Status = UsbBus->UsbHc->GetRootHubPortNumber (UsbBus->UsbHc, NumOfPort);\r
75\r
76 *MaxSpeed = EFI_USB_SPEED_FULL;\r
1436aea4 77 *Is64BitCapable = (UINT8)FALSE;\r
e237e7ae 78 }\r
79\r
80 return Status;\r
81}\r
82\r
e237e7ae 83/**\r
8616fc4c 84 Get the root hub port state.\r
e237e7ae 85\r
8616fc4c 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
e237e7ae 89\r
8616fc4c 90 @retval EFI_SUCCESS The root port state is returned in.\r
91 @retval Others Failed to get the root hub port state.\r
e237e7ae 92\r
93**/\r
94EFI_STATUS\r
95UsbHcGetRootHubPortStatus (\r
1436aea4
MK
96 IN USB_BUS *UsbBus,\r
97 IN UINT8 PortIndex,\r
98 OUT EFI_USB_PORT_STATUS *PortStatus\r
e237e7ae 99 )\r
100{\r
1436aea4 101 EFI_STATUS Status;\r
e237e7ae 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
e237e7ae 112/**\r
8616fc4c 113 Set the root hub port feature.\r
e237e7ae 114\r
8616fc4c 115 @param UsbBus The USB bus driver.\r
116 @param PortIndex The port index.\r
117 @param Feature The port feature to set.\r
e237e7ae 118\r
8616fc4c 119 @retval EFI_SUCCESS The port feature is set.\r
120 @retval Others Failed to set port feature.\r
e237e7ae 121\r
122**/\r
123EFI_STATUS\r
124UsbHcSetRootHubPortFeature (\r
1436aea4
MK
125 IN USB_BUS *UsbBus,\r
126 IN UINT8 PortIndex,\r
127 IN EFI_USB_PORT_FEATURE Feature\r
e237e7ae 128 )\r
129{\r
1436aea4 130 EFI_STATUS Status;\r
e237e7ae 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
e237e7ae 141/**\r
8616fc4c 142 Clear the root hub port feature.\r
e237e7ae 143\r
8616fc4c 144 @param UsbBus The USB bus driver.\r
145 @param PortIndex The port index.\r
146 @param Feature The port feature to clear.\r
e237e7ae 147\r
8616fc4c 148 @retval EFI_SUCCESS The port feature is clear.\r
149 @retval Others Failed to clear port feature.\r
e237e7ae 150\r
151**/\r
152EFI_STATUS\r
153UsbHcClearRootHubPortFeature (\r
1436aea4
MK
154 IN USB_BUS *UsbBus,\r
155 IN UINT8 PortIndex,\r
156 IN EFI_USB_PORT_FEATURE Feature\r
e237e7ae 157 )\r
158{\r
1436aea4 159 EFI_STATUS Status;\r
e237e7ae 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
e237e7ae 170/**\r
8616fc4c 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
e237e7ae 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
1436aea4
MK
204 EFI_STATUS Status;\r
205 BOOLEAN IsSlowDevice;\r
e237e7ae 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
e237e7ae 221 } else {\r
222 IsSlowDevice = (BOOLEAN)(EFI_USB_SPEED_LOW == DevSpeed);\r
1436aea4
MK
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
e237e7ae 235 }\r
236\r
237 return Status;\r
238}\r
239\r
e237e7ae 240/**\r
8616fc4c 241 Execute a bulk transfer to the device's endpoint.\r
e237e7ae 242\r
8616fc4c 243 @param UsbBus The USB bus driver.\r
244 @param DevAddr The target device address.\r
e237e7ae 245 @param EpAddr The target endpoint address, with direction encoded in\r
8616fc4c 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
e237e7ae 252 @param DataToggle On input, the initial data toggle to use, also return\r
253 the next toggle on output.\r
8616fc4c 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
e237e7ae 257\r
8616fc4c 258 @retval EFI_SUCCESS The bulk transfer is finished without error.\r
259 @retval Others Failed to execute bulk transfer, result in UsbResult.\r
e237e7ae 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[EFI_USB_MAX_BULK_BUFFER_NUM],\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
1436aea4 278 EFI_STATUS Status;\r
e237e7ae 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
1436aea4 300 (UINT8)MaxPacket,\r
e237e7ae 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
e237e7ae 312/**\r
8616fc4c 313 Queue or cancel an asynchronous interrupt transfer.\r
e237e7ae 314\r
8616fc4c 315 @param UsbBus The USB bus driver.\r
316 @param DevAddr The target device address.\r
e237e7ae 317 @param EpAddr The target endpoint address, with direction encoded in\r
8616fc4c 318 bit 7.\r
319 @param DevSpeed The device's speed.\r
320 @param MaxPacket The endpoint's max packet size.\r
e237e7ae 321 @param IsNewTransfer Whether this is a new request. If not, cancel the old\r
8616fc4c 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
e237e7ae 329\r
8616fc4c 330 @retval EFI_SUCCESS The asynchronous transfer is queued.\r
331 @retval Others Failed to queue the transfer.\r
e237e7ae 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
1436aea4
MK
350 EFI_STATUS Status;\r
351 BOOLEAN IsSlowDevice;\r
e237e7ae 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
1436aea4 376 (UINT8)MaxPacket,\r
e237e7ae 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
e237e7ae 389/**\r
8616fc4c 390 Execute a synchronous interrupt transfer to the target endpoint.\r
e237e7ae 391\r
8616fc4c 392 @param UsbBus The USB bus driver.\r
393 @param DevAddr The target device address.\r
e237e7ae 394 @param EpAddr The target endpoint address, with direction encoded in\r
8616fc4c 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
e237e7ae 400 @param DataToggle On input, the initial data toggle to use, also return\r
401 the next toggle on output.\r
8616fc4c 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
e237e7ae 405\r
8616fc4c 406 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.\r
407 @retval Others Failed to execute the synchronous interrupt transfer.\r
e237e7ae 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
1436aea4
MK
425 EFI_STATUS Status;\r
426 BOOLEAN IsSlowDevice;\r
e237e7ae 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
1436aea4
MK
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
e237e7ae 456 }\r
457\r
458 return Status;\r
459}\r
460\r
e237e7ae 461/**\r
8616fc4c 462 Open the USB host controller protocol BY_CHILD.\r
e237e7ae 463\r
8616fc4c 464 @param Bus The USB bus driver.\r
465 @param Child The child handle.\r
e237e7ae 466\r
8616fc4c 467 @return The open protocol return.\r
e237e7ae 468\r
469**/\r
470EFI_STATUS\r
471UsbOpenHostProtoByChild (\r
1436aea4
MK
472 IN USB_BUS *Bus,\r
473 IN EFI_HANDLE Child\r
e237e7ae 474 )\r
475{\r
1436aea4
MK
476 EFI_USB_HC_PROTOCOL *UsbHc;\r
477 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
478 EFI_STATUS Status;\r
e237e7ae 479\r
480 if (Bus->Usb2Hc != NULL) {\r
481 Status = gBS->OpenProtocol (\r
482 Bus->HostHandle,\r
483 &gEfiUsb2HcProtocolGuid,\r
1436aea4 484 (VOID **)&Usb2Hc,\r
e237e7ae 485 mUsbBusDriverBinding.DriverBindingHandle,\r
486 Child,\r
487 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
488 );\r
e237e7ae 489 } else {\r
490 Status = gBS->OpenProtocol (\r
491 Bus->HostHandle,\r
492 &gEfiUsbHcProtocolGuid,\r
1436aea4 493 (VOID **)&UsbHc,\r
e237e7ae 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
e237e7ae 503/**\r
8616fc4c 504 Close the USB host controller protocol BY_CHILD.\r
e237e7ae 505\r
8616fc4c 506 @param Bus The USB bus driver.\r
507 @param Child The child handle.\r
e237e7ae 508\r
e237e7ae 509**/\r
510VOID\r
511UsbCloseHostProtoByChild (\r
1436aea4
MK
512 IN USB_BUS *Bus,\r
513 IN EFI_HANDLE Child\r
e237e7ae 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
e237e7ae 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
e237e7ae 533/**\r
534 return the current TPL, copied from the EDKII glue lib.\r
535\r
8616fc4c 536 @param VOID.\r
e237e7ae 537\r
8616fc4c 538 @return Current TPL.\r
e237e7ae 539\r
540**/\r
541EFI_TPL\r
542UsbGetCurrentTpl (\r
543 VOID\r
544 )\r
545{\r
1436aea4 546 EFI_TPL Tpl;\r
e237e7ae 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
ecb575d9 554/**\r
8616fc4c 555 Create a new device path which only contain the first Usb part of the DevicePath.\r
ecb575d9 556\r
8616fc4c 557 @param DevicePath A full device path which contain the usb nodes.\r
ecb575d9 558\r
8616fc4c 559 @return A new device path which only contain the Usb part of the DevicePath.\r
ecb575d9 560\r
561**/\r
562EFI_DEVICE_PATH_PROTOCOL *\r
563EFIAPI\r
564GetUsbDPFromFullDP (\r
1436aea4 565 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
ecb575d9 566 )\r
567{\r
1436aea4
MK
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
ecb575d9 572\r
573 //\r
574 // Get the Usb part first Begin node in full device path\r
575 //\r
576 UsbDevicePathBeginPtr = DevicePath;\r
1436aea4 577 while ((!IsDevicePathEnd (UsbDevicePathBeginPtr)) &&\r
ecb575d9 578 ((UsbDevicePathBeginPtr->Type != MESSAGING_DEVICE_PATH) ||\r
1436aea4
MK
579 ( UsbDevicePathBeginPtr->SubType != MSG_USB_DP &&\r
580 UsbDevicePathBeginPtr->SubType != MSG_USB_CLASS_DP\r
ecb575d9 581 && UsbDevicePathBeginPtr->SubType != MSG_USB_WWID_DP\r
1436aea4
MK
582 )))\r
583 {\r
584 UsbDevicePathBeginPtr = NextDevicePathNode (UsbDevicePathBeginPtr);\r
ecb575d9 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
1436aea4 591 while ((!IsDevicePathEnd (UsbDevicePathEndPtr)) &&\r
ecb575d9 592 (UsbDevicePathEndPtr->Type == MESSAGING_DEVICE_PATH) &&\r
1436aea4
MK
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
ecb575d9 599 }\r
600\r
601 Size = GetDevicePathSize (UsbDevicePathBeginPtr);\r
602 Size -= GetDevicePathSize (UsbDevicePathEndPtr);\r
1436aea4 603 if (Size == 0) {\r
ecb575d9 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
1436aea4 619 UsbDevicePathEndPtr = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)UsbDevicePathPtr + Size);\r
ecb575d9 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
8616fc4c 627 @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM.\r
628 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list.\r
ecb575d9 629\r
8616fc4c 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
ecb575d9 632\r
633**/\r
634BOOLEAN\r
635EFIAPI\r
636SearchUsbDPInList (\r
1436aea4
MK
637 IN EFI_DEVICE_PATH_PROTOCOL *UsbDP,\r
638 IN LIST_ENTRY *UsbIoDPList\r
ecb575d9 639 )\r
640{\r
1436aea4
MK
641 LIST_ENTRY *ListIndex;\r
642 DEVICE_PATH_LIST_ITEM *ListItem;\r
643 BOOLEAN Found;\r
644 UINTN UsbDpDevicePathSize;\r
ecb575d9 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
1436aea4 653 Found = FALSE;\r
ecb575d9 654 ListIndex = UsbIoDPList->ForwardLink;\r
1436aea4
MK
655 while (ListIndex != UsbIoDPList) {\r
656 ListItem = CR (ListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);\r
ecb575d9 657 //\r
658 // Compare DEVICE_PATH_LIST_ITEM.DevicePath[]\r
659 //\r
660 ASSERT (ListItem->DevicePath != NULL);\r
661\r
1436aea4 662 UsbDpDevicePathSize = GetDevicePathSize (UsbDP);\r
ecb575d9 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
1436aea4 669\r
ecb575d9 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
8616fc4c 679 @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM.\r
680 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list.\r
ecb575d9 681\r
8616fc4c 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
ecb575d9 684\r
685**/\r
686EFI_STATUS\r
687EFIAPI\r
688AddUsbDPToList (\r
1436aea4
MK
689 IN EFI_DEVICE_PATH_PROTOCOL *UsbDP,\r
690 IN LIST_ENTRY *UsbIoDPList\r
ecb575d9 691 )\r
692{\r
1436aea4 693 DEVICE_PATH_LIST_ITEM *ListItem;\r
ecb575d9 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
1436aea4 702 if (SearchUsbDPInList (UsbDP, UsbIoDPList)) {\r
ecb575d9 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
1436aea4 711 ListItem->Signature = DEVICE_PATH_LIST_ITEM_SIGNATURE;\r
ecb575d9 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
8616fc4c 721 UsbClassDevicePathPtr whose is a short form usb class device path.\r
ecb575d9 722\r
8616fc4c 723 @param UsbClassDevicePathPtr a short form usb class device path.\r
724 @param UsbIf a usb device interface.\r
ecb575d9 725\r
8616fc4c 726 @retval TRUE the usb device match the usb class.\r
727 @retval FALSE the usb device does not match the usb class.\r
ecb575d9 728\r
729**/\r
730BOOLEAN\r
731EFIAPI\r
732MatchUsbClass (\r
1436aea4
MK
733 IN USB_CLASS_DEVICE_PATH *UsbClassDevicePathPtr,\r
734 IN USB_INTERFACE *UsbIf\r
ecb575d9 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
ecb575d9 741 if ((UsbClassDevicePathPtr->Header.Type != MESSAGING_DEVICE_PATH) ||\r
1436aea4
MK
742 (UsbClassDevicePathPtr->Header.SubType != MSG_USB_CLASS_DP))\r
743 {\r
ecb575d9 744 ASSERT (0);\r
745 return FALSE;\r
746 }\r
747\r
1436aea4 748 IfDesc = UsbIf->IfDesc;\r
a1b749d0 749 ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);\r
1436aea4
MK
750 ActIfDesc = &(IfDesc->Settings[IfDesc->ActiveIndex]->Desc);\r
751 DevDesc = &(UsbIf->Device->DevDesc->Desc);\r
ecb575d9 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
13a623cf 757 // In addition, hub interface is always matched for this policy.\r
ecb575d9 758 //\r
759 if ((ActIfDesc->InterfaceClass == USB_HUB_CLASS_CODE) &&\r
1436aea4
MK
760 (ActIfDesc->InterfaceSubClass == USB_HUB_SUBCLASS_CODE))\r
761 {\r
ecb575d9 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
1436aea4
MK
768 if (((UsbClassDevicePathPtr->VendorId == 0xffff) || (UsbClassDevicePathPtr->VendorId == DevDesc->IdVendor)) &&\r
769 ((UsbClassDevicePathPtr->ProductId == 0xffff) || (UsbClassDevicePathPtr->ProductId == DevDesc->IdProduct)))\r
770 {\r
ecb575d9 771 //\r
84909ad4 772 // If Class in Device Descriptor is set to 0, the counterparts in interface should be checked.\r
ecb575d9 773 //\r
84909ad4 774 if (DevDesc->DeviceClass == 0) {\r
1436aea4
MK
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
ecb575d9 782 return TRUE;\r
783 }\r
1436aea4
MK
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
ecb575d9 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
8616fc4c 800 UsbWWIDDevicePathPtr whose is a short form usb WWID device path.\r
ecb575d9 801\r
8616fc4c 802 @param UsbWWIDDevicePathPtr a short form usb WWID device path.\r
803 @param UsbIf a usb device interface.\r
ecb575d9 804\r
8616fc4c 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
ecb575d9 807\r
808**/\r
ecb575d9 809BOOLEAN\r
810MatchUsbWwid (\r
1436aea4
MK
811 IN USB_WWID_DEVICE_PATH *UsbWWIDDevicePathPtr,\r
812 IN USB_INTERFACE *UsbIf\r
ecb575d9 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
84909ad4 819 UINT16 Index;\r
820 CHAR16 *CompareStr;\r
821 UINTN CompareLen;\r
822 UINTN Length;\r
ecb575d9 823\r
824 if ((UsbWWIDDevicePathPtr->Header.Type != MESSAGING_DEVICE_PATH) ||\r
1436aea4
MK
825 (UsbWWIDDevicePathPtr->Header.SubType != MSG_USB_WWID_DP))\r
826 {\r
ecb575d9 827 ASSERT (0);\r
828 return FALSE;\r
829 }\r
830\r
1436aea4 831 IfDesc = UsbIf->IfDesc;\r
a1b749d0 832 ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);\r
1436aea4
MK
833 ActIfDesc = &(IfDesc->Settings[IfDesc->ActiveIndex]->Desc);\r
834 DevDesc = &(UsbIf->Device->DevDesc->Desc);\r
ecb575d9 835\r
836 //\r
84909ad4 837 // In addition, Hub interface is always matched for this policy.\r
ecb575d9 838 //\r
839 if ((ActIfDesc->InterfaceClass == USB_HUB_CLASS_CODE) &&\r
1436aea4
MK
840 (ActIfDesc->InterfaceSubClass == USB_HUB_SUBCLASS_CODE))\r
841 {\r
ecb575d9 842 return TRUE;\r
843 }\r
84909ad4 844\r
845 //\r
846 // Check Vendor Id, Product Id and Interface Number.\r
ecb575d9 847 //\r
84909ad4 848 if ((DevDesc->IdVendor != UsbWWIDDevicePathPtr->VendorId) ||\r
849 (DevDesc->IdProduct != UsbWWIDDevicePathPtr->ProductId) ||\r
1436aea4
MK
850 (ActIfDesc->InterfaceNumber != UsbWWIDDevicePathPtr->InterfaceNumber))\r
851 {\r
84909ad4 852 return FALSE;\r
853 }\r
854\r
ecb575d9 855 //\r
84909ad4 856 // Check SerialNumber.\r
ecb575d9 857 //\r
84909ad4 858 if (DevDesc->StrSerialNumber == 0) {\r
859 return FALSE;\r
860 }\r
ecb575d9 861\r
84909ad4 862 //\r
863 // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.\r
864 //\r
1436aea4 865 CompareStr = (CHAR16 *)(UINTN)(UsbWWIDDevicePathPtr + 1);\r
84909ad4 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
1436aea4
MK
882 (CompareMem (StrDesc->String + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0))\r
883 {\r
84909ad4 884 return TRUE;\r
885 }\r
ecb575d9 886 }\r
887\r
888 return FALSE;\r
889}\r
890\r
891/**\r
8616fc4c 892 Free a DEVICE_PATH_LIST_ITEM list.\r
ecb575d9 893\r
8616fc4c 894 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list pointer.\r
ecb575d9 895\r
8616fc4c 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
ecb575d9 898\r
899**/\r
900EFI_STATUS\r
901EFIAPI\r
902UsbBusFreeUsbDPList (\r
1436aea4 903 IN LIST_ENTRY *UsbIoDPList\r
ecb575d9 904 )\r
905{\r
1436aea4
MK
906 LIST_ENTRY *ListIndex;\r
907 DEVICE_PATH_LIST_ITEM *ListItem;\r
ecb575d9 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
1436aea4
MK
917 while (ListIndex != UsbIoDPList) {\r
918 ListItem = CR (ListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);\r
ecb575d9 919 //\r
920 // Free DEVICE_PATH_LIST_ITEM.DevicePath[]\r
921 //\r
1436aea4
MK
922 if (ListItem->DevicePath != NULL) {\r
923 FreePool (ListItem->DevicePath);\r
ecb575d9 924 }\r
1436aea4 925\r
ecb575d9 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
8616fc4c 940 RemainingDevicePath in a Usb bus which is indicated by UsbBusId.\r
ecb575d9 941\r
8616fc4c 942 @param UsbBusId Point to EFI_USB_BUS_PROTOCOL interface.\r
943 @param RemainingDevicePath The remaining device patch.\r
ecb575d9 944\r
8616fc4c 945 @retval EFI_SUCCESS Add operation is successful.\r
946 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
ecb575d9 947\r
948**/\r
949EFI_STATUS\r
950EFIAPI\r
951UsbBusAddWantedUsbIoDP (\r
1436aea4
MK
952 IN EFI_USB_BUS_PROTOCOL *UsbBusId,\r
953 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
ecb575d9 954 )\r
955{\r
1436aea4
MK
956 USB_BUS *Bus;\r
957 EFI_STATUS Status;\r
958 EFI_DEVICE_PATH_PROTOCOL *DevicePathPtr;\r
ecb575d9 959\r
960 //\r
961 // Check whether remaining device path is valid\r
962 //\r
1436aea4 963 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {\r
ecb575d9 964 if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) ||\r
1436aea4
MK
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
ecb575d9 970 return EFI_INVALID_PARAMETER;\r
971 }\r
972 }\r
973\r
1436aea4 974 if (UsbBusId == NULL) {\r
ecb575d9 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
af4a6385 982 // RemainingDevicePath == NULL means all Usb devices in this bus are wanted.\r
ecb575d9 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
1436aea4 988 DevicePathPtr = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *)&mAllUsbClassDevicePath);\r
af4a6385 989 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
ecb575d9 990 //\r
d1102dba 991 // If RemainingDevicePath isn't the End of Device Path Node,\r
ecb575d9 992 // Create new Usb device path according to the usb part in remaining device path\r
993 //\r
994 DevicePathPtr = GetUsbDPFromFullDP (RemainingDevicePath);\r
af4a6385 995 } else {\r
996 //\r
997 // If RemainingDevicePath is the End of Device Path Node,\r
13a623cf 998 // skip enumerate any device and return EFI_SUCCESS\r
d1102dba 999 //\r
af4a6385 1000 return EFI_SUCCESS;\r
ecb575d9 1001 }\r
1002\r
1003 ASSERT (DevicePathPtr != NULL);\r
1004 Status = AddUsbDPToList (DevicePathPtr, &Bus->WantedUsbIoDPList);\r
1005 ASSERT (!EFI_ERROR (Status));\r
af4a6385 1006 FreePool (DevicePathPtr);\r
ecb575d9 1007 return EFI_SUCCESS;\r
1008}\r
1009\r
1010/**\r
8616fc4c 1011 Check whether a usb child device is the wanted device in a bus.\r
ecb575d9 1012\r
8616fc4c 1013 @param Bus The Usb bus's private data pointer.\r
13a623cf 1014 @param UsbIf The usb child device interface.\r
ecb575d9 1015\r
8616fc4c 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
ecb575d9 1018\r
1019**/\r
1020BOOLEAN\r
1021EFIAPI\r
1022UsbBusIsWantedUsbIO (\r
1436aea4
MK
1023 IN USB_BUS *Bus,\r
1024 IN USB_INTERFACE *UsbIf\r
ecb575d9 1025 )\r
1026{\r
1436aea4
MK
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
ecb575d9 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
1436aea4 1040\r
ecb575d9 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
1436aea4 1051 if (SearchUsbDPInList ((EFI_DEVICE_PATH_PROTOCOL *)&mAllUsbClassDevicePath, &Bus->WantedUsbIoDPList)) {\r
ecb575d9 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
1436aea4 1065 DoConvert = FALSE;\r
ecb575d9 1066 WantedListIndex = WantedUsbIoDPListPtr->ForwardLink;\r
1436aea4
MK
1067 while (WantedListIndex != WantedUsbIoDPListPtr) {\r
1068 WantedListItem = CR (WantedListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);\r
ecb575d9 1069 ASSERT (WantedListItem->DevicePath->Type == MESSAGING_DEVICE_PATH);\r
1070 switch (WantedListItem->DevicePath->SubType) {\r
1436aea4
MK
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
ecb575d9 1088 DoConvert = TRUE;\r
1089 }\r
1436aea4
MK
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
ecb575d9 1101 }\r
1102\r
1103 if (DoConvert) {\r
1104 break;\r
1105 }\r
1106\r
1107 WantedListIndex = WantedListIndex->ForwardLink;\r
1108 }\r
1436aea4 1109\r
ecb575d9 1110 gBS->FreePool (DevicePathPtr);\r
1111\r
1112 //\r
1113 // Check whether the new Usb device path is wanted\r
1114 //\r
1436aea4 1115 if (DoConvert) {\r
ecb575d9 1116 return TRUE;\r
1117 } else {\r
1118 return FALSE;\r
1119 }\r
1120}\r
1121\r
1122/**\r
13a623cf 1123 Recursively connect every wanted usb child device to ensure they all fully connected.\r
8616fc4c 1124 Check all the child Usb IO handles in this bus, recursively connecte if it is wanted usb child device.\r
ecb575d9 1125\r
8616fc4c 1126 @param UsbBusId Point to EFI_USB_BUS_PROTOCOL interface.\r
ecb575d9 1127\r
8616fc4c 1128 @retval EFI_SUCCESS Connect is done successfully.\r
1129 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
ecb575d9 1130\r
1131**/\r
1132EFI_STATUS\r
1133EFIAPI\r
1134UsbBusRecursivelyConnectWantedUsbIo (\r
1436aea4 1135 IN EFI_USB_BUS_PROTOCOL *UsbBusId\r
ecb575d9 1136 )\r
1137{\r
1436aea4
MK
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
ecb575d9 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
1436aea4
MK
1157 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer);\r
1158 if ((Status == EFI_NOT_FOUND) || (UsbIoHandleCount == 0)) {\r
ecb575d9 1159 return EFI_SUCCESS;\r
1160 }\r
1436aea4 1161\r
ecb575d9 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
1436aea4
MK
1170 Status = gBS->HandleProtocol (UsbIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *)&UsbIoDevicePath);\r
1171 if (EFI_ERROR (Status) || (UsbIoDevicePath == NULL)) {\r
ecb575d9 1172 continue;\r
1173 }\r
1436aea4 1174\r
ecb575d9 1175 if (CompareMem (\r
1436aea4
MK
1176 UsbIoDevicePath,\r
1177 Bus->DevicePath,\r
1178 (GetDevicePathSize (Bus->DevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL))\r
1179 ) != 0)\r
1180 {\r
ecb575d9 1181 continue;\r
1182 }\r
1183\r
1184 //\r
1185 // Get the child Usb IO interface\r
1186 //\r
1436aea4
MK
1187 Status = gBS->HandleProtocol (\r
1188 UsbIoBuffer[Index],\r
1189 &gEfiUsbIoProtocolGuid,\r
1190 (VOID **)&UsbIo\r
1191 );\r
ecb575d9 1192 if (EFI_ERROR (Status)) {\r
1193 continue;\r
1194 }\r
1436aea4
MK
1195\r
1196 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);\r
ecb575d9 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
87000d77 1203 DEBUG ((DEBUG_INFO, "UsbBusRecursivelyConnectWantedUsbIo: TPL before connect is %d\n", (UINT32)UsbGetCurrentTpl ()));\r
1436aea4
MK
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
ecb575d9 1207 }\r
1208 }\r
1209 }\r
1210\r
2a09778d
AP
1211 FreePool (UsbIoBuffer);\r
1212\r
ecb575d9 1213 return EFI_SUCCESS;\r
1214}\r