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