1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxUsbDeviceUm.cpp 8 9 Abstract: 10 11 Author: 12 13 Environment: 14 15 User mode only 16 17 Revision History: 18 19 --*/ 20 extern "C" { 21 #include <initguid.h> 22 23 } 24 #include "fxusbpch.hpp" 25 extern "C" { 26 #include "FxUsbDeviceUm.tmh" 27 } 28 29 _Must_inspect_result_ 30 NTSTATUS 31 FxUsbDevice::SendSyncRequest( 32 __in FxSyncRequest* Request, 33 __in ULONGLONG Time 34 ) 35 { 36 NTSTATUS status; 37 WDF_REQUEST_SEND_OPTIONS options; 38 39 WDF_REQUEST_SEND_OPTIONS_INIT(&options, 0); 40 WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&options, WDF_REL_TIMEOUT_IN_SEC(Time)); 41 42 status = SubmitSync(Request->m_TrueRequest, &options); 43 if (!NT_SUCCESS(status)) { 44 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 45 "FxUsbDevice SubmitSync failed"); 46 goto Done; 47 } 48 49 Done: 50 return status; 51 } 52 53 _Must_inspect_result_ 54 NTSTATUS 55 FxUsbDevice::SendSyncUmUrb( 56 __inout PUMURB Urb, 57 __in ULONGLONG Time, 58 __in_opt WDFREQUEST Request, 59 __in_opt PWDF_REQUEST_SEND_OPTIONS Options 60 ) 61 { 62 NTSTATUS status; 63 WDF_REQUEST_SEND_OPTIONS options; 64 FxSyncRequest request(GetDriverGlobals(), NULL, Request); 65 66 status = request.Initialize(); 67 if (!NT_SUCCESS(status)) { 68 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 69 "Failed to initialize FxSyncRequest"); 70 return status; 71 } 72 73 if (NULL == Options) { 74 Options = &options; 75 } 76 77 WDF_REQUEST_SEND_OPTIONS_INIT(Options, 0); 78 WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(Options, WDF_REL_TIMEOUT_IN_SEC(Time)); 79 80 status = request.m_TrueRequest->ValidateTarget(this); 81 if (NT_SUCCESS(status)) { 82 FxUsbUmFormatRequest(request.m_TrueRequest, &Urb->UmUrbHeader, m_pHostTargetFile); 83 status = SubmitSync(request.m_TrueRequest, Options); 84 if (!NT_SUCCESS(status)) { 85 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 86 "FxUsbDevice SubmitSync failed"); 87 return status; 88 } 89 } 90 91 return status; 92 } 93 94 _Must_inspect_result_ 95 NTSTATUS 96 FxUsbDevice::InitDevice( 97 __in ULONG USBDClientContractVersionForWdfClient 98 ) 99 { 100 HRESULT hr = S_OK; 101 NTSTATUS status = STATUS_SUCCESS; 102 103 IWudfDevice* device = NULL; 104 IWudfDeviceStack2* devstack2 = NULL; 105 106 UMURB urb; 107 USB_CONFIGURATION_DESCRIPTOR config; 108 USHORT wTotalLength = 0; 109 110 FxRequestBuffer buf; 111 FxUsbDeviceControlContext context(FxUrbTypeLegacy); 112 113 WDF_USB_CONTROL_SETUP_PACKET setupPacket; 114 USHORT deviceStatus = 0; 115 UCHAR deviceSpeed = 0; 116 117 FxSyncRequest request(GetDriverGlobals(), NULL); 118 FxSyncRequest request2(GetDriverGlobals(), &context); 119 120 121 122 123 UNREFERENCED_PARAMETER(USBDClientContractVersionForWdfClient); 124 125 status = request.Initialize(); 126 if (!NT_SUCCESS(status)) { 127 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 128 "Failed to initialize FxSyncRequest"); 129 goto Done; 130 } 131 132 status = request2.Initialize(); 133 if (!NT_SUCCESS(status)) { 134 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 135 "Failed to initialize second FxSyncRequest"); 136 goto Done; 137 } 138 139 status = request.m_TrueRequest->ValidateTarget(this); 140 if (!NT_SUCCESS(status)) { 141 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 142 "Failed to validate FxSyncRequest target"); 143 goto Done; 144 } 145 146 status = request2.m_TrueRequest->ValidateTarget(this); 147 if (!NT_SUCCESS(status)) { 148 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 149 "Failed to validate second FxSyncRequest target"); 150 goto Done; 151 } 152 153 RtlZeroMemory(&urb, sizeof(urb)); 154 155 device = m_DeviceBase->GetDeviceObject(); 156 devstack2 = m_Device->GetDeviceStack2(); 157 158 if (m_pHostTargetFile == NULL) { 159 160 // 161 // Opens a handle on the reflector for USB side-band communication 162 // based on the currently selected dispatcher type. 163 // 164 hr = devstack2->OpenUSBCommunicationChannel(device, 165 device->GetAttachedDevice(), 166 &m_pHostTargetFile); 167 168 if (SUCCEEDED(hr)) { 169 m_WinUsbHandle = (WINUSB_INTERFACE_HANDLE)m_pHostTargetFile->GetCreateContext(); 170 } 171 } 172 173 // 174 // Get USB device descriptor 175 // 176 FxUsbUmInitDescriptorUrb(&urb, 177 m_WinUsbHandle, 178 USB_DEVICE_DESCRIPTOR_TYPE, 179 sizeof(m_DeviceDescriptor), 180 &m_DeviceDescriptor); 181 FxUsbUmFormatRequest(request.m_TrueRequest, 182 &urb.UmUrbHeader, 183 m_pHostTargetFile, 184 TRUE); 185 status = SendSyncRequest(&request, 5); 186 if (!NT_SUCCESS(status)) { 187 goto Done; 188 } 189 190 // 191 // Get USB configuration descriptor 192 // 193 FxUsbUmInitDescriptorUrb(&urb, 194 m_WinUsbHandle, 195 USB_CONFIGURATION_DESCRIPTOR_TYPE, 196 sizeof(config), 197 &config); 198 FxUsbUmFormatRequest(request.m_TrueRequest, 199 &urb.UmUrbHeader, 200 m_pHostTargetFile, 201 TRUE); 202 status = SendSyncRequest(&request, 5); 203 if (!NT_SUCCESS(status)) { 204 goto Done; 205 } 206 207 if (config.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR)) { 208 209 // 210 // Not enough info returned 211 // 212 status = STATUS_UNSUCCESSFUL; 213 DoTraceLevelMessage( 214 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 215 "Could not retrieve config descriptor size, config.wTotalLength %d < " 216 "sizeof(config descriptor) (%d), %!STATUS!", 217 config.wTotalLength, sizeof(USB_CONFIGURATION_DESCRIPTOR), status); 218 goto Done; 219 } 220 221 wTotalLength = config.wTotalLength; 222 m_ConfigDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR) 223 FxPoolAllocate(GetDriverGlobals(), 224 NonPagedPool, 225 wTotalLength); 226 if (NULL == m_ConfigDescriptor) { 227 status = STATUS_INSUFFICIENT_RESOURCES; 228 DoTraceLevelMessage( 229 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 230 "Could not allocate %d bytes for config descriptor, %!STATUS!", 231 sizeof(USB_CONFIGURATION_DESCRIPTOR), status); 232 goto Done; 233 } 234 235 // 236 // Get USB configuration descriptor and subsequent interface descriptors, etc. 237 // 238 FxUsbUmInitDescriptorUrb(&urb, 239 m_WinUsbHandle, 240 USB_CONFIGURATION_DESCRIPTOR_TYPE, 241 wTotalLength, 242 m_ConfigDescriptor); 243 FxUsbUmFormatRequest(request.m_TrueRequest, 244 &urb.UmUrbHeader, 245 m_pHostTargetFile, 246 TRUE); 247 status = SendSyncRequest(&request, 5); 248 if (!NT_SUCCESS(status)) { 249 goto Done; 250 } else if (m_ConfigDescriptor->wTotalLength != wTotalLength) { 251 // 252 // Invalid wTotalLength 253 // 254 status = STATUS_DEVICE_DATA_ERROR; 255 DoTraceLevelMessage( 256 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 257 "Defective USB device reported two different config descriptor " 258 "wTotalLength values: %d and %d, %!STATUS!", 259 wTotalLength, m_ConfigDescriptor->wTotalLength, status); 260 goto Done; 261 } 262 263 m_NumInterfaces = m_ConfigDescriptor->bNumInterfaces; 264 265 // 266 // Check to see if we are wait wake capable 267 // 268 if (m_ConfigDescriptor->bmAttributes & USB_CONFIG_REMOTE_WAKEUP) { 269 m_Traits |= WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE; 270 } 271 272 // 273 // Get the device status to check if device is self-powered. 274 // 275 WDF_USB_CONTROL_SETUP_PACKET_INIT_GET_STATUS(&setupPacket, 276 BmRequestToDevice, 277 0); // Device status 278 279 buf.SetBuffer(&deviceStatus, sizeof(USHORT)); 280 281 status = FormatControlRequest(request2.m_TrueRequest, 282 &setupPacket, 283 &buf); 284 if (!NT_SUCCESS(status)) { 285 goto Done; 286 } 287 288 status = SendSyncRequest(&request2, 5); 289 if (!NT_SUCCESS(status)) { 290 goto Done; 291 } 292 293 if (deviceStatus & USB_GETSTATUS_SELF_POWERED) { 294 m_Traits |= WDF_USB_DEVICE_TRAIT_SELF_POWERED; 295 } 296 297 // 298 // Get device speed information. 299 // 300 FxUsbUmInitInformationUrb(&urb, 301 m_WinUsbHandle, 302 sizeof(UCHAR), 303 &deviceSpeed); 304 FxUsbUmFormatRequest(request.m_TrueRequest, 305 &urb.UmUrbHeader, 306 m_pHostTargetFile, 307 TRUE); 308 status = SendSyncRequest(&request, 5); 309 if (!NT_SUCCESS(status)) { 310 goto Done; 311 } 312 313 if (deviceSpeed == 3) { 314 m_Traits |= WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED; 315 } 316 317 // 318 // User-mode events must be initialized manually. 319 // 320 status = m_InterfaceIterationLock.Initialize(); 321 if (!NT_SUCCESS(status)) { 322 goto Done; 323 } 324 325 Done: 326 return status; 327 } 328 329 330 331 332 _Must_inspect_result_ 333 NTSTATUS 334 FxUsbDevice::GetString( 335 __in_ecount(*NumCharacters) PUSHORT String, 336 __in PUSHORT NumCharacters, 337 __in UCHAR StringIndex, 338 __in_opt USHORT LangID, 339 __in_opt WDFREQUEST Request, 340 __in_opt PWDF_REQUEST_SEND_OPTIONS Options 341 ) 342 { 343 UMURB urb; 344 PUSB_STRING_DESCRIPTOR pDescriptor; 345 PVOID buffer = NULL; 346 USB_COMMON_DESCRIPTOR common; 347 ULONG length; 348 NTSTATUS status; 349 350 if (String != NULL) { 351 length = sizeof(USB_STRING_DESCRIPTOR) + (*NumCharacters - 1) * sizeof(WCHAR); 352 353 buffer = FxPoolAllocate(GetDriverGlobals(), 354 NonPagedPool, 355 length); 356 357 if (buffer == NULL) { 358 status = STATUS_INSUFFICIENT_RESOURCES; 359 goto Done; 360 } 361 362 RtlZeroMemory(buffer, length); 363 pDescriptor = (PUSB_STRING_DESCRIPTOR) buffer; 364 } 365 else { 366 RtlZeroMemory(&common, sizeof(common)); 367 368 length = sizeof(USB_COMMON_DESCRIPTOR); 369 pDescriptor = (PUSB_STRING_DESCRIPTOR) &common; 370 } 371 372 FxUsbUmInitDescriptorUrb(&urb, 373 m_WinUsbHandle, 374 USB_STRING_DESCRIPTOR_TYPE, 375 length, 376 pDescriptor); 377 urb.UmUrbDescriptorRequest.Index = StringIndex; 378 urb.UmUrbDescriptorRequest.LanguageID = LangID; 379 380 status = SendSyncUmUrb(&urb, 2, Request, Options); 381 if (NT_SUCCESS(status)) { 382 USHORT numChars; 383 384 // 385 // Make sure we got an even number of bytes and that we got a header 386 // 387 if ((pDescriptor->bLength & 0x1) || 388 pDescriptor->bLength < sizeof(USB_COMMON_DESCRIPTOR)) { 389 status = STATUS_DEVICE_DATA_ERROR; 390 } 391 else { 392 // 393 // bLength is the length of the entire descriptor. Subtract off 394 // the descriptor header and then divide by the size of a WCHAR. 395 // 396 numChars = 397 (pDescriptor->bLength - sizeof(USB_COMMON_DESCRIPTOR)) / sizeof(WCHAR); 398 399 if (String != NULL) { 400 if (*NumCharacters >= numChars) { 401 length = numChars * sizeof(WCHAR); 402 } 403 else { 404 length = *NumCharacters * sizeof(WCHAR); 405 status = STATUS_BUFFER_OVERFLOW; 406 } 407 408 *NumCharacters = numChars; 409 RtlCopyMemory(String, pDescriptor->bString, length); 410 } 411 else { 412 *NumCharacters = numChars; 413 } 414 } 415 } 416 417 if (buffer != NULL) { 418 FxPoolFree(buffer); 419 } 420 421 Done: 422 423 return status; 424 } 425 426 _Must_inspect_result_ 427 NTSTATUS 428 FxUsbDevice::FormatStringRequest( 429 __in FxRequestBase* Request, 430 __in FxRequestBuffer *RequestBuffer, 431 __in UCHAR StringIndex, 432 __in USHORT LangID 433 ) 434 /*++ 435 436 Routine Description: 437 Formats a request to retrieve a string from a string descriptor 438 439 Arguments: 440 Request - request to format 441 442 RequestBuffer - Buffer to be filled in when the request has completed 443 444 StringIndex - index of the string 445 446 LandID - language ID of the string to be retrieved 447 448 Return Value: 449 NTSTATUS 450 451 --*/ 452 { 453 NTSTATUS status; 454 FxUsbDeviceStringContext* pContext; 455 456 status = Request->ValidateTarget(this); 457 if (NT_SUCCESS(status)) { 458 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 459 "WDFUSBDEVICE %p, Request %p, setting target failed, " 460 "%!STATUS!", GetHandle(), Request, status); 461 462 return status; 463 } 464 465 if (Request->HasContextType(FX_RCT_USB_STRING_REQUEST)) { 466 pContext = (FxUsbDeviceStringContext*) Request->GetContext(); 467 } 468 else { 469 pContext = new(GetDriverGlobals()) FxUsbDeviceStringContext(FxUrbTypeLegacy); 470 if (pContext == NULL) { 471 return STATUS_INSUFFICIENT_RESOURCES; 472 } 473 474 Request->SetContext(pContext); 475 } 476 477 FxUsbUmInitDescriptorUrb(&pContext->m_UmUrb, 478 m_WinUsbHandle, 479 USB_STRING_DESCRIPTOR_TYPE, 480 0, 481 NULL); 482 483 status = pContext->AllocateDescriptor(GetDriverGlobals(), 484 RequestBuffer->GetBufferLength()); 485 if (!NT_SUCCESS(status)) { 486 return status; 487 } 488 489 pContext->StoreAndReferenceMemory(RequestBuffer); 490 pContext->SetUrbInfo(StringIndex, LangID); 491 492 FxUsbUmFormatRequest(Request, &pContext->m_UmUrb.UmUrbHeader, m_pHostTargetFile); 493 494 return STATUS_SUCCESS; 495 } 496 497 _Must_inspect_result_ 498 NTSTATUS 499 FxUsbDevice::FormatControlRequest( 500 __in FxRequestBase* Request, 501 __in PWDF_USB_CONTROL_SETUP_PACKET SetupPacket, 502 __in FxRequestBuffer *RequestBuffer 503 ) 504 { 505 FxUsbDeviceControlContext* pContext; 506 NTSTATUS status; 507 size_t bufferSize; 508 509 bufferSize = RequestBuffer->GetBufferLength(); 510 511 // 512 // We can only transfer 2 bytes worth of data, so if the buffer is larger, 513 // fail here. 514 // 515 if (bufferSize > 0xFFFF) { 516 DoTraceLevelMessage( 517 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 518 "Control transfer buffer is limited to 0xFFFF bytes in size, " 519 "%I64d requested ", bufferSize); 520 521 return STATUS_INVALID_PARAMETER; 522 } 523 524 status = Request->ValidateTarget(this); 525 if (!NT_SUCCESS(status)) { 526 DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 527 "WDFUSBDEVICE %p, Request %p, setting target failed, " 528 "%!STATUS!", GetHandle(), Request, status); 529 return status; 530 } 531 532 if (Request->HasContextType(FX_RCT_USB_CONTROL_REQUEST)) { 533 pContext = (FxUsbDeviceControlContext*) Request->GetContext(); 534 } 535 else { 536 pContext = new(GetDriverGlobals()) FxUsbDeviceControlContext(FxUrbTypeLegacy); 537 if (pContext == NULL) { 538 return STATUS_INSUFFICIENT_RESOURCES; 539 } 540 541 Request->SetContext(pContext); 542 } 543 544 FxUsbUmInitControlTransferUrb(&pContext->m_UmUrb, 545 m_WinUsbHandle, 546 0, 547 NULL); 548 549 pContext->StoreAndReferenceMemory(this, RequestBuffer, SetupPacket); 550 551 FxUsbUmFormatRequest(Request, &pContext->m_UmUrb.UmUrbHeader, m_pHostTargetFile); 552 553 return STATUS_SUCCESS; 554 } 555 556 VOID 557 FxUsbDeviceControlContext::StoreAndReferenceMemory( 558 __in FxUsbDevice* Device, 559 __in FxRequestBuffer* Buffer, 560 __in PWDF_USB_CONTROL_SETUP_PACKET SetupPacket 561 ) 562 { 563 SetUsbType(WdfUsbRequestTypeDeviceControlTransfer); 564 565 __super::StoreAndReferenceMemory(Buffer); 566 567 // 568 // Convert WDF_USB_CONTROL_SETUP_PACKET to WINUSB_SETUP_PACKET 569 // 570 m_UmUrb.UmUrbControlTransfer.SetupPacket.RequestType = SetupPacket->Packet.bm.Byte; 571 m_UmUrb.UmUrbControlTransfer.SetupPacket.Request = SetupPacket->Packet.bRequest; 572 m_UmUrb.UmUrbControlTransfer.SetupPacket.Value = SetupPacket->Packet.wValue.Value; 573 m_UmUrb.UmUrbControlTransfer.SetupPacket.Index = SetupPacket->Packet.wIndex.Value; 574 575 // 576 // Set the TransferBuffer values using what is stored in the Buffer 577 // 578 Buffer->AssignValues(&m_UmUrb.UmUrbControlTransfer.TransferBuffer, 579 NULL, 580 &m_UmUrb.UmUrbControlTransfer.TransferBufferLength); 581 582 m_UmUrb.UmUrbControlTransfer.SetupPacket.Length = 583 (USHORT)m_UmUrb.UmUrbControlTransfer.TransferBufferLength; 584 } 585 586 _Must_inspect_result_ 587 NTSTATUS 588 FxUsbDevice::QueryUsbCapability( 589 __in 590 CONST GUID* CapabilityType, 591 __in 592 ULONG CapabilityBufferLength, 593 __drv_when(CapabilityBufferLength == 0, __out_opt) 594 __drv_when(CapabilityBufferLength != 0 && ResultLength == NULL, __out_bcount(CapabilityBufferLength)) 595 __drv_when(CapabilityBufferLength != 0 && ResultLength != NULL, __out_bcount_part_opt(CapabilityBufferLength, *ResultLength)) 596 PVOID CapabilityBuffer, 597 __out_opt 598 __drv_when(ResultLength != NULL,__deref_out_range(<=,CapabilityBufferLength)) 599 PULONG ResultLength 600 ) 601 { 602 NTSTATUS status; 603 604 if (ResultLength != NULL) { 605 *ResultLength = 0; 606 } 607 608 // 609 // We cannot send an actual query to the USB stack through winusb. 610 // However, we have the information to handle this query. It is not 611 // ideal to implement this API in this manner because we are making 612 // assumptions about the behavior of USB stack that can change in future. 613 // However, it is too late in the OS cycle to implement a correct solution. 614 // The ideal way is for winusb to expose this information. We should 615 // revisit this API in blue+1 616 // 617 if (RtlCompareMemory(CapabilityType, 618 &GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE, 619 sizeof(GUID)) == sizeof(GUID)) { 620 if (m_Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) { 621 status = STATUS_SUCCESS; 622 } else { 623 status = STATUS_NOT_SUPPORTED; 624 } 625 } 626 else if (RtlCompareMemory(CapabilityType, 627 &GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE, 628 sizeof(GUID)) == sizeof(GUID)) { 629 if (m_DeviceDescriptor.bcdUSB >= 0x300) { 630 status = STATUS_SUCCESS; 631 } else { 632 status = STATUS_NOT_SUPPORTED; 633 } 634 } 635 else if (RtlCompareMemory(CapabilityType, 636 &GUID_USB_CAPABILITY_SELECTIVE_SUSPEND, 637 sizeof(GUID)) == sizeof(GUID)) { 638 // 639 // Both EHCI as well as XHCI stack support selective suspend. 640 // Since XHCI UCX interface is not open, there aren't any 641 // third party controller drivers to worry about. This can 642 // of course change in future 643 // 644 status = STATUS_SUCCESS; 645 } 646 else if (RtlCompareMemory(CapabilityType, 647 &GUID_USB_CAPABILITY_FUNCTION_SUSPEND, 648 sizeof(GUID)) == sizeof(GUID)) { 649 // 650 // Note that a SuperSpeed device will report a bcdUSB of 2.1 651 // when working on a 2.0 port. Therefore a bcdUSB of 3.0 also 652 // indicates that the device is actually working on 3.0, in 653 // which case we always support function suspend 654 // 655 if (m_DeviceDescriptor.bcdUSB >= 0x300) { 656 status = STATUS_SUCCESS; 657 } else { 658 status = STATUS_NOT_SUPPORTED; 659 } 660 } 661 else { 662 // 663 // We do not support chained MDLs or streams for a UMDF driver 664 // GUID_USB_CAPABILITY_CHAINED_MDLS 665 // GUID_USB_CAPABILITY_STATIC_STREAMS 666 // 667 status = STATUS_NOT_SUPPORTED; 668 } 669 670 return status; 671 } 672 673 _Must_inspect_result_ 674 NTSTATUS 675 FxUsbDevice::SelectConfigSingle( 676 __in PWDF_OBJECT_ATTRIBUTES PipeAttributes, 677 __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params 678 ) 679 /*++ 680 681 Routine Description: 682 Since the device is already configured, all this routine 683 does is to make sure the alternate setting 0 is selected, 684 in case the client driver selected some other alternate 685 setting after the initial configuration 686 687 Arguments: 688 689 690 Return Value: 691 NTSTATUS 692 693 --*/ 694 { 695 NTSTATUS status; 696 697 RtlZeroMemory(&Params->Types.SingleInterface, 698 sizeof(Params->Types.SingleInterface)); 699 700 if (m_NumInterfaces > 1) { 701 status = STATUS_INVALID_PARAMETER; 702 703 DoTraceLevelMessage( 704 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 705 "WDFUSBDEVICE %p cannot be auto configured for a single interface " 706 "since there are %d interfaces on the device, %!STATUS!", 707 GetHandle(), m_NumInterfaces, status); 708 709 return status; 710 } 711 712 // 713 // Use AlternateSetting 0 by default 714 // 715 if (m_Interfaces[0]->GetSettingDescriptor(0) == NULL) { 716 DoTraceLevelMessage( 717 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 718 "WDFUSBDEVICE %p could not retrieve AlternateSetting 0 for " 719 "bInterfaceNumber %d", GetHandle(), 720 m_Interfaces[0]->m_InterfaceNumber); 721 722 return STATUS_INVALID_PARAMETER; 723 } 724 725 status = m_Interfaces[0]->CheckAndSelectSettingByIndex(0); 726 727 if (!NT_SUCCESS(status)) { 728 DoTraceLevelMessage( 729 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 730 "WDFUSBDEVICE %p set AlternateSetting 0 for interface 0" 731 "failed, %!STATUS!", GetHandle(), status); 732 733 return status; 734 } 735 736 if (PipeAttributes) { 737 status = m_Interfaces[0]->UpdatePipeAttributes(PipeAttributes); 738 } 739 740 Params->Types.SingleInterface.ConfiguredUsbInterface = 741 m_Interfaces[0]->GetHandle(); 742 743 Params->Types.SingleInterface.NumberConfiguredPipes = 744 m_Interfaces[0]->GetNumConfiguredPipes(); 745 746 return status; 747 } 748 749 _Must_inspect_result_ 750 NTSTATUS 751 FxUsbDevice::SelectConfigMulti( 752 __in PWDF_OBJECT_ATTRIBUTES PipeAttributes, 753 __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params 754 ) 755 /*++ 756 757 Routine Description: 758 Since the device is already configured, all this routine 759 does is to make sure the alternate setting 0 is selected 760 for all interfaces, in case the client driver selected some 761 other alternate setting after the initial configuration 762 763 764 Arguments: 765 PipeAttributes - Should be NULL 766 767 Params - 768 769 Return Value: 770 NTSTATUS 771 772 --*/ 773 { 774 FxUsbInterface * pUsbInterface; 775 NTSTATUS status; 776 UCHAR i; 777 PFX_DRIVER_GLOBALS pFxDriverGlobals; 778 779 pFxDriverGlobals = GetDriverGlobals(); 780 781 Params->Types.MultiInterface.NumberOfConfiguredInterfaces = 0; 782 783 if (Params->Type == WdfUsbTargetDeviceSelectConfigTypeMultiInterface) { 784 for (i = 0; i < m_NumInterfaces; i++) { 785 786 if (m_Interfaces[i]->GetSettingDescriptor(0) == NULL) { 787 DoTraceLevelMessage( 788 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 789 "WDFUSBDEVICE %p could not retrieve AlternateSetting 0 for " 790 "bInterfaceNumber %d", GetHandle(), 791 m_Interfaces[i]->m_InterfaceNumber); 792 793 status = STATUS_INVALID_PARAMETER; 794 goto Done; 795 } 796 797 status = m_Interfaces[i]->CheckAndSelectSettingByIndex(0); 798 if (!NT_SUCCESS(status)) { 799 DoTraceLevelMessage( 800 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 801 "WDFUSBDEVICE %p set AlternateSetting 0 for bInterfaceNumber %d" 802 "failed, %!STATUS!", 803 GetHandle(), m_Interfaces[i]->m_InterfaceNumber, status); 804 goto Done; 805 } 806 if (PipeAttributes) { 807 status = m_Interfaces[i]->UpdatePipeAttributes(PipeAttributes); 808 } 809 } 810 } 811 else { 812 // 813 // Type is WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs 814 // 815 UCHAR interfacePairsNum = 0; 816 UCHAR bitArray[UCHAR_MAX/sizeof(UCHAR)]; 817 818 // 819 // initialize the bit array 820 // 821 RtlZeroMemory(bitArray, sizeof(bitArray)); 822 // 823 // Build a list of descriptors from the Setting pairs 824 // passed in by the user. There could be interfaces not 825 // covered in the setting/interface pairs array passed. 826 // If that is the case return STATUS_INVALID_PARAMETER 827 // 828 for (i = 0; i < Params->Types.MultiInterface.NumberInterfaces ; i++) { 829 PWDF_USB_INTERFACE_SETTING_PAIR settingPair; 830 UCHAR interfaceNumber; 831 UCHAR altSettingIndex; 832 833 settingPair = &Params->Types.MultiInterface.Pairs[i]; 834 835 FxObjectHandleGetPtr(GetDriverGlobals(), 836 settingPair->UsbInterface, 837 FX_TYPE_USB_INTERFACE , 838 (PVOID*) &pUsbInterface); 839 840 interfaceNumber = pUsbInterface->GetInterfaceNumber(); 841 altSettingIndex = settingPair->SettingIndex; 842 843 // 844 // do the following only if the bit is not already set 845 // 846 if (FxBitArraySet(&bitArray[0], interfaceNumber) == FALSE) { 847 848 if (pUsbInterface->GetSettingDescriptor(altSettingIndex) == NULL) { 849 status = STATUS_INVALID_PARAMETER; 850 DoTraceLevelMessage( 851 GetDriverGlobals(), TRACE_LEVEL_ERROR, 852 TRACINGIOTARGET, 853 "WDFUSBDEVICE %p could not retrieve " 854 "AlternateSetting %d for " 855 "bInterfaceNumber %d, returning %!STATUS!", 856 GetHandle(), 857 altSettingIndex, interfaceNumber, status); 858 goto Done; 859 } 860 861 interfacePairsNum++; 862 863 // 864 // Ensure alternate setting 0 is selected 865 // 866 status = pUsbInterface->CheckAndSelectSettingByIndex( 867 settingPair->SettingIndex); 868 869 if (!NT_SUCCESS(status)) { 870 DoTraceLevelMessage( 871 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 872 "WDFUSBDEVICE %p set AlternateSetting %d for bInterfaceNumber %d" 873 "failed, %!STATUS!", 874 GetHandle(), altSettingIndex, m_Interfaces[i]->m_InterfaceNumber, 875 status); 876 goto Done; 877 } 878 879 if (PipeAttributes) { 880 status = pUsbInterface->UpdatePipeAttributes(PipeAttributes); 881 } 882 } 883 884 } 885 886 if (m_NumInterfaces > interfacePairsNum) { 887 status = STATUS_INVALID_PARAMETER; 888 DoTraceLevelMessage( 889 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET, 890 "WDFUSBDEVICE %p interface pairs set (%d) is not equal to actual " 891 "# of interfaces (%d) reported by the device, %!STATUS!", 892 GetObjectHandle(), interfacePairsNum, m_NumInterfaces, status); 893 goto Done; 894 } 895 } //WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs 896 897 status = STATUS_SUCCESS; 898 Params->Types.MultiInterface.NumberOfConfiguredInterfaces = m_NumInterfaces; 899 900 Done: 901 return status; 902 } 903 904 905 _Must_inspect_result_ 906 NTSTATUS 907 FxUsbDevice::Reset( 908 VOID 909 ) 910 { 911 UMURB urb; 912 NTSTATUS status; 913 914 RtlZeroMemory(&urb, sizeof(UMURB)); 915 916 urb.UmUrbSelectInterface.Hdr.Function = UMURB_FUNCTION_RESET_PORT; 917 urb.UmUrbSelectInterface.Hdr.Length = sizeof(_UMURB_HEADER); 918 919 status = SendSyncUmUrb(&urb, 2); 920 921 return status; 922 } 923 924