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