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