]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
Make use of correct format String:
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbHub.c
CommitLineData
e237e7ae 1/** @file\r
2\r
8616fc4c 3 Unified interface for RootHub and Hub.\r
4\r
e237e7ae 5Copyright (c) 2007, Intel Corporation\r
6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
e237e7ae 14**/\r
15\r
16#include "UsbBus.h"\r
17\r
18//\r
19// USB hub class specific requests. Although USB hub\r
20// is related to an interface, these requests are sent\r
21// to the control endpoint of the device.\r
22//\r
23\r
24\r
25/**\r
8616fc4c 26 USB hub control transfer to clear the hub feature.\r
e237e7ae 27\r
8616fc4c 28 @param HubDev The device of the hub.\r
29 @param Feature The feature to clear.\r
e237e7ae 30\r
8616fc4c 31 @retval EFI_SUCCESS Feature of the hub is cleared.\r
32 @retval Others Failed to clear the feature.\r
e237e7ae 33\r
34**/\r
e237e7ae 35EFI_STATUS\r
36UsbHubCtrlClearHubFeature (\r
37 IN USB_DEVICE *HubDev,\r
38 IN UINT16 Feature\r
39 )\r
40{\r
41 EFI_STATUS Status;\r
42\r
43 Status = UsbCtrlRequest (\r
44 HubDev,\r
45 EfiUsbNoData,\r
46 USB_REQ_TYPE_CLASS,\r
47 USB_HUB_TARGET_HUB,\r
48 USB_HUB_REQ_CLEAR_FEATURE,\r
49 Feature,\r
50 0,\r
51 NULL,\r
52 0\r
53 );\r
54\r
55 return Status;\r
56}\r
57\r
58\r
59/**\r
8616fc4c 60 Clear the feature of the device's port.\r
e237e7ae 61\r
8616fc4c 62 @param HubDev The hub device.\r
63 @param Port The port to clear feature.\r
64 @param Feature The feature to clear.\r
e237e7ae 65\r
66 @retval EFI_SUCCESS The feature of the port is cleared.\r
67 @retval Others Failed to clear the feature.\r
68\r
69**/\r
e237e7ae 70EFI_STATUS\r
71UsbHubCtrlClearPortFeature (\r
72 IN USB_DEVICE *HubDev,\r
73 IN UINT8 Port,\r
74 IN UINT16 Feature\r
75 )\r
76{\r
77 EFI_STATUS Status;\r
78\r
79 //\r
80 // In USB bus, all the port index starts from 0. But HUB\r
81 // indexes its port from 1. So, port number is added one.\r
82 //\r
83 Status = UsbCtrlRequest (\r
84 HubDev,\r
85 EfiUsbNoData,\r
86 USB_REQ_TYPE_CLASS,\r
87 USB_HUB_TARGET_PORT,\r
88 USB_HUB_REQ_CLEAR_FEATURE,\r
89 Feature,\r
c52fa98c 90 (UINT16) (Port + 1),\r
e237e7ae 91 NULL,\r
92 0\r
93 );\r
94\r
95 return Status;\r
96}\r
97\r
98\r
e237e7ae 99/**\r
100 Clear the transaction translate buffer if full/low\r
101 speed control/bulk transfer failed and the transfer\r
102 uses this hub as translator.Remember to clear the TT\r
103 buffer of transaction translator, not that of the\r
104 parent.\r
105\r
8616fc4c 106 @param HubDev The hub device.\r
107 @param Port The port of the hub.\r
108 @param DevAddr Address of the failed transaction.\r
109 @param EpNum The endpoint number of the failed transaction.\r
110 @param EpType The type of failed transaction.\r
e237e7ae 111\r
8616fc4c 112 @retval EFI_SUCCESS The TT buffer is cleared.\r
113 @retval Others Failed to clear the TT buffer.\r
e237e7ae 114\r
115**/\r
116EFI_STATUS\r
117UsbHubCtrlClearTTBuffer (\r
118 IN USB_DEVICE *HubDev,\r
119 IN UINT8 Port,\r
120 IN UINT16 DevAddr,\r
121 IN UINT16 EpNum,\r
122 IN UINT16 EpType\r
123 )\r
124{\r
125 EFI_STATUS Status;\r
126 UINT16 Value;\r
127\r
128 //\r
129 // Check USB2.0 spec page 424 for wValue's encoding\r
130 //\r
c52fa98c 131 Value = (UINT16) ((EpNum & 0x0F) | (DevAddr << 4) |\r
132 ((EpType & 0x03) << 11) | ((EpNum & 0x80) << 15));\r
e237e7ae 133\r
134 Status = UsbCtrlRequest (\r
135 HubDev,\r
136 EfiUsbNoData,\r
137 USB_REQ_TYPE_CLASS,\r
138 USB_HUB_TARGET_PORT,\r
139 USB_HUB_REQ_CLEAR_TT,\r
140 Value,\r
c52fa98c 141 (UINT16) (Port + 1),\r
e237e7ae 142 NULL,\r
143 0\r
144 );\r
145\r
146 return Status;\r
147}\r
148\r
149\r
150/**\r
8616fc4c 151 Usb hub control transfer to get the hub descriptor.\r
e237e7ae 152\r
8616fc4c 153 @param HubDev The hub device.\r
154 @param Buf The buffer to hold the descriptor.\r
155 @param Len The length to retrieve.\r
e237e7ae 156\r
8616fc4c 157 @retval EFI_SUCCESS The hub descriptor is retrieved.\r
158 @retval Others Failed to retrieve the hub descriptor.\r
e237e7ae 159\r
160**/\r
e237e7ae 161EFI_STATUS\r
162UsbHubCtrlGetHubDesc (\r
163 IN USB_DEVICE *HubDev,\r
164 OUT VOID *Buf,\r
165 IN UINTN Len\r
166 )\r
167{\r
168 EFI_STATUS Status;\r
169\r
170 Status = UsbCtrlRequest (\r
171 HubDev,\r
172 EfiUsbDataIn,\r
173 USB_REQ_TYPE_CLASS,\r
174 USB_HUB_TARGET_HUB,\r
175 USB_HUB_REQ_GET_DESC,\r
176 (UINT16) (USB_DESC_TYPE_HUB << 8),\r
177 0,\r
178 Buf,\r
179 Len\r
180 );\r
181\r
182 return Status;\r
183}\r
184\r
185\r
186/**\r
8616fc4c 187 Usb hub control transfer to get the hub status.\r
e237e7ae 188\r
8616fc4c 189 @param HubDev The hub device.\r
190 @param State The variable to return the status.\r
e237e7ae 191\r
8616fc4c 192 @retval EFI_SUCCESS The hub status is returned in State.\r
193 @retval Others Failed to get the hub status.\r
e237e7ae 194\r
195**/\r
e237e7ae 196EFI_STATUS\r
197UsbHubCtrlGetHubStatus (\r
198 IN USB_DEVICE *HubDev,\r
199 OUT UINT32 *State\r
200 )\r
201{\r
202 EFI_STATUS Status;\r
203\r
204 Status = UsbCtrlRequest (\r
205 HubDev,\r
206 EfiUsbDataIn,\r
207 USB_REQ_TYPE_CLASS,\r
208 USB_HUB_TARGET_HUB,\r
209 USB_HUB_REQ_GET_STATUS,\r
210 0,\r
211 0,\r
212 State,\r
213 4\r
214 );\r
215\r
216 return Status;\r
217}\r
218\r
219\r
220/**\r
8616fc4c 221 Usb hub control transfer to get the port status.\r
e237e7ae 222\r
8616fc4c 223 @param HubDev The hub device.\r
224 @param Port The port of the hub.\r
225 @param State Variable to return the hub port state.\r
e237e7ae 226\r
8616fc4c 227 @retval EFI_SUCCESS The port state is returned in State.\r
228 @retval Others Failed to retrive the port state.\r
e237e7ae 229\r
230**/\r
e237e7ae 231EFI_STATUS\r
232UsbHubCtrlGetPortStatus (\r
233 IN USB_DEVICE *HubDev,\r
234 IN UINT8 Port,\r
235 OUT VOID *State\r
236 )\r
237{\r
238 EFI_STATUS Status;\r
239\r
240 //\r
241 // In USB bus, all the port index starts from 0. But HUB\r
242 // indexes its port from 1. So, port number is added one.\r
243 // No need to convert the hub bit to UEFI definition, they\r
244 // are the same\r
245 //\r
246 Status = UsbCtrlRequest (\r
247 HubDev,\r
248 EfiUsbDataIn,\r
249 USB_REQ_TYPE_CLASS,\r
250 USB_HUB_TARGET_PORT,\r
251 USB_HUB_REQ_GET_STATUS,\r
252 0,\r
c52fa98c 253 (UINT16) (Port + 1),\r
e237e7ae 254 State,\r
255 4\r
256 );\r
257\r
258 return Status;\r
259}\r
260\r
261\r
262/**\r
8616fc4c 263 Usb hub control transfer to reset the TT (Transaction Transaltor).\r
e237e7ae 264\r
8616fc4c 265 @param HubDev The hub device.\r
266 @param Port The port of the hub.\r
e237e7ae 267\r
8616fc4c 268 @retval EFI_SUCCESS The TT of the hub is reset.\r
269 @retval Others Failed to reset the port.\r
e237e7ae 270\r
271**/\r
e237e7ae 272EFI_STATUS\r
273UsbHubCtrlResetTT (\r
274 IN USB_DEVICE *HubDev,\r
275 IN UINT8 Port\r
276 )\r
277{\r
278 EFI_STATUS Status;\r
279\r
280 Status = UsbCtrlRequest (\r
281 HubDev,\r
282 EfiUsbNoData,\r
283 USB_REQ_TYPE_CLASS,\r
284 USB_HUB_TARGET_HUB,\r
285 USB_HUB_REQ_RESET_TT,\r
286 0,\r
c52fa98c 287 (UINT16) (Port + 1),\r
e237e7ae 288 NULL,\r
289 0\r
290 );\r
291\r
292 return Status;\r
293}\r
294\r
295\r
296/**\r
8616fc4c 297 Usb hub control transfer to set the hub feature.\r
e237e7ae 298\r
8616fc4c 299 @param HubDev The hub device.\r
300 @param Feature The feature to set.\r
e237e7ae 301\r
8616fc4c 302 @retval EFI_SUCESS The feature is set for the hub.\r
303 @retval Others Failed to set the feature.\r
e237e7ae 304\r
305**/\r
e237e7ae 306EFI_STATUS\r
307UsbHubCtrlSetHubFeature (\r
308 IN USB_DEVICE *HubDev,\r
309 IN UINT8 Feature\r
310 )\r
311{\r
312 EFI_STATUS Status;\r
313\r
314 Status = UsbCtrlRequest (\r
315 HubDev,\r
316 EfiUsbNoData,\r
317 USB_REQ_TYPE_CLASS,\r
318 USB_HUB_TARGET_HUB,\r
319 USB_HUB_REQ_SET_FEATURE,\r
320 Feature,\r
321 0,\r
322 NULL,\r
323 0\r
324 );\r
325\r
326 return Status;\r
327}\r
328\r
329\r
330/**\r
8616fc4c 331 Usb hub control transfer to set the port feature.\r
e237e7ae 332\r
8616fc4c 333 @param HubDev The Usb hub device.\r
334 @param Port The Usb port to set feature for.\r
335 @param Feature The feature to set.\r
e237e7ae 336\r
8616fc4c 337 @retval EFI_SUCCESS The feature is set for the port.\r
338 @retval Others Failed to set the feature.\r
e237e7ae 339\r
340**/\r
e237e7ae 341EFI_STATUS\r
342UsbHubCtrlSetPortFeature (\r
343 IN USB_DEVICE *HubDev,\r
344 IN UINT8 Port,\r
345 IN UINT8 Feature\r
346 )\r
347{\r
348 EFI_STATUS Status;\r
349\r
350 //\r
351 // In USB bus, all the port index starts from 0. But HUB\r
352 // indexes its port from 1. So, port number is added one.\r
353 //\r
354 Status = UsbCtrlRequest (\r
355 HubDev,\r
356 EfiUsbNoData,\r
357 USB_REQ_TYPE_CLASS,\r
358 USB_HUB_TARGET_PORT,\r
359 USB_HUB_REQ_SET_FEATURE,\r
360 Feature,\r
c52fa98c 361 (UINT16) (Port + 1),\r
e237e7ae 362 NULL,\r
363 0\r
364 );\r
365\r
366 return Status;\r
367}\r
368\r
369\r
370/**\r
371 Read the whole usb hub descriptor. It is necessary\r
372 to do it in two steps because hub descriptor is of\r
8616fc4c 373 variable length.\r
e237e7ae 374\r
8616fc4c 375 @param HubDev The hub device.\r
376 @param HubDesc The variable to return the descriptor.\r
e237e7ae 377\r
8616fc4c 378 @retval EFI_SUCCESS The hub descriptor is read.\r
379 @retval Others Failed to read the hub descriptor.\r
e237e7ae 380\r
381**/\r
e237e7ae 382EFI_STATUS\r
383UsbHubReadDesc (\r
384 IN USB_DEVICE *HubDev,\r
385 OUT EFI_USB_HUB_DESCRIPTOR *HubDesc\r
386 )\r
387{\r
388 EFI_STATUS Status;\r
389\r
390 //\r
391 // First get the hub descriptor length\r
392 //\r
393 Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);\r
394\r
395 if (EFI_ERROR (Status)) {\r
396 return Status;\r
397 }\r
398\r
399 //\r
400 // Get the whole hub descriptor\r
401 //\r
402 Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);\r
403\r
404 return Status;\r
405}\r
406\r
407\r
408\r
409/**\r
410 Ack the hub change bits. If these bits are not ACKed, Hub will\r
411 always return changed bit map from its interrupt endpoint.\r
412\r
8616fc4c 413 @param HubDev The hub device.\r
e237e7ae 414\r
8616fc4c 415 @retval EFI_SUCCESS The hub change status is ACKed.\r
416 @retval Others Failed to ACK the hub status.\r
e237e7ae 417\r
418**/\r
419EFI_STATUS\r
420UsbHubAckHubStatus (\r
421 IN USB_DEVICE *HubDev\r
422 )\r
423{\r
424 EFI_USB_PORT_STATUS HubState;\r
425 EFI_STATUS Status;\r
426\r
427 Status = UsbHubCtrlGetHubStatus (HubDev, (UINT32 *) &HubState);\r
428\r
429 if (EFI_ERROR (Status)) {\r
430 return Status;\r
431 }\r
432\r
433 if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_LOCAL_POWER)) {\r
434 UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_LOCAL_POWER);\r
435 }\r
436\r
437 if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_OVER_CURRENT)) {\r
438 UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_OVER_CURRENT);\r
439 }\r
440\r
441 return EFI_SUCCESS;\r
442}\r
443\r
444\r
445/**\r
446 Test whether the interface is a hub interface.\r
447\r
8616fc4c 448 @param UsbIf The interface to test.\r
e237e7ae 449\r
8616fc4c 450 @retval TRUE The interface is a hub interface.\r
451 @retval FALSE The interface isn't a hub interface.\r
e237e7ae 452\r
453**/\r
454BOOLEAN\r
455UsbIsHubInterface (\r
456 IN USB_INTERFACE *UsbIf\r
457 )\r
458{\r
459 EFI_USB_INTERFACE_DESCRIPTOR *Setting;\r
460\r
461 //\r
462 // If the hub is a high-speed hub with multiple TT,\r
463 // the hub will has a default setting of single TT.\r
464 //\r
465 Setting = &UsbIf->IfSetting->Desc;\r
466\r
467 if ((Setting->InterfaceClass == USB_HUB_CLASS_CODE) &&\r
468 (Setting->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {\r
469\r
470 return TRUE;\r
471 }\r
472\r
473 return FALSE;\r
474}\r
475\r
476\r
477/**\r
478 The callback function to the USB hub status change\r
479 interrupt endpoint. It is called periodically by\r
480 the underlying host controller.\r
481\r
8616fc4c 482 @param Data The data read.\r
483 @param DataLength The length of the data read.\r
484 @param Context The context.\r
485 @param Result The result of the last interrupt transfer.\r
e237e7ae 486\r
8616fc4c 487 @retval EFI_SUCCESS The process is OK.\r
488 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.\r
e237e7ae 489\r
490**/\r
e237e7ae 491EFI_STATUS\r
492UsbOnHubInterrupt (\r
493 IN VOID *Data,\r
494 IN UINTN DataLength,\r
495 IN VOID *Context,\r
496 IN UINT32 Result\r
497 )\r
498{\r
499 USB_INTERFACE *HubIf;\r
500 EFI_USB_IO_PROTOCOL *UsbIo;\r
501 EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc;\r
502 EFI_STATUS Status;\r
503\r
504 HubIf = (USB_INTERFACE *) Context;\r
505 UsbIo = &(HubIf->UsbIo);\r
506 EpDesc = &(HubIf->HubEp->Desc);\r
507\r
508 if (Result != EFI_USB_NOERROR) {\r
509 //\r
510 // If endpoint is stalled, clear the stall. Use UsbIo to access\r
511 // the control transfer so internal status are maintained.\r
512 //\r
513 if (USB_BIT_IS_SET (Result, EFI_USB_ERR_STALL)) {\r
514 UsbIoClearFeature (\r
515 UsbIo,\r
516 USB_TARGET_ENDPOINT,\r
517 USB_FEATURE_ENDPOINT_HALT,\r
518 EpDesc->EndpointAddress\r
519 );\r
520 }\r
521\r
522 //\r
523 // Delete and submit a new async interrupt\r
524 //\r
525 Status = UsbIo->UsbAsyncInterruptTransfer (\r
526 UsbIo,\r
527 EpDesc->EndpointAddress,\r
528 FALSE,\r
529 0,\r
530 0,\r
531 NULL,\r
532 NULL\r
533 );\r
534\r
535 if (EFI_ERROR (Status)) {\r
d2577026 536 DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to remove async transfer - %r\n", Status));\r
e237e7ae 537 return Status;\r
538 }\r
539\r
540 Status = UsbIo->UsbAsyncInterruptTransfer (\r
541 UsbIo,\r
542 EpDesc->EndpointAddress,\r
543 TRUE,\r
544 USB_HUB_POLL_INTERVAL,\r
545 HubIf->NumOfPort / 8 + 1,\r
546 UsbOnHubInterrupt,\r
547 HubIf\r
548 );\r
549\r
550 if (EFI_ERROR (Status)) {\r
d2577026 551 DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to submit new async transfer - %r\n", Status));\r
e237e7ae 552 }\r
553\r
554 return Status;\r
555 }\r
556\r
557 if ((DataLength == 0) || (Data == NULL)) {\r
558 return EFI_SUCCESS;\r
559 }\r
560\r
561 //\r
562 // OK, actually something is changed, save the change map\r
563 // then signal the HUB to do enumeration. This is a good\r
564 // practise since UsbOnHubInterrupt is called in the context\r
565 // of host contrller's AsyncInterrupt monitor.\r
566 //\r
567 HubIf->ChangeMap = AllocateZeroPool (DataLength);\r
568\r
569 if (HubIf->ChangeMap == NULL) {\r
570 return EFI_OUT_OF_RESOURCES;\r
571 }\r
572\r
573 CopyMem (HubIf->ChangeMap, Data, DataLength);\r
574 gBS->SignalEvent (HubIf->HubNotify);\r
575\r
576 return EFI_SUCCESS;\r
577}\r
578\r
579//\r
580// Array that maps the change bit to feature value which is\r
581// used to clear these change bit. USB HUB API will clear\r
582// these change bit automatically. For non-root hub, these\r
583// bits determine whether hub will report the port in changed\r
584// bit maps.\r
585//\r
586#define USB_HUB_MAP_SIZE 5\r
587\r
588USB_CHANGE_FEATURE_MAP mHubFeatureMap[USB_HUB_MAP_SIZE] = {\r
23c326c2 589 {USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},\r
590 {USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},\r
591 {USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},\r
592 {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},\r
593 {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange},\r
e237e7ae 594};\r
595\r
596#define USB_ROOT_HUB_MAP_SIZE 5\r
597\r
598USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[USB_ROOT_HUB_MAP_SIZE] = {\r
599 {USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},\r
600 {USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},\r
601 {USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},\r
602 {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},\r
603 {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange},\r
604};\r
605\r
606\r
607\r
608/**\r
8616fc4c 609 Initialize the device for a non-root hub.\r
e237e7ae 610\r
8616fc4c 611 @param HubIf The USB hub interface.\r
e237e7ae 612\r
8616fc4c 613 @retval EFI_SUCCESS The hub is initialized.\r
614 @retval EFI_DEVICE_ERROR Failed to initialize the hub.\r
e237e7ae 615\r
616**/\r
e237e7ae 617EFI_STATUS\r
618UsbHubInit (\r
619 IN USB_INTERFACE *HubIf\r
620 )\r
621{\r
622 EFI_USB_HUB_DESCRIPTOR HubDesc;\r
623 USB_ENDPOINT_DESC *EpDesc;\r
624 USB_INTERFACE_SETTING *Setting;\r
625 EFI_USB_IO_PROTOCOL *UsbIo;\r
626 USB_DEVICE *HubDev;\r
627 EFI_STATUS Status;\r
628 UINT8 Index;\r
629\r
630 //\r
631 // Locate the interrupt endpoint for port change map\r
632 //\r
633 HubIf->IsHub = FALSE;\r
634 Setting = HubIf->IfSetting;\r
635 HubDev = HubIf->Device;\r
636 EpDesc = NULL;\r
637\r
638 for (Index = 0; Index < Setting->Desc.NumEndpoints; Index++) {\r
639 ASSERT ((Setting->Endpoints != NULL) && (Setting->Endpoints[Index] != NULL));\r
640\r
641 EpDesc = Setting->Endpoints[Index];\r
642\r
643 if (USB_BIT_IS_SET (EpDesc->Desc.EndpointAddress, USB_ENDPOINT_DIR_IN) &&\r
644 (USB_ENDPOINT_TYPE (&EpDesc->Desc) == USB_ENDPOINT_INTERRUPT)) {\r
645 break;\r
646 }\r
647 }\r
648\r
649 if (Index == Setting->Desc.NumEndpoints) {\r
d2577026 650 DEBUG (( EFI_D_ERROR, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev->Address));\r
e237e7ae 651 return EFI_DEVICE_ERROR;\r
652 }\r
653\r
654 Status = UsbHubReadDesc (HubDev, &HubDesc);\r
655\r
656 if (EFI_ERROR (Status)) {\r
d2577026 657 DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status));\r
e237e7ae 658 return Status;\r
659 }\r
660\r
661 HubIf->NumOfPort = HubDesc.NumPorts;\r
662\r
d2577026 663 DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort));\r
e237e7ae 664\r
665 //\r
666 // Create an event to enumerate the hub's port. On\r
667 //\r
668 Status = gBS->CreateEvent (\r
669 EVT_NOTIFY_SIGNAL,\r
670 TPL_CALLBACK,\r
671 UsbHubEnumeration,\r
672 HubIf,\r
673 &HubIf->HubNotify\r
674 );\r
675\r
676 if (EFI_ERROR (Status)) {\r
d2577026 677 DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to create signal for hub %d - %r\n",\r
e237e7ae 678 HubDev->Address, Status));\r
679\r
680 return Status;\r
681 }\r
682\r
683 //\r
684 // Create AsyncInterrupt to query hub port change endpoint\r
685 // periodically. If the hub ports are changed, hub will return\r
686 // changed port map from the interrupt endpoint. The port map\r
687 // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for\r
688 // host change status).\r
689 //\r
690 UsbIo = &HubIf->UsbIo;\r
691 Status = UsbIo->UsbAsyncInterruptTransfer (\r
692 UsbIo,\r
693 EpDesc->Desc.EndpointAddress,\r
694 TRUE,\r
695 USB_HUB_POLL_INTERVAL,\r
696 HubIf->NumOfPort / 8 + 1,\r
697 UsbOnHubInterrupt,\r
698 HubIf\r
699 );\r
700\r
701 if (EFI_ERROR (Status)) {\r
d2577026 702 DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n",\r
e237e7ae 703 HubDev->Address, Status));\r
704\r
705 gBS->CloseEvent (HubIf->HubNotify);\r
706 HubIf->HubNotify = NULL;\r
707\r
708 return Status;\r
709 }\r
710\r
711 //\r
712 // OK, set IsHub to TRUE. Now usb bus can handle this device\r
713 // as a working HUB. If failed eariler, bus driver will not\r
714 // recognize it as a hub. Other parts of the bus should be able\r
715 // to work.\r
716 //\r
717 HubIf->IsHub = TRUE;\r
718 HubIf->HubApi = &mUsbHubApi;\r
719 HubIf->HubEp = EpDesc;\r
720\r
721 //\r
722 // Feed power to all the hub ports. It should be ok\r
723 // for both gang/individual powered hubs.\r
724 //\r
725 for (Index = 0; Index < HubDesc.NumPorts; Index++) {\r
c52fa98c 726 UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);\r
e237e7ae 727 }\r
728\r
41e8ff27 729 gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);\r
e237e7ae 730 UsbHubAckHubStatus (HubIf->Device);\r
731\r
d2577026 732 DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address));\r
e237e7ae 733 return Status;\r
734}\r
735\r
736\r
737\r
738/**\r
739 Get the port status. This function is required to\r
740 ACK the port change bits although it will return\r
741 the port changes in PortState. Bus enumeration code\r
742 doesn't need to ACK the port change bits.\r
743\r
8616fc4c 744 @param HubIf The hub interface.\r
745 @param Port The port of the hub to get state.\r
746 @param PortState Variable to return the port state.\r
e237e7ae 747\r
8616fc4c 748 @retval EFI_SUCCESS The port status is successfully returned.\r
749 @retval Others Failed to return the status.\r
e237e7ae 750\r
751**/\r
e237e7ae 752EFI_STATUS\r
753UsbHubGetPortStatus (\r
754 IN USB_INTERFACE *HubIf,\r
755 IN UINT8 Port,\r
756 OUT EFI_USB_PORT_STATUS *PortState\r
757 )\r
758{\r
759 EFI_STATUS Status;\r
760\r
761 Status = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);\r
762\r
763 return Status;\r
764}\r
765\r
766\r
767\r
768/**\r
769 Clear the port change status.\r
770\r
8616fc4c 771 @param HubIf The hub interface.\r
772 @param Port The hub port.\r
e237e7ae 773\r
8616fc4c 774 @return None.\r
e237e7ae 775\r
776**/\r
e237e7ae 777VOID\r
778UsbHubClearPortChange (\r
779 IN USB_INTERFACE *HubIf,\r
780 IN UINT8 Port\r
781 )\r
782{\r
783 EFI_USB_PORT_STATUS PortState;\r
784 USB_CHANGE_FEATURE_MAP *Map;\r
785 UINTN Index;\r
786 EFI_STATUS Status;\r
787\r
788 Status = UsbHubGetPortStatus (HubIf, Port, &PortState);\r
789\r
790 if (EFI_ERROR (Status)) {\r
791 return;\r
792 }\r
793\r
794 //\r
795 // OK, get the usb port status, now ACK the change bits.\r
796 // Don't return error when failed to clear the change bits.\r
797 // It may lead to extra port state report. USB bus should\r
798 // be able to handle this.\r
799 //\r
800 for (Index = 0; Index < USB_HUB_MAP_SIZE; Index++) {\r
801 Map = &mHubFeatureMap[Index];\r
802\r
803 if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
23c326c2 804 UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT16) Map->Feature);\r
e237e7ae 805 }\r
806 }\r
807}\r
808\r
809\r
810\r
811/**\r
8616fc4c 812 Function to set the port feature for non-root hub.\r
e237e7ae 813\r
8616fc4c 814 @param HubIf The hub interface.\r
815 @param Port The port of the hub.\r
816 @param Feature The feature of the port to set.\r
e237e7ae 817\r
8616fc4c 818 @retval EFI_SUCCESS The hub port feature is set.\r
819 @retval Others Failed to set the port feature.\r
e237e7ae 820\r
821**/\r
e237e7ae 822EFI_STATUS\r
823UsbHubSetPortFeature (\r
824 IN USB_INTERFACE *HubIf,\r
825 IN UINT8 Port,\r
826 IN EFI_USB_PORT_FEATURE Feature\r
827 )\r
828{\r
829 EFI_STATUS Status;\r
830\r
c52fa98c 831 Status = UsbHubCtrlSetPortFeature (HubIf->Device, Port, (UINT8) Feature);\r
e237e7ae 832\r
833 return Status;\r
834}\r
835\r
836\r
837/**\r
8616fc4c 838 Interface function to clear the port feature for non-root hub.\r
e237e7ae 839\r
8616fc4c 840 @param HubIf The hub interface.\r
841 @param Port The port of the hub to clear feature for.\r
842 @param Feature The feature to clear.\r
e237e7ae 843\r
8616fc4c 844 @retval EFI_SUCCESS The port feature is cleared.\r
845 @retval Others Failed to clear the port feature.\r
e237e7ae 846\r
847**/\r
e237e7ae 848EFI_STATUS\r
849UsbHubClearPortFeature (\r
850 IN USB_INTERFACE *HubIf,\r
851 IN UINT8 Port,\r
852 IN EFI_USB_PORT_FEATURE Feature\r
853 )\r
854{\r
855 EFI_STATUS Status;\r
856\r
c52fa98c 857 Status = UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT8) Feature);\r
e237e7ae 858\r
859 return Status;\r
860}\r
861\r
862\r
863/**\r
8616fc4c 864 Interface funtion to reset the port.\r
e237e7ae 865\r
8616fc4c 866 @param HubIf The hub interface.\r
867 @param Port The port to reset.\r
e237e7ae 868\r
8616fc4c 869 @retval EFI_SUCCESS The hub port is reset.\r
870 @retval EFI_TIMEOUT Failed to reset the port in time.\r
871 @retval Others Failed to reset the port.\r
e237e7ae 872\r
873**/\r
e237e7ae 874EFI_STATUS\r
875UsbHubResetPort (\r
876 IN USB_INTERFACE *HubIf,\r
877 IN UINT8 Port\r
878 )\r
879{\r
880 EFI_USB_PORT_STATUS PortState;\r
881 UINTN Index;\r
882 EFI_STATUS Status;\r
883\r
c52fa98c 884 Status = UsbHubSetPortFeature (HubIf, Port, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_RESET);\r
e237e7ae 885\r
886 if (EFI_ERROR (Status)) {\r
887 return Status;\r
888 }\r
889\r
890 //\r
891 // Drive the reset signal for at least 10ms. Check USB 2.0 Spec\r
892 // section 7.1.7.5 for timing requirements.\r
893 //\r
41e8ff27 894 gBS->Stall (USB_SET_PORT_RESET_STALL);\r
e237e7ae 895\r
896 //\r
897 // USB hub will clear RESET bit if reset is actually finished.\r
898 //\r
899 ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));\r
900\r
41e8ff27 901 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
e237e7ae 902 Status = UsbHubGetPortStatus (HubIf, Port, &PortState);\r
903\r
904 if (!EFI_ERROR (Status) &&\r
905 !USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {\r
906\r
907 return EFI_SUCCESS;\r
908 }\r
909\r
41e8ff27 910 gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);\r
e237e7ae 911 }\r
912\r
913 return EFI_TIMEOUT;\r
914}\r
915\r
916\r
917/**\r
8616fc4c 918 Release the hub's control of the interface.\r
e237e7ae 919\r
8616fc4c 920 @param HubIf The hub interface.\r
e237e7ae 921\r
8616fc4c 922 @retval EFI_SUCCESS The interface is release of hub control.\r
e237e7ae 923\r
924**/\r
e237e7ae 925EFI_STATUS\r
926UsbHubRelease (\r
927 IN USB_INTERFACE *HubIf\r
928 )\r
929{\r
930 EFI_USB_IO_PROTOCOL *UsbIo;\r
931 EFI_STATUS Status;\r
932\r
933 UsbIo = &HubIf->UsbIo;\r
934 Status = UsbIo->UsbAsyncInterruptTransfer (\r
935 UsbIo,\r
936 HubIf->HubEp->Desc.EndpointAddress,\r
937 FALSE,\r
938 USB_HUB_POLL_INTERVAL,\r
939 0,\r
940 NULL,\r
941 0\r
942 );\r
943\r
944 if (EFI_ERROR (Status)) {\r
945 return Status;\r
946 }\r
947\r
948 gBS->CloseEvent (HubIf->HubNotify);\r
949\r
950 HubIf->IsHub = FALSE;\r
951 HubIf->HubApi = NULL;\r
952 HubIf->HubEp = NULL;\r
953 HubIf->HubNotify = NULL;\r
954\r
d2577026 955 DEBUG (( EFI_D_INFO, "UsbHubRelease: hub device %d released\n", HubIf->Device->Address));\r
e237e7ae 956 return EFI_SUCCESS;\r
957}\r
958\r
959\r
960\r
961/**\r
8616fc4c 962 Initialize the interface for root hub.\r
e237e7ae 963\r
8616fc4c 964 @param HubIf The root hub interface.\r
e237e7ae 965\r
8616fc4c 966 @retval EFI_SUCCESS The interface is initialied for root hub.\r
967 @retval Others Failed to initialize the hub.\r
e237e7ae 968\r
969**/\r
e237e7ae 970EFI_STATUS\r
971UsbRootHubInit (\r
972 IN USB_INTERFACE *HubIf\r
973 )\r
974{\r
975 EFI_STATUS Status;\r
976 UINT8 MaxSpeed;\r
977 UINT8 NumOfPort;\r
978 UINT8 Support64;\r
979\r
980 Status = UsbHcGetCapability (HubIf->Device->Bus, &MaxSpeed, &NumOfPort, &Support64);\r
981\r
982 if (EFI_ERROR (Status)) {\r
983 return Status;\r
984 }\r
985\r
0e549d5b 986 DEBUG (( EFI_D_INFO, "UsbRootHubInit: root hub %p - max speed %d, %d ports\n",\r
e237e7ae 987 HubIf, MaxSpeed, NumOfPort));\r
988\r
989 HubIf->IsHub = TRUE;\r
990 HubIf->HubApi = &mUsbRootHubApi;\r
991 HubIf->HubEp = NULL;\r
992 HubIf->MaxSpeed = MaxSpeed;\r
993 HubIf->NumOfPort = NumOfPort;\r
994 HubIf->HubNotify = NULL;\r
995\r
996 //\r
997 // Create a timer to poll root hub ports periodically\r
998 //\r
999 Status = gBS->CreateEvent (\r
1000 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1001 TPL_CALLBACK,\r
1002 UsbRootHubEnumeration,\r
1003 HubIf,\r
1004 &HubIf->HubNotify\r
1005 );\r
1006\r
1007 if (EFI_ERROR (Status)) {\r
1008 return Status;\r
1009 }\r
1010\r
d2577026 1011 //\r
1012 // It should signal the event immediately here, or device detection\r
1013 // by bus enumeration might be delayed by the timer interval.\r
1014 //\r
1015 gBS->SignalEvent (HubIf->HubNotify);\r
1016\r
e237e7ae 1017 Status = gBS->SetTimer (\r
1018 HubIf->HubNotify,\r
1019 TimerPeriodic,\r
1020 USB_ROOTHUB_POLL_INTERVAL\r
1021 );\r
1022\r
1023 if (EFI_ERROR (Status)) {\r
1024 gBS->CloseEvent (HubIf->HubNotify);\r
1025 }\r
1026\r
1027 return Status;\r
1028}\r
1029\r
1030\r
e237e7ae 1031/**\r
1032 Get the port status. This function is required to\r
1033 ACK the port change bits although it will return\r
1034 the port changes in PortState. Bus enumeration code\r
1035 doesn't need to ACK the port change bits.\r
1036\r
8616fc4c 1037 @param HubIf The root hub interface.\r
1038 @param Port The root hub port to get the state.\r
1039 @param PortState Variable to return the port state.\r
e237e7ae 1040\r
8616fc4c 1041 @retval EFI_SUCCESS The port state is returned.\r
1042 @retval Others Failed to retrieve the port state.\r
e237e7ae 1043\r
1044**/\r
e237e7ae 1045EFI_STATUS\r
1046UsbRootHubGetPortStatus (\r
1047 IN USB_INTERFACE *HubIf,\r
1048 IN UINT8 Port,\r
1049 OUT EFI_USB_PORT_STATUS *PortState\r
1050 )\r
1051{\r
1052 USB_BUS *Bus;\r
1053 EFI_STATUS Status;\r
1054\r
1055 Bus = HubIf->Device->Bus;\r
1056 Status = UsbHcGetRootHubPortStatus (Bus, Port, PortState);\r
1057\r
1058 return Status;\r
1059}\r
1060\r
1061\r
1062/**\r
1063 Clear the port change status.\r
1064\r
8616fc4c 1065 @param HubIf The root hub interface.\r
1066 @param Port The root hub port.\r
e237e7ae 1067\r
eb6d5108 1068 @return None.\r
e237e7ae 1069\r
1070**/\r
e237e7ae 1071VOID\r
1072UsbRootHubClearPortChange (\r
1073 IN USB_INTERFACE *HubIf,\r
1074 IN UINT8 Port\r
1075 )\r
1076{\r
1077 EFI_USB_PORT_STATUS PortState;\r
1078 USB_CHANGE_FEATURE_MAP *Map;\r
1079 UINTN Index;\r
1080 EFI_STATUS Status;\r
1081\r
1082 Status = UsbRootHubGetPortStatus (HubIf, Port, &PortState);\r
1083\r
1084 if (EFI_ERROR (Status)) {\r
1085 return;\r
1086 }\r
1087\r
1088 //\r
1089 // OK, get the usb port status, now ACK the change bits.\r
1090 // Don't return error when failed to clear the change bits.\r
1091 // It may lead to extra port state report. USB bus should\r
1092 // be able to handle this.\r
1093 //\r
1094 for (Index = 0; Index < USB_ROOT_HUB_MAP_SIZE; Index++) {\r
1095 Map = &mRootHubFeatureMap[Index];\r
1096\r
1097 if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
c52fa98c 1098 UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, (EFI_USB_PORT_FEATURE) Map->Feature);\r
e237e7ae 1099 }\r
1100 }\r
1101}\r
1102\r
1103\r
e237e7ae 1104/**\r
8616fc4c 1105 Set the root hub port feature.\r
e237e7ae 1106\r
8616fc4c 1107 @param HubIf The Usb hub interface.\r
1108 @param Port The hub port.\r
1109 @param Feature The feature to set.\r
e237e7ae 1110\r
8616fc4c 1111 @retval EFI_SUCCESS The root hub port is set with the feature.\r
1112 @retval Others Failed to set the feature.\r
e237e7ae 1113\r
1114**/\r
e237e7ae 1115EFI_STATUS\r
1116UsbRootHubSetPortFeature (\r
1117 IN USB_INTERFACE *HubIf,\r
1118 IN UINT8 Port,\r
1119 IN EFI_USB_PORT_FEATURE Feature\r
1120 )\r
1121{\r
1122 EFI_STATUS Status;\r
1123\r
1124 Status = UsbHcSetRootHubPortFeature (HubIf->Device->Bus, Port, Feature);\r
1125\r
1126 return Status;\r
1127}\r
1128\r
1129\r
1130/**\r
8616fc4c 1131 Clear the root hub port feature.\r
e237e7ae 1132\r
8616fc4c 1133 @param HubIf The root hub interface.\r
1134 @param Port The root hub port.\r
1135 @param Feature The feature to clear.\r
e237e7ae 1136\r
8616fc4c 1137 @retval EFI_SUCCESS The root hub port is cleared of the feature.\r
1138 @retval Others Failed to clear the feature.\r
e237e7ae 1139\r
1140**/\r
e237e7ae 1141EFI_STATUS\r
1142UsbRootHubClearPortFeature (\r
1143 IN USB_INTERFACE *HubIf,\r
1144 IN UINT8 Port,\r
1145 IN EFI_USB_PORT_FEATURE Feature\r
1146 )\r
1147{\r
1148 EFI_STATUS Status;\r
1149\r
1150 Status = UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, Feature);\r
1151\r
1152 return Status;\r
1153}\r
1154\r
1155\r
1156/**\r
8616fc4c 1157 Interface funtion to reset the root hub port.\r
e237e7ae 1158\r
8616fc4c 1159 @param RootIf The root hub interface.\r
1160 @param Port The port to reset.\r
e237e7ae 1161\r
8616fc4c 1162 @retval EFI_SUCCESS The hub port is reset.\r
1163 @retval EFI_TIMEOUT Failed to reset the port in time.\r
1164 @retval EFI_NOT_FOUND The low/full speed device connected to high speed.\r
1165 root hub is released to the companion UHCI.\r
1166 @retval Others Failed to reset the port.\r
e237e7ae 1167\r
1168**/\r
e237e7ae 1169EFI_STATUS\r
1170UsbRootHubResetPort (\r
1171 IN USB_INTERFACE *RootIf,\r
1172 IN UINT8 Port\r
1173 )\r
1174{\r
1175 USB_BUS *Bus;\r
1176 EFI_STATUS Status;\r
1177 EFI_USB_PORT_STATUS PortState;\r
1178 UINTN Index;\r
1179\r
1180 //\r
1181 // Notice: although EHCI requires that ENABLED bit be cleared\r
1182 // when reset the port, we don't need to care that here. It\r
1183 // should be handled in the EHCI driver.\r
1184 //\r
1185 Bus = RootIf->Device->Bus;\r
1186 Status = UsbHcSetRootHubPortFeature (Bus, Port, EfiUsbPortReset);\r
1187\r
1188 if (EFI_ERROR (Status)) {\r
d2577026 1189 DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to start reset on port %d\n", Port));\r
e237e7ae 1190 return Status;\r
1191 }\r
1192\r
1193 //\r
1194 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1195 // section 7.1.7.5 for timing requirements.\r
1196 //\r
41e8ff27 1197 gBS->Stall (USB_SET_ROOT_PORT_RESET_STALL);\r
e237e7ae 1198\r
1199 Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset);\r
1200\r
1201 if (EFI_ERROR (Status)) {\r
d2577026 1202 DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to clear reset on port %d\n", Port));\r
e237e7ae 1203 return Status;\r
1204 }\r
1205\r
41e8ff27 1206 gBS->Stall (USB_CLR_ROOT_PORT_RESET_STALL);\r
e237e7ae 1207\r
1208 //\r
1209 // USB host controller won't clear the RESET bit until\r
1210 // reset is actually finished.\r
1211 //\r
1212 ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));\r
1213\r
41e8ff27 1214 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
e237e7ae 1215 Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);\r
1216\r
1217 if (EFI_ERROR (Status)) {\r
1218 return Status;\r
1219 }\r
1220\r
1221 if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {\r
1222 break;\r
1223 }\r
1224\r
41e8ff27 1225 gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);\r
e237e7ae 1226 }\r
1227\r
41e8ff27 1228 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
1229 DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port));\r
e237e7ae 1230 return EFI_TIMEOUT;\r
1231 }\r
1232\r
1233 if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_ENABLE)) {\r
1234 //\r
1235 // OK, the port is reset. If root hub is of high speed and\r
1236 // the device is of low/full speed, release the ownership to\r
1237 // companion UHCI. If root hub is of full speed, it won't\r
1238 // automatically enable the port, we need to enable it manually.\r
1239 //\r
1240 if (RootIf->MaxSpeed == EFI_USB_SPEED_HIGH) {\r
d2577026 1241 DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: release low/full speed device (%d) to UHCI\n", Port));\r
e237e7ae 1242\r
1243 UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortOwner);\r
1244 return EFI_NOT_FOUND;\r
1245\r
1246 } else {\r
1247\r
1248 Status = UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortEnable);\r
1249\r
1250 if (EFI_ERROR (Status)) {\r
d2577026 1251 DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to enable port %d for UHCI\n", Port));\r
e237e7ae 1252 return Status;\r
1253 }\r
1254\r
41e8ff27 1255 gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL);\r
e237e7ae 1256 }\r
1257 }\r
1258\r
1259 return EFI_SUCCESS;\r
1260}\r
1261\r
1262\r
1263/**\r
8616fc4c 1264 Release the root hub's control of the interface.\r
e237e7ae 1265\r
8616fc4c 1266 @param HubIf The root hub interface.\r
e237e7ae 1267\r
1268 @retval EFI_SUCCESS The root hub's control of the interface is\r
1269 released.\r
1270\r
1271**/\r
e237e7ae 1272EFI_STATUS\r
1273UsbRootHubRelease (\r
1274 IN USB_INTERFACE *HubIf\r
1275 )\r
1276{\r
0e549d5b 1277 DEBUG (( EFI_D_INFO, "UsbRootHubRelease: root hub released for hub %p\n", HubIf));\r
e237e7ae 1278\r
1279 gBS->SetTimer (HubIf->HubNotify, TimerCancel, USB_ROOTHUB_POLL_INTERVAL);\r
1280 gBS->CloseEvent (HubIf->HubNotify);\r
1281\r
1282 return EFI_SUCCESS;\r
1283}\r
1284\r
1285USB_HUB_API mUsbHubApi = {\r
1286 UsbHubInit,\r
1287 UsbHubGetPortStatus,\r
1288 UsbHubClearPortChange,\r
1289 UsbHubSetPortFeature,\r
1290 UsbHubClearPortFeature,\r
1291 UsbHubResetPort,\r
1292 UsbHubRelease\r
1293};\r
1294\r
1295USB_HUB_API mUsbRootHubApi = {\r
1296 UsbRootHubInit,\r
1297 UsbRootHubGetPortStatus,\r
1298 UsbRootHubClearPortChange,\r
1299 UsbRootHubSetPortFeature,\r
1300 UsbRootHubClearPortFeature,\r
1301 UsbRootHubResetPort,\r
1302 UsbRootHubRelease\r
1303};\r