1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxUsbDeviceAPI.cpp 8 9 Abstract: 10 11 12 Author: 13 14 Environment: 15 16 Both kernel and user mode 17 18 Revision History: 19 20 --*/ 21 22 #include "fxusbpch.hpp" 23 24 extern "C" { 25 #include "FxUsbDeviceAPI.tmh" 26 } 27 28 // 29 // Extern "C" all APIs 30 // 31 extern "C" { 32 33 _Must_inspect_result_ 34 __drv_maxIRQL(PASSIVE_LEVEL) 35 NTSTATUS 36 WDFAPI 37 FxUsbTargetDeviceCreate( 38 __in 39 PFX_DRIVER_GLOBALS FxDriverGlobals, 40 __in 41 FxDeviceBase* Device, 42 __in 43 ULONG USBDClientContractVersion, 44 __in_opt 45 PWDF_OBJECT_ATTRIBUTES Attributes, 46 __out 47 WDFUSBDEVICE* UsbDevice 48 ) 49 /*++ 50 51 Routine Description: 52 Creates a WDFUSBDEVICE handle for the client. 53 54 Arguments: 55 56 Device - FxDeviceBase object 57 58 USBDClientContractVersion - The USBD Client Contract version of the client driver 59 60 UsbDevice - Pointer which will receive the created handle 61 62 Return Value: 63 STATUS_SUCCESS - success 64 STATUS_INSUFFICIENT_RESOURCES - no memory available 65 ... 66 67 --*/ 68 { 69 FxUsbDevice* pUsbDevice; 70 NTSTATUS status; 71 72 // 73 // Basic parameter validation 74 // 75 76 FxPointerNotNull(FxDriverGlobals, UsbDevice); 77 *UsbDevice = NULL; 78 79 status = FxVerifierCheckIrqlLevel(FxDriverGlobals, PASSIVE_LEVEL); 80 if (!NT_SUCCESS(status)) { 81 return status; 82 } 83 84 status = FxValidateObjectAttributes(FxDriverGlobals, 85 Attributes, 86 FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED); 87 if (!NT_SUCCESS(status)) { 88 return status; 89 } 90 91 pUsbDevice = new(FxDriverGlobals, Attributes) FxUsbDevice(FxDriverGlobals); 92 if (pUsbDevice == NULL) { 93 return STATUS_INSUFFICIENT_RESOURCES; 94 } 95 96 // 97 // Perform all init and handle creation functions. Check for error at the 98 // end and clean up there. 99 // 100 status = pUsbDevice->Init(Device); 101 102 if (NT_SUCCESS(status)) { 103 WDFOBJECT device; 104 105 device = NULL; 106 107 status = pUsbDevice->InitDevice(USBDClientContractVersion); 108 109 if (NT_SUCCESS(status)) { 110 status = pUsbDevice->CreateInterfaces(); 111 } 112 113 if (NT_SUCCESS(status)) { 114 status = Device->AddIoTarget(pUsbDevice); 115 } 116 117 if (NT_SUCCESS(status)) { 118 status = pUsbDevice->Commit(Attributes, &device, Device); 119 } 120 121 if (NT_SUCCESS(status)) { 122 *UsbDevice = (WDFUSBDEVICE) device; 123 } 124 } 125 126 if (!NT_SUCCESS(status)) { 127 // 128 // And now free it 129 // 130 pUsbDevice->DeleteFromFailedCreate(); 131 } 132 133 return status; 134 } 135 136 _Must_inspect_result_ 137 __drv_maxIRQL(PASSIVE_LEVEL) 138 NTSTATUS 139 WDFAPI 140 WDFEXPORT(WdfUsbTargetDeviceCreate)( 141 __in 142 PWDF_DRIVER_GLOBALS DriverGlobals, 143 __in 144 WDFDEVICE Device, 145 __in_opt 146 PWDF_OBJECT_ATTRIBUTES Attributes, 147 __out 148 WDFUSBDEVICE* UsbDevice 149 ) 150 /*++ 151 152 Routine Description: 153 Creates a WDFUSBDEVICE handle for the client. 154 155 Arguments: 156 Device - WDFDEVICE handle to which we are attaching the WDFUSBDEVICE handle 157 to 158 PUsbDevice - Pointer which will receive the created handle 159 160 Return Value: 161 STATUS_SUCCESS - success 162 STATUS_INSUFFICIENT_RESOURCES - no memory available 163 ... 164 165 --*/ 166 { 167 DDI_ENTRY(); 168 169 PFX_DRIVER_GLOBALS pFxDriverGlobals; 170 FxDeviceBase* pDevice; 171 172 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 173 Device, 174 FX_TYPE_DEVICE_BASE, 175 (PVOID*)&pDevice, 176 &pFxDriverGlobals); 177 178 return FxUsbTargetDeviceCreate(pFxDriverGlobals, 179 pDevice, 180 USBD_CLIENT_CONTRACT_VERSION_INVALID, 181 Attributes, 182 UsbDevice); 183 } 184 185 __checkReturn 186 __drv_maxIRQL(PASSIVE_LEVEL) 187 NTSTATUS 188 WDFAPI 189 WDFEXPORT(WdfUsbTargetDeviceCreateWithParameters)( 190 __in 191 PWDF_DRIVER_GLOBALS DriverGlobals, 192 __in 193 WDFDEVICE Device, 194 __in 195 PWDF_USB_DEVICE_CREATE_CONFIG Config, 196 __in_opt 197 PWDF_OBJECT_ATTRIBUTES Attributes, 198 __out 199 WDFUSBDEVICE* UsbDevice 200 ) 201 /*++ 202 203 Routine Description: 204 Creates a WDFUSBDEVICE handle for the client. 205 206 Arguments: 207 Device - WDFDEVICE handle to which we are attaching the WDFUSBDEVICE handle 208 to 209 PUsbDevice - Pointer which will receive the created handle 210 211 Return Value: 212 STATUS_SUCCESS - success 213 STATUS_INSUFFICIENT_RESOURCES - no memory available 214 ... 215 216 --*/ 217 { 218 DDI_ENTRY(); 219 220 PFX_DRIVER_GLOBALS pFxDriverGlobals; 221 FxDeviceBase* pDevice; 222 NTSTATUS status; 223 224 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 225 Device, 226 FX_TYPE_DEVICE_BASE, 227 (PVOID*)&pDevice, 228 &pFxDriverGlobals); 229 230 FxPointerNotNull(pFxDriverGlobals, Config); 231 232 if (Config->Size != sizeof(WDF_USB_DEVICE_CREATE_CONFIG)) { 233 status = STATUS_INFO_LENGTH_MISMATCH; 234 235 DoTraceLevelMessage( 236 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 237 "WDF_USB_DEVICE_CREATE_CONFIG Size 0x%x, expected 0x%x, %!STATUS!", 238 Config->Size, sizeof(WDF_USB_DEVICE_CREATE_CONFIG), status); 239 240 return status; 241 } 242 243 return FxUsbTargetDeviceCreate(pFxDriverGlobals, 244 pDevice, 245 Config->USBDClientContractVersion, 246 Attributes, 247 UsbDevice); 248 } 249 250 _Must_inspect_result_ 251 __drv_maxIRQL(DISPATCH_LEVEL) 252 NTSTATUS 253 WDFAPI 254 WDFEXPORT(WdfUsbTargetDeviceRetrieveInformation)( 255 __in 256 PWDF_DRIVER_GLOBALS DriverGlobals, 257 __in 258 WDFUSBDEVICE UsbDevice, 259 __out 260 PWDF_USB_DEVICE_INFORMATION Information 261 ) 262 { 263 DDI_ENTRY(); 264 265 PFX_DRIVER_GLOBALS pFxDriverGlobals; 266 FxUsbDevice* pUsbDevice; 267 NTSTATUS status; 268 269 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 270 UsbDevice, 271 FX_TYPE_IO_TARGET_USB_DEVICE, 272 (PVOID*) &pUsbDevice, 273 &pFxDriverGlobals); 274 275 FxPointerNotNull(pFxDriverGlobals, Information); 276 277 if (Information->Size != sizeof(WDF_USB_DEVICE_INFORMATION)) { 278 status = STATUS_INFO_LENGTH_MISMATCH; 279 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 280 "Information size %d, expected %d %!STATUS!", 281 Information->Size, sizeof(WDF_USB_DEVICE_INFORMATION), 282 status); 283 return status; 284 } 285 286 pUsbDevice->GetInformation(Information); 287 288 return STATUS_SUCCESS; 289 } 290 291 __drv_maxIRQL(PASSIVE_LEVEL) 292 VOID 293 WDFAPI 294 WDFEXPORT(WdfUsbTargetDeviceGetDeviceDescriptor)( 295 __in 296 PWDF_DRIVER_GLOBALS DriverGlobals, 297 __in 298 WDFUSBDEVICE UsbDevice, 299 __out 300 PUSB_DEVICE_DESCRIPTOR UsbDeviceDescriptor 301 ) 302 { 303 DDI_ENTRY(); 304 305 PFX_DRIVER_GLOBALS pFxDriverGlobals; 306 FxUsbDevice* pUsbDevice; 307 NTSTATUS status; 308 309 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 310 UsbDevice, 311 FX_TYPE_IO_TARGET_USB_DEVICE, 312 (PVOID*) &pUsbDevice, 313 &pFxDriverGlobals); 314 315 FxPointerNotNull(pFxDriverGlobals, UsbDeviceDescriptor); 316 317 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 318 if (!NT_SUCCESS(status)) { 319 return; 320 } 321 322 pUsbDevice->CopyDeviceDescriptor(UsbDeviceDescriptor); 323 } 324 325 _Must_inspect_result_ 326 __drv_maxIRQL(PASSIVE_LEVEL) 327 NTSTATUS 328 WDFAPI 329 WDFEXPORT(WdfUsbTargetDeviceRetrieveConfigDescriptor)( 330 __in 331 PWDF_DRIVER_GLOBALS DriverGlobals, 332 __in 333 WDFUSBDEVICE UsbDevice, 334 __out_bcount_part_opt(*ConfigDescriptorLength, *ConfigDescriptorLength) 335 PVOID ConfigDescriptor, 336 __inout 337 PUSHORT ConfigDescriptorLength 338 ) 339 { 340 DDI_ENTRY(); 341 342 PFX_DRIVER_GLOBALS pFxDriverGlobals; 343 FxUsbDevice* pUsbDevice; 344 NTSTATUS status; 345 346 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 347 UsbDevice, 348 FX_TYPE_IO_TARGET_USB_DEVICE, 349 (PVOID*) &pUsbDevice, 350 &pFxDriverGlobals); 351 352 FxPointerNotNull(pFxDriverGlobals, ConfigDescriptorLength); 353 354 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 355 if (!NT_SUCCESS(status)) { 356 return status; 357 } 358 359 return pUsbDevice->GetConfigDescriptor(ConfigDescriptor, 360 ConfigDescriptorLength); 361 } 362 363 _Must_inspect_result_ 364 __drv_maxIRQL(PASSIVE_LEVEL) 365 NTSTATUS 366 WDFAPI 367 WDFEXPORT(WdfUsbTargetDeviceQueryString)( 368 __in 369 PWDF_DRIVER_GLOBALS DriverGlobals, 370 __in 371 WDFUSBDEVICE UsbDevice, 372 __in_opt 373 WDFREQUEST Request, 374 __in_opt 375 PWDF_REQUEST_SEND_OPTIONS RequestOptions, 376 __out_ecount_opt(*NumCharacters) 377 PUSHORT String, 378 __inout 379 PUSHORT NumCharacters, 380 __in 381 UCHAR StringIndex, 382 __in_opt 383 USHORT LangID 384 ) 385 { 386 DDI_ENTRY(); 387 388 PFX_DRIVER_GLOBALS pFxDriverGlobals; 389 FxUsbDevice* pUsbDevice; 390 NTSTATUS status; 391 392 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 393 UsbDevice, 394 FX_TYPE_IO_TARGET_USB_DEVICE, 395 (PVOID*) &pUsbDevice, 396 &pFxDriverGlobals); 397 398 FxPointerNotNull(pFxDriverGlobals, NumCharacters); 399 400 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 401 if (!NT_SUCCESS(status)) { 402 return status; 403 } 404 405 status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions); 406 if (!NT_SUCCESS(status)) { 407 return status; 408 } 409 410 status = pUsbDevice->GetString(String, 411 NumCharacters, 412 StringIndex, 413 LangID, 414 Request, 415 RequestOptions); 416 417 return status; 418 } 419 420 _Must_inspect_result_ 421 __drv_maxIRQL(PASSIVE_LEVEL) 422 NTSTATUS 423 WDFAPI 424 WDFEXPORT(WdfUsbTargetDeviceAllocAndQueryString)( 425 __in 426 PWDF_DRIVER_GLOBALS DriverGlobals, 427 __in 428 WDFUSBDEVICE UsbDevice, 429 __in_opt 430 PWDF_OBJECT_ATTRIBUTES StringMemoryAttributes, 431 __out 432 WDFMEMORY* StringMemory, 433 __out_opt 434 PUSHORT NumCharacters, 435 __in 436 UCHAR StringIndex, 437 __in_opt 438 USHORT LangID 439 ) 440 { 441 DDI_ENTRY(); 442 443 PFX_DRIVER_GLOBALS pFxDriverGlobals; 444 WDFMEMORY hMemory; 445 FxUsbDevice* pUsbDevice; 446 NTSTATUS status; 447 USHORT numChars = 0; 448 449 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 450 UsbDevice, 451 FX_TYPE_IO_TARGET_USB_DEVICE, 452 (PVOID*) &pUsbDevice, 453 &pFxDriverGlobals); 454 455 FxPointerNotNull(pFxDriverGlobals, StringMemory); 456 457 *StringMemory = NULL; 458 if (NumCharacters != NULL) { 459 *NumCharacters = 0; 460 } 461 462 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 463 if (!NT_SUCCESS(status)) { 464 return status; 465 } 466 467 status = FxValidateObjectAttributes(pFxDriverGlobals, StringMemoryAttributes); 468 if (!NT_SUCCESS(status)) { 469 return status; 470 } 471 472 status = pUsbDevice->GetString(NULL, &numChars, StringIndex, LangID); 473 474 if (NT_SUCCESS(status) && numChars > 0) { 475 FxMemoryObject* pBuffer; 476 477 status = FxMemoryObject::_Create(pFxDriverGlobals, 478 StringMemoryAttributes, 479 NonPagedPool, 480 pFxDriverGlobals->Tag, 481 numChars * sizeof(WCHAR), 482 &pBuffer); 483 484 if (!NT_SUCCESS(status)) { 485 return STATUS_INSUFFICIENT_RESOURCES; 486 } 487 488 status = pBuffer->Commit(StringMemoryAttributes, 489 (WDFOBJECT*)&hMemory); 490 491 if (NT_SUCCESS(status)) { 492 status = pUsbDevice->GetString((PUSHORT) pBuffer->GetBuffer(), 493 &numChars, 494 StringIndex, 495 LangID); 496 497 if (NT_SUCCESS(status)) { 498 if (NumCharacters != NULL) { 499 *NumCharacters = numChars; 500 } 501 *StringMemory = hMemory; 502 } 503 } 504 505 if (!NT_SUCCESS(status)) { 506 // 507 // There can only be one context on this object right now, 508 // so just clear out the one. 509 // 510 pBuffer->DeleteFromFailedCreate(); 511 } 512 } 513 514 return status; 515 } 516 517 _Must_inspect_result_ 518 __drv_maxIRQL(DISPATCH_LEVEL) 519 NTSTATUS 520 WDFEXPORT(WdfUsbTargetDeviceFormatRequestForString)( 521 __in 522 PWDF_DRIVER_GLOBALS DriverGlobals, 523 __in 524 WDFUSBDEVICE UsbDevice, 525 __in 526 WDFREQUEST Request, 527 __in 528 WDFMEMORY Memory, 529 __in_opt 530 PWDFMEMORY_OFFSET Offset, 531 __in 532 UCHAR StringIndex, 533 __in_opt 534 USHORT LangID 535 ) 536 /*++ 537 538 Routine Description: 539 Formats a request so that it can be used to query for a string from the 540 device. 541 542 Arguments: 543 UsbDevice - device to be queried 544 545 Request - request to format 546 547 Memory - memory to write the string into 548 549 550 Return Value: 551 552 553 --*/ 554 555 { 556 DDI_ENTRY(); 557 558 PFX_DRIVER_GLOBALS pFxDriverGlobals; 559 IFxMemory* pMemory; 560 FxUsbDevice* pUsbDevice; 561 FxRequestBuffer buf; 562 FxRequest* pRequest; 563 NTSTATUS status; 564 size_t bufferSize; 565 566 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 567 UsbDevice, 568 FX_TYPE_IO_TARGET_USB_DEVICE, 569 (PVOID*) &pUsbDevice, 570 &pFxDriverGlobals); 571 572 DoTraceLevelMessage( 573 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 574 "WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p, StringIndex %d, LandID 0x%x", 575 UsbDevice, Request, Memory, StringIndex, LangID); 576 577 FxObjectHandleGetPtr(pFxDriverGlobals, 578 Memory, 579 IFX_TYPE_MEMORY, 580 (PVOID*) &pMemory); 581 582 FxObjectHandleGetPtr(pFxDriverGlobals, 583 Request, 584 FX_TYPE_REQUEST, 585 (PVOID*) &pRequest); 586 587 status = pMemory->ValidateMemoryOffsets(Offset); 588 if (!NT_SUCCESS(status)) { 589 return status; 590 } 591 592 buf.SetMemory(pMemory, Offset); 593 594 bufferSize = buf.GetBufferLength(); 595 596 // 597 // the string descriptor is array of WCHARs so the buffer being used must be 598 // of an integral number of them. 599 // 600 if ((bufferSize % sizeof(WCHAR)) != 0) { 601 status = STATUS_INVALID_PARAMETER; 602 603 DoTraceLevelMessage( 604 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 605 "WDFMEMORY %p length must be even number of WCHARs, but is %I64d in " 606 "length, %!STATUS!", 607 Memory, bufferSize, status); 608 609 return status; 610 } 611 612 // 613 // While the length in the descriptor (bLength) is a byte, so the requested 614 // buffer cannot be bigger then that, do not check the bufferSize < 0xFF. 615 // We don't check because the driver can be using the WDFMEMORY as a part 616 // of a larger structure. 617 // 618 619 // 620 // Format the request 621 // 622 status = pUsbDevice->FormatStringRequest(pRequest, &buf, StringIndex, LangID); 623 624 if (NT_SUCCESS(status)) { 625 FxUsbDeviceStringContext* pContext; 626 627 pContext = (FxUsbDeviceStringContext*) pRequest->GetContext(); 628 pContext->m_UsbParameters.Parameters.DeviceString.Buffer = Memory; 629 pContext->m_UsbParameters.Parameters.DeviceString.StringIndex = StringIndex; 630 pContext->m_UsbParameters.Parameters.DeviceString.LangID = LangID; 631 } 632 633 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 634 "WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p, %!STATUS!", 635 UsbDevice, Request, Memory, status); 636 637 return status; 638 } 639 640 _Must_inspect_result_ 641 __drv_maxIRQL(PASSIVE_LEVEL) 642 NTSTATUS 643 WDFAPI 644 WDFEXPORT(WdfUsbTargetDeviceSelectConfig)( 645 __in 646 PWDF_DRIVER_GLOBALS DriverGlobals, 647 __in 648 WDFUSBDEVICE UsbDevice, 649 __in_opt 650 PWDF_OBJECT_ATTRIBUTES PipesAttributes, 651 __inout 652 PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params 653 ) 654 { 655 DDI_ENTRY(); 656 657 PFX_DRIVER_GLOBALS pFxDriverGlobals; 658 FxUsbDevice* pUsbDevice; 659 NTSTATUS status; 660 661 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 662 UsbDevice, 663 FX_TYPE_IO_TARGET_USB_DEVICE, 664 (PVOID*) &pUsbDevice, 665 &pFxDriverGlobals); 666 667 FxPointerNotNull(pFxDriverGlobals, Params); 668 669 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 670 if (!NT_SUCCESS(status)) { 671 return status; 672 } 673 674 if (Params->Size != sizeof(WDF_USB_DEVICE_SELECT_CONFIG_PARAMS)) { 675 status = STATUS_INFO_LENGTH_MISMATCH; 676 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 677 "Params size %d, expected %d %!STATUS!", 678 Params->Size, sizeof(WDF_USB_DEVICE_SELECT_CONFIG_PARAMS), 679 status); 680 return status; 681 } 682 683 // 684 // Sanity check the Type value as well to be in range. 685 // 686 if (Params->Type < WdfUsbTargetDeviceSelectConfigTypeDeconfig 687 || 688 Params->Type > WdfUsbTargetDeviceSelectConfigTypeUrb) { 689 690 status = STATUS_INVALID_PARAMETER; 691 692 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 693 "Params Type %d not a valid value, %!STATUS!", 694 Params->Size, status); 695 696 return status; 697 } 698 699 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 700 if ((Params->Type == WdfUsbTargetDeviceSelectConfigTypeDeconfig) || 701 (Params->Type == WdfUsbTargetDeviceSelectConfigTypeUrb) || 702 (Params->Type == WdfUsbTargetDeviceSelectConfigTypeInterfacesDescriptor)) { 703 status = STATUS_NOT_SUPPORTED; 704 705 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 706 "Params Type %d not supported for UMDF, %!STATUS!", 707 Params->Type, status); 708 709 return status; 710 711 } 712 #endif 713 714 status = FxValidateObjectAttributes(pFxDriverGlobals, 715 PipesAttributes, 716 FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED); 717 if (!NT_SUCCESS(status)) { 718 return status; 719 } 720 721 if (pUsbDevice->HasMismatchedInterfacesInConfigDescriptor()) { 722 // 723 // Config descriptor reported zero interfaces, but we found an 724 // interface descriptor in it. 725 // 726 status = STATUS_INVALID_DEVICE_REQUEST; 727 728 DoTraceLevelMessage( 729 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 730 "WDFUSBDEVICE %p number of interfaces found in the config descriptor " 731 "does not match bNumInterfaces in config descriptor, failing config " 732 "operation %!WdfUsbTargetDeviceSelectConfigType!, %!STATUS!", 733 UsbDevice, Params->Type, status); 734 735 return status; 736 } 737 else if (pUsbDevice->GetNumInterfaces() == 0) { 738 // 739 // Special case the zero interface case and exit early 740 // 741 status = STATUS_SUCCESS; 742 743 DoTraceLevelMessage( 744 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 745 "WDFUSBDEVICE %p succeeding config operation " 746 "%!WdfUsbTargetDeviceSelectConfigType! on zero interfaces " 747 "immediately, %!STATUS!", UsbDevice, Params->Type, status); 748 749 return status; 750 } 751 752 switch (Params->Type) { 753 754 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 755 756 case WdfUsbTargetDeviceSelectConfigTypeDeconfig: 757 status = pUsbDevice->Deconfig(); 758 break; 759 760 case WdfUsbTargetDeviceSelectConfigTypeInterfacesDescriptor: 761 if (Params->Types.Descriptor.InterfaceDescriptors == NULL || 762 Params->Types.Descriptor.NumInterfaceDescriptors == 0) { 763 status = STATUS_INVALID_PARAMETER; 764 DoTraceLevelMessage( 765 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 766 "Either InterfaceDescriptor is NULL or NumInterfaceDescriptors is zero " 767 "WDFUSBDEVICE %p InterfaceDescriptor %p NumInterfaceDescriptors 0x%x" 768 "%!WdfUsbTargetDeviceSelectConfigType! %!STATUS!", UsbDevice, 769 Params->Types.Descriptor.InterfaceDescriptors, 770 Params->Types.Descriptor.NumInterfaceDescriptors, 771 Params->Type, 772 status); 773 774 } 775 else { 776 status = pUsbDevice->SelectConfigDescriptor( 777 PipesAttributes, 778 Params); 779 } 780 break; 781 782 case WdfUsbTargetDeviceSelectConfigTypeUrb: 783 // 784 // Since the USBD macro's dont include the USBD_PIPE_INFORMATION for 0 EP's, 785 // make the length check to use 786 // sizeof(struct _URB_SELECT_CONFIGURATION) - sizeof(USBD_PIPE_INFORMATION) 787 // 788 if (Params->Types.Urb.Urb == NULL || 789 Params->Types.Urb.Urb->UrbHeader.Function != URB_FUNCTION_SELECT_CONFIGURATION || 790 Params->Types.Urb.Urb->UrbHeader.Length < 791 (sizeof(struct _URB_SELECT_CONFIGURATION) - sizeof(USBD_PIPE_INFORMATION))) { 792 status = STATUS_INVALID_PARAMETER; 793 DoTraceLevelMessage( 794 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 795 "Either URB passed in was NULL or the URB Function or Length was invalid " 796 " WDFUSBDEVICE %p Urb 0x%p " 797 "%!WdfUsbTargetDeviceSelectConfigType!" 798 " %!STATUS!", UsbDevice, 799 Params->Types.Urb.Urb, 800 Params->Type, 801 status); 802 803 } 804 else { 805 status = pUsbDevice->SelectConfig( 806 PipesAttributes, 807 Params->Types.Urb.Urb, 808 FxUrbTypeLegacy, 809 NULL); 810 } 811 break; 812 813 #endif 814 815 816 817 818 819 case WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs: 820 if (Params->Types.MultiInterface.Pairs == NULL) { 821 status = STATUS_INVALID_PARAMETER; 822 823 DoTraceLevelMessage( 824 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 825 "WDFUSBDEVICE %p SettingPairs Array passed is NULL, %!STATUS!", 826 pUsbDevice->GetHandle(),status); 827 828 break; 829 } 830 else if (Params->Types.MultiInterface.NumberInterfaces != 831 pUsbDevice->GetNumInterfaces()) { 832 status = STATUS_INVALID_PARAMETER; 833 834 DoTraceLevelMessage( 835 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 836 "WDFUSBDEVICE %p MultiInterface.NumberInterfaces %d != %d " 837 "(reported num interfaces), %!STATUS!", 838 pUsbDevice->GetHandle(), 839 Params->Types.MultiInterface.NumberInterfaces, 840 pUsbDevice->GetNumInterfaces(), status); 841 842 break; 843 } 844 845 // || || Fall through || || 846 // \/ \/ \/ \/ 847 case WdfUsbTargetDeviceSelectConfigTypeMultiInterface: 848 849 // 850 // Validate SettingIndexes passed-in 851 // 852 for (ULONG i = 0; 853 i < Params->Types.MultiInterface.NumberInterfaces; 854 i++) { 855 856 PWDF_USB_INTERFACE_SETTING_PAIR pair; 857 FxUsbInterface * pUsbInterface; 858 UCHAR numSettings; 859 860 pair = &(Params->Types.MultiInterface.Pairs[i]); 861 862 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 863 pair->UsbInterface, 864 FX_TYPE_USB_INTERFACE, 865 (PVOID*) &pUsbInterface); 866 867 numSettings = pUsbInterface->GetNumSettings(); 868 869 if (pair->SettingIndex >= numSettings) { 870 status = STATUS_INVALID_PARAMETER; 871 872 DoTraceLevelMessage( 873 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 874 "WDFUSBDEVICE %p SettingPairs contains invalid SettingIndex" 875 " for WDFUSBINTERFACE %p. Setting index passed in: %d, " 876 "max index: %d, returning %!STATUS!", 877 pUsbDevice->GetHandle(), 878 pair->UsbInterface, 879 pair->SettingIndex, 880 pUsbInterface->GetNumSettings() - 1, 881 status); 882 883 return status; 884 } 885 } 886 887 status = pUsbDevice->SelectConfigMulti( 888 PipesAttributes, 889 Params); 890 break; 891 892 case WdfUsbTargetDeviceSelectConfigTypeSingleInterface: 893 status = pUsbDevice->SelectConfigSingle( //vm changed name from SelectConfigAuto 894 PipesAttributes, 895 Params); 896 break; 897 898 default: 899 status = STATUS_INVALID_PARAMETER; 900 } 901 902 return status; 903 } 904 905 906 __drv_maxIRQL(DISPATCH_LEVEL) 907 UCHAR 908 WDFAPI 909 WDFEXPORT(WdfUsbTargetDeviceGetNumInterfaces)( 910 __in 911 PWDF_DRIVER_GLOBALS DriverGlobals, 912 __in 913 WDFUSBDEVICE UsbDevice 914 ) 915 { 916 DDI_ENTRY(); 917 918 FxUsbDevice* pUsbDevice; 919 920 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 921 UsbDevice, 922 FX_TYPE_IO_TARGET_USB_DEVICE, 923 (PVOID*) &pUsbDevice); 924 925 return pUsbDevice->GetNumInterfaces(); 926 } 927 928 929 __drv_maxIRQL(DISPATCH_LEVEL) 930 USBD_CONFIGURATION_HANDLE 931 WDFAPI 932 WDFEXPORT(WdfUsbTargetDeviceWdmGetConfigurationHandle)( 933 __in 934 PWDF_DRIVER_GLOBALS DriverGlobals, 935 __in 936 WDFUSBDEVICE UsbDevice 937 ) 938 { 939 DDI_ENTRY(); 940 941 FxUsbDevice* pUsbDevice; 942 943 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals), 944 UsbDevice, 945 FX_TYPE_IO_TARGET_USB_DEVICE, 946 (PVOID*) &pUsbDevice); 947 948 return pUsbDevice->GetConfigHandle(); 949 } 950 951 _Must_inspect_result_ 952 __drv_maxIRQL(PASSIVE_LEVEL) 953 NTSTATUS 954 WDFEXPORT(WdfUsbTargetDeviceSendControlTransferSynchronously)( 955 __in 956 PWDF_DRIVER_GLOBALS DriverGlobals, 957 __in 958 WDFUSBDEVICE UsbDevice, 959 __in_opt 960 WDFREQUEST Request, 961 __in_opt 962 PWDF_REQUEST_SEND_OPTIONS RequestOptions, 963 __in 964 PWDF_USB_CONTROL_SETUP_PACKET SetupPacket, 965 __in_opt 966 PWDF_MEMORY_DESCRIPTOR MemoryDescriptor, 967 __out_opt 968 PULONG BytesTransferred 969 ) 970 /*++ 971 972 Routine Description: 973 Synchronously sends a control transfer to the default control pipe on the 974 device. 975 976 Arguments: 977 UsbDevice - the target representing the device 978 979 Request - Request whose PIRP to use 980 981 RequestOptions - options to use when sending the request 982 983 SetupPacket - control setup packet to be used in the transfer 984 985 MemoryDescriptor - memory to use in the transfer after the setup packet 986 987 BytesTransferred - number of bytes sent to or by the device 988 989 Return Value: 990 NTSTATUS 991 992 --*/ 993 { 994 DDI_ENTRY(); 995 996 PFX_DRIVER_GLOBALS pFxDriverGlobals; 997 FxUsbDevice* pUsbDevice; 998 NTSTATUS status; 999 FxRequestBuffer buf; 1000 1001 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1002 UsbDevice, 1003 FX_TYPE_IO_TARGET_USB_DEVICE, 1004 (PVOID*) &pUsbDevice, 1005 &pFxDriverGlobals); 1006 1007 FxUsbDeviceControlContext context(FxUrbTypeLegacy); 1008 1009 FxSyncRequest request(pFxDriverGlobals, &context, Request); 1010 1011 // 1012 // FxSyncRequest always succeesds for KM but can fail for UM. 1013 // 1014 status = request.Initialize(); 1015 if (!NT_SUCCESS(status)) { 1016 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 1017 "Failed to initialize FxSyncRequest"); 1018 return status; 1019 } 1020 1021 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 1022 "WDFUSBDEVICE %p control transfer sync", UsbDevice); 1023 1024 FxPointerNotNull(pFxDriverGlobals, SetupPacket); 1025 1026 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1027 if (!NT_SUCCESS(status)) { 1028 return status; 1029 } 1030 1031 status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions); 1032 if (!NT_SUCCESS(status)) { 1033 return status; 1034 } 1035 1036 status = buf.ValidateMemoryDescriptor( 1037 pFxDriverGlobals, 1038 MemoryDescriptor, 1039 MemoryDescriptorNullAllowed | MemoryDescriptorNoBufferAllowed 1040 ); 1041 1042 if (!NT_SUCCESS(status)) { 1043 return status; 1044 } 1045 1046 status = pUsbDevice->FormatControlRequest(request.m_TrueRequest, 1047 SetupPacket, 1048 &buf); 1049 1050 if (NT_SUCCESS(status)) { 1051 DoTraceLevelMessage( 1052 pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 1053 "WDFUSBDEVICE %p, WDFREQUEST %p being submitted", 1054 UsbDevice, request.m_TrueRequest->GetTraceObjectHandle()); 1055 1056 status = pUsbDevice->SubmitSync(request.m_TrueRequest, RequestOptions); 1057 1058 if (BytesTransferred != NULL) { 1059 if (NT_SUCCESS(status)) { 1060 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) 1061 *BytesTransferred = context.m_Urb->TransferBufferLength; 1062 #elif (FX_CORE_MODE == FX_CORE_USER_MODE) 1063 *BytesTransferred = context.m_UmUrb.UmUrbControlTransfer.TransferBufferLength; 1064 #endif 1065 } 1066 else { 1067 *BytesTransferred = 0; 1068 } 1069 } 1070 } 1071 1072 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 1073 "WDFUSBDEVICE %p, %!STATUS!", UsbDevice, status); 1074 1075 return status; 1076 } 1077 1078 _Must_inspect_result_ 1079 __drv_maxIRQL(DISPATCH_LEVEL) 1080 NTSTATUS 1081 WDFEXPORT(WdfUsbTargetDeviceFormatRequestForControlTransfer)( 1082 __in 1083 PWDF_DRIVER_GLOBALS DriverGlobals, 1084 __in 1085 WDFUSBDEVICE UsbDevice, 1086 __in 1087 WDFREQUEST Request, 1088 __in 1089 PWDF_USB_CONTROL_SETUP_PACKET SetupPacket, 1090 __in_opt 1091 WDFMEMORY TransferMemory, 1092 __in_opt 1093 PWDFMEMORY_OFFSET TransferOffset 1094 ) 1095 /*++ 1096 1097 Routine Description: 1098 Formats a request so that a control transfer can be sent to the device 1099 after this call returns successfully. 1100 1101 Arguments: 1102 UsbDevice - the target representing the device 1103 1104 Request - Request to format 1105 1106 SetupPacket - control setup packet to be used in the transfer 1107 1108 TransferMemory - memory to use in the transfer after the setup packet 1109 1110 TransferOffset - offset into TransferMemory and size override for transfer 1111 length 1112 1113 Return Value: 1114 NTSTATUS 1115 1116 --*/ 1117 { 1118 DDI_ENTRY(); 1119 1120 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1121 IFxMemory* pMemory; 1122 FxUsbDevice* pUsbDevice; 1123 FxRequestBuffer buf; 1124 FxRequest* pRequest; 1125 NTSTATUS status; 1126 1127 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1128 UsbDevice, 1129 FX_TYPE_IO_TARGET_USB_DEVICE, 1130 (PVOID*) &pUsbDevice, 1131 &pFxDriverGlobals); 1132 1133 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 1134 "WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p", 1135 UsbDevice, Request, TransferMemory); 1136 1137 FxPointerNotNull(pFxDriverGlobals, SetupPacket); 1138 1139 if (TransferMemory != NULL) { 1140 FxObjectHandleGetPtr(pFxDriverGlobals, 1141 TransferMemory, 1142 IFX_TYPE_MEMORY, 1143 (PVOID*) &pMemory); 1144 1145 status = pMemory->ValidateMemoryOffsets(TransferOffset); 1146 if (!NT_SUCCESS(status)) { 1147 return status; 1148 } 1149 1150 buf.SetMemory(pMemory, TransferOffset); 1151 } 1152 else { 1153 pMemory = NULL; 1154 } 1155 1156 FxObjectHandleGetPtr(pFxDriverGlobals, 1157 Request, 1158 FX_TYPE_REQUEST, 1159 (PVOID*) &pRequest); 1160 1161 status = pUsbDevice->FormatControlRequest(pRequest, SetupPacket, &buf); 1162 1163 if (NT_SUCCESS(status)) { 1164 FxUsbDeviceControlContext* pContext; 1165 1166 pContext = (FxUsbDeviceControlContext*) pRequest->GetContext(); 1167 1168 RtlCopyMemory( 1169 &pContext->m_UsbParameters.Parameters.DeviceControlTransfer.SetupPacket, 1170 SetupPacket, 1171 sizeof(*SetupPacket) 1172 ); 1173 1174 if (pMemory != NULL) { 1175 pContext->m_UsbParameters.Parameters.DeviceControlTransfer.Buffer = 1176 TransferMemory; 1177 } 1178 } 1179 1180 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET, 1181 "format control request WDFUSBDEVICE %p, WDFREQWUEST %p, WDFMEMORY %p, %!STATUS!", 1182 UsbDevice, Request, TransferMemory, status); 1183 1184 return status; 1185 } 1186 1187 _Must_inspect_result_ 1188 __drv_maxIRQL(PASSIVE_LEVEL) 1189 NTSTATUS 1190 WDFAPI 1191 WDFEXPORT(WdfUsbTargetDeviceResetPortSynchronously)( 1192 __in 1193 PWDF_DRIVER_GLOBALS DriverGlobals, 1194 __in 1195 WDFUSBDEVICE UsbDevice 1196 ) 1197 { 1198 DDI_ENTRY(); 1199 1200 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1201 FxUsbDevice* pUsbDevice; 1202 NTSTATUS status; 1203 1204 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1205 UsbDevice, 1206 FX_TYPE_IO_TARGET_USB_DEVICE, 1207 (PVOID*) &pUsbDevice, 1208 &pFxDriverGlobals); 1209 1210 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL); 1211 if (!NT_SUCCESS(status)) { 1212 return status; 1213 } 1214 1215 status = pUsbDevice->Reset(); 1216 1217 return status; 1218 } 1219 1220 #pragma warning(disable:28285) 1221 __checkReturn 1222 __drv_maxIRQL(DISPATCH_LEVEL) 1223 NTSTATUS 1224 WDFAPI 1225 WDFEXPORT(WdfUsbTargetDeviceCreateIsochUrb)( 1226 __in 1227 PWDF_DRIVER_GLOBALS DriverGlobals, 1228 __in 1229 WDFUSBDEVICE UsbDevice, 1230 __in_opt 1231 PWDF_OBJECT_ATTRIBUTES Attributes, 1232 __in 1233 ULONG NumberOfIsochPackets, 1234 __out 1235 WDFMEMORY* UrbMemory, 1236 __deref_opt_out_bcount(GET_ISOCH_URB_SIZE(NumberOfIsochPackets)) 1237 PURB* Urb 1238 ) 1239 /*++ 1240 1241 Routine Description: 1242 Creates a WDFUSBDEVICE handle for the client. 1243 1244 Arguments: 1245 Attributes - Attributes associated with this object 1246 1247 NumberOfIsochPacket - Maximum number of Isoch packets that will be programmed into this Urb 1248 1249 UrbMemory - The returned handle to the caller for the allocated Urb 1250 1251 Urb - (opt) Pointer to the associated urb buffer. 1252 1253 Return Value: 1254 STATUS_INVALID_PARAMETER - any required parameters are not present/invalid 1255 1256 STATUS_INVALID_DEVICE_STATE - If the client did not specify a client contract verion while 1257 creating the WDFUSBDEVICE 1258 1259 STATUS_INSUFFICIENT_RESOURCES - could not allocated the object that backs 1260 the handle 1261 1262 STATUS_SUCCESS - success 1263 1264 ... 1265 1266 --*/ 1267 { 1268 DDI_ENTRY(); 1269 1270 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1271 FxUsbDevice* pUsbDevice; 1272 NTSTATUS status; 1273 1274 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1275 UsbDevice, 1276 FX_TYPE_IO_TARGET_USB_DEVICE, 1277 (PVOID*) &pUsbDevice, 1278 &pFxDriverGlobals); 1279 1280 // 1281 // Basic parameter validation 1282 // 1283 FxPointerNotNull(pFxDriverGlobals, UrbMemory); 1284 1285 if (pUsbDevice->GetUSBDHandle() == NULL) { 1286 status = STATUS_INVALID_DEVICE_STATE; 1287 1288 DoTraceLevelMessage( 1289 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 1290 "USBDEVICE Must have been created with Client Contract Verion Info, %!STATUS!", 1291 status); 1292 1293 return status; 1294 } 1295 1296 status = pUsbDevice->CreateIsochUrb(Attributes, 1297 NumberOfIsochPackets, 1298 UrbMemory, 1299 Urb); 1300 1301 return status; 1302 } 1303 1304 __drv_maxIRQL(DISPATCH_LEVEL) 1305 WDFUSBINTERFACE 1306 WDFAPI 1307 WDFEXPORT(WdfUsbTargetDeviceGetInterface)( 1308 __in 1309 PWDF_DRIVER_GLOBALS DriverGlobals, 1310 __in 1311 WDFUSBDEVICE UsbDevice, 1312 __in 1313 UCHAR InterfaceIndex 1314 ) 1315 /*++ 1316 1317 Routine Description: 1318 1319 1320 Arguments: 1321 1322 Return Value: 1323 1324 1325 --*/ 1326 1327 { 1328 DDI_ENTRY(); 1329 1330 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1331 FxUsbDevice* pUsbDevice; 1332 FxUsbInterface *pUsbInterface; 1333 1334 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1335 UsbDevice, 1336 FX_TYPE_IO_TARGET_USB_DEVICE, 1337 (PVOID*) &pUsbDevice, 1338 &pFxDriverGlobals); 1339 1340 pUsbInterface = pUsbDevice->GetInterfaceFromIndex(InterfaceIndex); 1341 1342 if (pUsbInterface != NULL) { 1343 return pUsbInterface->GetHandle(); 1344 } 1345 else { 1346 DoTraceLevelMessage( 1347 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET, 1348 "WDFUSBDEVICE %p has %d interfaces, index %d requested, returning " 1349 "NULL handle", 1350 UsbDevice, pUsbDevice->GetNumInterfaces(), InterfaceIndex); 1351 1352 return NULL; 1353 } 1354 } 1355 1356 _Must_inspect_result_ 1357 __drv_maxIRQL(PASSIVE_LEVEL) 1358 NTSTATUS 1359 WDFAPI 1360 WDFEXPORT(WdfUsbTargetDeviceQueryUsbCapability)( 1361 __in 1362 PWDF_DRIVER_GLOBALS DriverGlobals, 1363 __in 1364 WDFUSBDEVICE UsbDevice, 1365 __in 1366 CONST GUID* CapabilityType, 1367 __in 1368 ULONG CapabilityBufferLength, 1369 __drv_when(CapabilityBufferLength == 0, __out_opt) 1370 __drv_when(CapabilityBufferLength != 0 && ResultLength == NULL, __out_bcount(CapabilityBufferLength)) 1371 __drv_when(CapabilityBufferLength != 0 && ResultLength != NULL, __out_bcount_part_opt(CapabilityBufferLength, *ResultLength)) 1372 PVOID CapabilityBuffer, 1373 __out_opt 1374 __drv_when(ResultLength != NULL,__deref_out_range(<=,CapabilityBufferLength)) 1375 PULONG ResultLength 1376 ) 1377 /*++ 1378 1379 Routine Description: 1380 Queries USB capability for the device. Such capabilities are available 1381 only with USB 3.0 stack. On earlier stacks this API will fail with 1382 STATUS_NOT_IMPLEMENTED 1383 1384 Arguments: 1385 UsbDevice - Device whose capability is to be queried. 1386 1387 CapabilityType - Type of capability as defined by 1388 IOCTL_INTERNAL_USB_GET_USB_CAPABILITY 1389 1390 CapabilityBufferLength - Length of Capability buffer 1391 1392 CapabilityBuffer - Buffer for capability. Can be NULL if 1393 CapabilitiyBufferLength is 0 1394 1395 ResultLength - Actual length of the capability. This parameter is optional. 1396 1397 Return Value: 1398 STATUS_SUCCESS - success 1399 STATUS_NOT_IMPLEMENTED - Capabilties are not supported by USB stack 1400 STATUS_INSUFFICIENT_RESOURCES - no memory available 1401 ... 1402 1403 --*/ 1404 { 1405 DDI_ENTRY(); 1406 1407 NTSTATUS status; 1408 PFX_DRIVER_GLOBALS pFxDriverGlobals; 1409 FxUsbDevice* pUsbDevice; 1410 1411 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), 1412 UsbDevice, 1413 FX_TYPE_IO_TARGET_USB_DEVICE, 1414 (PVOID*) &pUsbDevice, 1415 &pFxDriverGlobals); 1416 1417 if (CapabilityBufferLength > 0) { 1418 FxPointerNotNull(pFxDriverGlobals, CapabilityBuffer); 1419 } 1420 1421 status = pUsbDevice->QueryUsbCapability(CapabilityType, 1422 CapabilityBufferLength, 1423 CapabilityBuffer, 1424 ResultLength); 1425 return status; 1426 } 1427 1428 } // extern "C" 1429