]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
Update the copyright notice format
[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
cd5ebaa0
HT
5Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>\r
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
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
efe9186f 852\r
853 gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);\r
7e388f85 854 \r
e237e7ae 855 if (EFI_ERROR (Status)) {\r
d2577026 856 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",\r
e237e7ae 857 Address, Status));\r
858\r
859 goto ON_EXIT;\r
860 }\r
861\r
efe9186f 862 Dev->Address = Address;\r
e237e7ae 863\r
7e388f85 864 DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address));\r
865 \r
e237e7ae 866 //\r
867 // Reset the current active configure, after this device\r
868 // is in CONFIGURED state.\r
869 //\r
870 if (Dev->ActiveConfig != NULL) {\r
871 Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);\r
872\r
873 if (EFI_ERROR (Status)) {\r
d2577026 874 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",\r
e237e7ae 875 Address, Status));\r
876 }\r
877 }\r
878\r
879ON_EXIT:\r
880 gBS->RestoreTPL (OldTpl);\r
881 return Status;\r
882}\r
883\r
ecb575d9 884\r
885/**\r
8616fc4c 886 Install Usb Bus Protocol on host controller, and start the Usb bus.\r
ecb575d9 887\r
8616fc4c 888 @param This The USB bus driver binding instance.\r
889 @param Controller The controller to check.\r
890 @param RemainingDevicePath The remaining device patch.\r
ecb575d9 891\r
8616fc4c 892 @retval EFI_SUCCESS The controller is controlled by the usb bus.\r
893 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.\r
894 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
ecb575d9 895\r
896**/\r
897EFI_STATUS\r
898EFIAPI\r
899UsbBusBuildProtocol (\r
900 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
901 IN EFI_HANDLE Controller,\r
902 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
903 )\r
904{\r
905 USB_BUS *UsbBus;\r
906 USB_DEVICE *RootHub;\r
907 USB_INTERFACE *RootIf;\r
908 EFI_STATUS Status;\r
909 EFI_STATUS Status2;\r
910\r
911 UsbBus = AllocateZeroPool (sizeof (USB_BUS));\r
912\r
913 if (UsbBus == NULL) {\r
914 return EFI_OUT_OF_RESOURCES;\r
915 }\r
916\r
917 UsbBus->Signature = USB_BUS_SIGNATURE;\r
918 UsbBus->HostHandle = Controller;\r
919\r
920 Status = gBS->OpenProtocol (\r
921 Controller,\r
922 &gEfiDevicePathProtocolGuid,\r
923 (VOID **) &UsbBus->DevicePath,\r
924 This->DriverBindingHandle,\r
925 Controller,\r
926 EFI_OPEN_PROTOCOL_BY_DRIVER\r
927 );\r
928\r
929 if (EFI_ERROR (Status)) {\r
930 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));\r
931\r
d17371e8 932 FreePool (UsbBus);\r
ecb575d9 933 return Status;\r
934 }\r
935\r
936 //\r
937 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).\r
d17371e8 938 // This is for backward compatibility with EFI 1.x. In UEFI\r
ecb575d9 939 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2\r
940 // and USB_HC because EHCI driver will install both protocols\r
941 // (for the same reason). If we don't consume both of them,\r
942 // the unconsumed one may be opened by others.\r
943 //\r
944 Status = gBS->OpenProtocol (\r
945 Controller,\r
946 &gEfiUsb2HcProtocolGuid,\r
947 (VOID **) &(UsbBus->Usb2Hc),\r
948 This->DriverBindingHandle,\r
949 Controller,\r
950 EFI_OPEN_PROTOCOL_BY_DRIVER\r
951 );\r
952\r
953 Status2 = gBS->OpenProtocol (\r
954 Controller,\r
955 &gEfiUsbHcProtocolGuid,\r
956 (VOID **) &(UsbBus->UsbHc),\r
957 This->DriverBindingHandle,\r
958 Controller,\r
959 EFI_OPEN_PROTOCOL_BY_DRIVER\r
960 );\r
961\r
962 if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {\r
963 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));\r
964\r
965 Status = EFI_DEVICE_ERROR;\r
966 goto CLOSE_HC;\r
967 }\r
968\r
969 UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
970 UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
971\r
972 //\r
d17371e8 973 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.\r
ecb575d9 974 //\r
975 Status = gBS->InstallProtocolInterface (\r
976 &Controller,\r
977 &mUsbBusProtocolGuid,\r
978 EFI_NATIVE_INTERFACE,\r
979 &UsbBus->BusId\r
980 );\r
981\r
982 if (EFI_ERROR (Status)) {\r
983 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));\r
984 goto CLOSE_HC;\r
985 }\r
986\r
987 //\r
988 // Initial the wanted child device path list, and add first RemainingDevicePath\r
989 //\r
990 InitializeListHead (&UsbBus->WantedUsbIoDPList);\r
991 Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);\r
992 ASSERT (!EFI_ERROR (Status));\r
993 //\r
994 // Create a fake usb device for root hub\r
995 //\r
996 RootHub = AllocateZeroPool (sizeof (USB_DEVICE));\r
997\r
998 if (RootHub == NULL) {\r
999 Status = EFI_OUT_OF_RESOURCES;\r
1000 goto UNINSTALL_USBBUS;\r
1001 }\r
1002\r
1003 RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));\r
1004\r
1005 if (RootIf == NULL) {\r
d17371e8 1006 FreePool (RootHub);\r
ecb575d9 1007 Status = EFI_OUT_OF_RESOURCES;\r
1008 goto FREE_ROOTHUB;\r
1009 }\r
1010\r
1011 RootHub->Bus = UsbBus;\r
1012 RootHub->NumOfInterface = 1;\r
1013 RootHub->Interfaces[0] = RootIf;\r
1014 RootIf->Signature = USB_INTERFACE_SIGNATURE;\r
1015 RootIf->Device = RootHub;\r
1016 RootIf->DevicePath = UsbBus->DevicePath;\r
1017\r
1018 Status = mUsbRootHubApi.Init (RootIf);\r
1019\r
1020 if (EFI_ERROR (Status)) {\r
1021 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));\r
1022 goto FREE_ROOTHUB;\r
1023 }\r
1024\r
1025 UsbBus->Devices[0] = RootHub;\r
1026\r
0e549d5b 1027 DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf));\r
ecb575d9 1028 return EFI_SUCCESS;\r
1029\r
1030FREE_ROOTHUB:\r
1031 if (RootIf != NULL) {\r
d17371e8 1032 FreePool (RootIf);\r
ecb575d9 1033 }\r
1034 if (RootHub != NULL) {\r
d17371e8 1035 FreePool (RootHub);\r
ecb575d9 1036 }\r
1037\r
1038UNINSTALL_USBBUS:\r
1039 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);\r
1040\r
1041CLOSE_HC:\r
1042 if (UsbBus->Usb2Hc != NULL) {\r
1043 gBS->CloseProtocol (\r
1044 Controller,\r
1045 &gEfiUsb2HcProtocolGuid,\r
1046 This->DriverBindingHandle,\r
1047 Controller\r
1048 );\r
1049 }\r
1050 if (UsbBus->UsbHc != NULL) {\r
1051 gBS->CloseProtocol (\r
1052 Controller,\r
1053 &gEfiUsbHcProtocolGuid,\r
1054 This->DriverBindingHandle,\r
1055 Controller\r
1056 );\r
1057 }\r
1058 gBS->CloseProtocol (\r
1059 Controller,\r
1060 &gEfiDevicePathProtocolGuid,\r
1061 This->DriverBindingHandle,\r
1062 Controller\r
1063 );\r
d17371e8 1064 FreePool (UsbBus);\r
ecb575d9 1065\r
1066 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));\r
1067 return Status;\r
1068}\r
1069\r
e237e7ae 1070\r
8616fc4c 1071/**\r
1072 The USB bus driver entry pointer.\r
1073\r
1074 @param ImageHandle The driver image handle.\r
1075 @param SystemTable The system table.\r
1076\r
1077 @return EFI_SUCCESS The component name protocol is installed.\r
1078 @return Others Failed to init the usb driver.\r
1079\r
1080**/\r
e237e7ae 1081EFI_STATUS\r
1082EFIAPI\r
1083UsbBusDriverEntryPoint (\r
1084 IN EFI_HANDLE ImageHandle,\r
1085 IN EFI_SYSTEM_TABLE *SystemTable\r
1086 )\r
e237e7ae 1087{\r
62b9bb55 1088 return EfiLibInstallDriverBindingComponentName2 (\r
e237e7ae 1089 ImageHandle,\r
1090 SystemTable,\r
1091 &mUsbBusDriverBinding,\r
1092 ImageHandle,\r
1093 &mUsbBusComponentName,\r
62b9bb55 1094 &mUsbBusComponentName2\r
e237e7ae 1095 );\r
1096}\r
1097\r
1098\r
1099/**\r
8616fc4c 1100 Check whether USB bus driver support this device.\r
e237e7ae 1101\r
8616fc4c 1102 @param This The USB bus driver binding protocol.\r
34a0bac4 1103 @param Controller The controller handle to check.\r
8616fc4c 1104 @param RemainingDevicePath The remaining device path.\r
e237e7ae 1105\r
1106 @retval EFI_SUCCESS The bus supports this controller.\r
8616fc4c 1107 @retval EFI_UNSUPPORTED This device isn't supported.\r
e237e7ae 1108\r
1109**/\r
1110EFI_STATUS\r
1111EFIAPI\r
1112UsbBusControllerDriverSupported (\r
1113 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1114 IN EFI_HANDLE Controller,\r
1115 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1116 )\r
1117{\r
1118 EFI_DEV_PATH_PTR DevicePathNode;\r
1119 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1120 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
1121 EFI_USB_HC_PROTOCOL *UsbHc;\r
1122 EFI_STATUS Status;\r
1123\r
1124 //\r
1125 // Check whether device path is valid\r
1126 //\r
1127 if (RemainingDevicePath != NULL) {\r
af4a6385 1128 //\r
1129 // Check if RemainingDevicePath is the End of Device Path Node, \r
1130 // if yes, go on checking other conditions\r
1131 //\r
1132 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
1133 //\r
1134 // If RemainingDevicePath isn't the End of Device Path Node,\r
1135 // check its validation\r
1136 //\r
1137 DevicePathNode.DevPath = RemainingDevicePath;\r
1138 \r
1139 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||\r
1140 (DevicePathNode.DevPath->SubType != MSG_USB_DP &&\r
1141 DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP\r
1142 && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP\r
1143 )) {\r
1144 \r
1145 return EFI_UNSUPPORTED;\r
1146 }\r
e237e7ae 1147 }\r
1148 }\r
1149\r
e237e7ae 1150 //\r
1151 // Check whether USB_HC2 protocol is installed\r
1152 //\r
1153 Status = gBS->OpenProtocol (\r
1154 Controller,\r
1155 &gEfiUsb2HcProtocolGuid,\r
1156 (VOID **) &Usb2Hc,\r
1157 This->DriverBindingHandle,\r
1158 Controller,\r
1159 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1160 );\r
e237e7ae 1161 if (Status == EFI_ALREADY_STARTED) {\r
1162 return EFI_SUCCESS;\r
1163 }\r
1164\r
af4a6385 1165 if (EFI_ERROR (Status)) {\r
1166 //\r
1167 // If failed to open USB_HC2, fall back to USB_HC\r
1168 //\r
1169 Status = gBS->OpenProtocol (\r
1170 Controller,\r
1171 &gEfiUsbHcProtocolGuid,\r
1172 (VOID **) &UsbHc,\r
1173 This->DriverBindingHandle,\r
1174 Controller,\r
1175 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1176 );\r
1177 if (Status == EFI_ALREADY_STARTED) {\r
1178 return EFI_SUCCESS;\r
1179 }\r
1180 \r
1181 if (EFI_ERROR (Status)) {\r
1182 return Status;\r
1183 }\r
1184\r
1185 //\r
1186 // Close the USB_HC used to perform the supported test\r
1187 //\r
e237e7ae 1188 gBS->CloseProtocol (\r
1189 Controller,\r
af4a6385 1190 &gEfiUsbHcProtocolGuid,\r
e237e7ae 1191 This->DriverBindingHandle,\r
1192 Controller\r
1193 );\r
1194\r
af4a6385 1195 } else {\r
e237e7ae 1196\r
af4a6385 1197 //\r
1198 // Close the USB_HC2 used to perform the supported test\r
1199 //\r
1200 gBS->CloseProtocol (\r
1201 Controller,\r
1202 &gEfiUsb2HcProtocolGuid,\r
1203 This->DriverBindingHandle,\r
1204 Controller\r
1205 );\r
1206 }\r
1207 \r
e237e7ae 1208 //\r
af4a6385 1209 // Open the EFI Device Path protocol needed to perform the supported test\r
e237e7ae 1210 //\r
1211 Status = gBS->OpenProtocol (\r
1212 Controller,\r
af4a6385 1213 &gEfiDevicePathProtocolGuid,\r
1214 (VOID **) &ParentDevicePath,\r
e237e7ae 1215 This->DriverBindingHandle,\r
1216 Controller,\r
1217 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1218 );\r
e237e7ae 1219 if (Status == EFI_ALREADY_STARTED) {\r
1220 return EFI_SUCCESS;\r
1221 }\r
1222\r
1223 if (!EFI_ERROR (Status)) {\r
af4a6385 1224 //\r
1225 // Close protocol, don't use device path protocol in the Support() function\r
1226 //\r
e237e7ae 1227 gBS->CloseProtocol (\r
1228 Controller,\r
af4a6385 1229 &gEfiDevicePathProtocolGuid,\r
e237e7ae 1230 This->DriverBindingHandle,\r
1231 Controller\r
1232 );\r
af4a6385 1233\r
1234 return EFI_SUCCESS;\r
e237e7ae 1235 }\r
1236\r
1237 return Status;\r
1238}\r
1239\r
1240\r
1241/**\r
8616fc4c 1242 Start to process the controller.\r
e237e7ae 1243\r
8616fc4c 1244 @param This The USB bus driver binding instance.\r
1245 @param Controller The controller to check.\r
1246 @param RemainingDevicePath The remaining device patch.\r
e237e7ae 1247\r
8616fc4c 1248 @retval EFI_SUCCESS The controller is controlled by the usb bus.\r
e237e7ae 1249 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb\r
8616fc4c 1250 bus.\r
1251 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
e237e7ae 1252\r
1253**/\r
1254EFI_STATUS\r
1255EFIAPI\r
1256UsbBusControllerDriverStart (\r
1257 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1258 IN EFI_HANDLE Controller,\r
1259 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1260 )\r
1261{\r
ecb575d9 1262 EFI_USB_BUS_PROTOCOL *UsbBusId;\r
1263 EFI_STATUS Status;\r
e237e7ae 1264\r
1265 //\r
1266 // Locate the USB bus protocol, if it is found, USB bus\r
1267 // is already started on this controller.\r
1268 //\r
1269 Status = gBS->OpenProtocol (\r
1270 Controller,\r
1271 &mUsbBusProtocolGuid,\r
1272 (VOID **) &UsbBusId,\r
1273 This->DriverBindingHandle,\r
1274 Controller,\r
1275 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1276 );\r
1277\r
e237e7ae 1278 if (EFI_ERROR (Status)) {\r
ecb575d9 1279 //\r
d17371e8 1280 // If first start, build the bus execute environment and install bus protocol\r
ecb575d9 1281 //\r
1282 Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);\r
1283 if (EFI_ERROR (Status)) {\r
1284 return Status;\r
1285 }\r
1286 //\r
1287 // Try get the Usb Bus protocol interface again\r
1288 //\r
1289 Status = gBS->OpenProtocol (\r
1290 Controller,\r
1291 &mUsbBusProtocolGuid,\r
1292 (VOID **) &UsbBusId,\r
1293 This->DriverBindingHandle,\r
1294 Controller,\r
1295 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1296 );\r
1297 ASSERT (!EFI_ERROR (Status));\r
1298 } else {\r
1299 //\r
1300 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted\r
1301 // usb child device will be recursively connected.\r
1302 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.\r
1303 // All wanted usb child devices will be remembered by the usb bus driver itself.\r
1304 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.\r
1305 //\r
1306 // Save the passed in RemainingDevicePath this time\r
1307 //\r
af4a6385 1308 if (RemainingDevicePath != NULL) {\r
1309 if (IsDevicePathEnd (RemainingDevicePath)) {\r
1310 //\r
1311 // If RemainingDevicePath is the End of Device Path Node,\r
1312 // skip enumerate any device and return EFI_SUCESSS\r
1313 // \r
1314 return EFI_SUCCESS;\r
1315 }\r
1316 }\r
1317\r
ecb575d9 1318 Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);\r
1319 ASSERT (!EFI_ERROR (Status));\r
1320 //\r
1321 // Ensure all wanted child usb devices are fully recursively connected\r
1322 //\r
1323 Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);\r
1324 ASSERT (!EFI_ERROR (Status));\r
e237e7ae 1325 }\r
1326\r
e237e7ae 1327\r
e237e7ae 1328 return EFI_SUCCESS;\r
e237e7ae 1329}\r
1330\r
1331\r
1332/**\r
8616fc4c 1333 Stop handle the controller by this USB bus driver.\r
e237e7ae 1334\r
8616fc4c 1335 @param This The USB bus driver binding protocol.\r
1336 @param Controller The controller to release.\r
e237e7ae 1337 @param NumberOfChildren The child of USB bus that opened controller\r
8616fc4c 1338 BY_CHILD.\r
1339 @param ChildHandleBuffer The array of child handle.\r
e237e7ae 1340\r
8616fc4c 1341 @retval EFI_SUCCESS The controller or children are stopped.\r
1342 @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
e237e7ae 1343\r
1344**/\r
1345EFI_STATUS\r
1346EFIAPI\r
1347UsbBusControllerDriverStop (\r
1348 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1349 IN EFI_HANDLE Controller,\r
1350 IN UINTN NumberOfChildren,\r
1351 IN EFI_HANDLE *ChildHandleBuffer\r
1352 )\r
1353{\r
1354 USB_BUS *Bus;\r
1355 USB_DEVICE *RootHub;\r
1356 USB_DEVICE *UsbDev;\r
1357 USB_INTERFACE *RootIf;\r
1358 USB_INTERFACE *UsbIf;\r
1359 EFI_USB_BUS_PROTOCOL *BusId;\r
1360 EFI_USB_IO_PROTOCOL *UsbIo;\r
1361 EFI_TPL OldTpl;\r
1362 UINTN Index;\r
1363 EFI_STATUS Status;\r
1364\r
1365 Status = EFI_SUCCESS;\r
1366\r
1367 if (NumberOfChildren > 0) {\r
ecb575d9 1368 //\r
1369 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
1370 //\r
1371 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
e237e7ae 1372\r
1373 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1374 Status = gBS->OpenProtocol (\r
1375 ChildHandleBuffer[Index],\r
1376 &gEfiUsbIoProtocolGuid,\r
1377 (VOID **) &UsbIo,\r
1378 This->DriverBindingHandle,\r
1379 Controller,\r
1380 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1381 );\r
1382\r
1383 if (EFI_ERROR (Status)) {\r
1384 //\r
1385 // It is possible that the child has already been released:\r
1386 // 1. For combo device, free one device will release others.\r
1387 // 2. If a hub is released, all devices on its down facing\r
1388 // ports are released also.\r
1389 //\r
1390 continue;\r
1391 }\r
1392\r
1393 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);\r
1394 UsbDev = UsbIf->Device;\r
1395\r
1396 UsbRemoveDevice (UsbDev);\r
1397 }\r
1398\r
1399 gBS->RestoreTPL (OldTpl);\r
1400 return EFI_SUCCESS;\r
1401 }\r
1402\r
0e549d5b 1403 DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));\r
e237e7ae 1404\r
1405 //\r
1406 // Locate USB_BUS for the current host controller\r
1407 //\r
1408 Status = gBS->OpenProtocol (\r
1409 Controller,\r
1410 &mUsbBusProtocolGuid,\r
1411 (VOID **) &BusId,\r
1412 This->DriverBindingHandle,\r
1413 Controller,\r
1414 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1415 );\r
1416\r
1417 if (EFI_ERROR (Status)) {\r
1418 return Status;\r
1419 }\r
1420\r
1421 Bus = USB_BUS_FROM_THIS (BusId);\r
1422\r
1423 //\r
1424 // Stop the root hub, then free all the devices\r
1425 //\r
ecb575d9 1426 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
1427 //\r
1428 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
e237e7ae 1429 UsbHcSetState (Bus, EfiUsbHcStateHalt);\r
1430\r
1431 RootHub = Bus->Devices[0];\r
1432 RootIf = RootHub->Interfaces[0];\r
1433\r
1434 mUsbRootHubApi.Release (RootIf);\r
1435\r
1436 for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
1437 if (Bus->Devices[Index] != NULL) {\r
1438 UsbRemoveDevice (Bus->Devices[Index]);\r
1439 }\r
1440 }\r
1441\r
1442 gBS->RestoreTPL (OldTpl);\r
1443\r
1444 gBS->FreePool (RootIf);\r
1445 gBS->FreePool (RootHub);\r
ecb575d9 1446 Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
1447 ASSERT (!EFI_ERROR (Status));\r
e237e7ae 1448\r
1449 //\r
1450 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols\r
1451 //\r
1452 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);\r
1453\r
1454 if (Bus->Usb2Hc != NULL) {\r
1455 gBS->CloseProtocol (\r
1456 Controller,\r
1457 &gEfiUsb2HcProtocolGuid,\r
1458 This->DriverBindingHandle,\r
1459 Controller\r
1460 );\r
1461 }\r
1462\r
1463 if (Bus->UsbHc != NULL) {\r
1464 gBS->CloseProtocol (\r
1465 Controller,\r
1466 &gEfiUsbHcProtocolGuid,\r
1467 This->DriverBindingHandle,\r
1468 Controller\r
1469 );\r
1470 }\r
1471\r
1472 gBS->CloseProtocol (\r
1473 Controller,\r
1474 &gEfiDevicePathProtocolGuid,\r
1475 This->DriverBindingHandle,\r
1476 Controller\r
1477 );\r
1478\r
1479 gBS->FreePool (Bus);\r
1480\r
1481 return Status;\r
1482}\r