1 /** @file 2 3 The library provides the USB Standard Device Requests defined 4 in Usb specification 9.4 section. 5 6 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR> 7 This program and the accompanying materials are 8 licensed and made available under the terms and conditions of 9 the BSD License which accompanies this distribution. The full 10 text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php. 12 13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15 16 **/ 17 18 #include "UefiUsbLibInternal.h" 19 20 21 /** 22 Get the descriptor of the specified USB device. 23 24 Submit a USB get descriptor request for the USB device specified by UsbIo, Value, 25 and Index, and return the descriptor in the buffer specified by Descriptor. 26 The status of the transfer is returned in Status. 27 If UsbIo is NULL, then ASSERT(). 28 If Descriptor is NULL, then ASSERT(). 29 If Status is NULL, then ASSERT(). 30 31 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 32 @param Value The device request value. 33 @param Index The device request index. 34 @param DescriptorLength The size, in bytes, of Descriptor. 35 @param Descriptor A pointer to the descriptor buffer to get. 36 @param Status A pointer to the status of the transfer. 37 38 @retval EFI_SUCCESS The request executed successfully. 39 @retval EFI_OUT_OF_RESOURCES The request could not be completed because the 40 buffer specified by DescriptorLength and Descriptor 41 is not large enough to hold the result of the request. 42 @retval EFI_TIMEOUT A timeout occurred executing the request. 43 @retval EFI_DEVICE_ERROR The request failed due to a device error. The transfer 44 status is returned in Status. 45 46 **/ 47 EFI_STATUS 48 EFIAPI 49 UsbGetDescriptor ( 50 IN EFI_USB_IO_PROTOCOL *UsbIo, 51 IN UINT16 Value, 52 IN UINT16 Index, 53 IN UINT16 DescriptorLength, 54 OUT VOID *Descriptor, 55 OUT UINT32 *Status 56 ) 57 { 58 EFI_USB_DEVICE_REQUEST DevReq; 59 60 ASSERT (UsbIo != NULL); 61 ASSERT (Descriptor != NULL); 62 ASSERT (Status != NULL); 63 64 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 65 66 DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE; 67 DevReq.Request = USB_REQ_GET_DESCRIPTOR; 68 DevReq.Value = Value; 69 DevReq.Index = Index; 70 DevReq.Length = DescriptorLength; 71 72 return UsbIo->UsbControlTransfer ( 73 UsbIo, 74 &DevReq, 75 EfiUsbDataIn, 76 PcdGet32 (PcdUsbTransferTimeoutValue), 77 Descriptor, 78 DescriptorLength, 79 Status 80 ); 81 } 82 83 84 /** 85 Set the descriptor of the specified USB device. 86 87 Submit a USB set descriptor request for the USB device specified by UsbIo, 88 Value, and Index, and set the descriptor using the buffer specified by DesriptorLength 89 and Descriptor. The status of the transfer is returned in Status. 90 If UsbIo is NULL, then ASSERT(). 91 If Descriptor is NULL, then ASSERT(). 92 If Status is NULL, then ASSERT(). 93 94 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 95 @param Value The device request value. 96 @param Index The device request index. 97 @param DescriptorLength The size, in bytes, of Descriptor. 98 @param Descriptor A pointer to the descriptor buffer to set. 99 @param Status A pointer to the status of the transfer. 100 101 @retval EFI_SUCCESS The request executed successfully. 102 @retval EFI_TIMEOUT A timeout occurred executing the request. 103 @retval EFI_DEVICE_ERROR The request failed due to a device error. 104 The transfer status is returned in Status. 105 106 **/ 107 EFI_STATUS 108 EFIAPI 109 UsbSetDescriptor ( 110 IN EFI_USB_IO_PROTOCOL *UsbIo, 111 IN UINT16 Value, 112 IN UINT16 Index, 113 IN UINT16 DescriptorLength, 114 IN VOID *Descriptor, 115 OUT UINT32 *Status 116 ) 117 { 118 EFI_USB_DEVICE_REQUEST DevReq; 119 120 ASSERT (UsbIo != NULL); 121 ASSERT (Descriptor != NULL); 122 ASSERT (Status != NULL); 123 124 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 125 126 DevReq.RequestType = USB_DEV_SET_DESCRIPTOR_REQ_TYPE; 127 DevReq.Request = USB_REQ_SET_DESCRIPTOR; 128 DevReq.Value = Value; 129 DevReq.Index = Index; 130 DevReq.Length = DescriptorLength; 131 132 return UsbIo->UsbControlTransfer ( 133 UsbIo, 134 &DevReq, 135 EfiUsbDataOut, 136 PcdGet32 (PcdUsbTransferTimeoutValue), 137 Descriptor, 138 DescriptorLength, 139 Status 140 ); 141 } 142 143 144 /** 145 Get the interface setting of the specified USB device. 146 147 Submit a USB get interface request for the USB device specified by UsbIo, 148 and Interface, and place the result in the buffer specified by AlternateSetting. 149 The status of the transfer is returned in Status. 150 If UsbIo is NULL, then ASSERT(). 151 If AlternateSetting is NULL, then ASSERT(). 152 If Status is NULL, then ASSERT(). 153 154 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 155 @param Interface The interface index value. 156 @param AlternateSetting A pointer to the alternate setting to be retrieved. 157 @param Status A pointer to the status of the transfer. 158 159 @retval EFI_SUCCESS The request executed successfully. 160 @retval EFI_TIMEOUT A timeout occurred executing the request. 161 @retval EFI_DEVICE_ERROR The request failed due to a device error. 162 The transfer status is returned in Status. 163 164 **/ 165 EFI_STATUS 166 EFIAPI 167 UsbGetInterface ( 168 IN EFI_USB_IO_PROTOCOL *UsbIo, 169 IN UINT16 Interface, 170 OUT UINT16 *AlternateSetting, 171 OUT UINT32 *Status 172 ) 173 { 174 EFI_USB_DEVICE_REQUEST DevReq; 175 176 ASSERT (UsbIo != NULL); 177 ASSERT (AlternateSetting != NULL); 178 ASSERT (Status != NULL); 179 180 *AlternateSetting = 0; 181 182 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 183 184 DevReq.RequestType = USB_DEV_GET_INTERFACE_REQ_TYPE; 185 DevReq.Request = USB_REQ_GET_INTERFACE; 186 DevReq.Index = Interface; 187 DevReq.Length = 1; 188 189 return UsbIo->UsbControlTransfer ( 190 UsbIo, 191 &DevReq, 192 EfiUsbDataIn, 193 PcdGet32 (PcdUsbTransferTimeoutValue), 194 AlternateSetting, 195 1, 196 Status 197 ); 198 } 199 200 201 /** 202 Set the interface setting of the specified USB device. 203 204 Submit a USB set interface request for the USB device specified by UsbIo, and 205 Interface, and set the alternate setting to the value specified by AlternateSetting. 206 The status of the transfer is returned in Status. 207 If UsbIo is NULL, then ASSERT(). 208 If Status is NULL, then ASSERT(). 209 210 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 211 @param Interface The interface index value. 212 @param AlternateSetting The alternate setting to be set. 213 @param Status A pointer to the status of the transfer. 214 215 @retval EFI_SUCCESS The request executed successfully. 216 @retval EFI_TIMEOUT A timeout occurred executing the request. 217 @retval EFI_SUCCESS The request failed due to a device error. 218 The transfer status is returned in Status. 219 220 **/ 221 EFI_STATUS 222 EFIAPI 223 UsbSetInterface ( 224 IN EFI_USB_IO_PROTOCOL *UsbIo, 225 IN UINT16 Interface, 226 IN UINT16 AlternateSetting, 227 OUT UINT32 *Status 228 ) 229 { 230 EFI_USB_DEVICE_REQUEST DevReq; 231 232 ASSERT (UsbIo != NULL); 233 ASSERT (Status != NULL); 234 235 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 236 237 DevReq.RequestType = USB_DEV_SET_INTERFACE_REQ_TYPE; 238 DevReq.Request = USB_REQ_SET_INTERFACE; 239 DevReq.Value = AlternateSetting; 240 DevReq.Index = Interface; 241 242 return UsbIo->UsbControlTransfer ( 243 UsbIo, 244 &DevReq, 245 EfiUsbNoData, 246 PcdGet32 (PcdUsbTransferTimeoutValue), 247 NULL, 248 0, 249 Status 250 ); 251 } 252 253 254 /** 255 Get the device configuration. 256 257 Submit a USB get configuration request for the USB device specified by UsbIo 258 and place the result in the buffer specified by ConfigurationValue. The status 259 of the transfer is returned in Status. 260 If UsbIo is NULL, then ASSERT(). 261 If ConfigurationValue is NULL, then ASSERT(). 262 If Status is NULL, then ASSERT(). 263 264 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 265 @param ConfigurationValue A pointer to the device configuration to be retrieved. 266 @param Status A pointer to the status of the transfer. 267 268 @retval EFI_SUCCESS The request executed successfully. 269 @retval EFI_TIMEOUT A timeout occurred executing the request. 270 @retval EFI_DEVICE_ERROR The request failed due to a device error. 271 The transfer status is returned in Status. 272 273 **/ 274 EFI_STATUS 275 EFIAPI 276 UsbGetConfiguration ( 277 IN EFI_USB_IO_PROTOCOL *UsbIo, 278 OUT UINT16 *ConfigurationValue, 279 OUT UINT32 *Status 280 ) 281 { 282 EFI_USB_DEVICE_REQUEST DevReq; 283 284 ASSERT (UsbIo != NULL); 285 ASSERT (ConfigurationValue != NULL); 286 ASSERT (Status != NULL); 287 288 *ConfigurationValue = 0; 289 290 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 291 292 DevReq.RequestType = USB_DEV_GET_CONFIGURATION_REQ_TYPE; 293 DevReq.Request = USB_REQ_GET_CONFIG; 294 DevReq.Length = 1; 295 296 return UsbIo->UsbControlTransfer ( 297 UsbIo, 298 &DevReq, 299 EfiUsbDataIn, 300 PcdGet32 (PcdUsbTransferTimeoutValue), 301 ConfigurationValue, 302 1, 303 Status 304 ); 305 } 306 307 308 /** 309 Set the device configuration. 310 311 Submit a USB set configuration request for the USB device specified by UsbIo 312 and set the device configuration to the value specified by ConfigurationValue. 313 The status of the transfer is returned in Status. 314 If UsbIo is NULL, then ASSERT(). 315 If Status is NULL, then ASSERT(). 316 317 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 318 @param ConfigurationValue The device configuration value to be set. 319 @param Status A pointer to the status of the transfer. 320 321 @retval EFI_SUCCESS The request executed successfully. 322 @retval EFI_TIMEOUT A timeout occurred executing the request. 323 @retval EFI_DEVICE_ERROR The request failed due to a device error. 324 The transfer status is returned in Status. 325 326 **/ 327 EFI_STATUS 328 EFIAPI 329 UsbSetConfiguration ( 330 IN EFI_USB_IO_PROTOCOL *UsbIo, 331 IN UINT16 ConfigurationValue, 332 OUT UINT32 *Status 333 ) 334 { 335 EFI_USB_DEVICE_REQUEST DevReq; 336 337 ASSERT (UsbIo != NULL); 338 ASSERT (Status != NULL); 339 340 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 341 342 DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE; 343 DevReq.Request = USB_REQ_SET_CONFIG; 344 DevReq.Value = ConfigurationValue; 345 346 return UsbIo->UsbControlTransfer ( 347 UsbIo, 348 &DevReq, 349 EfiUsbNoData, 350 PcdGet32 (PcdUsbTransferTimeoutValue), 351 NULL, 352 0, 353 Status 354 ); 355 } 356 357 358 /** 359 Set the specified feature of the specified device. 360 361 Submit a USB set device feature request for the USB device specified by UsbIo, 362 Recipient, and Target to the value specified by Value. The status of the 363 transfer is returned in Status. 364 If UsbIo is NULL, then ASSERT(). 365 If Status is NULL, then ASSERT(). 366 367 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 368 @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint). 369 Type USB_TYPES_DEFINITION is defined in the MDE Package Industry 370 Standard include file Usb.h. 371 @param Value The value of the feature to be set. 372 @param Target The index of the device to be set. 373 @param Status A pointer to the status of the transfer. 374 375 @retval EFI_SUCCESS The request executed successfully. 376 @retval EFI_TIMEOUT A timeout occurred executing the request. 377 @retval EFI_DEVICE_ERROR The request failed due to a device error. 378 The transfer status is returned in Status. 379 380 **/ 381 EFI_STATUS 382 EFIAPI 383 UsbSetFeature ( 384 IN EFI_USB_IO_PROTOCOL *UsbIo, 385 IN USB_TYPES_DEFINITION Recipient, 386 IN UINT16 Value, 387 IN UINT16 Target, 388 OUT UINT32 *Status 389 ) 390 { 391 EFI_USB_DEVICE_REQUEST DevReq; 392 393 ASSERT (UsbIo != NULL); 394 ASSERT (Status != NULL); 395 396 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 397 398 switch (Recipient) { 399 400 case USB_TARGET_DEVICE: 401 DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_D; 402 break; 403 404 case USB_TARGET_INTERFACE: 405 DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_I; 406 break; 407 408 case USB_TARGET_ENDPOINT: 409 DevReq.RequestType = USB_DEV_SET_FEATURE_REQ_TYPE_E; 410 break; 411 412 default: 413 break; 414 } 415 // 416 // Fill device request, see USB1.1 spec 417 // 418 DevReq.Request = USB_REQ_SET_FEATURE; 419 DevReq.Value = Value; 420 DevReq.Index = Target; 421 422 423 return UsbIo->UsbControlTransfer ( 424 UsbIo, 425 &DevReq, 426 EfiUsbNoData, 427 PcdGet32 (PcdUsbTransferTimeoutValue), 428 NULL, 429 0, 430 Status 431 ); 432 } 433 434 435 /** 436 Clear the specified feature of the specified device. 437 438 Submit a USB clear device feature request for the USB device specified by UsbIo, 439 Recipient, and Target to the value specified by Value. The status of the transfer 440 is returned in Status. 441 If UsbIo is NULL, then ASSERT(). 442 If Status is NULL, then ASSERT(). 443 444 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 445 @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint). 446 Type USB_TYPES_DEFINITION is defined in the MDE Package Industry Standard 447 include file Usb.h. 448 @param Value The value of the feature to be cleared. 449 @param Target The index of the device to be cleared. 450 @param Status A pointer to the status of the transfer. 451 452 @retval EFI_SUCCESS The request executed successfully. 453 @retval EFI_TIMEOUT A timeout occurred executing the request. 454 @retval EFI_DEVICE_ERROR The request failed due to a device error. 455 The transfer status is returned in Status. 456 457 **/ 458 EFI_STATUS 459 EFIAPI 460 UsbClearFeature ( 461 IN EFI_USB_IO_PROTOCOL *UsbIo, 462 IN USB_TYPES_DEFINITION Recipient, 463 IN UINT16 Value, 464 IN UINT16 Target, 465 OUT UINT32 *Status 466 ) 467 { 468 EFI_USB_DEVICE_REQUEST DevReq; 469 470 ASSERT (UsbIo != NULL); 471 ASSERT (Status != NULL); 472 473 474 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 475 476 switch (Recipient) { 477 478 case USB_TARGET_DEVICE: 479 DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_D; 480 break; 481 482 case USB_TARGET_INTERFACE: 483 DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_I; 484 break; 485 486 case USB_TARGET_ENDPOINT: 487 DevReq.RequestType = USB_DEV_CLEAR_FEATURE_REQ_TYPE_E; 488 break; 489 490 default: 491 break; 492 } 493 // 494 // Fill device request, see USB1.1 spec 495 // 496 DevReq.Request = USB_REQ_CLEAR_FEATURE; 497 DevReq.Value = Value; 498 DevReq.Index = Target; 499 500 501 return UsbIo->UsbControlTransfer ( 502 UsbIo, 503 &DevReq, 504 EfiUsbNoData, 505 PcdGet32 (PcdUsbTransferTimeoutValue), 506 NULL, 507 0, 508 Status 509 ); 510 } 511 512 513 /** 514 Get the status of the specified device. 515 516 Submit a USB device get status request for the USB device specified by UsbIo, 517 Recipient, and Target and place the result in the buffer specified by DeviceStatus. 518 The status of the transfer is returned in Status. 519 If UsbIo is NULL, then ASSERT(). 520 If DeviceStatus is NULL, then ASSERT(). 521 If Status is NULL, then ASSERT(). 522 523 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 524 @param Recipient The USB data recipient type (i.e. Device, Interface, Endpoint). 525 Type USB_TYPES_DEFINITION is defined in the MDE Package Industry Standard 526 include file Usb.h. 527 @param Target The index of the device to be get the status of. 528 @param DeviceStatus A pointer to the device status to be retrieved. 529 @param Status A pointer to the status of the transfer. 530 531 @retval EFI_SUCCESS The request executed successfully. 532 @retval EFI_TIMEOUT A timeout occurred executing the request. 533 @retval EFI_DEVICE_ERROR The request failed due to a device error. 534 The transfer status is returned in Status. 535 536 **/ 537 EFI_STATUS 538 EFIAPI 539 UsbGetStatus ( 540 IN EFI_USB_IO_PROTOCOL *UsbIo, 541 IN USB_TYPES_DEFINITION Recipient, 542 IN UINT16 Target, 543 OUT UINT16 *DeviceStatus, 544 OUT UINT32 *Status 545 ) 546 { 547 EFI_USB_DEVICE_REQUEST DevReq; 548 549 ASSERT (UsbIo != NULL); 550 ASSERT (DeviceStatus != NULL); 551 ASSERT (Status != NULL); 552 553 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); 554 555 switch (Recipient) { 556 557 case USB_TARGET_DEVICE: 558 DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_D; 559 break; 560 561 case USB_TARGET_INTERFACE: 562 DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_I; 563 break; 564 565 case USB_TARGET_ENDPOINT: 566 DevReq.RequestType = USB_DEV_GET_STATUS_REQ_TYPE_E; 567 break; 568 569 default: 570 break; 571 } 572 // 573 // Fill device request, see USB1.1 spec 574 // 575 DevReq.Request = USB_REQ_GET_STATUS; 576 DevReq.Value = 0; 577 DevReq.Index = Target; 578 DevReq.Length = 2; 579 580 return UsbIo->UsbControlTransfer ( 581 UsbIo, 582 &DevReq, 583 EfiUsbDataIn, 584 PcdGet32 (PcdUsbTransferTimeoutValue), 585 DeviceStatus, 586 2, 587 Status 588 ); 589 } 590 591 592 /** 593 Clear halt feature of the specified usb endpoint. 594 595 Retrieve the USB endpoint descriptor specified by UsbIo and EndPoint. 596 If the USB endpoint descriptor can not be retrieved, then return EFI_NOT_FOUND. 597 If the endpoint descriptor is found, then clear the halt feature of this USB endpoint. 598 The status of the transfer is returned in Status. 599 If UsbIo is NULL, then ASSERT(). 600 If Status is NULL, then ASSERT(). 601 602 @param UsbIo A pointer to the USB I/O Protocol instance for the specific USB target. 603 @param Endpoint The endpoint address. 604 @param Status A pointer to the status of the transfer. 605 606 @retval EFI_SUCCESS The request executed successfully. 607 @retval EFI_TIMEOUT A timeout occurred executing the request. 608 @retval EFI_DEVICE_ERROR The request failed due to a device error. 609 The transfer status is returned in Status. 610 @retval EFI_NOT_FOUND The specified USB endpoint descriptor can not be found 611 612 **/ 613 EFI_STATUS 614 EFIAPI 615 UsbClearEndpointHalt ( 616 IN EFI_USB_IO_PROTOCOL *UsbIo, 617 IN UINT8 Endpoint, 618 OUT UINT32 *Status 619 ) 620 { 621 EFI_STATUS Result; 622 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; 623 EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; 624 UINT8 Index; 625 626 ASSERT (UsbIo != NULL); 627 ASSERT (Status != NULL); 628 629 ZeroMem (&EndpointDescriptor, sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)); 630 // 631 // First seach the endpoint descriptor for that endpoint addr 632 // 633 Result = UsbIo->UsbGetInterfaceDescriptor ( 634 UsbIo, 635 &InterfaceDescriptor 636 ); 637 if (EFI_ERROR (Result)) { 638 return Result; 639 } 640 641 for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) { 642 Result = UsbIo->UsbGetEndpointDescriptor ( 643 UsbIo, 644 Index, 645 &EndpointDescriptor 646 ); 647 if (EFI_ERROR (Result)) { 648 continue; 649 } 650 651 if (EndpointDescriptor.EndpointAddress == Endpoint) { 652 break; 653 } 654 } 655 656 if (Index == InterfaceDescriptor.NumEndpoints) { 657 // 658 // No such endpoint 659 // 660 return EFI_NOT_FOUND; 661 } 662 663 Result = UsbClearFeature ( 664 UsbIo, 665 USB_TARGET_ENDPOINT, 666 USB_FEATURE_ENDPOINT_HALT, 667 EndpointDescriptor.EndpointAddress, 668 Status 669 ); 670 671 return Result; 672 } 673