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