TianoCore EDK2 master
Loading...
Searching...
No Matches
UsbEnumer.c
Go to the documentation of this file.
1
10#include "UsbBus.h"
11
23 IN USB_INTERFACE *UsbIf,
24 IN UINT8 EpAddr
25 )
26{
27 USB_ENDPOINT_DESC *EpDesc;
28 UINT8 Index;
29 UINT8 NumEndpoints;
30
31 NumEndpoints = UsbIf->IfSetting->Desc.NumEndpoints;
32
33 for (Index = 0; Index < NumEndpoints; Index++) {
34 EpDesc = UsbIf->IfSetting->Endpoints[Index];
35
36 if (EpDesc->Desc.EndpointAddress == EpAddr) {
37 return EpDesc;
38 }
39 }
40
41 return NULL;
42}
43
54 IN USB_INTERFACE *UsbIf
55 )
56{
57 EFI_STATUS Status;
58
59 UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
60
61 Status = gBS->UninstallMultipleProtocolInterfaces (
62 UsbIf->Handle,
63 &gEfiDevicePathProtocolGuid,
64 UsbIf->DevicePath,
65 &gEfiUsbIoProtocolGuid,
66 &UsbIf->UsbIo,
67 NULL
68 );
69 if (!EFI_ERROR (Status)) {
70 if (UsbIf->DevicePath != NULL) {
71 FreePool (UsbIf->DevicePath);
72 }
73
74 FreePool (UsbIf);
75 } else {
76 UsbOpenHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
77 }
78
79 return Status;
80}
81
94 IN USB_DEVICE *Device,
96 )
97{
98 USB_DEVICE_PATH UsbNode;
99 USB_INTERFACE *UsbIf;
100 USB_INTERFACE *HubIf;
101 EFI_STATUS Status;
102
103 UsbIf = AllocateZeroPool (sizeof (USB_INTERFACE));
104
105 if (UsbIf == NULL) {
106 return NULL;
107 }
108
109 UsbIf->Signature = USB_INTERFACE_SIGNATURE;
110 UsbIf->Device = Device;
111 UsbIf->IfDesc = IfDesc;
112 ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);
113 UsbIf->IfSetting = IfDesc->Settings[IfDesc->ActiveIndex];
114
115 CopyMem (
116 &(UsbIf->UsbIo),
117 &mUsbIoProtocol,
118 sizeof (EFI_USB_IO_PROTOCOL)
119 );
120
121 //
122 // Install protocols for USBIO and device path
123 //
124 UsbNode.Header.Type = MESSAGING_DEVICE_PATH;
125 UsbNode.Header.SubType = MSG_USB_DP;
126 UsbNode.ParentPortNumber = Device->ParentPort;
127 UsbNode.InterfaceNumber = UsbIf->IfSetting->Desc.InterfaceNumber;
128
129 SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
130
131 HubIf = Device->ParentIf;
132 ASSERT (HubIf != NULL);
133
134 UsbIf->DevicePath = AppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header);
135
136 if (UsbIf->DevicePath == NULL) {
137 DEBUG ((DEBUG_ERROR, "UsbCreateInterface: failed to create device path\n"));
138
139 Status = EFI_OUT_OF_RESOURCES;
140 goto ON_ERROR;
141 }
142
143 Status = gBS->InstallMultipleProtocolInterfaces (
144 &UsbIf->Handle,
145 &gEfiDevicePathProtocolGuid,
146 UsbIf->DevicePath,
147 &gEfiUsbIoProtocolGuid,
148 &UsbIf->UsbIo,
149 NULL
150 );
151
152 if (EFI_ERROR (Status)) {
153 DEBUG ((DEBUG_ERROR, "UsbCreateInterface: failed to install UsbIo - %r\n", Status));
154 goto ON_ERROR;
155 }
156
157 //
158 // Open USB Host Controller Protocol by Child
159 //
160 Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);
161
162 if (EFI_ERROR (Status)) {
163 gBS->UninstallMultipleProtocolInterfaces (
164 UsbIf->Handle,
165 &gEfiDevicePathProtocolGuid,
166 UsbIf->DevicePath,
167 &gEfiUsbIoProtocolGuid,
168 &UsbIf->UsbIo,
169 NULL
170 );
171
172 DEBUG ((DEBUG_ERROR, "UsbCreateInterface: failed to open host for child - %r\n", Status));
173 goto ON_ERROR;
174 }
175
176 return UsbIf;
177
178ON_ERROR:
179 if (UsbIf->DevicePath != NULL) {
180 FreePool (UsbIf->DevicePath);
181 }
182
183 FreePool (UsbIf);
184 return NULL;
185}
186
193VOID
195 IN USB_DEVICE *Device
196 )
197{
198 if (Device->DevDesc != NULL) {
199 UsbFreeDevDesc (Device->DevDesc);
200 }
201
202 gBS->FreePool (Device);
203}
204
216 IN USB_INTERFACE *ParentIf,
217 IN UINT8 ParentPort
218 )
219{
220 USB_DEVICE *Device;
221
222 ASSERT (ParentIf != NULL);
223
224 Device = AllocateZeroPool (sizeof (USB_DEVICE));
225
226 if (Device == NULL) {
227 return NULL;
228 }
229
230 Device->Bus = ParentIf->Device->Bus;
231 Device->MaxPacket0 = 8;
232 Device->ParentAddr = ParentIf->Device->Address;
233 Device->ParentIf = ParentIf;
234 Device->ParentPort = ParentPort;
235 Device->Tier = (UINT8)(ParentIf->Device->Tier + 1);
236 return Device;
237}
238
251 IN USB_INTERFACE *UsbIf
252 )
253{
254 EFI_STATUS Status;
255 EFI_TPL OldTpl;
256
257 Status = EFI_SUCCESS;
258
259 //
260 // Hub is maintained by the USB bus driver. Otherwise try to
261 // connect drivers with this interface
262 //
263 if (UsbIsHubInterface (UsbIf)) {
264 DEBUG ((DEBUG_INFO, "UsbConnectDriver: found a hub device\n"));
265 Status = mUsbHubApi.Init (UsbIf);
266 } else {
267 //
268 // This function is called in both UsbIoControlTransfer and
269 // the timer callback in hub enumeration. So, at least it is
270 // called at TPL_CALLBACK. Some driver sitting on USB has
271 // twisted TPL used. It should be no problem for us to connect
272 // or disconnect at CALLBACK.
273 //
274
275 //
276 // Only recursively wanted usb child device
277 //
278 if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {
279 OldTpl = UsbGetCurrentTpl ();
280 DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL before connect is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
281
282 gBS->RestoreTPL (TPL_CALLBACK);
283
284 Status = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
285 UsbIf->IsManaged = (BOOLEAN) !EFI_ERROR (Status);
286
287 DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl ()));
288 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
289
290 gBS->RaiseTPL (OldTpl);
291 }
292 }
293
294 return Status;
295}
296
312 IN USB_INTERFACE_DESC *IfDesc,
313 IN UINT8 Alternate
314 )
315{
316 USB_INTERFACE_SETTING *Setting;
317 UINTN Index;
318
319 //
320 // Locate the active alternate setting
321 //
322 Setting = NULL;
323
324 for (Index = 0; Index < IfDesc->NumOfSetting; Index++) {
325 ASSERT (Index < USB_MAX_INTERFACE_SETTING);
326 Setting = IfDesc->Settings[Index];
327
328 if (Setting->Desc.AlternateSetting == Alternate) {
329 break;
330 }
331 }
332
333 if (Index == IfDesc->NumOfSetting) {
334 return EFI_NOT_FOUND;
335 }
336
337 IfDesc->ActiveIndex = Index;
338
339 ASSERT (Setting != NULL);
340 DEBUG ((
341 DEBUG_INFO,
342 "UsbSelectSetting: setting %d selected for interface %d\n",
343 Alternate,
344 Setting->Desc.InterfaceNumber
345 ));
346
347 //
348 // Reset the endpoint toggle to zero
349 //
350 for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {
351 Setting->Endpoints[Index]->Toggle = 0;
352 }
353
354 return EFI_SUCCESS;
355}
356
371 IN USB_DEVICE *Device,
372 IN UINT8 ConfigValue
373 )
374{
375 USB_DEVICE_DESC *DevDesc;
376 USB_CONFIG_DESC *ConfigDesc;
377 USB_INTERFACE_DESC *IfDesc;
378 USB_INTERFACE *UsbIf;
379 EFI_STATUS Status;
380 UINT8 Index;
381
382 //
383 // Locate the active config, then set the device's pointer
384 //
385 DevDesc = Device->DevDesc;
386 ConfigDesc = NULL;
387
388 for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {
389 ConfigDesc = DevDesc->Configs[Index];
390
391 if (ConfigDesc->Desc.ConfigurationValue == ConfigValue) {
392 break;
393 }
394 }
395
396 if (Index == DevDesc->Desc.NumConfigurations) {
397 return EFI_NOT_FOUND;
398 }
399
400 Device->ActiveConfig = ConfigDesc;
401
402 DEBUG ((
403 DEBUG_INFO,
404 "UsbSelectConfig: config %d selected for device %d\n",
405 ConfigValue,
406 Device->Address
407 ));
408
409 //
410 // Create interfaces for each USB interface descriptor.
411 //
412 for (Index = 0; Index < ConfigDesc->Desc.NumInterfaces; Index++) {
413 //
414 // First select the default interface setting, and reset
415 // the endpoint toggles to zero for its endpoints.
416 //
417 IfDesc = ConfigDesc->Interfaces[Index];
418 UsbSelectSetting (IfDesc, IfDesc->Settings[0]->Desc.AlternateSetting);
419
420 //
421 // Create a USB_INTERFACE and install USB_IO and other protocols
422 //
423 UsbIf = UsbCreateInterface (Device, ConfigDesc->Interfaces[Index]);
424
425 if (UsbIf == NULL) {
426 Device->NumOfInterface = Index;
427 return EFI_OUT_OF_RESOURCES;
428 }
429
430 ASSERT (Index < USB_MAX_INTERFACE);
431 Device->Interfaces[Index] = UsbIf;
432
433 //
434 // Connect the device to drivers, if it failed, ignore
435 // the error. Don't let the unsupported interfaces to block
436 // the supported interfaces.
437 //
438 Status = UsbConnectDriver (UsbIf);
439
440 if (EFI_ERROR (Status)) {
441 DEBUG ((
442 DEBUG_WARN,
443 "UsbSelectConfig: failed to connect driver - %r, ignored\n",
444 Status
445 ));
446 }
447 }
448
449 Device->NumOfInterface = Index;
450
451 return EFI_SUCCESS;
452}
453
462 IN USB_INTERFACE *UsbIf
463 )
464{
465 EFI_TPL OldTpl;
466 EFI_STATUS Status;
467
468 //
469 // Release the hub if it's a hub controller, otherwise
470 // disconnect the driver if it is managed by other drivers.
471 //
472 Status = EFI_SUCCESS;
473 if (UsbIf->IsHub) {
474 Status = UsbIf->HubApi->Release (UsbIf);
475 } else if (UsbIf->IsManaged) {
476 //
477 // This function is called in both UsbIoControlTransfer and
478 // the timer callback in hub enumeration. So, at least it is
479 // called at TPL_CALLBACK. Some driver sitting on USB has
480 // twisted TPL used. It should be no problem for us to connect
481 // or disconnect at CALLBACK.
482 //
483 OldTpl = UsbGetCurrentTpl ();
484 DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: old TPL is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
485
486 gBS->RestoreTPL (TPL_CALLBACK);
487
488 Status = gBS->DisconnectController (UsbIf->Handle, NULL, NULL);
489 if (!EFI_ERROR (Status)) {
490 UsbIf->IsManaged = FALSE;
491 }
492
493 DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl (), Status));
494 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
495
496 gBS->RaiseTPL (OldTpl);
497 }
498
499 return Status;
500}
501
510 IN USB_DEVICE *Device
511 )
512{
513 USB_INTERFACE *UsbIf;
514 UINTN Index;
515 EFI_STATUS Status;
516 EFI_STATUS ReturnStatus;
517
518 //
519 // Remove each interface of the device
520 //
521 ReturnStatus = EFI_SUCCESS;
522 for (Index = 0; Index < Device->NumOfInterface; Index++) {
523 ASSERT (Index < USB_MAX_INTERFACE);
524 UsbIf = Device->Interfaces[Index];
525
526 if (UsbIf == NULL) {
527 continue;
528 }
529
530 Status = UsbDisconnectDriver (UsbIf);
531 if (!EFI_ERROR (Status)) {
532 Status = UsbFreeInterface (UsbIf);
533 if (EFI_ERROR (Status)) {
534 UsbConnectDriver (UsbIf);
535 }
536 }
537
538 if (!EFI_ERROR (Status)) {
539 Device->Interfaces[Index] = NULL;
540 } else {
541 ReturnStatus = Status;
542 }
543 }
544
545 Device->ActiveConfig = NULL;
546 return ReturnStatus;
547}
548
559 IN USB_DEVICE *Device
560 )
561{
562 USB_BUS *Bus;
564 EFI_STATUS Status;
565 EFI_STATUS ReturnStatus;
566 UINTN Index;
567
568 Bus = Device->Bus;
569
570 //
571 // Remove all the devices on its downstream ports. Search from devices[1].
572 // Devices[0] is the root hub.
573 //
574 ReturnStatus = EFI_SUCCESS;
575 for (Index = 1; Index < Bus->MaxDevices; Index++) {
576 Child = Bus->Devices[Index];
577
578 if ((Child == NULL) || (Child->ParentAddr != Device->Address)) {
579 continue;
580 }
581
582 Status = UsbRemoveDevice (Child);
583
584 if (!EFI_ERROR (Status)) {
585 Bus->Devices[Index] = NULL;
586 } else {
587 Bus->Devices[Index]->DisconnectFail = TRUE;
588 ReturnStatus = Status;
589 DEBUG ((DEBUG_INFO, "UsbRemoveDevice: failed to remove child %p at parent %p\n", Child, Device));
590 }
591 }
592
593 if (EFI_ERROR (ReturnStatus)) {
594 return ReturnStatus;
595 }
596
597 Status = UsbRemoveConfig (Device);
598
599 if (!EFI_ERROR (Status)) {
600 DEBUG ((DEBUG_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address));
601
602 ASSERT (Device->Address < Bus->MaxDevices);
603 Bus->Devices[Device->Address] = NULL;
604 UsbFreeDevice (Device);
605 } else {
606 Bus->Devices[Device->Address]->DisconnectFail = TRUE;
607 }
608
609 return Status;
610}
611
623 IN USB_INTERFACE *HubIf,
624 IN UINT8 Port
625 )
626{
627 USB_DEVICE *Device;
628 USB_BUS *Bus;
629 UINTN Index;
630
631 Bus = HubIf->Device->Bus;
632
633 //
634 // Start checking from device 1, device 0 is the root hub
635 //
636 for (Index = 1; Index < Bus->MaxDevices; Index++) {
637 Device = Bus->Devices[Index];
638
639 if ((Device != NULL) && (Device->ParentAddr == HubIf->Device->Address) &&
640 (Device->ParentPort == Port))
641 {
642 return Device;
643 }
644 }
645
646 return NULL;
647}
648
663 IN USB_INTERFACE *HubIf,
664 IN UINT8 Port,
665 IN BOOLEAN ResetIsNeeded
666 )
667{
668 USB_BUS *Bus;
669 USB_HUB_API *HubApi;
671 USB_DEVICE *Parent;
672 EFI_USB_PORT_STATUS PortState;
673 UINTN Address;
674 UINT8 Config;
675 EFI_STATUS Status;
676
677 Parent = HubIf->Device;
678 Bus = Parent->Bus;
679 HubApi = HubIf->HubApi;
680 Address = Bus->MaxDevices;
681
682 gBS->Stall (USB_WAIT_PORT_STABLE_STALL);
683
684 //
685 // Hub resets the device for at least 10 milliseconds.
686 // Host learns device speed. If device is of low/full speed
687 // and the hub is a EHCI root hub, ResetPort will release
688 // the device to its companion UHCI and return an error.
689 //
690 if (ResetIsNeeded) {
691 Status = HubApi->ResetPort (HubIf, Port);
692 if (EFI_ERROR (Status)) {
693 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));
694
695 return Status;
696 }
697
698 DEBUG ((DEBUG_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port));
699 } else {
700 DEBUG ((DEBUG_INFO, "UsbEnumerateNewDev: hub port %d reset is skipped\n", Port));
701 }
702
703 Child = UsbCreateDevice (HubIf, Port);
704
705 if (Child == NULL) {
706 return EFI_OUT_OF_RESOURCES;
707 }
708
709 //
710 // OK, now identify the device speed. After reset, hub
711 // fully knows the actual device speed.
712 //
713 Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
714
715 if (EFI_ERROR (Status)) {
716 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to get speed of port %d\n", Port));
717 goto ON_ERROR;
718 }
719
720 if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
721 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: No device present at port %d\n", Port));
722 Status = EFI_NOT_FOUND;
723 goto ON_ERROR;
724 } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {
725 Child->Speed = EFI_USB_SPEED_SUPER;
726 Child->MaxPacket0 = 512;
727 } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
728 Child->Speed = EFI_USB_SPEED_HIGH;
729 Child->MaxPacket0 = 64;
730 } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
731 Child->Speed = EFI_USB_SPEED_LOW;
732 Child->MaxPacket0 = 8;
733 } else {
734 Child->Speed = EFI_USB_SPEED_FULL;
735 Child->MaxPacket0 = 8;
736 }
737
738 DEBUG ((DEBUG_INFO, "UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));
739
740 if (((Child->Speed == EFI_USB_SPEED_LOW) || (Child->Speed == EFI_USB_SPEED_FULL)) &&
741 (Parent->Speed == EFI_USB_SPEED_HIGH))
742 {
743 //
744 // If the child is a low or full speed device, it is necessary to
745 // set the transaction translator. Port TT is 1-based.
746 // This is quite simple:
747 // 1. if parent is of high speed, then parent is our translator
748 // 2. otherwise use parent's translator.
749 //
750 Child->Translator.TranslatorHubAddress = Parent->Address;
751 Child->Translator.TranslatorPortNumber = (UINT8)(Port + 1);
752 } else {
753 Child->Translator = Parent->Translator;
754 }
755
756 DEBUG ((
757 DEBUG_INFO,
758 "UsbEnumerateNewDev: device uses translator (%d, %d)\n",
759 Child->Translator.TranslatorHubAddress,
760 Child->Translator.TranslatorPortNumber
761 ));
762
763 //
764 // After port is reset, hub establishes a signal path between
765 // the device and host (DEFAULT state). Device's registers are
766 // reset, use default address 0 (host enumerates one device at
767 // a time) , and ready to respond to control transfer at EP 0.
768 //
769
770 //
771 // Host assigns an address to the device. Device completes the
772 // status stage with default address, then switches to new address.
773 // ADDRESS state. Address zero is reserved for root hub.
774 //
775 ASSERT (Bus->MaxDevices <= 256);
776 for (Address = 1; Address < Bus->MaxDevices; Address++) {
777 if (Bus->Devices[Address] == NULL) {
778 break;
779 }
780 }
781
782 if (Address >= Bus->MaxDevices) {
783 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: address pool is full for port %d\n", Port));
784
785 Status = EFI_ACCESS_DENIED;
786 goto ON_ERROR;
787 }
788
789 Status = UsbSetAddress (Child, (UINT8)Address);
790 Child->Address = (UINT8)Address;
791 Bus->Devices[Address] = Child;
792
793 if (EFI_ERROR (Status)) {
794 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status));
795 goto ON_ERROR;
796 }
797
798 gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
799
800 DEBUG ((DEBUG_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));
801
802 //
803 // Host sends a Get_Descriptor request to learn the max packet
804 // size of default pipe (only part of the device's descriptor).
805 //
806 Status = UsbGetMaxPacketSize0 (Child);
807
808 if (EFI_ERROR (Status)) {
809 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status));
810 goto ON_ERROR;
811 }
812
813 DEBUG ((DEBUG_INFO, "UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0));
814
815 //
816 // Host learns about the device's abilities by requesting device's
817 // entire descriptions.
818 //
819 Status = UsbBuildDescTable (Child);
820
821 if (EFI_ERROR (Status)) {
822 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status));
823 goto ON_ERROR;
824 }
825
826 //
827 // Select a default configuration: UEFI must set the configuration
828 // before the driver can connect to the device.
829 //
830 Config = Child->DevDesc->Configs[0]->Desc.ConfigurationValue;
831 Status = UsbSetConfig (Child, Config);
832
833 if (EFI_ERROR (Status)) {
834 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status));
835 goto ON_ERROR;
836 }
837
838 DEBUG ((DEBUG_INFO, "UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address));
839
840 //
841 // Host assigns and loads a device driver.
842 //
843 Status = UsbSelectConfig (Child, Config);
844
845 if (EFI_ERROR (Status)) {
846 DEBUG ((DEBUG_ERROR, "UsbEnumerateNewDev: failed to create interfaces - %r\n", Status));
847 goto ON_ERROR;
848 }
849
850 //
851 // Report Status Code to indicate USB device has been detected by hotplug
852 //
855 (EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG),
856 Bus->DevicePath
857 );
858 return EFI_SUCCESS;
859
860ON_ERROR:
861 //
862 // If reach here, it means the enumeration process on a given port is interrupted due to error.
863 // The s/w resources, including the assigned address(Address) and the allocated usb device data
864 // structure(Bus->Devices[Address]), will NOT be freed here. These resources will be freed when
865 // the device is unplugged from the port or DriverBindingStop() is invoked.
866 //
867 // This way is used to co-work with the lower layer EDKII UHCI/EHCI/XHCI host controller driver.
868 // It's mainly because to keep UEFI spec unchanged EDKII XHCI driver have to maintain a state machine
869 // to keep track of the mapping between actual address and request address. If the request address
870 // (Address) is freed here, the Address value will be used by next enumerated device. Then EDKII XHCI
871 // host controller driver will have wrong information, which will cause further transaction error.
872 //
873 // EDKII UHCI/EHCI doesn't get impacted as it's make sense to reserve s/w resource till it gets unplugged.
874 //
875 return Status;
876}
877
891 IN USB_INTERFACE *HubIf,
892 IN UINT8 Port
893 )
894{
895 USB_HUB_API *HubApi;
897 EFI_USB_PORT_STATUS PortState;
898 EFI_STATUS Status;
899
900 Child = NULL;
901 HubApi = HubIf->HubApi;
902
903 //
904 // Host learns of the new device by polling the hub for port changes.
905 //
906 Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
907
908 if (EFI_ERROR (Status)) {
909 DEBUG ((DEBUG_ERROR, "UsbEnumeratePort: failed to get state of port %d\n", Port));
910 return Status;
911 }
912
913 //
914 // Only handle connection/enable/overcurrent/reset change.
915 // Usb super speed hub may report other changes, such as warm reset change. Ignore them.
916 //
917 if ((PortState.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
918 return EFI_SUCCESS;
919 }
920
921 DEBUG ((
922 DEBUG_INFO,
923 "UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",
924 Port,
925 PortState.PortStatus,
926 PortState.PortChangeStatus,
927 HubIf
928 ));
929
930 //
931 // This driver only process two kinds of events now: over current and
932 // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.
933 // ENABLE/RESET is used to reset port. SUSPEND isn't supported.
934 //
935
936 if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {
937 if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
938 //
939 // Case1:
940 // Both OverCurrent and OverCurrentChange set, means over current occurs,
941 // which probably is caused by short circuit. It has to wait system hardware
942 // to perform recovery.
943 //
944 DEBUG ((DEBUG_ERROR, "UsbEnumeratePort: Critical Over Current (port %d)\n", Port));
945 return EFI_DEVICE_ERROR;
946 }
947
948 //
949 // Case2:
950 // Only OverCurrentChange set, means system has been recoveried from
951 // over current. As a result, all ports are nearly power-off, so
952 // it's necessary to detach and enumerate all ports again.
953 //
954 DEBUG ((DEBUG_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current (port %d)\n", Port));
955 }
956
957 if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {
958 //
959 // Case3:
960 // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart
961 // on 2.0 roothub does. When over-current has influence on 1.1 device, the port
962 // would be disabled, so it's also necessary to detach and enumerate again.
963 //
964 DEBUG ((DEBUG_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current (port %d)\n", Port));
965 }
966
967 if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
968 //
969 // Case4:
970 // Device connected or disconnected normally.
971 //
972 DEBUG ((DEBUG_INFO, "UsbEnumeratePort: Device Connect/Disconnect Normally (port %d)\n", Port));
973 }
974
975 //
976 // Following as the above cases, it's safety to remove and create again.
977 //
978 Child = UsbFindChild (HubIf, Port);
979
980 if (Child != NULL) {
981 DEBUG ((DEBUG_INFO, "UsbEnumeratePort: device at port %d removed from root hub %p\n", Port, HubIf));
983 }
984
985 if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
986 //
987 // Now, new device connected, enumerate and configure the device
988 //
989 DEBUG ((DEBUG_INFO, "UsbEnumeratePort: new device connected at port %d\n", Port));
990 if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
991 Status = UsbEnumerateNewDev (HubIf, Port, FALSE);
992 } else {
993 Status = UsbEnumerateNewDev (HubIf, Port, TRUE);
994 }
995 } else {
996 DEBUG ((DEBUG_INFO, "UsbEnumeratePort: device disconnected event on port %d\n", Port));
997 }
998
999 HubApi->ClearPortChange (HubIf, Port);
1000 return Status;
1001}
1002
1010VOID
1011EFIAPI
1013 IN EFI_EVENT Event,
1014 IN VOID *Context
1015 )
1016{
1017 USB_INTERFACE *HubIf;
1018 UINT8 Byte;
1019 UINT8 Bit;
1020 UINT8 Index;
1022
1023 ASSERT (Context != NULL);
1024
1025 HubIf = (USB_INTERFACE *)Context;
1026
1027 for (Index = 0; Index < HubIf->NumOfPort; Index++) {
1028 Child = UsbFindChild (HubIf, Index);
1029 if ((Child != NULL) && (Child->DisconnectFail == TRUE)) {
1030 DEBUG ((DEBUG_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from hub %p, try again\n", Index, HubIf));
1032 }
1033 }
1034
1035 if (HubIf->ChangeMap == NULL) {
1036 return;
1037 }
1038
1039 //
1040 // HUB starts its port index with 1.
1041 //
1042 Byte = 0;
1043 Bit = 1;
1044
1045 for (Index = 0; Index < HubIf->NumOfPort; Index++) {
1046 if (USB_BIT_IS_SET (HubIf->ChangeMap[Byte], USB_BIT (Bit))) {
1047 UsbEnumeratePort (HubIf, Index);
1048 }
1049
1050 USB_NEXT_BIT (Byte, Bit);
1051 }
1052
1053 UsbHubAckHubStatus (HubIf->Device);
1054
1055 gBS->FreePool (HubIf->ChangeMap);
1056 HubIf->ChangeMap = NULL;
1057 return;
1058}
1059
1067VOID
1068EFIAPI
1070 IN EFI_EVENT Event,
1071 IN VOID *Context
1072 )
1073{
1074 USB_INTERFACE *RootHub;
1075 UINT8 Index;
1077
1078 RootHub = (USB_INTERFACE *)Context;
1079
1080 for (Index = 0; Index < RootHub->NumOfPort; Index++) {
1081 Child = UsbFindChild (RootHub, Index);
1082 if ((Child != NULL) && (Child->DisconnectFail == TRUE)) {
1083 DEBUG ((DEBUG_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from root hub %p, try again\n", Index, RootHub));
1085 }
1086
1087 UsbEnumeratePort (RootHub, Index);
1088 }
1089}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
NODE Child(IN NODE LoopVar6, IN UINT8 LoopVar5)
Definition: Compress.c:265
#define MSG_USB_DP
Definition: DevicePath.h:418
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
UINT16 EFIAPI SetDevicePathNodeLength(IN OUT VOID *Node, IN UINTN Length)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE_WITH_DEVICE_PATH(Type, Value, DevicePathParameter)
#define USB_PORT_STAT_C_CONNECTION
#define EFI_USB_SPEED_SUPER
4.8 Gb/s, USB 3.0 XHCI HC.
#define USB_PORT_STAT_CONNECTION
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
BOOLEAN EFIAPI UsbBusIsWantedUsbIO(IN USB_BUS *Bus, IN USB_INTERFACE *UsbIf)
Definition: UsbUtility.c:1022
EFI_STATUS UsbBuildDescTable(IN USB_DEVICE *UsbDev)
Definition: UsbDesc.c:811
EFI_STATUS UsbSetConfig(IN USB_DEVICE *UsbDev, IN UINT8 ConfigIndex)
Definition: UsbDesc.c:946
EFI_STATUS UsbSetAddress(IN USB_DEVICE *UsbDev, IN UINT8 Address)
Definition: UsbDesc.c:911
EFI_STATUS UsbGetMaxPacketSize0(IN USB_DEVICE *UsbDev)
Definition: UsbDesc.c:548
VOID UsbFreeDevDesc(IN USB_DEVICE_DESC *DevDesc)
Definition: UsbDesc.c:101
VOID UsbFreeDevice(IN USB_DEVICE *Device)
Definition: UsbEnumer.c:194
EFI_STATUS UsbSelectConfig(IN USB_DEVICE *Device, IN UINT8 ConfigValue)
Definition: UsbEnumer.c:370
EFI_STATUS UsbRemoveDevice(IN USB_DEVICE *Device)
Definition: UsbEnumer.c:558
EFI_STATUS UsbRemoveConfig(IN USB_DEVICE *Device)
Definition: UsbEnumer.c:509
EFI_STATUS UsbSelectSetting(IN USB_INTERFACE_DESC *IfDesc, IN UINT8 Alternate)
Definition: UsbEnumer.c:311
EFI_STATUS UsbDisconnectDriver(IN USB_INTERFACE *UsbIf)
Definition: UsbEnumer.c:461
USB_INTERFACE * UsbCreateInterface(IN USB_DEVICE *Device, IN USB_INTERFACE_DESC *IfDesc)
Definition: UsbEnumer.c:93
USB_ENDPOINT_DESC * UsbGetEndpointDesc(IN USB_INTERFACE *UsbIf, IN UINT8 EpAddr)
Definition: UsbEnumer.c:22
VOID EFIAPI UsbHubEnumeration(IN EFI_EVENT Event, IN VOID *Context)
Definition: UsbEnumer.c:1012
USB_DEVICE * UsbCreateDevice(IN USB_INTERFACE *ParentIf, IN UINT8 ParentPort)
Definition: UsbEnumer.c:215
EFI_STATUS UsbEnumerateNewDev(IN USB_INTERFACE *HubIf, IN UINT8 Port, IN BOOLEAN ResetIsNeeded)
Definition: UsbEnumer.c:662
USB_DEVICE * UsbFindChild(IN USB_INTERFACE *HubIf, IN UINT8 Port)
Definition: UsbEnumer.c:622
EFI_STATUS UsbEnumeratePort(IN USB_INTERFACE *HubIf, IN UINT8 Port)
Definition: UsbEnumer.c:890
EFI_STATUS UsbConnectDriver(IN USB_INTERFACE *UsbIf)
Definition: UsbEnumer.c:250
EFI_STATUS UsbFreeInterface(IN USB_INTERFACE *UsbIf)
Definition: UsbEnumer.c:53
VOID EFIAPI UsbRootHubEnumeration(IN EFI_EVENT Event, IN VOID *Context)
Definition: UsbEnumer.c:1069
EFI_STATUS UsbHubAckHubStatus(IN USB_DEVICE *HubDev)
Definition: UsbHub.c:395
BOOLEAN UsbIsHubInterface(IN USB_INTERFACE *UsbIf)
Definition: UsbHub.c:429
EFI_STATUS UsbOpenHostProtoByChild(IN USB_BUS *Bus, IN EFI_HANDLE Child)
Definition: UsbUtility.c:471
EFI_TPL UsbGetCurrentTpl(VOID)
Definition: UsbUtility.c:542
VOID UsbCloseHostProtoByChild(IN USB_BUS *Bus, IN EFI_HANDLE Child)
Definition: UsbUtility.c:511
UINT16 PortChangeStatus
Contains current port status change bitmap.
UINT16 PortStatus
Contains current port status bitmap.
UINT8 InterfaceNumber
Definition: DevicePath.h:428
UINT8 ParentPortNumber
Definition: DevicePath.h:424