1 /** @file 2 3 Usb Bus Driver Binding and Bus IO Protocol. 4 5 Copyright (c) 2004 - 2013, 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 UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL); 980 UsbHcSetState (UsbBus, EfiUsbHcStateOperational); 981 982 // 983 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it. 984 // 985 Status = gBS->InstallProtocolInterface ( 986 &Controller, 987 &gEfiCallerIdGuid, 988 EFI_NATIVE_INTERFACE, 989 &UsbBus->BusId 990 ); 991 992 if (EFI_ERROR (Status)) { 993 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status)); 994 goto CLOSE_HC; 995 } 996 997 // 998 // Initial the wanted child device path list, and add first RemainingDevicePath 999 // 1000 InitializeListHead (&UsbBus->WantedUsbIoDPList); 1001 Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath); 1002 ASSERT (!EFI_ERROR (Status)); 1003 // 1004 // Create a fake usb device for root hub 1005 // 1006 RootHub = AllocateZeroPool (sizeof (USB_DEVICE)); 1007 1008 if (RootHub == NULL) { 1009 Status = EFI_OUT_OF_RESOURCES; 1010 goto UNINSTALL_USBBUS; 1011 } 1012 1013 RootIf = AllocateZeroPool (sizeof (USB_INTERFACE)); 1014 1015 if (RootIf == NULL) { 1016 FreePool (RootHub); 1017 Status = EFI_OUT_OF_RESOURCES; 1018 goto FREE_ROOTHUB; 1019 } 1020 1021 RootHub->Bus = UsbBus; 1022 RootHub->NumOfInterface = 1; 1023 RootHub->Interfaces[0] = RootIf; 1024 RootHub->Tier = 0; 1025 RootIf->Signature = USB_INTERFACE_SIGNATURE; 1026 RootIf->Device = RootHub; 1027 RootIf->DevicePath = UsbBus->DevicePath; 1028 1029 // 1030 // Report Status Code here since we will enumerate the USB devices 1031 // 1032 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 1033 EFI_PROGRESS_CODE, 1034 (EFI_IO_BUS_USB | EFI_IOB_PC_DETECT), 1035 UsbBus->DevicePath 1036 ); 1037 1038 Status = mUsbRootHubApi.Init (RootIf); 1039 1040 if (EFI_ERROR (Status)) { 1041 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status)); 1042 goto FREE_ROOTHUB; 1043 } 1044 1045 UsbBus->Devices[0] = RootHub; 1046 1047 DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf)); 1048 return EFI_SUCCESS; 1049 1050 FREE_ROOTHUB: 1051 if (RootIf != NULL) { 1052 FreePool (RootIf); 1053 } 1054 if (RootHub != NULL) { 1055 FreePool (RootHub); 1056 } 1057 1058 UNINSTALL_USBBUS: 1059 gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &UsbBus->BusId); 1060 1061 CLOSE_HC: 1062 if (UsbBus->Usb2Hc != NULL) { 1063 gBS->CloseProtocol ( 1064 Controller, 1065 &gEfiUsb2HcProtocolGuid, 1066 This->DriverBindingHandle, 1067 Controller 1068 ); 1069 } 1070 if (UsbBus->UsbHc != NULL) { 1071 gBS->CloseProtocol ( 1072 Controller, 1073 &gEfiUsbHcProtocolGuid, 1074 This->DriverBindingHandle, 1075 Controller 1076 ); 1077 } 1078 gBS->CloseProtocol ( 1079 Controller, 1080 &gEfiDevicePathProtocolGuid, 1081 This->DriverBindingHandle, 1082 Controller 1083 ); 1084 FreePool (UsbBus); 1085 1086 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status)); 1087 return Status; 1088 } 1089 1090 1091 /** 1092 The USB bus driver entry pointer. 1093 1094 @param ImageHandle The driver image handle. 1095 @param SystemTable The system table. 1096 1097 @return EFI_SUCCESS The component name protocol is installed. 1098 @return Others Failed to init the usb driver. 1099 1100 **/ 1101 EFI_STATUS 1102 EFIAPI 1103 UsbBusDriverEntryPoint ( 1104 IN EFI_HANDLE ImageHandle, 1105 IN EFI_SYSTEM_TABLE *SystemTable 1106 ) 1107 { 1108 return EfiLibInstallDriverBindingComponentName2 ( 1109 ImageHandle, 1110 SystemTable, 1111 &mUsbBusDriverBinding, 1112 ImageHandle, 1113 &mUsbBusComponentName, 1114 &mUsbBusComponentName2 1115 ); 1116 } 1117 1118 1119 /** 1120 Check whether USB bus driver support this device. 1121 1122 @param This The USB bus driver binding protocol. 1123 @param Controller The controller handle to check. 1124 @param RemainingDevicePath The remaining device path. 1125 1126 @retval EFI_SUCCESS The bus supports this controller. 1127 @retval EFI_UNSUPPORTED This device isn't supported. 1128 1129 **/ 1130 EFI_STATUS 1131 EFIAPI 1132 UsbBusControllerDriverSupported ( 1133 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1134 IN EFI_HANDLE Controller, 1135 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 1136 ) 1137 { 1138 EFI_DEV_PATH_PTR DevicePathNode; 1139 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 1140 EFI_USB2_HC_PROTOCOL *Usb2Hc; 1141 EFI_USB_HC_PROTOCOL *UsbHc; 1142 EFI_STATUS Status; 1143 1144 // 1145 // Check whether device path is valid 1146 // 1147 if (RemainingDevicePath != NULL) { 1148 // 1149 // Check if RemainingDevicePath is the End of Device Path Node, 1150 // if yes, go on checking other conditions 1151 // 1152 if (!IsDevicePathEnd (RemainingDevicePath)) { 1153 // 1154 // If RemainingDevicePath isn't the End of Device Path Node, 1155 // check its validation 1156 // 1157 DevicePathNode.DevPath = RemainingDevicePath; 1158 1159 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) || 1160 (DevicePathNode.DevPath->SubType != MSG_USB_DP && 1161 DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP 1162 && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP 1163 )) { 1164 1165 return EFI_UNSUPPORTED; 1166 } 1167 } 1168 } 1169 1170 // 1171 // Check whether USB_HC2 protocol is installed 1172 // 1173 Status = gBS->OpenProtocol ( 1174 Controller, 1175 &gEfiUsb2HcProtocolGuid, 1176 (VOID **) &Usb2Hc, 1177 This->DriverBindingHandle, 1178 Controller, 1179 EFI_OPEN_PROTOCOL_BY_DRIVER 1180 ); 1181 if (Status == EFI_ALREADY_STARTED) { 1182 return EFI_SUCCESS; 1183 } 1184 1185 if (EFI_ERROR (Status)) { 1186 // 1187 // If failed to open USB_HC2, fall back to USB_HC 1188 // 1189 Status = gBS->OpenProtocol ( 1190 Controller, 1191 &gEfiUsbHcProtocolGuid, 1192 (VOID **) &UsbHc, 1193 This->DriverBindingHandle, 1194 Controller, 1195 EFI_OPEN_PROTOCOL_BY_DRIVER 1196 ); 1197 if (Status == EFI_ALREADY_STARTED) { 1198 return EFI_SUCCESS; 1199 } 1200 1201 if (EFI_ERROR (Status)) { 1202 return Status; 1203 } 1204 1205 // 1206 // Close the USB_HC used to perform the supported test 1207 // 1208 gBS->CloseProtocol ( 1209 Controller, 1210 &gEfiUsbHcProtocolGuid, 1211 This->DriverBindingHandle, 1212 Controller 1213 ); 1214 1215 } else { 1216 1217 // 1218 // Close the USB_HC2 used to perform the supported test 1219 // 1220 gBS->CloseProtocol ( 1221 Controller, 1222 &gEfiUsb2HcProtocolGuid, 1223 This->DriverBindingHandle, 1224 Controller 1225 ); 1226 } 1227 1228 // 1229 // Open the EFI Device Path protocol needed to perform the supported test 1230 // 1231 Status = gBS->OpenProtocol ( 1232 Controller, 1233 &gEfiDevicePathProtocolGuid, 1234 (VOID **) &ParentDevicePath, 1235 This->DriverBindingHandle, 1236 Controller, 1237 EFI_OPEN_PROTOCOL_BY_DRIVER 1238 ); 1239 if (Status == EFI_ALREADY_STARTED) { 1240 return EFI_SUCCESS; 1241 } 1242 1243 if (!EFI_ERROR (Status)) { 1244 // 1245 // Close protocol, don't use device path protocol in the Support() function 1246 // 1247 gBS->CloseProtocol ( 1248 Controller, 1249 &gEfiDevicePathProtocolGuid, 1250 This->DriverBindingHandle, 1251 Controller 1252 ); 1253 1254 return EFI_SUCCESS; 1255 } 1256 1257 return Status; 1258 } 1259 1260 1261 /** 1262 Start to process the controller. 1263 1264 @param This The USB bus driver binding instance. 1265 @param Controller The controller to check. 1266 @param RemainingDevicePath The remaining device patch. 1267 1268 @retval EFI_SUCCESS The controller is controlled by the usb bus. 1269 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb 1270 bus. 1271 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. 1272 1273 **/ 1274 EFI_STATUS 1275 EFIAPI 1276 UsbBusControllerDriverStart ( 1277 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1278 IN EFI_HANDLE Controller, 1279 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 1280 ) 1281 { 1282 EFI_USB_BUS_PROTOCOL *UsbBusId; 1283 EFI_STATUS Status; 1284 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 1285 1286 Status = gBS->OpenProtocol ( 1287 Controller, 1288 &gEfiDevicePathProtocolGuid, 1289 (VOID **) &ParentDevicePath, 1290 This->DriverBindingHandle, 1291 Controller, 1292 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1293 ); 1294 ASSERT_EFI_ERROR (Status); 1295 1296 // 1297 // Report Status Code here since we will initialize the host controller 1298 // 1299 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 1300 EFI_PROGRESS_CODE, 1301 (EFI_IO_BUS_USB | EFI_IOB_PC_INIT), 1302 ParentDevicePath 1303 ); 1304 1305 // 1306 // Locate the USB bus protocol, if it is found, USB bus 1307 // is already started on this controller. 1308 // 1309 Status = gBS->OpenProtocol ( 1310 Controller, 1311 &gEfiCallerIdGuid, 1312 (VOID **) &UsbBusId, 1313 This->DriverBindingHandle, 1314 Controller, 1315 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1316 ); 1317 1318 if (EFI_ERROR (Status)) { 1319 // 1320 // If first start, build the bus execute environment and install bus protocol 1321 // 1322 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_P_PC_ENABLE)); 1323 Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath); 1324 if (EFI_ERROR (Status)) { 1325 return Status; 1326 } 1327 // 1328 // Try get the Usb Bus protocol interface again 1329 // 1330 Status = gBS->OpenProtocol ( 1331 Controller, 1332 &gEfiCallerIdGuid, 1333 (VOID **) &UsbBusId, 1334 This->DriverBindingHandle, 1335 Controller, 1336 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1337 ); 1338 ASSERT (!EFI_ERROR (Status)); 1339 } else { 1340 // 1341 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted 1342 // usb child device will be recursively connected. 1343 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time. 1344 // All wanted usb child devices will be remembered by the usb bus driver itself. 1345 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices. 1346 // 1347 // Save the passed in RemainingDevicePath this time 1348 // 1349 if (RemainingDevicePath != NULL) { 1350 if (IsDevicePathEnd (RemainingDevicePath)) { 1351 // 1352 // If RemainingDevicePath is the End of Device Path Node, 1353 // skip enumerate any device and return EFI_SUCESSS 1354 // 1355 return EFI_SUCCESS; 1356 } 1357 } 1358 1359 Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath); 1360 ASSERT (!EFI_ERROR (Status)); 1361 // 1362 // Ensure all wanted child usb devices are fully recursively connected 1363 // 1364 Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId); 1365 ASSERT (!EFI_ERROR (Status)); 1366 } 1367 1368 1369 return EFI_SUCCESS; 1370 } 1371 1372 1373 /** 1374 Stop handle the controller by this USB bus driver. 1375 1376 @param This The USB bus driver binding protocol. 1377 @param Controller The controller to release. 1378 @param NumberOfChildren The child of USB bus that opened controller 1379 BY_CHILD. 1380 @param ChildHandleBuffer The array of child handle. 1381 1382 @retval EFI_SUCCESS The controller or children are stopped. 1383 @retval EFI_DEVICE_ERROR Failed to stop the driver. 1384 1385 **/ 1386 EFI_STATUS 1387 EFIAPI 1388 UsbBusControllerDriverStop ( 1389 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1390 IN EFI_HANDLE Controller, 1391 IN UINTN NumberOfChildren, 1392 IN EFI_HANDLE *ChildHandleBuffer 1393 ) 1394 { 1395 USB_BUS *Bus; 1396 USB_DEVICE *RootHub; 1397 USB_DEVICE *UsbDev; 1398 USB_INTERFACE *RootIf; 1399 USB_INTERFACE *UsbIf; 1400 EFI_USB_BUS_PROTOCOL *BusId; 1401 EFI_USB_IO_PROTOCOL *UsbIo; 1402 EFI_TPL OldTpl; 1403 UINTN Index; 1404 EFI_STATUS Status; 1405 EFI_STATUS ReturnStatus; 1406 1407 Status = EFI_SUCCESS; 1408 1409 if (NumberOfChildren > 0) { 1410 // 1411 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict 1412 // 1413 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1414 1415 ReturnStatus = EFI_SUCCESS; 1416 for (Index = 0; Index < NumberOfChildren; Index++) { 1417 Status = gBS->OpenProtocol ( 1418 ChildHandleBuffer[Index], 1419 &gEfiUsbIoProtocolGuid, 1420 (VOID **) &UsbIo, 1421 This->DriverBindingHandle, 1422 Controller, 1423 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1424 ); 1425 1426 if (EFI_ERROR (Status)) { 1427 // 1428 // It is possible that the child has already been released: 1429 // 1. For combo device, free one device will release others. 1430 // 2. If a hub is released, all devices on its down facing 1431 // ports are released also. 1432 // 1433 continue; 1434 } 1435 1436 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo); 1437 UsbDev = UsbIf->Device; 1438 1439 ReturnStatus = UsbRemoveDevice (UsbDev); 1440 } 1441 1442 gBS->RestoreTPL (OldTpl); 1443 return ReturnStatus; 1444 } 1445 1446 DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller)); 1447 1448 // 1449 // Locate USB_BUS for the current host controller 1450 // 1451 Status = gBS->OpenProtocol ( 1452 Controller, 1453 &gEfiCallerIdGuid, 1454 (VOID **) &BusId, 1455 This->DriverBindingHandle, 1456 Controller, 1457 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1458 ); 1459 1460 if (EFI_ERROR (Status)) { 1461 return Status; 1462 } 1463 1464 Bus = USB_BUS_FROM_THIS (BusId); 1465 1466 // 1467 // Stop the root hub, then free all the devices 1468 // 1469 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict 1470 // 1471 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1472 1473 RootHub = Bus->Devices[0]; 1474 RootIf = RootHub->Interfaces[0]; 1475 1476 ASSERT (Bus->MaxDevices <= 256); 1477 ReturnStatus = EFI_SUCCESS; 1478 for (Index = 1; Index < Bus->MaxDevices; Index++) { 1479 if (Bus->Devices[Index] != NULL) { 1480 Status = UsbRemoveDevice (Bus->Devices[Index]); 1481 if (EFI_ERROR (Status)) { 1482 ReturnStatus = Status; 1483 } 1484 } 1485 } 1486 1487 gBS->RestoreTPL (OldTpl); 1488 1489 if (!EFI_ERROR (ReturnStatus)) { 1490 mUsbRootHubApi.Release (RootIf); 1491 gBS->FreePool (RootIf); 1492 gBS->FreePool (RootHub); 1493 1494 Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList); 1495 ASSERT (!EFI_ERROR (Status)); 1496 1497 // 1498 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols 1499 // 1500 gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &Bus->BusId); 1501 1502 if (Bus->Usb2Hc != NULL) { 1503 Status = gBS->CloseProtocol ( 1504 Controller, 1505 &gEfiUsb2HcProtocolGuid, 1506 This->DriverBindingHandle, 1507 Controller 1508 ); 1509 } 1510 1511 if (Bus->UsbHc != NULL) { 1512 Status = gBS->CloseProtocol ( 1513 Controller, 1514 &gEfiUsbHcProtocolGuid, 1515 This->DriverBindingHandle, 1516 Controller 1517 ); 1518 } 1519 1520 if (!EFI_ERROR (Status)) { 1521 gBS->CloseProtocol ( 1522 Controller, 1523 &gEfiDevicePathProtocolGuid, 1524 This->DriverBindingHandle, 1525 Controller 1526 ); 1527 1528 gBS->FreePool (Bus); 1529 } 1530 } 1531 return Status; 1532 } 1533