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