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