]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbEnumer.c
1 /** @file
2
3 Usb bus enumeration support.
4
5 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UsbBus.h"
11
12 /**
13 Return the endpoint descriptor in this interface.
14
15 @param UsbIf The interface to search in.
16 @param EpAddr The address of the endpoint to return.
17
18 @return The endpoint descriptor or NULL.
19
20 **/
21 USB_ENDPOINT_DESC *
22 UsbGetEndpointDesc (
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
44
45 /**
46 Free the resource used by USB interface.
47
48 @param UsbIf The USB interface to free.
49
50 @retval EFI_ACCESS_DENIED The interface is still occupied.
51 @retval EFI_SUCCESS The interface is freed.
52 **/
53 EFI_STATUS
54 UsbFreeInterface (
55 IN USB_INTERFACE *UsbIf
56 )
57 {
58 EFI_STATUS Status;
59
60 UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
61
62 Status = gBS->UninstallMultipleProtocolInterfaces (
63 UsbIf->Handle,
64 &gEfiDevicePathProtocolGuid, UsbIf->DevicePath,
65 &gEfiUsbIoProtocolGuid, &UsbIf->UsbIo,
66 NULL
67 );
68 if (!EFI_ERROR (Status)) {
69 if (UsbIf->DevicePath != NULL) {
70 FreePool (UsbIf->DevicePath);
71 }
72 FreePool (UsbIf);
73 } else {
74 UsbOpenHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
75 }
76 return Status;
77 }
78
79
80 /**
81 Create an interface for the descriptor IfDesc. Each
82 device's configuration can have several interfaces.
83
84 @param Device The device has the interface descriptor.
85 @param IfDesc The interface descriptor.
86
87 @return The created USB interface for the descriptor, or NULL.
88
89 **/
90 USB_INTERFACE *
91 UsbCreateInterface (
92 IN USB_DEVICE *Device,
93 IN USB_INTERFACE_DESC *IfDesc
94 )
95 {
96 USB_DEVICE_PATH UsbNode;
97 USB_INTERFACE *UsbIf;
98 USB_INTERFACE *HubIf;
99 EFI_STATUS Status;
100
101 UsbIf = AllocateZeroPool (sizeof (USB_INTERFACE));
102
103 if (UsbIf == NULL) {
104 return NULL;
105 }
106
107 UsbIf->Signature = USB_INTERFACE_SIGNATURE;
108 UsbIf->Device = Device;
109 UsbIf->IfDesc = IfDesc;
110 ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);
111 UsbIf->IfSetting = IfDesc->Settings[IfDesc->ActiveIndex];
112
113 CopyMem (
114 &(UsbIf->UsbIo),
115 &mUsbIoProtocol,
116 sizeof (EFI_USB_IO_PROTOCOL)
117 );
118
119 //
120 // Install protocols for USBIO and device path
121 //
122 UsbNode.Header.Type = MESSAGING_DEVICE_PATH;
123 UsbNode.Header.SubType = MSG_USB_DP;
124 UsbNode.ParentPortNumber = Device->ParentPort;
125 UsbNode.InterfaceNumber = UsbIf->IfSetting->Desc.InterfaceNumber;
126
127 SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
128
129 HubIf = Device->ParentIf;
130 ASSERT (HubIf != NULL);
131
132 UsbIf->DevicePath = AppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header);
133
134 if (UsbIf->DevicePath == NULL) {
135 DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to create device path\n"));
136
137 Status = EFI_OUT_OF_RESOURCES;
138 goto ON_ERROR;
139 }
140
141 Status = gBS->InstallMultipleProtocolInterfaces (
142 &UsbIf->Handle,
143 &gEfiDevicePathProtocolGuid,
144 UsbIf->DevicePath,
145 &gEfiUsbIoProtocolGuid,
146 &UsbIf->UsbIo,
147 NULL
148 );
149
150 if (EFI_ERROR (Status)) {
151 DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to install UsbIo - %r\n", Status));
152 goto ON_ERROR;
153 }
154
155 //
156 // Open USB Host Controller Protocol by Child
157 //
158 Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);
159
160 if (EFI_ERROR (Status)) {
161 gBS->UninstallMultipleProtocolInterfaces (
162 &UsbIf->Handle,
163 &gEfiDevicePathProtocolGuid,
164 UsbIf->DevicePath,
165 &gEfiUsbIoProtocolGuid,
166 &UsbIf->UsbIo,
167 NULL
168 );
169
170 DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to open host for child - %r\n", Status));
171 goto ON_ERROR;
172 }
173
174 return UsbIf;
175
176 ON_ERROR:
177 if (UsbIf->DevicePath != NULL) {
178 FreePool (UsbIf->DevicePath);
179 }
180
181 FreePool (UsbIf);
182 return NULL;
183 }
184
185
186 /**
187 Free the resource used by this USB device.
188
189 @param Device The USB device to free.
190
191 **/
192 VOID
193 UsbFreeDevice (
194 IN USB_DEVICE *Device
195 )
196 {
197 if (Device->DevDesc != NULL) {
198 UsbFreeDevDesc (Device->DevDesc);
199 }
200
201 gBS->FreePool (Device);
202 }
203
204
205 /**
206 Create a device which is on the parent's ParentPort port.
207
208 @param ParentIf The parent HUB interface.
209 @param ParentPort The port on the HUB this device is connected to.
210
211 @return Created USB device, Or NULL.
212
213 **/
214 USB_DEVICE *
215 UsbCreateDevice (
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
239
240 /**
241 Connect the USB interface with its driver. EFI USB bus will
242 create a USB interface for each separate interface descriptor.
243
244 @param UsbIf The interface to connect driver to.
245
246 @return EFI_SUCCESS Interface is managed by some driver.
247 @return Others Failed to locate a driver for this interface.
248
249 **/
250 EFI_STATUS
251 UsbConnectDriver (
252 IN USB_INTERFACE *UsbIf
253 )
254 {
255 EFI_STATUS Status;
256 EFI_TPL OldTpl;
257
258 Status = EFI_SUCCESS;
259
260 //
261 // Hub is maintained by the USB bus driver. Otherwise try to
262 // connect drivers with this interface
263 //
264 if (UsbIsHubInterface (UsbIf)) {
265 DEBUG ((EFI_D_INFO, "UsbConnectDriver: found a hub device\n"));
266 Status = mUsbHubApi.Init (UsbIf);
267
268 } else {
269 //
270 // This function is called in both UsbIoControlTransfer and
271 // the timer callback in hub enumeration. So, at least it is
272 // called at TPL_CALLBACK. Some driver sitting on USB has
273 // twisted TPL used. It should be no problem for us to connect
274 // or disconnect at CALLBACK.
275 //
276
277 //
278 // Only recursively wanted usb child device
279 //
280 if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {
281 OldTpl = UsbGetCurrentTpl ();
282 DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
283
284 gBS->RestoreTPL (TPL_CALLBACK);
285
286 Status = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
287 UsbIf->IsManaged = (BOOLEAN)!EFI_ERROR (Status);
288
289 DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl()));
290 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
291
292 gBS->RaiseTPL (OldTpl);
293 }
294 }
295
296 return Status;
297 }
298
299
300 /**
301 Select an alternate setting for the interface.
302 Each interface can have several mutually exclusive
303 settings. Only one setting is active. It will
304 also reset its endpoints' toggle to zero.
305
306 @param IfDesc The interface descriptor to set.
307 @param Alternate The alternate setting number to locate.
308
309 @retval EFI_NOT_FOUND There is no setting with this alternate index.
310 @retval EFI_SUCCESS The interface is set to Alternate setting.
311
312 **/
313 EFI_STATUS
314 UsbSelectSetting (
315 IN USB_INTERFACE_DESC *IfDesc,
316 IN UINT8 Alternate
317 )
318 {
319 USB_INTERFACE_SETTING *Setting;
320 UINTN Index;
321
322 //
323 // Locate the active alternate setting
324 //
325 Setting = NULL;
326
327 for (Index = 0; Index < IfDesc->NumOfSetting; Index++) {
328 ASSERT (Index < USB_MAX_INTERFACE_SETTING);
329 Setting = IfDesc->Settings[Index];
330
331 if (Setting->Desc.AlternateSetting == Alternate) {
332 break;
333 }
334 }
335
336 if (Index == IfDesc->NumOfSetting) {
337 return EFI_NOT_FOUND;
338 }
339
340 IfDesc->ActiveIndex = Index;
341
342 ASSERT (Setting != NULL);
343 DEBUG ((EFI_D_INFO, "UsbSelectSetting: setting %d selected for interface %d\n",
344 Alternate, Setting->Desc.InterfaceNumber));
345
346 //
347 // Reset the endpoint toggle to zero
348 //
349 for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {
350 Setting->Endpoints[Index]->Toggle = 0;
351 }
352
353 return EFI_SUCCESS;
354 }
355
356
357 /**
358 Select a new configuration for the device. Each
359 device may support several configurations.
360
361 @param Device The device to select configuration.
362 @param ConfigValue The index of the configuration ( != 0).
363
364 @retval EFI_NOT_FOUND There is no configuration with the index.
365 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.
366 @retval EFI_SUCCESS The configuration is selected.
367
368 **/
369 EFI_STATUS
370 UsbSelectConfig (
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 ((EFI_D_INFO, "UsbSelectConfig: config %d selected for device %d\n",
403 ConfigValue, Device->Address));
404
405 //
406 // Create interfaces for each USB interface descriptor.
407 //
408 for (Index = 0; Index < ConfigDesc->Desc.NumInterfaces; Index++) {
409 //
410 // First select the default interface setting, and reset
411 // the endpoint toggles to zero for its endpoints.
412 //
413 IfDesc = ConfigDesc->Interfaces[Index];
414 UsbSelectSetting (IfDesc, IfDesc->Settings[0]->Desc.AlternateSetting);
415
416 //
417 // Create a USB_INTERFACE and install USB_IO and other protocols
418 //
419 UsbIf = UsbCreateInterface (Device, ConfigDesc->Interfaces[Index]);
420
421 if (UsbIf == NULL) {
422 Device->NumOfInterface = Index;
423 return EFI_OUT_OF_RESOURCES;
424 }
425
426 ASSERT (Index < USB_MAX_INTERFACE);
427 Device->Interfaces[Index] = UsbIf;
428
429 //
430 // Connect the device to drivers, if it failed, ignore
431 // the error. Don't let the unsupported interfaces to block
432 // the supported interfaces.
433 //
434 Status = UsbConnectDriver (UsbIf);
435
436 if (EFI_ERROR (Status)) {
437 DEBUG ((
438 DEBUG_WARN,
439 "UsbSelectConfig: failed to connect driver %r, ignored\n",
440 Status
441 ));
442 }
443 }
444
445 Device->NumOfInterface = Index;
446
447 return EFI_SUCCESS;
448 }
449
450
451 /**
452 Disconnect the USB interface with its driver.
453
454 @param UsbIf The interface to disconnect driver from.
455
456 **/
457 EFI_STATUS
458 UsbDisconnectDriver (
459 IN USB_INTERFACE *UsbIf
460 )
461 {
462 EFI_TPL OldTpl;
463 EFI_STATUS Status;
464
465 //
466 // Release the hub if it's a hub controller, otherwise
467 // disconnect the driver if it is managed by other drivers.
468 //
469 Status = EFI_SUCCESS;
470 if (UsbIf->IsHub) {
471 Status = UsbIf->HubApi->Release (UsbIf);
472
473 } else if (UsbIf->IsManaged) {
474 //
475 // This function is called in both UsbIoControlTransfer and
476 // the timer callback in hub enumeration. So, at least it is
477 // called at TPL_CALLBACK. Some driver sitting on USB has
478 // twisted TPL used. It should be no problem for us to connect
479 // or disconnect at CALLBACK.
480 //
481 OldTpl = UsbGetCurrentTpl ();
482 DEBUG ((EFI_D_INFO, "UsbDisconnectDriver: old TPL is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
483
484 gBS->RestoreTPL (TPL_CALLBACK);
485
486 Status = gBS->DisconnectController (UsbIf->Handle, NULL, NULL);
487 if (!EFI_ERROR (Status)) {
488 UsbIf->IsManaged = FALSE;
489 }
490
491 DEBUG (( EFI_D_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl(), Status));
492 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
493
494 gBS->RaiseTPL (OldTpl);
495 }
496
497 return Status;
498 }
499
500
501 /**
502 Remove the current device configuration.
503
504 @param Device The USB device to remove configuration from.
505
506 **/
507 EFI_STATUS
508 UsbRemoveConfig (
509 IN USB_DEVICE *Device
510 )
511 {
512 USB_INTERFACE *UsbIf;
513 UINTN Index;
514 EFI_STATUS Status;
515 EFI_STATUS ReturnStatus;
516
517 //
518 // Remove each interface of the device
519 //
520 ReturnStatus = EFI_SUCCESS;
521 for (Index = 0; Index < Device->NumOfInterface; Index++) {
522 ASSERT (Index < USB_MAX_INTERFACE);
523 UsbIf = Device->Interfaces[Index];
524
525 if (UsbIf == NULL) {
526 continue;
527 }
528
529 Status = UsbDisconnectDriver (UsbIf);
530 if (!EFI_ERROR (Status)) {
531 Status = UsbFreeInterface (UsbIf);
532 if (EFI_ERROR (Status)) {
533 UsbConnectDriver (UsbIf);
534 }
535 }
536
537 if (!EFI_ERROR (Status)) {
538 Device->Interfaces[Index] = NULL;
539 } else {
540 ReturnStatus = Status;
541 }
542 }
543
544 Device->ActiveConfig = NULL;
545 return ReturnStatus;
546 }
547
548
549 /**
550 Remove the device and all its children from the bus.
551
552 @param Device The device to remove.
553
554 @retval EFI_SUCCESS The device is removed.
555
556 **/
557 EFI_STATUS
558 UsbRemoveDevice (
559 IN USB_DEVICE *Device
560 )
561 {
562 USB_BUS *Bus;
563 USB_DEVICE *Child;
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 ((EFI_D_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 (( EFI_D_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 return Status;
609 }
610
611
612 /**
613 Find the child device on the hub's port.
614
615 @param HubIf The hub interface.
616 @param Port The port of the hub this child is connected to.
617
618 @return The device on the hub's port, or NULL if there is none.
619
620 **/
621 USB_DEVICE *
622 UsbFindChild (
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
649
650 /**
651 Enumerate and configure the new device on the port of this HUB interface.
652
653 @param HubIf The HUB that has the device connected.
654 @param Port The port index of the hub (started with zero).
655 @param ResetIsNeeded The boolean to control whether skip the reset of the port.
656
657 @retval EFI_SUCCESS The device is enumerated (added or removed).
658 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device.
659 @retval Others Failed to enumerate the device.
660
661 **/
662 EFI_STATUS
663 UsbEnumerateNewDev (
664 IN USB_INTERFACE *HubIf,
665 IN UINT8 Port,
666 IN BOOLEAN ResetIsNeeded
667 )
668 {
669 USB_BUS *Bus;
670 USB_HUB_API *HubApi;
671 USB_DEVICE *Child;
672 USB_DEVICE *Parent;
673 EFI_USB_PORT_STATUS PortState;
674 UINTN Address;
675 UINT8 Config;
676 EFI_STATUS Status;
677
678 Parent = HubIf->Device;
679 Bus = Parent->Bus;
680 HubApi = HubIf->HubApi;
681 Address = Bus->MaxDevices;
682
683 gBS->Stall (USB_WAIT_PORT_STABLE_STALL);
684
685 //
686 // Hub resets the device for at least 10 milliseconds.
687 // Host learns device speed. If device is of low/full speed
688 // and the hub is a EHCI root hub, ResetPort will release
689 // the device to its companion UHCI and return an error.
690 //
691 if (ResetIsNeeded) {
692 Status = HubApi->ResetPort (HubIf, Port);
693 if (EFI_ERROR (Status)) {
694 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));
695
696 return Status;
697 }
698 DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port));
699 } else {
700 DEBUG (( EFI_D_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 ((EFI_D_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 ((EFI_D_ERROR, "UsbEnumerateNewDev: No device present at port %d\n", Port));
722 goto ON_ERROR;
723 } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
724 Child->Speed = EFI_USB_SPEED_SUPER;
725 Child->MaxPacket0 = 512;
726 } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
727 Child->Speed = EFI_USB_SPEED_HIGH;
728 Child->MaxPacket0 = 64;
729 } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
730 Child->Speed = EFI_USB_SPEED_LOW;
731 Child->MaxPacket0 = 8;
732 } else {
733 Child->Speed = EFI_USB_SPEED_FULL;
734 Child->MaxPacket0 = 8;
735 }
736
737 DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));
738
739 if (((Child->Speed == EFI_USB_SPEED_LOW) || (Child->Speed == EFI_USB_SPEED_FULL)) &&
740 (Parent->Speed == EFI_USB_SPEED_HIGH)) {
741 //
742 // If the child is a low or full speed device, it is necessary to
743 // set the transaction translator. Port TT is 1-based.
744 // This is quite simple:
745 // 1. if parent is of high speed, then parent is our translator
746 // 2. otherwise use parent's translator.
747 //
748 Child->Translator.TranslatorHubAddress = Parent->Address;
749 Child->Translator.TranslatorPortNumber = (UINT8) (Port + 1);
750 } else {
751 Child->Translator = Parent->Translator;
752 }
753 DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device uses translator (%d, %d)\n",
754 Child->Translator.TranslatorHubAddress,
755 Child->Translator.TranslatorPortNumber));
756
757 //
758 // After port is reset, hub establishes a signal path between
759 // the device and host (DEFALUT state). Device's registers are
760 // reset, use default address 0 (host enumerates one device at
761 // a time) , and ready to respond to control transfer at EP 0.
762 //
763
764 //
765 // Host assigns an address to the device. Device completes the
766 // status stage with default address, then switches to new address.
767 // ADDRESS state. Address zero is reserved for root hub.
768 //
769 ASSERT (Bus->MaxDevices <= 256);
770 for (Address = 1; Address < Bus->MaxDevices; Address++) {
771 if (Bus->Devices[Address] == NULL) {
772 break;
773 }
774 }
775
776 if (Address >= Bus->MaxDevices) {
777 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: address pool is full for port %d\n", Port));
778
779 Status = EFI_ACCESS_DENIED;
780 goto ON_ERROR;
781 }
782
783 Status = UsbSetAddress (Child, (UINT8)Address);
784 Child->Address = (UINT8)Address;
785 Bus->Devices[Address] = Child;
786
787 if (EFI_ERROR (Status)) {
788 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status));
789 goto ON_ERROR;
790 }
791
792 gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
793
794 DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address));
795
796 //
797 // Host sends a Get_Descriptor request to learn the max packet
798 // size of default pipe (only part of the device's descriptor).
799 //
800 Status = UsbGetMaxPacketSize0 (Child);
801
802 if (EFI_ERROR (Status)) {
803 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status));
804 goto ON_ERROR;
805 }
806
807 DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0));
808
809 //
810 // Host learns about the device's abilities by requesting device's
811 // entire descriptions.
812 //
813 Status = UsbBuildDescTable (Child);
814
815 if (EFI_ERROR (Status)) {
816 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status));
817 goto ON_ERROR;
818 }
819
820 //
821 // Select a default configuration: UEFI must set the configuration
822 // before the driver can connect to the device.
823 //
824 Config = Child->DevDesc->Configs[0]->Desc.ConfigurationValue;
825 Status = UsbSetConfig (Child, Config);
826
827 if (EFI_ERROR (Status)) {
828 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status));
829 goto ON_ERROR;
830 }
831
832 DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address));
833
834 //
835 // Host assigns and loads a device driver.
836 //
837 Status = UsbSelectConfig (Child, Config);
838
839 if (EFI_ERROR (Status)) {
840 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to create interfaces - %r\n", Status));
841 goto ON_ERROR;
842 }
843
844 //
845 // Report Status Code to indicate USB device has been detected by hotplug
846 //
847 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
848 EFI_PROGRESS_CODE,
849 (EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG),
850 Bus->DevicePath
851 );
852 return EFI_SUCCESS;
853
854 ON_ERROR:
855 //
856 // If reach here, it means the enumeration process on a given port is interrupted due to error.
857 // The s/w resources, including the assigned address(Address) and the allocated usb device data
858 // structure(Bus->Devices[Address]), will NOT be freed here. These resources will be freed when
859 // the device is unplugged from the port or DriverBindingStop() is invoked.
860 //
861 // This way is used to co-work with the lower layer EDKII UHCI/EHCI/XHCI host controller driver.
862 // It's mainly because to keep UEFI spec unchanged EDKII XHCI driver have to maintain a state machine
863 // to keep track of the mapping between actual address and request address. If the request address
864 // (Address) is freed here, the Address value will be used by next enumerated device. Then EDKII XHCI
865 // host controller driver will have wrong information, which will cause further transaction error.
866 //
867 // EDKII UHCI/EHCI doesn't get impacted as it's make sense to reserve s/w resource till it gets unplugged.
868 //
869 return Status;
870 }
871
872
873 /**
874 Process the events on the port.
875
876 @param HubIf The HUB that has the device connected.
877 @param Port The port index of the hub (started with zero).
878
879 @retval EFI_SUCCESS The device is enumerated (added or removed).
880 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device.
881 @retval Others Failed to enumerate the device.
882
883 **/
884 EFI_STATUS
885 UsbEnumeratePort (
886 IN USB_INTERFACE *HubIf,
887 IN UINT8 Port
888 )
889 {
890 USB_HUB_API *HubApi;
891 USB_DEVICE *Child;
892 EFI_USB_PORT_STATUS PortState;
893 EFI_STATUS Status;
894
895 Child = NULL;
896 HubApi = HubIf->HubApi;
897
898 //
899 // Host learns of the new device by polling the hub for port changes.
900 //
901 Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
902
903 if (EFI_ERROR (Status)) {
904 DEBUG ((EFI_D_ERROR, "UsbEnumeratePort: failed to get state of port %d\n", Port));
905 return Status;
906 }
907
908 //
909 // Only handle connection/enable/overcurrent/reset change.
910 // Usb super speed hub may report other changes, such as warm reset change. Ignore them.
911 //
912 if ((PortState.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
913 return EFI_SUCCESS;
914 }
915
916 DEBUG (( EFI_D_INFO, "UsbEnumeratePort: port %d state - %02x, change - %02x on %p\n",
917 Port, PortState.PortStatus, PortState.PortChangeStatus, HubIf));
918
919 //
920 // This driver only process two kinds of events now: over current and
921 // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.
922 // ENABLE/RESET is used to reset port. SUSPEND isn't supported.
923 //
924
925 if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {
926
927 if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
928 //
929 // Case1:
930 // Both OverCurrent and OverCurrentChange set, means over current occurs,
931 // which probably is caused by short circuit. It has to wait system hardware
932 // to perform recovery.
933 //
934 DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port));
935 return EFI_DEVICE_ERROR;
936
937 }
938 //
939 // Case2:
940 // Only OverCurrentChange set, means system has been recoveried from
941 // over current. As a result, all ports are nearly power-off, so
942 // it's necessary to detach and enumerate all ports again.
943 //
944 DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port));
945 }
946
947 if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {
948 //
949 // Case3:
950 // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart
951 // on 2.0 roothub does. When over-current has influence on 1.1 device, the port
952 // would be disabled, so it's also necessary to detach and enumerate again.
953 //
954 DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port));
955 }
956
957 if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
958 //
959 // Case4:
960 // Device connected or disconnected normally.
961 //
962 DEBUG ((EFI_D_INFO, "UsbEnumeratePort: Device Connect/Disconnect Normally\n", Port));
963 }
964
965 //
966 // Following as the above cases, it's safety to remove and create again.
967 //
968 Child = UsbFindChild (HubIf, Port);
969
970 if (Child != NULL) {
971 DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device at port %d removed from root hub %p\n", Port, HubIf));
972 UsbRemoveDevice (Child);
973 }
974
975 if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
976 //
977 // Now, new device connected, enumerate and configure the device
978 //
979 DEBUG (( EFI_D_INFO, "UsbEnumeratePort: new device connected at port %d\n", Port));
980 if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
981 Status = UsbEnumerateNewDev (HubIf, Port, FALSE);
982 } else {
983 Status = UsbEnumerateNewDev (HubIf, Port, TRUE);
984 }
985
986 } else {
987 DEBUG (( EFI_D_INFO, "UsbEnumeratePort: device disconnected event on port %d\n", Port));
988 }
989
990 HubApi->ClearPortChange (HubIf, Port);
991 return Status;
992 }
993
994
995 /**
996 Enumerate all the changed hub ports.
997
998 @param Event The event that is triggered.
999 @param Context The context to the event.
1000
1001 **/
1002 VOID
1003 EFIAPI
1004 UsbHubEnumeration (
1005 IN EFI_EVENT Event,
1006 IN VOID *Context
1007 )
1008 {
1009 USB_INTERFACE *HubIf;
1010 UINT8 Byte;
1011 UINT8 Bit;
1012 UINT8 Index;
1013 USB_DEVICE *Child;
1014
1015 ASSERT (Context != NULL);
1016
1017 HubIf = (USB_INTERFACE *) Context;
1018
1019 for (Index = 0; Index < HubIf->NumOfPort; Index++) {
1020 Child = UsbFindChild (HubIf, Index);
1021 if ((Child != NULL) && (Child->DisconnectFail == TRUE)) {
1022 DEBUG (( EFI_D_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from hub %p, try again\n", Index, HubIf));
1023 UsbRemoveDevice (Child);
1024 }
1025 }
1026
1027 if (HubIf->ChangeMap == NULL) {
1028 return ;
1029 }
1030
1031 //
1032 // HUB starts its port index with 1.
1033 //
1034 Byte = 0;
1035 Bit = 1;
1036
1037 for (Index = 0; Index < HubIf->NumOfPort; Index++) {
1038 if (USB_BIT_IS_SET (HubIf->ChangeMap[Byte], USB_BIT (Bit))) {
1039 UsbEnumeratePort (HubIf, Index);
1040 }
1041
1042 USB_NEXT_BIT (Byte, Bit);
1043 }
1044
1045 UsbHubAckHubStatus (HubIf->Device);
1046
1047 gBS->FreePool (HubIf->ChangeMap);
1048 HubIf->ChangeMap = NULL;
1049 return ;
1050 }
1051
1052
1053 /**
1054 Enumerate all the changed hub ports.
1055
1056 @param Event The event that is triggered.
1057 @param Context The context to the event.
1058
1059 **/
1060 VOID
1061 EFIAPI
1062 UsbRootHubEnumeration (
1063 IN EFI_EVENT Event,
1064 IN VOID *Context
1065 )
1066 {
1067 USB_INTERFACE *RootHub;
1068 UINT8 Index;
1069 USB_DEVICE *Child;
1070
1071 RootHub = (USB_INTERFACE *) Context;
1072
1073 for (Index = 0; Index < RootHub->NumOfPort; Index++) {
1074 Child = UsbFindChild (RootHub, Index);
1075 if ((Child != NULL) && (Child->DisconnectFail == TRUE)) {
1076 DEBUG (( EFI_D_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from root hub %p, try again\n", Index, RootHub));
1077 UsbRemoveDevice (Child);
1078 }
1079
1080 UsbEnumeratePort (RootHub, Index);
1081 }
1082 }