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