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