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