]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
Merge in some fix from R8 on USB Bus driver:
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbEnumer.c
CommitLineData
e237e7ae 1/** @file\r
2\r
3Copyright (c) 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12 Module Name:\r
13\r
14 UsbEnumer.c\r
15\r
16 Abstract:\r
17\r
18 Usb bus enumeration support\r
19\r
20 Revision History\r
21\r
22\r
23**/\r
24\r
25#include "UsbBus.h"\r
26\r
27\r
28/**\r
29 Return the endpoint descriptor in this interface\r
30\r
31 @param UsbIf The interface to search in\r
32 @param EpAddr The address of the endpoint to return\r
33\r
34 @return The endpoint descriptor or NULL\r
35\r
36**/\r
37USB_ENDPOINT_DESC *\r
38UsbGetEndpointDesc (\r
39 IN USB_INTERFACE *UsbIf,\r
40 IN UINT8 EpAddr\r
41 )\r
42{\r
43 USB_ENDPOINT_DESC *EpDesc;\r
44 UINTN Index;\r
45\r
46 for (Index = 0; Index < UsbIf->IfSetting->Desc.NumEndpoints; Index++) {\r
47 EpDesc = UsbIf->IfSetting->Endpoints[Index];\r
48\r
49 if (EpDesc->Desc.EndpointAddress == EpAddr) {\r
50 return EpDesc;\r
51 }\r
52 }\r
53\r
54 return NULL;\r
55}\r
56\r
57\r
58/**\r
59 Free the resource used by USB interface\r
60\r
61 @param UsbIf The USB interface to free\r
62\r
63 @return None\r
64\r
65**/\r
66STATIC\r
67VOID\r
68UsbFreeInterface (\r
69 IN USB_INTERFACE *UsbIf\r
70 )\r
71{\r
72 UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);\r
73\r
74 gBS->UninstallMultipleProtocolInterfaces (\r
75 UsbIf->Handle,\r
76 &gEfiDevicePathProtocolGuid,\r
77 UsbIf->DevicePath,\r
78 &gEfiUsbIoProtocolGuid,\r
79 &UsbIf->UsbIo,\r
80 NULL\r
81 );\r
82\r
83 if (UsbIf->DevicePath != NULL) {\r
84 gBS->FreePool (UsbIf->DevicePath);\r
85 }\r
86\r
87 gBS->FreePool (UsbIf);\r
88}\r
89\r
90\r
91/**\r
92 Create an interface for the descriptor IfDesc. Each\r
93 device's configuration can have several interfaces.\r
94\r
95 @param Device The device has the interface descriptor\r
96 @param IfDesc The interface descriptor\r
97\r
98 @return The created USB interface for the descriptor, or NULL.\r
99\r
100**/\r
101STATIC\r
102USB_INTERFACE *\r
103UsbCreateInterface (\r
104 IN USB_DEVICE *Device,\r
105 IN USB_INTERFACE_DESC *IfDesc\r
106 )\r
107{\r
108 USB_DEVICE_PATH UsbNode;\r
109 USB_INTERFACE *UsbIf;\r
110 USB_INTERFACE *HubIf;\r
111 EFI_STATUS Status;\r
112\r
113 UsbIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
114\r
115 if (UsbIf == NULL) {\r
116 return NULL;\r
117 }\r
118\r
119 UsbIf->Signature = USB_INTERFACE_SIGNATURE;\r
120 UsbIf->Device = Device;\r
121 UsbIf->IfDesc = IfDesc;\r
122 UsbIf->IfSetting = IfDesc->Settings[IfDesc->ActiveIndex];\r
e61d30b0 123\r
124 CopyMem (\r
125 &(UsbIf->UsbIo),\r
126 &mUsbIoProtocol,\r
127 sizeof (EFI_USB_IO_PROTOCOL)\r
128 );\r
e237e7ae 129\r
130 //\r
131 // Install protocols for USBIO and device path\r
132 //\r
133 UsbNode.Header.Type = MESSAGING_DEVICE_PATH;\r
134 UsbNode.Header.SubType = MSG_USB_DP;\r
135 UsbNode.ParentPortNumber = Device->ParentPort;\r
136 UsbNode.InterfaceNumber = UsbIf->IfSetting->Desc.InterfaceNumber;\r
137\r
138 SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));\r
139\r
140 HubIf = Device->ParentIf;\r
141 ASSERT (HubIf != NULL);\r
142\r
143 UsbIf->DevicePath = AppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header);\r
144\r
145 if (UsbIf->DevicePath == NULL) {\r
d2577026 146 DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to create device path\n"));\r
e237e7ae 147\r
148 Status = EFI_OUT_OF_RESOURCES;\r
149 goto ON_ERROR;\r
150 }\r
151\r
152 Status = gBS->InstallMultipleProtocolInterfaces (\r
153 &UsbIf->Handle,\r
154 &gEfiDevicePathProtocolGuid,\r
155 UsbIf->DevicePath,\r
156 &gEfiUsbIoProtocolGuid,\r
157 &UsbIf->UsbIo,\r
158 NULL\r
159 );\r
160\r
161 if (EFI_ERROR (Status)) {\r
d2577026 162 DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to install UsbIo - %r\n", Status));\r
e237e7ae 163 goto ON_ERROR;\r
164 }\r
165\r
166 //\r
167 // Open USB Host Controller Protocol by Child\r
168 //\r
169 Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);\r
170\r
171 if (EFI_ERROR (Status)) {\r
172 gBS->UninstallMultipleProtocolInterfaces (\r
173 &UsbIf->Handle,\r
174 &gEfiDevicePathProtocolGuid,\r
175 UsbIf->DevicePath,\r
176 &gEfiUsbIoProtocolGuid,\r
177 &UsbIf->UsbIo,\r
178 NULL\r
179 );\r
180\r
d2577026 181 DEBUG ((EFI_D_ERROR, "UsbCreateInterface: failed to open host for child - %r\n", Status));\r
e237e7ae 182 goto ON_ERROR;\r
183 }\r
184\r
185 return UsbIf;\r
186\r
187ON_ERROR:\r
188 if (UsbIf->DevicePath) {\r
189 gBS->FreePool (UsbIf->DevicePath);\r
190 }\r
191\r
192 gBS->FreePool (UsbIf);\r
193 return NULL;\r
194}\r
195\r
196\r
197/**\r
198 Free the resource used by this USB device\r
199\r
200 @param Device The USB device to free\r
201\r
202 @return None\r
203\r
204**/\r
205STATIC\r
206VOID\r
207UsbFreeDevice (\r
208 IN USB_DEVICE *Device\r
209 )\r
210{\r
211 if (Device->DevDesc != NULL) {\r
212 UsbFreeDevDesc (Device->DevDesc);\r
213 }\r
214\r
215 gBS->FreePool (Device);\r
216}\r
217\r
218\r
219/**\r
220 Create a device which is on the parent's ParentPort port.\r
221\r
222 @param ParentIf The parent HUB interface\r
223 @param ParentPort The port on the HUB this device is connected to\r
224\r
225 @return Created USB device\r
226\r
227**/\r
228STATIC\r
229USB_DEVICE *\r
230UsbCreateDevice (\r
231 IN USB_INTERFACE *ParentIf,\r
232 IN UINT8 ParentPort\r
233 )\r
234{\r
235 USB_DEVICE *Device;\r
236\r
237 ASSERT (ParentIf != NULL);\r
238\r
239 Device = AllocateZeroPool (sizeof (USB_DEVICE));\r
240\r
241 if (Device == NULL) {\r
242 return NULL;\r
243 }\r
244\r
245 Device->Bus = ParentIf->Device->Bus;\r
246 Device->MaxPacket0 = 8;\r
247 Device->ParentAddr = ParentIf->Device->Address;\r
248 Device->ParentIf = ParentIf;\r
249 Device->ParentPort = ParentPort;\r
250 return Device;\r
251}\r
252\r
253\r
254/**\r
255 Connect the USB interface with its driver. EFI USB bus will\r
256 create a USB interface for each seperate interface descriptor.\r
257\r
258 @param UsbIf The interface to connect driver to\r
259\r
260 @return EFI_SUCCESS : Interface is managed by some driver\r
261 @return Others : Failed to locate a driver for this interface\r
262\r
263**/\r
264STATIC\r
265EFI_STATUS\r
266UsbConnectDriver (\r
267 IN USB_INTERFACE *UsbIf\r
268 )\r
269{\r
270 EFI_STATUS Status;\r
271 EFI_TPL OldTpl;\r
272\r
273 Status = EFI_SUCCESS;\r
274\r
275 //\r
276 // Hub is maintained by the USB bus driver. Otherwise try to\r
277 // connect drivers with this interface\r
278 //\r
279 if (UsbIsHubInterface (UsbIf)) {\r
d2577026 280 DEBUG ((EFI_D_INFO, "UsbConnectDriver: found a hub device\n"));\r
e237e7ae 281 Status = mUsbHubApi.Init (UsbIf);\r
282\r
283 } else {\r
284 //\r
285 // This function is called in both UsbIoControlTransfer and\r
286 // the timer callback in hub enumeration. So, at least it is\r
287 // called at TPL_CALLBACK. Some driver sitting on USB has\r
288 // twisted TPL used. It should be no problem for us to connect\r
289 // or disconnect at CALLBACK.\r
290 //\r
291 OldTpl = UsbGetCurrentTpl ();\r
d2577026 292 DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d\n", OldTpl));\r
e237e7ae 293\r
294 gBS->RestoreTPL (TPL_CALLBACK);\r
295\r
296 Status = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);\r
297 UsbIf->IsManaged = (BOOLEAN)!EFI_ERROR (Status);\r
298\r
d2577026 299 DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));\r
e237e7ae 300 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);\r
301\r
302 gBS->RaiseTPL (OldTpl);\r
303 }\r
304\r
305 return Status;\r
306}\r
307\r
308\r
309/**\r
310 Select an alternate setting for the interface.\r
311 Each interface can have several mutually exclusive\r
312 settings. Only one setting is active. It will\r
313 also reset its endpoints' toggle to zero.\r
314\r
315 @param IfDesc The interface descriptor to set\r
316 @param Alternate The alternate setting number to locate\r
317\r
318 @retval EFI_NOT_FOUND There is no setting with this alternate index\r
319 @retval EFI_SUCCESS The interface is set to Alternate setting.\r
320\r
321**/\r
322EFI_STATUS\r
323UsbSelectSetting (\r
324 IN USB_INTERFACE_DESC *IfDesc,\r
325 IN UINT8 Alternate\r
326 )\r
327{\r
328 USB_INTERFACE_SETTING *Setting;\r
329 UINT8 Index;\r
330\r
331 //\r
332 // Locate the active alternate setting\r
333 //\r
334 Setting = NULL;\r
335\r
336 for (Index = 0; Index < IfDesc->NumOfSetting; Index++) {\r
337 Setting = IfDesc->Settings[Index];\r
338\r
339 if (Setting->Desc.AlternateSetting == Alternate) {\r
340 break;\r
341 }\r
342 }\r
343\r
344 if (Index == IfDesc->NumOfSetting) {\r
345 return EFI_NOT_FOUND;\r
346 }\r
347\r
348 IfDesc->ActiveIndex = Index;\r
349\r
d2577026 350 DEBUG ((EFI_D_INFO, "UsbSelectSetting: setting %d selected for interface %d\n",\r
e237e7ae 351 Alternate, Setting->Desc.InterfaceNumber));\r
352\r
353 //\r
354 // Reset the endpoint toggle to zero\r
355 //\r
356 for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {\r
357 Setting->Endpoints[Index]->Toggle = 0;\r
358 }\r
359\r
360 return EFI_SUCCESS;\r
361}\r
362\r
363\r
364/**\r
365 Select a new configuration for the device. Each\r
366 device may support several configurations.\r
367\r
368 @param Device The device to select configuration\r
369 @param ConfigValue The index of the configuration ( != 0)\r
370\r
371 @retval EFI_NOT_FOUND There is no configuration with the index\r
372 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource\r
373 @retval EFI_SUCCESS The configuration is selected.\r
374\r
375**/\r
376EFI_STATUS\r
377UsbSelectConfig (\r
378 IN USB_DEVICE *Device,\r
379 IN UINT8 ConfigValue\r
380 )\r
381{\r
382 USB_DEVICE_DESC *DevDesc;\r
383 USB_CONFIG_DESC *ConfigDesc;\r
384 USB_INTERFACE_DESC *IfDesc;\r
385 USB_INTERFACE *UsbIf;\r
386 EFI_STATUS Status;\r
387 UINT8 Index;\r
388\r
389 //\r
390 // Locate the active config, then set the device's pointer\r
391 //\r
392 DevDesc = Device->DevDesc;\r
393 ConfigDesc = NULL;\r
394\r
395 for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) {\r
396 ConfigDesc = DevDesc->Configs[Index];\r
397\r
398 if (ConfigDesc->Desc.ConfigurationValue == ConfigValue) {\r
399 break;\r
400 }\r
401 }\r
402\r
403 if (Index == DevDesc->Desc.NumConfigurations) {\r
404 return EFI_NOT_FOUND;\r
405 }\r
406\r
407 Device->ActiveConfig = ConfigDesc;\r
408\r
d2577026 409 DEBUG ((EFI_D_INFO, "UsbSelectConfig: config %d selected for device %d\n",\r
e237e7ae 410 ConfigValue, Device->Address));\r
411\r
412 //\r
413 // Create interfaces for each USB interface descriptor.\r
414 //\r
415 for (Index = 0; Index < ConfigDesc->Desc.NumInterfaces; Index++) {\r
416 //\r
417 // First select the default interface setting, and reset\r
418 // the endpoint toggles to zero for its endpoints.\r
419 //\r
420 IfDesc = ConfigDesc->Interfaces[Index];\r
421 UsbSelectSetting (IfDesc, IfDesc->Settings[0]->Desc.AlternateSetting);\r
422\r
423 //\r
424 // Create a USB_INTERFACE and install USB_IO and other protocols\r
425 //\r
426 UsbIf = UsbCreateInterface (Device, ConfigDesc->Interfaces[Index]);\r
427\r
428 if (UsbIf == NULL) {\r
429 return EFI_OUT_OF_RESOURCES;\r
430 }\r
431\r
432 Device->Interfaces[Index] = UsbIf;\r
433\r
434 //\r
435 // Connect the device to drivers, if it failed, ignore\r
436 // the error. Don't let the unsupported interfaces to block\r
437 // the supported interfaces.\r
438 //\r
439 Status = UsbConnectDriver (UsbIf);\r
440\r
441 if (EFI_ERROR (Status)) {\r
d2577026 442 DEBUG ((EFI_D_ERROR, "UsbSelectConfig: failed to connect driver %r, ignored\n", Status));\r
e237e7ae 443 }\r
444 }\r
445\r
446 Device->NumOfInterface = Index;\r
447\r
448 return EFI_SUCCESS;\r
449}\r
450\r
451\r
452\r
453/**\r
454 Disconnect the USB interface with its driver.\r
455\r
456 @param UsbIf The interface to disconnect driver from\r
457\r
458 @return None\r
459\r
460**/\r
461STATIC\r
462VOID\r
463UsbDisconnectDriver (\r
464 IN USB_INTERFACE *UsbIf\r
465 )\r
466{\r
467 EFI_TPL OldTpl;\r
468\r
469 //\r
470 // Release the hub if it's a hub controller, otherwise\r
471 // disconnect the driver if it is managed by other drivers.\r
472 //\r
473 if (UsbIf->IsHub) {\r
474 UsbIf->HubApi->Release (UsbIf);\r
475\r
476 } else if (UsbIf->IsManaged) {\r
477 //\r
478 // This function is called in both UsbIoControlTransfer and\r
479 // the timer callback in hub enumeration. So, at least it is\r
480 // called at TPL_CALLBACK. Some driver sitting on USB has\r
481 // twisted TPL used. It should be no problem for us to connect\r
482 // or disconnect at CALLBACK.\r
483 //\r
484 OldTpl = UsbGetCurrentTpl ();\r
d2577026 485 DEBUG ((EFI_D_INFO, "UsbDisconnectDriver: old TPL is %d\n", OldTpl));\r
e237e7ae 486\r
487 gBS->RestoreTPL (TPL_CALLBACK);\r
488\r
489 gBS->DisconnectController (UsbIf->Handle, NULL, NULL);\r
490 UsbIf->IsManaged = FALSE;\r
491\r
d2577026 492 DEBUG (( EFI_D_INFO, "UsbDisconnectDriver: TPL after disconnect is %d\n", UsbGetCurrentTpl()));\r
e237e7ae 493 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);\r
494\r
495 gBS->RaiseTPL (OldTpl);\r
496 }\r
497}\r
498\r
499\r
500\r
501/**\r
502 Remove the current device configuration\r
503\r
504 @param Device The USB device to remove configuration from\r
505\r
506 @return None\r
507\r
508**/\r
509VOID\r
510UsbRemoveConfig (\r
511 IN USB_DEVICE *Device\r
512 )\r
513{\r
514 USB_INTERFACE *UsbIf;\r
515 UINTN Index;\r
516\r
517 //\r
518 // Remove each interface of the device\r
519 //\r
520 for (Index = 0; Index < Device->NumOfInterface; Index++) {\r
521 UsbIf = Device->Interfaces[Index];\r
522\r
523 if (UsbIf == NULL) {\r
524 continue;\r
525 }\r
526\r
527 UsbDisconnectDriver (UsbIf);\r
528 UsbFreeInterface (UsbIf);\r
529 Device->Interfaces[Index] = NULL;\r
530 }\r
531\r
532 Device->ActiveConfig = NULL;\r
533 Device->NumOfInterface = 0;\r
534}\r
535\r
536\r
537\r
538/**\r
539 Remove the device and all its children from the bus.\r
540\r
541 @param Device The device to remove\r
542\r
543 @retval EFI_SUCCESS The device is removed\r
544\r
545**/\r
546EFI_STATUS\r
547UsbRemoveDevice (\r
548 IN USB_DEVICE *Device\r
549 )\r
550{\r
551 USB_BUS *Bus;\r
552 USB_DEVICE *Child;\r
553 EFI_STATUS Status;\r
554 UINT8 Index;\r
555\r
556 Bus = Device->Bus;\r
557\r
558 //\r
559 // Remove all the devices on its downstream ports. Search from devices[1].\r
560 // Devices[0] is the root hub.\r
561 //\r
562 for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
563 Child = Bus->Devices[Index];\r
564\r
565 if ((Child == NULL) || (Child->ParentAddr != Device->Address)) {\r
566 continue;\r
567 }\r
568\r
569 Status = UsbRemoveDevice (Child);\r
570\r
571 if (EFI_ERROR (Status)) {\r
d2577026 572 DEBUG ((EFI_D_ERROR, "UsbRemoveDevice: failed to remove child, ignore error\n"));\r
e237e7ae 573 Bus->Devices[Index] = NULL;\r
574 }\r
575 }\r
576\r
577 UsbRemoveConfig (Device);\r
578\r
d2577026 579 DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address));\r
e237e7ae 580\r
581 Bus->Devices[Device->Address] = NULL;\r
582 UsbFreeDevice (Device);\r
583\r
584 return EFI_SUCCESS;\r
585}\r
586\r
587\r
588/**\r
589 Find the child device on the hub's port\r
590\r
591 @param HubIf The hub interface\r
592 @param Port The port of the hub this child is connected to\r
593\r
594 @return The device on the hub's port, or NULL if there is none\r
595\r
596**/\r
597STATIC\r
598USB_DEVICE *\r
599UsbFindChild (\r
600 IN USB_INTERFACE *HubIf,\r
601 IN UINT8 Port\r
602 )\r
603{\r
604 USB_DEVICE *Device;\r
605 USB_BUS *Bus;\r
606 UINTN Index;\r
607\r
608 Bus = HubIf->Device->Bus;\r
609\r
610 //\r
611 // Start checking from device 1, device 0 is the root hub\r
612 //\r
613 for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
614 Device = Bus->Devices[Index];\r
615\r
616 if ((Device != NULL) && (Device->ParentAddr == HubIf->Device->Address) &&\r
617 (Device->ParentPort == Port)) {\r
618\r
619 return Device;\r
620 }\r
621 }\r
622\r
623 return NULL;\r
624}\r
625\r
626\r
627\r
628/**\r
629 Enumerate and configure the new device on the port of this HUB interface.\r
630\r
631 @param HubIf The HUB that has the device connected\r
632 @param Port The port index of the hub (started with zero)\r
633\r
634 @retval EFI_SUCCESS The device is enumerated (added or removed)\r
635 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device\r
636 @retval Others Failed to enumerate the device\r
637\r
638**/\r
639STATIC\r
640EFI_STATUS\r
641UsbEnumerateNewDev (\r
642 IN USB_INTERFACE *HubIf,\r
643 IN UINT8 Port\r
644 )\r
645{\r
646 USB_BUS *Bus;\r
647 USB_HUB_API *HubApi;\r
648 USB_DEVICE *Child;\r
649 USB_DEVICE *Parent;\r
650 EFI_USB_PORT_STATUS PortState;\r
651 UINT8 Address;\r
652 UINT8 Config;\r
653 EFI_STATUS Status;\r
654\r
655 Address = USB_MAX_DEVICES;\r
656 Parent = HubIf->Device;\r
657 Bus = Parent->Bus;\r
658 HubApi = HubIf->HubApi;\r
659\r
660\r
661 //\r
662 // Wait at least 100 ms for the power on port to stable\r
663 //\r
664 gBS->Stall (100 * USB_STALL_1_MS);\r
665\r
666 //\r
667 // Hub resets the device for at least 10 milliseconds.\r
668 // Host learns device speed. If device is of low/full speed\r
669 // and the hub is a EHCI root hub, ResetPort will release\r
670 // the device to its companion UHCI and return an error.\r
671 //\r
672 Status = HubApi->ResetPort (HubIf, Port);\r
673\r
674 if (EFI_ERROR (Status)) {\r
d2577026 675 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status));\r
e237e7ae 676\r
677 return Status;\r
678 }\r
679\r
d2577026 680 DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: hub port %d is reset\n", Port));\r
e237e7ae 681\r
682 Child = UsbCreateDevice (HubIf, Port);\r
683\r
684 if (Child == NULL) {\r
685 return EFI_OUT_OF_RESOURCES;\r
686 }\r
687\r
688 //\r
689 // OK, now identify the device speed. After reset, hub\r
690 // fully knows the actual device speed.\r
691 //\r
692 Status = HubApi->GetPortStatus (HubIf, Port, &PortState);\r
693\r
694 if (EFI_ERROR (Status)) {\r
d2577026 695 DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to get speed of port %d\n", Port));\r
e237e7ae 696 goto ON_ERROR;\r
697 }\r
698\r
699 if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) {\r
700 Child->Speed = EFI_USB_SPEED_LOW;\r
701\r
702 } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {\r
703 Child->Speed = EFI_USB_SPEED_HIGH;\r
704\r
705 } else {\r
706 Child->Speed = EFI_USB_SPEED_FULL;\r
707 }\r
708\r
d2577026 709 DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device is of %d speed\n", Child->Speed));\r
e237e7ae 710\r
711 if (Child->Speed != EFI_USB_SPEED_HIGH) {\r
712 //\r
713 // If the child isn't a high speed device, it is necessary to\r
714 // set the transaction translator. This is quite simple:\r
715 // 1. if parent is of high speed, then parent is our translator\r
716 // 2. otherwise use parent's translator.\r
717 //\r
718 if (Parent->Speed == EFI_USB_SPEED_HIGH) {\r
719 Child->Translator.TranslatorHubAddress = Parent->Address;\r
720 Child->Translator.TranslatorPortNumber = Port;\r
721\r
722 } else {\r
723 Child->Translator = Parent->Translator;\r
724 }\r
725\r
d2577026 726 DEBUG (( EFI_D_INFO, "UsbEnumerateNewDev: device uses translator (%d, %d)\n",\r
e237e7ae 727 Child->Translator.TranslatorHubAddress,\r
728 Child->Translator.TranslatorPortNumber));\r
729 }\r
730\r
731 //\r
732 // After port is reset, hub establishes a signal path between\r
733