]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
added EFI_SIGNATURE_XX in Base.h, and updated the industry header files to use them.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbBus.c
... / ...
CommitLineData
1/** @file\r
2\r
3 Usb Bus Driver Binding and Bus IO Protocol.\r
4\r
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
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
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
143 DEBUG ((EFI_D_INFO, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));\r
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
184 Execute a bulk transfer to the device endpoint.\r
185\r
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
192\r
193 @retval EFI_SUCCESS The bulk transfer is OK.\r
194 @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
195 @retval Others Failed to execute transfer, reason returned in\r
196 UsbStatus.\r
197\r
198**/\r
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
278 Execute a synchronous interrupt transfer.\r
279\r
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
286\r
287 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.\r
288 @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
289 @retval Others Failed to execute transfer, reason returned in\r
290 UsbStatus.\r
291\r
292**/\r
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
354 request if (IsNewTransfer == FALSE).\r
355\r
356 @param This The USB_IO instance.\r
357 @param Endpoint The device endpoint.\r
358 @param IsNewTransfer Whether this is a new request, if it's old, remove\r
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
362 @param Callback The function to call periodicaly when transfer is\r
363 ready.\r
364 @param Context The context to the callback.\r
365\r
366 @retval EFI_SUCCESS New transfer is queued or old request is removed.\r
367 @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
368 @retval Others Failed to queue the new request or remove the old\r
369 request.\r
370\r
371**/\r
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
431 Execute a synchronous isochronous transfer.\r
432\r
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
438\r
439 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.\r
440\r
441**/\r
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
457 Queue an asynchronous isochronous transfer.\r
458\r
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
463 @param IsochronousCallBack The function to call periodicaly when transfer is\r
464 ready.\r
465 @param Context The context to the callback.\r
466\r
467 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.\r
468\r
469**/\r
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
486 Retrieve the device descriptor of the device.\r
487\r
488 @param This The USB IO instance.\r
489 @param Descriptor The variable to receive the device descriptor.\r
490\r
491 @retval EFI_SUCCESS The device descriptor is returned.\r
492 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
493\r
494**/\r
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
523 Return the configuration descriptor of the current active configuration.\r
524\r
525 @param This The USB IO instance.\r
526 @param Descriptor The USB configuration descriptor.\r
527\r
528 @retval EFI_SUCCESS The active configuration descriptor is returned.\r
529 @retval EFI_INVALID_PARAMETER Some parameter is invalid.\r
530 @retval EFI_NOT_FOUND Currently no active configuration is selected.\r
531\r
532**/\r
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
569 Retrieve the active interface setting descriptor for this USB IO instance.\r
570\r
571 @param This The USB IO instance.\r
572 @param Descriptor The variable to receive active interface setting.\r
573\r
574 @retval EFI_SUCCESS The active interface setting is returned.\r
575 @retval EFI_INVALID_PARAMETER Some parameter is invalid.\r
576\r
577**/\r
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
603 Retrieve the endpoint descriptor from this interface setting.\r
604\r
605 @param This The USB IO instance.\r
606 @param Index The index (start from zero) of the endpoint to\r
607 retrieve.\r
608 @param Descriptor The variable to receive the descriptor.\r
609\r
610 @retval EFI_SUCCESS The endpoint descriptor is returned.\r
611 @retval EFI_INVALID_PARAMETER Some parameter is invalid.\r
612\r
613**/\r
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
629 if ((Descriptor == NULL) || (Index > 15)) {\r
630 gBS->RestoreTPL (OldTpl);\r
631 return EFI_INVALID_PARAMETER;\r
632 }\r
633\r
634 if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {\r
635 gBS->RestoreTPL (OldTpl);\r
636 return EFI_NOT_FOUND;\r
637 }\r
638\r
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
651 Retrieve the supported language ID table from the device.\r
652\r
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
656\r
657 @retval EFI_SUCCESS The language ID is return.\r
658\r
659**/\r
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
686 Retrieve an indexed string in the language of LangID.\r
687\r
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
692\r
693 @retval EFI_SUCCESS The string is returned.\r
694 @retval EFI_NOT_FOUND No such string existed.\r
695\r
696**/\r
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
776 @param This The USB IO instance.\r
777\r
778 @retval EFI_SUCCESS The device is reset and configured.\r
779 @retval Others Failed to reset the device.\r
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
800 if (UsbIf->IsHub) {\r
801 Status = EFI_INVALID_PARAMETER;\r
802 goto ON_EXIT;\r
803 }\r
804\r
805 HubIf = Dev->ParentIf;\r
806 Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);\r
807\r
808 if (EFI_ERROR (Status)) {\r
809 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",\r
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
823 Dev->Address = Address;\r
824 \r
825 if (EFI_ERROR (Status)) {\r
826 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",\r
827 Address, Status));\r
828\r
829 goto ON_EXIT;\r
830 }\r
831\r
832 gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);\r
833\r
834 DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address));\r
835 \r
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
844 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",\r
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
854\r
855/**\r
856 Install Usb Bus Protocol on host controller, and start the Usb bus.\r
857\r
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
861\r
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
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
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
1056\r
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
1067EFI_STATUS\r
1068EFIAPI\r
1069UsbBusDriverEntryPoint (\r
1070 IN EFI_HANDLE ImageHandle,\r
1071 IN EFI_SYSTEM_TABLE *SystemTable\r
1072 )\r
1073{\r
1074 return EfiLibInstallDriverBindingComponentName2 (\r
1075 ImageHandle,\r
1076 SystemTable,\r
1077 &mUsbBusDriverBinding,\r
1078 ImageHandle,\r
1079 &mUsbBusComponentName,\r
1080 &mUsbBusComponentName2\r
1081 );\r
1082}\r
1083\r
1084\r
1085/**\r
1086 Check whether USB bus driver support this device.\r
1087\r
1088 @param This The USB bus driver binding protocol.\r
1089 @param Controller The controller handle to check.\r
1090 @param RemainingDevicePath The remaining device path.\r
1091\r
1092 @retval EFI_SUCCESS The bus supports this controller.\r
1093 @retval EFI_UNSUPPORTED This device isn't supported.\r
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
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
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
1207 Start to process the controller.\r
1208\r
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
1212\r
1213 @retval EFI_SUCCESS The controller is controlled by the usb bus.\r
1214 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb\r
1215 bus.\r
1216 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
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
1227 EFI_USB_BUS_PROTOCOL *UsbBusId;\r
1228 EFI_STATUS Status;\r
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
1243 if (EFI_ERROR (Status)) {\r
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
1280 }\r
1281\r
1282\r
1283 return EFI_SUCCESS;\r
1284}\r
1285\r
1286\r
1287/**\r
1288 Stop handle the controller by this USB bus driver.\r
1289\r
1290 @param This The USB bus driver binding protocol.\r
1291 @param Controller The controller to release.\r
1292 @param NumberOfChildren The child of USB bus that opened controller\r
1293 BY_CHILD.\r
1294 @param ChildHandleBuffer The array of child handle.\r
1295\r
1296 @retval EFI_SUCCESS The controller or children are stopped.\r
1297 @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
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
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
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
1358 DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %x\n", Controller));\r
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
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
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
1401 Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
1402 ASSERT (!EFI_ERROR (Status));\r
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