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