1 /** @file 2 3 Usb Bus Driver Binding and Bus IO Protocol. 4 5 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "UsbBus.h" 17 18 EFI_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 34 EFI_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 **/ 62 EFI_STATUS 63 EFIAPI 64 UsbIoControlTransfer ( 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 198 ON_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 **/ 220 EFI_STATUS 221 EFIAPI 222 UsbIoBulkTransfer ( 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 293 ON_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 **/ 315 EFI_STATUS 316 EFIAPI 317 UsbIoSyncInterruptTransfer ( 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 368 ON_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 **/ 394 EFI_STATUS 395 EFIAPI 396 UsbIoAsyncInterruptTransfer ( 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 446 ON_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 **/ 464 EFI_STATUS 465 EFIAPI 466 UsbIoIsochronousTransfer ( 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 **/ 492 EFI_STATUS 493 EFIAPI 494 UsbIoAsyncIsochronousTransfer ( 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 **/ 517 EFI_STATUS 518 EFIAPI 519 UsbIoGetDeviceDescriptor ( 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 **/ 555 EFI_STATUS 556 EFIAPI 557 UsbIoGetActiveConfigDescriptor ( 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 584 ON_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 **/ 600 EFI_STATUS 601 EFIAPI 602 UsbIoGetInterfaceDescriptor ( 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 **/ 636 EFI_STATUS 637 EFIAPI 638 UsbIoGetEndpointDescriptor ( 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 **/ 682 EFI_STATUS 683 EFIAPI 684 UsbIoGetSupportedLanguages ( 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 **/ 719 EFI_STATUS 720 EFIAPI 721 UsbIoGetStringDescriptor ( 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 786 FREE_STR: 787 gBS->FreePool (StrDesc); 788 789 ON_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 **/ 805 EFI_STATUS 806 EFIAPI 807 UsbIoPortReset ( 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 877 ON_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 **/ 895 EFI_STATUS 896 EFIAPI 897 UsbBusBuildProtocol ( 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 1047 FREE_ROOTHUB: 1048 if (RootIf != NULL) { 1049 FreePool (RootIf); 1050 } 1051 if (RootHub != NULL) { 1052 FreePool (RootHub); 1053 } 1054 1055 UNINSTALL_USBBUS: 1056 gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &UsbBus->BusId); 1057 1058 CLOSE_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 **/ 1098 EFI_STATUS 1099 EFIAPI 1100 UsbBusDriverEntryPoint ( 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 **/ 1127 EFI_STATUS 1128 EFIAPI 1129 UsbBusControllerDriverSupported ( 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 **/ 1271 EFI_STATUS 1272 EFIAPI 1273 UsbBusControllerDriverStart ( 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 **/ 1383 EFI_STATUS 1384 EFIAPI 1385 UsbBusControllerDriverStop ( 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