]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
Rename the Msa2Inf.exe to MigrationMsa2Inf to indicate the real usage.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / usbbus.c
CommitLineData
e237e7ae 1/** @file\r
2\r
3Copyright (c) 2004 - 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 UsbBus.c\r
15\r
16 Abstract:\r
17\r
18 Usb Bus Driver Binding and Bus IO Protocol\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// USB_BUS_PROTOCOL is only used to locate USB_BUS\r
29//\r
30EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;\r
31\r
32\r
33/**\r
34 USB_IO function to execute a control transfer. This\r
35 function will execute the USB transfer. If transfer\r
36 successes, it will sync the internal state of USB bus\r
37 with device state.\r
38\r
39 @param This The USB_IO instance\r
40 @param Request The control transfer request\r
41 @param Direction Direction for data stage\r
42 @param Timeout The time to wait before timeout\r
43 @param Data The buffer holding the data\r
44 @param DataLength Then length of the data\r
45 @param UsbStatus USB result\r
46\r
47 @retval EFI_INVALID_PARAMETER The parameters are invalid\r
48 @retval EFI_SUCCESS The control transfer succeded.\r
49 @retval Others Failed to execute the transfer\r
50\r
51**/\r
52STATIC\r
53EFI_STATUS\r
54EFIAPI\r
55UsbIoControlTransfer (\r
56 IN EFI_USB_IO_PROTOCOL *This,\r
57 IN EFI_USB_DEVICE_REQUEST *Request,\r
58 IN EFI_USB_DATA_DIRECTION Direction,\r
59 IN UINT32 Timeout,\r
60 IN OUT VOID *Data, OPTIONAL\r
61 IN UINTN DataLength, OPTIONAL\r
62 OUT UINT32 *UsbStatus\r
63 )\r
64{\r
65 USB_DEVICE *Dev;\r
66 USB_INTERFACE *UsbIf;\r
67 USB_ENDPOINT_DESC *EpDesc;\r
68 EFI_TPL OldTpl;\r
69 EFI_STATUS Status;\r
70\r
71 if (UsbStatus == NULL) {\r
72 return EFI_INVALID_PARAMETER;\r
73 }\r
74\r
75 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
76\r
77 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
78 Dev = UsbIf->Device;\r
79\r
80 Status = UsbHcControlTransfer (\r
81 Dev->Bus,\r
82 Dev->Address,\r
83 Dev->Speed,\r
84 Dev->MaxPacket0,\r
85 Request,\r
86 Direction,\r
87 Data,\r
88 &DataLength,\r
89 (UINTN) Timeout,\r
90 &Dev->Translator,\r
91 UsbStatus\r
92 );\r
93\r
94 if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
95 //\r
96 // Clear TT buffer when CTRL/BULK split transaction failes\r
97 // Clear the TRANSLATOR TT buffer, not parent's buffer\r
98 //\r
99 if (Dev->Translator.TranslatorHubAddress != 0) {\r
100 UsbHubCtrlClearTTBuffer (\r
101 Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
102 Dev->Translator.TranslatorPortNumber,\r
103 Dev->Address,\r
104 0,\r
105 USB_ENDPOINT_CONTROL\r
106 );\r
107 }\r
108\r
109 goto ON_EXIT;\r
110 }\r
111\r
112 //\r
113 // Some control transfer will change the device's internal\r
114 // status, such as Set_Configuration and Set_Interface.\r
115 // We must synchronize the bus driver's status with that in\r
116 // device. We ignore the Set_Descriptor request because it's\r
117 // hardly used by any device, especially in pre-boot environment\r
118 //\r
119\r
120 //\r
121 // Reset the endpoint toggle when endpoint stall is cleared\r
122 //\r
123 if ((Request->Request == USB_REQ_CLEAR_FEATURE) &&\r
124 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
125 USB_TARGET_ENDPOINT)) &&\r
126 (Request->Value == USB_FEATURE_ENDPOINT_HALT)) {\r
127\r
128 EpDesc = UsbGetEndpointDesc (UsbIf, (UINT8) Request->Index);\r
129\r
130 if (EpDesc != NULL) {\r
131 EpDesc->Toggle = 0;\r
132 }\r
133 }\r
134\r
135 //\r
136 // Select a new configuration. This is a dangerous action. Upper driver\r
137 // should stop use its current UsbIo after calling this driver. The old\r
138 // UsbIo will be uninstalled and new UsbIo be installed. We can't use\r
139 // ReinstallProtocol since interfaces in different configuration may be\r
140 // completely irrellvant.\r
141 //\r
142 if ((Request->Request == USB_REQ_SET_CONFIG) &&\r
143 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
144 USB_TARGET_DEVICE))) {\r
145 //\r
146 // Don't re-create the USB interfaces if configuration isn't changed.\r
147 //\r
148 if ((Dev->ActiveConfig != NULL) &&\r
149 (Request->Value == Dev->ActiveConfig->Desc.ConfigurationValue)) {\r
150\r
151 goto ON_EXIT;\r
152 }\r
153\r
154 USB_DEBUG (("UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));\r
155\r
156 if (Dev->ActiveConfig != NULL) {\r
157 UsbRemoveConfig (Dev);\r
158 }\r
159\r
160 if (Request->Value != 0) {\r
161 Status = UsbSelectConfig (Dev, (UINT8) Request->Value);\r
162 }\r
163\r
164 //\r
165 // Exit now, Old USB_IO is invalid now\r
166 //\r
167 goto ON_EXIT;\r
168 }\r
169\r
170 //\r
171 // A new alternative setting is selected for the interface.\r
172 // No need to reinstall UsbIo in this case because only\r
173 // underlying communication endpoints are changed. Functionality\r
174 // should remains the same.\r
175 //\r
176 if ((Request->Request == USB_REQ_SET_INTERFACE) &&\r
177 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,\r
178 USB_TARGET_INTERFACE)) &&\r
179 (Request->Index == UsbIf->IfSetting->Desc.InterfaceNumber)) {\r
180\r
181 Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);\r
182\r
183 if (!EFI_ERROR (Status)) {\r
184 UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];\r
185 }\r
186 }\r
187\r
188ON_EXIT:\r
189 gBS->RestoreTPL (OldTpl);\r
190 return Status;\r
191}\r
192\r
193\r
194/**\r
195 Execute a bulk transfer to the device endpoint\r
196\r
197 @param This The USB IO instance\r
198 @param Endpoint The device endpoint\r
199 @param Data The data to transfer\r
200 @param DataLength The length of the data to transfer\r
201 @param Timeout Time to wait before timeout\r
202 @param UsbStatus The result of USB transfer\r
203\r
204 @retval EFI_SUCCESS The bulk transfer is OK\r
205 @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
206 @retval Others Failed to execute transfer, reason returned in\r
207 UsbStatus\r
208\r
209**/\r
210STATIC\r
211EFI_STATUS\r
212EFIAPI\r
213UsbIoBulkTransfer (\r
214 IN EFI_USB_IO_PROTOCOL *This,\r
215 IN UINT8 Endpoint,\r
216 IN OUT VOID *Data,\r
217 IN OUT UINTN *DataLength,\r
218 IN UINTN Timeout,\r
219 OUT UINT32 *UsbStatus\r
220 )\r
221{\r
222 USB_DEVICE *Dev;\r
223 USB_INTERFACE *UsbIf;\r
224 USB_ENDPOINT_DESC *EpDesc;\r
225 UINT8 BufNum;\r
226 UINT8 Toggle;\r
227 EFI_TPL OldTpl;\r
228 EFI_STATUS Status;\r
229\r
230 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
231 (UsbStatus == NULL)) {\r
232\r
233 return EFI_INVALID_PARAMETER;\r
234 }\r
235\r
236 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
237\r
238 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
239 Dev = UsbIf->Device;\r
240\r
241 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
242\r
243 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_BULK)) {\r
244 Status = EFI_INVALID_PARAMETER;\r
245 goto ON_EXIT;\r
246 }\r
247\r
248 BufNum = 1;\r
249 Toggle = EpDesc->Toggle;\r
250 Status = UsbHcBulkTransfer (\r
251 Dev->Bus,\r
252 Dev->Address,\r
253 Endpoint,\r
254 Dev->Speed,\r
255 EpDesc->Desc.MaxPacketSize,\r
256 BufNum,\r
257 &Data,\r
258 DataLength,\r
259 &Toggle,\r
260 Timeout,\r
261 &Dev->Translator,\r
262 UsbStatus\r
263 );\r
264\r
265 EpDesc->Toggle = Toggle;\r
266\r
267 if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
268 //\r
269 // Clear TT buffer when CTRL/BULK split transaction failes.\r
270 // Clear the TRANSLATOR TT buffer, not parent's buffer\r
271 //\r
272 if (Dev->Translator.TranslatorHubAddress != 0) {\r
273 UsbHubCtrlClearTTBuffer (\r
274 Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
275 Dev->Translator.TranslatorPortNumber,\r
276 Dev->Address,\r
277 0,\r
278 USB_ENDPOINT_BULK\r
279 );\r
280 }\r
281 }\r
282\r
283ON_EXIT:\r
284 gBS->RestoreTPL (OldTpl);\r
285 return Status;\r
286}\r
287\r
288\r
289/**\r
290 Execute a synchronous interrupt transfer\r
291\r
292 @param This The USB IO instance\r
293 @param Endpoint The device endpoint\r
294 @param Data The data to transfer\r
295 @param DataLength The length of the data to transfer\r
296 @param Timeout Time to wait before timeout\r
297 @param UsbStatus The result of USB transfer\r
298\r
299 @retval EFI_SUCCESS The synchronous interrupt transfer is OK\r
300 @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
301 @retval Others Failed to execute transfer, reason returned in\r
302 UsbStatus\r
303\r
304**/\r
305STATIC\r
306EFI_STATUS\r
307EFIAPI\r
308UsbIoSyncInterruptTransfer (\r
309 IN EFI_USB_IO_PROTOCOL *This,\r
310 IN UINT8 Endpoint,\r
311 IN OUT VOID *Data,\r
312 IN OUT UINTN *DataLength,\r
313 IN UINTN Timeout,\r
314 OUT UINT32 *UsbStatus\r
315 )\r
316{\r
317 USB_DEVICE *Dev;\r
318 USB_INTERFACE *UsbIf;\r
319 USB_ENDPOINT_DESC *EpDesc;\r
320 EFI_TPL OldTpl;\r
321 UINT8 Toggle;\r
322 EFI_STATUS Status;\r
323\r
324 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||\r
325 (UsbStatus == NULL)) {\r
326\r
327 return EFI_INVALID_PARAMETER;\r
328 }\r
329\r
330 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
331\r
332 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
333 Dev = UsbIf->Device;\r
334\r
335 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
336\r
337 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
338 Status = EFI_INVALID_PARAMETER;\r
339 goto ON_EXIT;\r
340 }\r
341\r
342 Toggle = EpDesc->Toggle;\r
343 Status = UsbHcSyncInterruptTransfer (\r
344 Dev->Bus,\r
345 Dev->Address,\r
346 Endpoint,\r
347 Dev->Speed,\r
348 EpDesc->Desc.MaxPacketSize,\r
349 Data,\r
350 DataLength,\r
351 &Toggle,\r
352 Timeout,\r
353 &Dev->Translator,\r
354 UsbStatus\r
355 );\r
356\r
357 EpDesc->Toggle = Toggle;\r
358\r
359ON_EXIT:\r
360 gBS->RestoreTPL (OldTpl);\r
361 return Status;\r
362}\r
363\r
364\r
365/**\r
366 Queue a new asynchronous interrupt transfer, or remove the old\r
367 request if (IsNewTransfer == FALSE)\r
368\r
369 @param This The USB_IO instance\r
370 @param Endpoint The device endpoint\r
371 @param IsNewTransfer Whether this is a new request, if it's old, remove\r
372 the request\r
373 @param PollInterval The interval to poll the transfer result, (in ms)\r
374 @param DataLength The length of perodic data transfer\r
375 @param Callback The function to call periodicaly when transfer is\r
376 ready\r
377 @param Context The context to the callback\r
378\r
379 @retval EFI_SUCCESS New transfer is queued or old request is removed\r
380 @retval EFI_INVALID_PARAMETER Some parameters are invalid\r
381 @retval Others Failed to queue the new request or remove the old\r
382 request\r
383\r
384**/\r
385STATIC\r
386EFI_STATUS\r
387EFIAPI\r
388UsbIoAsyncInterruptTransfer (\r
389 IN EFI_USB_IO_PROTOCOL *This,\r
390 IN UINT8 Endpoint,\r
391 IN BOOLEAN IsNewTransfer,\r
392 IN UINTN PollInterval, OPTIONAL\r
393 IN UINTN DataLength, OPTIONAL\r
394 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, OPTIONAL\r
395 IN VOID *Context OPTIONAL\r
396 )\r
397{\r
398 USB_DEVICE *Dev;\r
399 USB_INTERFACE *UsbIf;\r
400 USB_ENDPOINT_DESC *EpDesc;\r
401 EFI_TPL OldTpl;\r
402 UINT8 Toggle;\r
403 EFI_STATUS Status;\r
404\r
405 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR (Endpoint) > 15)) {\r
406 return EFI_INVALID_PARAMETER;\r
407 }\r
408\r
409 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
410 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
411 Dev = UsbIf->Device;\r
412\r
413 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);\r
414\r
415 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {\r
416 Status = EFI_INVALID_PARAMETER;\r
417 goto ON_EXIT;\r
418 }\r
419\r
420 Toggle = EpDesc->Toggle;\r
421 Status = UsbHcAsyncInterruptTransfer (\r
422 Dev->Bus,\r
423 Dev->Address,\r
424 Endpoint,\r
425 Dev->Speed,\r
426 EpDesc->Desc.MaxPacketSize,\r
427 IsNewTransfer,\r
428 &Toggle,\r
429 PollInterval,\r
430 DataLength,\r
431 &Dev->Translator,\r
432 Callback,\r
433 Context\r
434 );\r
435\r
436 EpDesc->Toggle = Toggle;\r
437\r
438ON_EXIT:\r
439 gBS->RestoreTPL (OldTpl);\r
440 return Status;\r
441}\r
442\r
443\r
444/**\r
445 Execute a synchronous isochronous transfer\r
446\r
447 @param This The USB IO instance\r
448 @param DeviceEndpoint The device endpoint\r
449 @param Data The data to transfer\r
450 @param DataLength The length of the data to transfer\r
451 @param UsbStatus The result of USB transfer\r
452\r
453 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported\r
454\r
455**/\r
456STATIC\r
457EFI_STATUS\r
458EFIAPI\r
459UsbIoIsochronousTransfer (\r
460 IN EFI_USB_IO_PROTOCOL *This,\r
461 IN UINT8 DeviceEndpoint,\r
462 IN OUT VOID *Data,\r
463 IN UINTN DataLength,\r
464 OUT UINT32 *Status\r
465 )\r
466{\r
467 return EFI_UNSUPPORTED;\r
468}\r
469\r
470\r
471/**\r
472 Queue an asynchronous isochronous transfer\r
473\r
474 @param This The USB_IO instance\r
475 @param DeviceEndpoint The device endpoint\r
476 @param DataLength The length of perodic data transfer\r
477 @param IsochronousCallBack The function to call periodicaly when transfer is\r
478 ready\r
479 @param Context The context to the callback\r
480\r
481 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported\r
482\r
483**/\r
484STATIC\r
485EFI_STATUS\r
486EFIAPI\r
487UsbIoAsyncIsochronousTransfer (\r
488 IN EFI_USB_IO_PROTOCOL *This,\r
489 IN UINT8 DeviceEndpoint,\r
490 IN OUT VOID *Data,\r
491 IN UINTN DataLength,\r
492 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
493 IN VOID *Context OPTIONAL\r
494 )\r
495{\r
496 return EFI_UNSUPPORTED;\r
497}\r
498\r
499\r
500/**\r
501 Retrieve the device descriptor of the device\r
502\r
503 @param This The USB IO instance\r
504 @param Descriptor The variable to receive the device descriptor\r
505\r
506 @retval EFI_SUCCESS The device descriptor is returned\r
507 @retval EFI_INVALID_PARAMETER The parameter is invalid\r
508\r
509**/\r
510STATIC\r
511EFI_STATUS\r
512EFIAPI\r
513UsbIoGetDeviceDescriptor (\r
514 IN EFI_USB_IO_PROTOCOL *This,\r
515 OUT EFI_USB_DEVICE_DESCRIPTOR *Descriptor\r
516 )\r
517{\r
518 USB_DEVICE *Dev;\r
519 USB_INTERFACE *UsbIf;\r
520 EFI_TPL OldTpl;\r
521\r
522 if (Descriptor == NULL) {\r
523 return EFI_INVALID_PARAMETER;\r
524 }\r
525\r
526 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
527\r
528 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
529 Dev = UsbIf->Device;\r
530\r
531 CopyMem (Descriptor, &Dev->DevDesc->Desc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
532\r
533 gBS->RestoreTPL (OldTpl);\r
534 return EFI_SUCCESS;\r
535}\r
536\r
537\r
538/**\r
539 Return the configuration descriptor of the current active configuration\r
540\r
541 @param This The USB IO instance\r
542 @param Descriptor The USB configuration descriptor\r
543\r
544 @retval EFI_SUCCESS The active configuration descriptor is returned\r
545 @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
546 @retval EFI_NOT_FOUND Currently no active configuration is selected.\r
547\r
548**/\r
549STATIC\r
550EFI_STATUS\r
551EFIAPI\r
552UsbIoGetActiveConfigDescriptor (\r
553 IN EFI_USB_IO_PROTOCOL *This,\r
554 OUT EFI_USB_CONFIG_DESCRIPTOR *Descriptor\r
555 )\r
556{\r
557 USB_DEVICE *Dev;\r
558 USB_INTERFACE *UsbIf;\r
559 EFI_STATUS Status;\r
560 EFI_TPL OldTpl;\r
561\r
562 if (Descriptor == NULL) {\r
563 return EFI_INVALID_PARAMETER;\r
564 }\r
565\r
566 Status = EFI_SUCCESS;\r
567 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
568\r
569 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
570 Dev = UsbIf->Device;\r
571\r
572 if (Dev->ActiveConfig == NULL) {\r
573 Status = EFI_NOT_FOUND;\r
574 goto ON_EXIT;\r
575 }\r
576\r
577 CopyMem (Descriptor, &(Dev->ActiveConfig->Desc), sizeof (EFI_USB_CONFIG_DESCRIPTOR));\r
578\r
579ON_EXIT:\r
580 gBS->RestoreTPL (OldTpl);\r
581 return Status;\r
582}\r
583\r
584\r
585/**\r
586 Retrieve the active interface setting descriptor for this USB IO instance\r
587\r
588 @param This The USB IO instance\r
589 @param Descriptor The variable to receive active interface setting\r
590\r
591 @retval EFI_SUCCESS The active interface setting is returned\r
592 @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
593\r
594**/\r
595STATIC\r
596EFI_STATUS\r
597EFIAPI\r
598UsbIoGetInterfaceDescriptor (\r
599 IN EFI_USB_IO_PROTOCOL *This,\r
600 OUT EFI_USB_INTERFACE_DESCRIPTOR *Descriptor\r
601 )\r
602{\r
603 USB_INTERFACE *UsbIf;\r
604 EFI_TPL OldTpl;\r
605\r
606 if (Descriptor == NULL) {\r
607 return EFI_INVALID_PARAMETER;\r
608 }\r
609\r
610 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
611\r
612 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
613 CopyMem (Descriptor, &(UsbIf->IfSetting->Desc), sizeof (EFI_USB_INTERFACE_DESCRIPTOR));\r
614\r
615 gBS->RestoreTPL (OldTpl);\r
616 return EFI_SUCCESS;\r
617}\r
618\r
619\r
620/**\r
621 Retrieve the endpoint descriptor from this interface setting\r
622\r
623 @param This The USB IO instance\r
624 @param Index The index (start from zero) of the endpoint to\r
625 retrieve\r
626 @param Descriptor The variable to receive the descriptor\r
627\r
628 @retval EFI_SUCCESS The endpoint descriptor is returned\r
629 @retval EFI_INVALID_PARAMETER Some parameter is invalid\r
630\r
631**/\r
632STATIC\r
633EFI_STATUS\r
634EFIAPI\r
635UsbIoGetEndpointDescriptor (\r
636 IN EFI_USB_IO_PROTOCOL *This,\r
637 IN UINT8 Index,\r
638 OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor\r
639 )\r
640{\r
641 USB_INTERFACE *UsbIf;\r
642 EFI_TPL OldTpl;\r
643\r
644 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
645\r
646 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
647\r
50fa1b3a 648 if ((Descriptor == NULL) || (Index > 15)) {\r
e237e7ae 649 gBS->RestoreTPL (OldTpl);\r
650 return EFI_INVALID_PARAMETER;\r
651 }\r
652\r
50fa1b3a 653 if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {\r
654 gBS->RestoreTPL (OldTpl);\r
655 return EFI_NOT_FOUND;\r
656 }\r
657\r
e237e7ae 658 CopyMem (\r
659 Descriptor,\r
660 &(UsbIf->IfSetting->Endpoints[Index]->Desc),\r
661 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)\r
662 );\r
663\r
664 gBS->RestoreTPL (OldTpl);\r
665 return EFI_SUCCESS;\r
666}\r
667\r
668\r
669/**\r
670 Retrieve the supported language ID table from the device\r
671\r
672 @param This The USB IO instance\r
673 @param LangIDTable The table to return the language IDs\r
674 @param TableSize The number of supported languanges\r
675\r
676 @retval EFI_SUCCESS The language ID is return\r
677\r
678**/\r
679STATIC\r
680EFI_STATUS\r
681EFIAPI\r
682UsbIoGetSupportedLanguages (\r
683 IN EFI_USB_IO_PROTOCOL *This,\r
684 OUT UINT16 **LangIDTable,\r
685 OUT UINT16 *TableSize\r
686 )\r
687{\r
688 USB_DEVICE *Dev;\r
689 USB_INTERFACE *UsbIf;\r
690 EFI_TPL OldTpl;\r
691\r
692 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
693\r
694 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
695 Dev = UsbIf->Device;\r
696\r
697 *LangIDTable = Dev->LangId;\r
698 *TableSize = Dev->TotalLangId;\r
699\r
700 gBS->RestoreTPL (OldTpl);\r
701 return EFI_SUCCESS;\r
702}\r
703\r
704\r
705/**\r
706 Retrieve an indexed string in the language of LangID\r
707\r
708 @param This The USB IO instance\r
709 @param LangID The language ID of the string to retrieve\r
710 @param StringIndex The index of the string\r
711 @param String The variable to receive the string\r
712\r
713 @retval EFI_SUCCESS The string is returned\r
714 @retval EFI_NOT_FOUND No such string existed\r
715\r
716**/\r
717STATIC\r
718EFI_STATUS\r
719EFIAPI\r
720UsbIoGetStringDescriptor (\r
721 IN EFI_USB_IO_PROTOCOL *This,\r
722 IN UINT16 LangID,\r
723 IN UINT8 StringIndex,\r
724 OUT CHAR16 **String\r
725 )\r
726{\r
727 USB_DEVICE *Dev;\r
728 USB_INTERFACE *UsbIf;\r
729 EFI_USB_STRING_DESCRIPTOR *StrDesc;\r
730 EFI_TPL OldTpl;\r
731 UINT8 *Buf;\r
732 UINT8 Index;\r
733 EFI_STATUS Status;\r
734\r
735 if ((StringIndex == 0) || (LangID == 0)) {\r
736 return EFI_NOT_FOUND;\r
737 }\r
738\r
739 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
740\r
741 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
742 Dev = UsbIf->Device;\r
743\r
744 //\r
745 // Check whether language ID is supported\r
746 //\r
747 Status = EFI_NOT_FOUND;\r
748\r
749 for (Index = 0; Index < Dev->TotalLangId; Index++) {\r
750 if (Dev->LangId[Index] == LangID) {\r
751 break;\r
752 }\r
753 }\r
754\r
755 if (Index == Dev->TotalLangId) {\r
756 goto ON_EXIT;\r
757 }\r
758\r
759 //\r
760 // Retrieve the string descriptor then allocate a buffer\r
761 // to hold the string itself.\r
762 //\r
763 StrDesc = UsbGetOneString (Dev, StringIndex, LangID);\r
764\r
765 if (StrDesc == NULL) {\r
766 goto ON_EXIT;\r
767 }\r
768\r
769 if (StrDesc->Length <= 2) {\r
770 goto FREE_STR;\r
771 }\r
772\r
773 Buf = AllocateZeroPool (StrDesc->Length);\r
774\r
775 if (Buf == NULL) {\r
776 Status = EFI_OUT_OF_RESOURCES;\r
777 goto FREE_STR;\r
778 }\r
779\r
780 CopyMem (Buf, StrDesc->String, StrDesc->Length - 2);\r
781 *String = (CHAR16 *) Buf;\r
782 Status = EFI_SUCCESS;\r
783\r
784FREE_STR:\r
785 gBS->FreePool (StrDesc);\r
786\r
787ON_EXIT:\r
788 gBS->RestoreTPL (OldTpl);\r
789 return Status;\r
790}\r
791\r
792\r
793/**\r
794 Reset the device, then if that succeeds, reconfigure the\r
795 device with its address and current active configuration.\r
796\r
797 @param This The USB IO instance\r
798\r
799 @retval EFI_SUCCESS The device is reset and configured\r
800 @retval Others Failed to reset the device\r
801\r
802**/\r
803EFI_STATUS\r
804EFIAPI\r
805UsbIoPortReset (\r
806 IN EFI_USB_IO_PROTOCOL *This\r
807 )\r
808{\r
809 USB_INTERFACE *UsbIf;\r
810 USB_INTERFACE *HubIf;\r
811 USB_DEVICE *Dev;\r
812 UINT8 Address;\r
813 EFI_TPL OldTpl;\r
814 EFI_STATUS Status;\r
815\r
816 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
817\r
818 UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
819 Dev = UsbIf->Device;\r
820\r
50fa1b3a 821 if (UsbIf->IsHub == TRUE) {\r
822 Status = EFI_INVALID_PARAMETER;\r
823 goto ON_EXIT;\r
824 }\r
825\r
e237e7ae 826 HubIf = Dev->ParentIf;\r
827 Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);\r
828\r
829 if (EFI_ERROR (Status)) {\r
830 USB_ERROR (("UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",\r
831 Dev->ParentPort, Dev->ParentAddr, Status));\r
832\r
833 goto ON_EXIT;\r
834 }\r
835\r
836 //\r
837 // Reset the device to its current address. The device now has a\r
838 // address of ZERO, so need to set Dev->Address to zero first for\r
839 // host to communicate with the device\r
840 //\r
841 Address = Dev->Address;\r
842 Dev->Address = 0;\r
843 Status = UsbSetAddress (Dev, Address);\r
844\r
845 if (EFI_ERROR (Status)) {\r
846 USB_ERROR (("UsbIoPortReset: failed to set address for device %d - %r\n",\r
847 Address, Status));\r
848\r
849 goto ON_EXIT;\r
850 }\r
851\r
852 Dev->Address = Address;\r
853\r
854 //\r
855 // Reset the current active configure, after this device\r
856 // is in CONFIGURED state.\r
857 //\r
858 if (Dev->ActiveConfig != NULL) {\r
859 Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);\r
860\r
861 if (EFI_ERROR (Status)) {\r
862 USB_ERROR (("UsbIoPortReset: failed to set configure for device %d - %r\n",\r
863 Address, Status));\r
864 }\r
865 }\r
866\r
867ON_EXIT:\r
868 gBS->RestoreTPL (OldTpl);\r
869 return Status;\r
870}\r
871\r
872EFI_USB_IO_PROTOCOL mUsbIoProtocol = {\r
873 UsbIoControlTransfer,\r
874 UsbIoBulkTransfer,\r
875 UsbIoAsyncInterruptTransfer,\r
876 UsbIoSyncInterruptTransfer,\r
877 UsbIoIsochronousTransfer,\r
878 UsbIoAsyncIsochronousTransfer,\r
879 UsbIoGetDeviceDescriptor,\r
880 UsbIoGetActiveConfigDescriptor,\r
881 UsbIoGetInterfaceDescriptor,\r
882 UsbIoGetEndpointDescriptor,\r
883 UsbIoGetStringDescriptor,\r
884 UsbIoGetSupportedLanguages,\r
885 UsbIoPortReset\r
886};\r
887\r
e237e7ae 888\r
889EFI_STATUS\r
890EFIAPI\r
891UsbBusDriverEntryPoint (\r
892 IN EFI_HANDLE ImageHandle,\r
893 IN EFI_SYSTEM_TABLE *SystemTable\r
894 )\r
895/*++\r
896\r
897Routine Description:\r
898\r
899 The USB bus driver entry pointer\r
900\r
901Arguments:\r
902\r
903 ImageHandle - The driver image handle\r
904 SystemTable - The system table\r
905\r
906Returns:\r
907\r
908 EFI_SUCCESS - The component name protocol is installed\r
909 Others - Failed to init the usb driver\r
910\r
911--*/\r
912{\r
913 return EfiLibInstallAllDriverProtocols (\r
914 ImageHandle,\r
915 SystemTable,\r
916 &mUsbBusDriverBinding,\r
917 ImageHandle,\r
918 &mUsbBusComponentName,\r
919 NULL,\r
920 NULL\r
921 );\r
922}\r
923\r
924\r
925/**\r
926 Check whether USB bus driver support this device\r
927\r
928 @param This The USB bus driver binding protocol\r
929 @param Controller The controller handle to test againist\r
930 @param RemainingDevicePath The remaining device path\r
931\r
932 @retval EFI_SUCCESS The bus supports this controller.\r
933 @retval EFI_UNSUPPORTED This device isn't supported\r
934\r
935**/\r
936EFI_STATUS\r
937EFIAPI\r
938UsbBusControllerDriverSupported (\r
939 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
940 IN EFI_HANDLE Controller,\r
941 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
942 )\r
943{\r
944 EFI_DEV_PATH_PTR DevicePathNode;\r
945 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
946 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
947 EFI_USB_HC_PROTOCOL *UsbHc;\r
948 EFI_STATUS Status;\r
949\r
950 //\r
951 // Check whether device path is valid\r
952 //\r
953 if (RemainingDevicePath != NULL) {\r
954 DevicePathNode.DevPath = RemainingDevicePath;\r
955\r
956 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||\r
957 (DevicePathNode.DevPath->SubType != MSG_USB_DP) ||\r
958 (DevicePathNodeLength (DevicePathNode.DevPath) != sizeof (USB_DEVICE_PATH))) {\r
959\r
960 return EFI_UNSUPPORTED;\r
961 }\r
962 }\r
963\r
964 Status = gBS->OpenProtocol (\r
965 Controller,\r
966 &gEfiDevicePathProtocolGuid,\r
967 (VOID **) &ParentDevicePath,\r
968 This->DriverBindingHandle,\r
969 Controller,\r
970 EFI_OPEN_PROTOCOL_BY_DRIVER\r
971 );\r
972\r
973 if (Status == EFI_ALREADY_STARTED) {\r
974 return EFI_SUCCESS;\r
975 }\r
976\r
977 if (EFI_ERROR (Status)) {\r
978 return Status;\r
979 }\r
980\r
981 gBS->CloseProtocol (\r
982 Controller,\r
983 &gEfiDevicePathProtocolGuid,\r
984 This->DriverBindingHandle,\r
985 Controller\r
986 );\r
987\r
988 //\r
989 // Check whether USB_HC2 protocol is installed\r
990 //\r
991 Status = gBS->OpenProtocol (\r
992 Controller,\r
993 &gEfiUsb2HcProtocolGuid,\r
994 (VOID **) &Usb2Hc,\r
995 This->DriverBindingHandle,\r
996 Controller,\r
997 EFI_OPEN_PROTOCOL_BY_DRIVER\r
998 );\r
999\r
1000 if (Status == EFI_ALREADY_STARTED) {\r
1001 return EFI_SUCCESS;\r
1002 }\r
1003\r
1004 if (!EFI_ERROR (Status)) {\r
1005 gBS->CloseProtocol (\r
1006 Controller,\r
1007 &gEfiUsb2HcProtocolGuid,\r
1008 This->DriverBindingHandle,\r
1009 Controller\r
1010 );\r
1011\r
1012 return EFI_SUCCESS;\r
1013 }\r
1014\r
1015 //\r
1016 // If failed to open USB_HC2, fall back to USB_HC\r
1017 //\r
1018 Status = gBS->OpenProtocol (\r
1019 Controller,\r
1020 &gEfiUsbHcProtocolGuid,\r
1021 (VOID **) &UsbHc,\r
1022 This->DriverBindingHandle,\r
1023 Controller,\r
1024 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1025 );\r
1026\r
1027 if (Status == EFI_ALREADY_STARTED) {\r
1028 return EFI_SUCCESS;\r
1029 }\r
1030\r
1031 if (!EFI_ERROR (Status)) {\r
1032 gBS->CloseProtocol (\r
1033 Controller,\r
1034 &gEfiUsbHcProtocolGuid,\r
1035 This->DriverBindingHandle,\r
1036 Controller\r
1037 );\r
1038 }\r
1039\r
1040 return Status;\r
1041}\r
1042\r
1043\r
1044/**\r
1045 Start to process the controller\r
1046\r
1047 @param This The USB bus driver binding instance\r
1048 @param Controller The controller to check\r
1049 @param RemainingDevicePath The remaining device patch\r
1050\r
1051 @retval EFI_SUCCESS The controller is controlled by the usb bus\r
1052 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb\r
1053 bus\r
1054 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources\r
1055\r
1056**/\r
1057EFI_STATUS\r
1058EFIAPI\r
1059UsbBusControllerDriverStart (\r
1060 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1061 IN EFI_HANDLE Controller,\r
1062 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1063 )\r
1064{\r
1065 USB_BUS *UsbBus;\r
1066 USB_DEVICE *RootHub;\r
1067 USB_INTERFACE *RootIf;\r
1068 EFI_USB_BUS_PROTOCOL *UsbBusId;\r
1069 EFI_STATUS Status;\r
1070 EFI_STATUS Status2;\r
1071\r
1072 //\r
1073 // Locate the USB bus protocol, if it is found, USB bus\r
1074 // is already started on this controller.\r
1075 //\r
1076 Status = gBS->OpenProtocol (\r
1077 Controller,\r
1078 &mUsbBusProtocolGuid,\r
1079 (VOID **) &UsbBusId,\r
1080 This->DriverBindingHandle,\r
1081 Controller,\r
1082 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1083 );\r
1084\r
1085 if (!EFI_ERROR (Status)) {\r
1086 return EFI_ALREADY_STARTED;\r
1087 }\r
1088\r
1089 UsbBus = AllocateZeroPool (sizeof (USB_BUS));\r
1090\r
1091 if (UsbBus == NULL) {\r
1092 return EFI_OUT_OF_RESOURCES;\r
1093 }\r
1094\r
1095 UsbBus->Signature = USB_BUS_SIGNATURE;\r
1096 UsbBus->HostHandle = Controller;\r
1097\r
1098 Status = gBS->OpenProtocol (\r
1099 Controller,\r
1100 &gEfiDevicePathProtocolGuid,\r
1101 (VOID **) &UsbBus->DevicePath,\r
1102 This->DriverBindingHandle,\r
1103 Controller,\r
1104 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1105 );\r
1106\r
1107 if (EFI_ERROR (Status)) {\r
1108 USB_ERROR (("UsbBusStart: Failed to open device path %r\n", Status));\r
1109\r
1110 gBS->FreePool (UsbBus);\r
1111 return Status;\r
1112 }\r
1113\r
1114 //\r
1115 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).\r
1116 // This is for backward compatbility with EFI 1.x. In UEFI\r
1117 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2\r
1118 // and USB_HC because EHCI driver will install both protocols\r
1119 // (for the same reason). If we don't consume both of them,\r
1120 // the unconsumed one may be opened by others.\r
1121 //\r
1122 Status = gBS->OpenProtocol (\r
1123 Controller,\r
1124 &gEfiUsb2HcProtocolGuid,\r
1125 (VOID **) &(UsbBus->Usb2Hc),\r
1126 This->DriverBindingHandle,\r
1127 Controller,\r
1128 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1129 );\r
1130\r
1131 Status2 = gBS->OpenProtocol (\r
1132 Controller,\r
1133 &gEfiUsbHcProtocolGuid,\r
1134 (VOID **) &(UsbBus->UsbHc),\r
1135 This->DriverBindingHandle,\r
1136 Controller,\r
1137 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1138 );\r
1139\r
1140 if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {\r
1141 USB_ERROR (("UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));\r
1142\r
1143 Status = EFI_DEVICE_ERROR;\r
1144 goto CLOSE_HC;\r
1145 }\r
1146\r
1147 //\r
1148 // Create a fake usb device for root hub\r
1149 //\r
1150 RootHub = AllocateZeroPool (sizeof (USB_DEVICE));\r
1151\r
1152 if (RootHub == NULL) {\r
1153 Status = EFI_OUT_OF_RESOURCES;\r
1154 goto CLOSE_HC;\r
1155 }\r
1156\r
1157 RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
1158\r
1159 if (RootIf == NULL) {\r
1160 gBS->FreePool (RootHub);\r
1161 Status = EFI_OUT_OF_RESOURCES;\r
1162 goto CLOSE_HC;\r
1163 }\r
1164\r
1165 RootHub->Bus = UsbBus;\r
1166 RootHub->NumOfInterface = 1;\r
1167 RootHub->Interfaces[0] = RootIf;\r
1168 RootIf->Signature = USB_INTERFACE_SIGNATURE;\r
1169 RootIf->Device = RootHub;\r
1170 RootIf->DevicePath = UsbBus->DevicePath;\r
1171\r
1172 Status = mUsbRootHubApi.Init (RootIf);\r
1173\r
1174 if (EFI_ERROR (Status)) {\r
1175 USB_ERROR (("UsbBusStart: Failed to init root hub %r\n", Status));\r
1176 goto FREE_ROOTHUB;\r
1177 }\r
1178\r
1179 UsbBus->Devices[0] = RootHub;\r
1180\r
1181 //\r
1182 // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.\r
1183 //\r
1184 Status = gBS->InstallProtocolInterface (\r
1185 &Controller,\r
1186 &mUsbBusProtocolGuid,\r
1187 EFI_NATIVE_INTERFACE,\r
1188 &UsbBus->BusId\r
1189 );\r
1190\r
1191 if (EFI_ERROR (Status)) {\r
1192 USB_ERROR (("UsbBusStart: Failed to install bus protocol %r\n", Status));\r
1193\r
1194 mUsbRootHubApi.Release (RootIf);\r
1195 goto FREE_ROOTHUB;\r
1196 }\r
1197\r
1198 UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
1199 UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
1200\r
1201 USB_DEBUG (("UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));\r
1202 return EFI_SUCCESS;\r
1203\r
1204FREE_ROOTHUB:\r
1205 gBS->FreePool (RootIf);\r
1206 gBS->FreePool (RootHub);\r
1207\r
1208CLOSE_HC:\r
1209 if (UsbBus->Usb2Hc != NULL) {\r
1210 gBS->CloseProtocol (\r
1211 Controller,\r
1212 &gEfiUsb2HcProtocolGuid,\r
1213 This->DriverBindingHandle,\r
1214 Controller\r
1215 );\r
1216 }\r
1217\r
1218 if (UsbBus->UsbHc != NULL) {\r
1219 gBS->CloseProtocol (\r
1220 Controller,\r
1221 &gEfiUsbHcProtocolGuid,\r
1222 This->DriverBindingHandle,\r
1223 Controller\r
1224 );\r
1225 }\r
1226\r
1227 gBS->CloseProtocol (\r
1228 Controller,\r
1229 &gEfiDevicePathProtocolGuid,\r
1230 This->DriverBindingHandle,\r
1231 Controller\r
1232 );\r
1233\r
1234 gBS->FreePool (UsbBus);\r
1235\r
1236 USB_ERROR (("UsbBusStart: Failed to start bus driver %r\n", Status));\r
1237 return Status;\r
1238}\r
1239\r
1240\r
1241/**\r
1242 Stop handle the controller by this USB bus driver\r
1243\r
1244 @param This The USB bus driver binding protocol\r
1245 @param Controller The controller to release\r
1246 @param NumberOfChildren The child of USB bus that opened controller\r
1247 BY_CHILD\r
1248 @param ChildHandleBuffer The array of child handle\r
1249\r
1250 @retval EFI_SUCCESS The controller or children are stopped\r
1251 @retval EFI_DEVICE_ERROR Failed to stop the driver\r
1252\r
1253**/\r
1254EFI_STATUS\r
1255EFIAPI\r
1256UsbBusControllerDriverStop (\r
1257 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1258 IN EFI_HANDLE Controller,\r
1259 IN UINTN NumberOfChildren,\r
1260 IN EFI_HANDLE *ChildHandleBuffer\r
1261 )\r
1262{\r
1263 USB_BUS *Bus;\r
1264 USB_DEVICE *RootHub;\r
1265 USB_DEVICE *UsbDev;\r
1266 USB_INTERFACE *RootIf;\r
1267 USB_INTERFACE *UsbIf;\r
1268 EFI_USB_BUS_PROTOCOL *BusId;\r
1269 EFI_USB_IO_PROTOCOL *UsbIo;\r
1270 EFI_TPL OldTpl;\r
1271 UINTN Index;\r
1272 EFI_STATUS Status;\r
1273\r
1274 Status = EFI_SUCCESS;\r
1275\r
1276 if (NumberOfChildren > 0) {\r
1277 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
1278\r
1279 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1280 Status = gBS->OpenProtocol (\r
1281 ChildHandleBuffer[Index],\r
1282 &gEfiUsbIoProtocolGuid,\r
1283 (VOID **) &UsbIo,\r
1284 This->DriverBindingHandle,\r
1285 Controller,\r
1286 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1287 );\r
1288\r
1289 if (EFI_ERROR (Status)) {\r
1290 //\r
1291 // It is possible that the child has already been released:\r
1292 // 1. For combo device, free one device will release others.\r
1293 // 2. If a hub is released, all devices on its down facing\r
1294 // ports are released also.\r
1295 //\r
1296 continue;\r
1297 }\r
1298\r
1299 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);\r
1300 UsbDev = UsbIf->Device;\r
1301\r
1302 UsbRemoveDevice (UsbDev);\r
1303 }\r
1304\r
1305 gBS->RestoreTPL (OldTpl);\r
1306 return EFI_SUCCESS;\r
1307 }\r
1308\r
1309 USB_DEBUG (("UsbBusStop: usb bus stopped on %x\n", Controller));\r
1310\r
1311 //\r
1312 // Locate USB_BUS for the current host controller\r
1313 //\r
1314 Status = gBS->OpenProtocol (\r
1315 Controller,\r
1316 &mUsbBusProtocolGuid,\r
1317 (VOID **) &BusId,\r
1318 This->DriverBindingHandle,\r
1319 Controller,\r
1320 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1321 );\r
1322\r
1323 if (EFI_ERROR (Status)) {\r
1324 return Status;\r
1325 }\r
1326\r
1327 Bus = USB_BUS_FROM_THIS (BusId);\r
1328\r
1329 //\r
1330 // Stop the root hub, then free all the devices\r
1331 //\r
1332 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
1333 UsbHcSetState (Bus, EfiUsbHcStateHalt);\r
1334\r
1335 RootHub = Bus->Devices[0];\r
1336 RootIf = RootHub->Interfaces[0];\r
1337\r
1338 mUsbRootHubApi.Release (RootIf);\r
1339\r
1340 for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
1341 if (Bus->Devices[Index] != NULL) {\r
1342 UsbRemoveDevice (Bus->Devices[Index]);\r
1343 }\r
1344 }\r
1345\r
1346 gBS->RestoreTPL (OldTpl);\r
1347\r
1348 gBS->FreePool (RootIf);\r
1349 gBS->FreePool (RootHub);\r
1350\r
1351 //\r
1352 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols\r
1353 //\r
1354 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);\r
1355\r
1356 if (Bus->Usb2Hc != NULL) {\r
1357 gBS->CloseProtocol (\r
1358 Controller,\r
1359 &gEfiUsb2HcProtocolGuid,\r
1360 This->DriverBindingHandle,\r
1361 Controller\r
1362 );\r
1363 }\r
1364\r
1365 if (Bus->UsbHc != NULL) {\r
1366 gBS->CloseProtocol (\r
1367 Controller,\r
1368 &gEfiUsbHcProtocolGuid,\r
1369 This->DriverBindingHandle,\r
1370 Controller\r
1371 );\r
1372 }\r
1373\r
1374 gBS->CloseProtocol (\r
1375 Controller,\r
1376 &gEfiDevicePathProtocolGuid,\r
1377 This->DriverBindingHandle,\r
1378 Controller\r
1379 );\r
1380\r
1381 gBS->FreePool (Bus);\r
1382\r
1383 return Status;\r
1384}\r
1385\r
1386EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {\r
1387 UsbBusControllerDriverSupported,\r
1388 UsbBusControllerDriverStart,\r
1389 UsbBusControllerDriverStop,\r
1390 0xa,\r
1391 NULL,\r
1392 NULL\r
1393};\r