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