1 /*++ 2 3 Copyright (c) Microsoft Corporation 4 5 Module Name: 6 7 FxUsbDevice.hpp 8 9 Abstract: 10 11 Author: 12 13 Environment: 14 15 kernel mode only 16 17 Revision History: 18 19 --*/ 20 21 #ifndef _FXUSBDEVICE_H_ 22 #define _FXUSBDEVICE_H_ 23 24 #include "fxusbrequestcontext.hpp" 25 26 typedef enum _FX_URB_TYPE : UCHAR { 27 FxUrbTypeLegacy, 28 FxUrbTypeUsbdAllocated 29 } FX_URB_TYPE; 30 31 struct FxUsbDeviceControlContext : public FxUsbRequestContext { 32 FxUsbDeviceControlContext( 33 __in FX_URB_TYPE FxUrbType 34 ); 35 36 ~FxUsbDeviceControlContext( 37 VOID 38 ); 39 40 __checkReturn 41 NTSTATUS 42 AllocateUrb( 43 __in USBD_HANDLE USBDHandle 44 ); 45 46 virtual 47 VOID 48 Dispose( 49 VOID 50 ); 51 52 virtual 53 VOID 54 CopyParameters( 55 __in FxRequestBase* Request 56 ); 57 58 VOID 59 StoreAndReferenceMemory( 60 __in FxUsbDevice* Device, 61 __in FxRequestBuffer* Buffer, 62 __in PWDF_USB_CONTROL_SETUP_PACKET SetupPacket 63 ); 64 65 virtual 66 VOID 67 ReleaseAndRestore( 68 __in FxRequestBase* Request 69 ); 70 71 USBD_STATUS 72 GetUsbdStatus( 73 VOID 74 ); 75 76 private: 77 USBD_HANDLE m_USBDHandle; 78 79 public: 80 81 _URB_CONTROL_TRANSFER m_UrbLegacy; 82 83 // 84 // m_Urb will either point to m_UrbLegacy or one allocated by USBD_UrbAllocate 85 // 86 _URB_CONTROL_TRANSFER* m_Urb; 87 88 PMDL m_PartialMdl; 89 90 BOOLEAN m_UnlockPages; 91 }; 92 93 struct FxUsbDeviceStringContext : public FxUsbRequestContext { 94 FxUsbDeviceStringContext( 95 __in FX_URB_TYPE FxUrbType 96 ); 97 98 ~FxUsbDeviceStringContext( 99 VOID 100 ); 101 102 __checkReturn 103 NTSTATUS 104 AllocateUrb( 105 __in USBD_HANDLE USBDHandle 106 ); 107 108 virtual 109 VOID 110 Dispose( 111 VOID 112 ); 113 114 virtual 115 VOID 116 CopyParameters( 117 __in FxRequestBase* Request 118 ); 119 120 VOID 121 SetUrbInfo( 122 __in UCHAR StringIndex, 123 __in USHORT LangID 124 ); 125 126 USBD_STATUS 127 GetUsbdStatus( 128 VOID 129 ); 130 131 _Must_inspect_result_ 132 NTSTATUS 133 AllocateDescriptor( 134 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 135 __in size_t BufferSize 136 ); 137 138 private: 139 USBD_HANDLE m_USBDHandle; 140 141 public: 142 143 _URB_CONTROL_DESCRIPTOR_REQUEST m_UrbLegacy; 144 145 // 146 // m_Urb will either point to m_UrbLegacy or one allocated by USBD_UrbAllocate 147 // 148 _URB_CONTROL_DESCRIPTOR_REQUEST* m_Urb; 149 150 PUSB_STRING_DESCRIPTOR m_StringDescriptor; 151 152 ULONG m_StringDescriptorLength; 153 }; 154 155 class FxUsbUrb : public FxMemoryBufferPreallocated { 156 public: 157 158 FxUsbUrb( 159 __in PFX_DRIVER_GLOBALS FxDriverGlobals, 160 __in USBD_HANDLE USBDHandle, 161 __in_bcount(BufferSize) PVOID Buffer, 162 __in size_t BufferSize 163 ); 164 165 protected: 166 167 virtual 168 BOOLEAN 169 Dispose( 170 VOID 171 ); 172 173 ~FxUsbUrb(); 174 175 private: 176 177 USBD_HANDLE m_USBDHandle; 178 }; 179 180 181 #define FX_USB_DEVICE_TAG 'sUfD' 182 183 class FxUsbDevice : public FxIoTarget { 184 public: 185 friend FxUsbPipe; 186 friend FxUsbInterface; 187 188 FxUsbDevice( 189 __in PFX_DRIVER_GLOBALS FxDriverGlobals 190 ); 191 192 _Must_inspect_result_ 193 NTSTATUS 194 InitDevice( 195 __in ULONG USBDClientContractVersionForWdfClient 196 ); 197 198 _Must_inspect_result_ 199 NTSTATUS 200 GetConfigDescriptor( 201 __out PVOID ConfigDescriptor, 202 __inout PUSHORT ConfigDescriptorLength 203 ); 204 205 _Must_inspect_result_ 206 NTSTATUS 207 GetString( 208 __in_ecount(*NumCharacters) PUSHORT String, 209 __in PUSHORT NumCharacters, 210 __in UCHAR StringIndex, 211 __in_opt USHORT LangID, 212 __in_opt WDFREQUEST Request = NULL, 213 __in_opt PWDF_REQUEST_SEND_OPTIONS Options = NULL 214 ); 215 216 __inline 217 VOID CopyDeviceDescriptor(__out PUSB_DEVICE_DESCRIPTOR UsbDeviceDescriptor)218 CopyDeviceDescriptor( 219 __out PUSB_DEVICE_DESCRIPTOR UsbDeviceDescriptor 220 ) 221 { 222 RtlCopyMemory(UsbDeviceDescriptor, 223 &m_DeviceDescriptor, 224 sizeof(m_DeviceDescriptor)); 225 } 226 227 VOID 228 GetInformation( 229 __out PWDF_USB_DEVICE_INFORMATION Information 230 ); 231 232 __inline 233 USBD_CONFIGURATION_HANDLE GetConfigHandle(VOID)234 GetConfigHandle( 235 VOID 236 ) 237 { 238 return m_ConfigHandle; 239 } 240 241 _Must_inspect_result_ 242 __inline 243 NTSTATUS GetCurrentFrameNumber(__in PULONG Current)244 GetCurrentFrameNumber( 245 __in PULONG Current 246 ) 247 { 248 if (m_QueryBusTime != NULL) { 249 return m_QueryBusTime(m_BusInterfaceContext, Current); 250 } 251 else { 252 return STATUS_UNSUCCESSFUL; 253 } 254 } 255 256 _Must_inspect_result_ 257 NTSTATUS 258 SelectConfigAuto( 259 __in PWDF_OBJECT_ATTRIBUTES PipeAttributes 260 ); 261 262 _Must_inspect_result_ 263 NTSTATUS 264 SelectConfigInterfaces( 265 __in PWDF_OBJECT_ATTRIBUTES PipesAttributes, 266 __in PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, 267 __in_ecount(NumInterfaces)PUSB_INTERFACE_DESCRIPTOR* InterfaceDescriptors, 268 __in ULONG NumInterfaces 269 ); 270 271 _Must_inspect_result_ 272 NTSTATUS 273 SelectConfig( 274 __in PWDF_OBJECT_ATTRIBUTES PipesAttributes, 275 __in PURB Urb, 276 __in FX_URB_TYPE FxUrbType, 277 __out_opt PUCHAR NumConfiguredInterfaces 278 ); 279 280 _Must_inspect_result_ 281 NTSTATUS 282 Deconfig( 283 VOID 284 ); 285 286 _Must_inspect_result_ 287 NTSTATUS 288 SelectInterfaceByInterface( 289 __in PWDF_OBJECT_ATTRIBUTES PipesAttributes, 290 __in PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor 291 ); 292 293 _Must_inspect_result_ 294 NTSTATUS 295 SelectInterface( 296 __in PWDF_OBJECT_ATTRIBUTES PipesAttributes, 297 __in PURB Urb 298 ); 299 300 UCHAR GetNumInterfaces(VOID)301 GetNumInterfaces( 302 VOID 303 ) 304 { 305 return m_NumInterfaces; 306 } 307 308 UCHAR 309 GetInterfaceNumEndpoints( 310 __in UCHAR InterfaceNumber 311 ); 312 313 WDFUSBPIPE 314 GetInterfacePipeReferenced( 315 __in UCHAR InterfaceNumber, 316 __in UCHAR EndpointNumber 317 ); 318 319 _Must_inspect_result_ 320 NTSTATUS 321 FormatStringRequest( 322 __in FxRequestBase* Request, 323 __in FxRequestBuffer *RequestBuffer, 324 __in UCHAR StringIndex, 325 __in USHORT LangID 326 ); 327 328 _Must_inspect_result_ 329 NTSTATUS 330 FormatControlRequest( 331 __in FxRequestBase* Request, 332 __in PWDF_USB_CONTROL_SETUP_PACKET Packet, 333 __in FxRequestBuffer *RequestBuffer 334 ); 335 336 _Must_inspect_result_ 337 NTSTATUS 338 IsConnected( 339 VOID 340 ); 341 342 _Must_inspect_result_ 343 NTSTATUS 344 Reset( 345 VOID 346 ); 347 348 _Must_inspect_result_ 349 NTSTATUS 350 CyclePort( 351 VOID 352 ); 353 354 _Must_inspect_result_ 355 NTSTATUS 356 FormatCycleRequest( 357 __in FxRequestBase* Request 358 ); 359 360 BOOLEAN OnUSBD(VOID)361 OnUSBD( 362 VOID 363 ) 364 { 365 return m_OnUSBD; 366 } 367 368 USBD_PIPE_HANDLE GetControlPipeHandle(VOID)369 GetControlPipeHandle( 370 VOID 371 ) 372 { 373 return m_ControlPipe; 374 } 375 376 _Must_inspect_result_ 377 NTSTATUS 378 CreateInterfaces( 379 VOID 380 ); 381 382 _Must_inspect_result_ 383 NTSTATUS 384 SelectConfigSingle( 385 __in PWDF_OBJECT_ATTRIBUTES PipeAttributes, 386 __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params 387 ); 388 389 _Must_inspect_result_ 390 NTSTATUS 391 SelectConfigMulti( 392 __in PWDF_OBJECT_ATTRIBUTES PipeAttributes, 393 __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params 394 ); 395 396 _Must_inspect_result_ 397 NTSTATUS 398 SelectConfigDescriptor( 399 __in PWDF_OBJECT_ATTRIBUTES PipeAttributes, 400 __in PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params 401 ); 402 403 FxUsbInterface * 404 GetInterfaceFromIndex( 405 __in UCHAR InterfaceIndex 406 ); 407 408 BOOLEAN HasMismatchedInterfacesInConfigDescriptor(VOID)409 HasMismatchedInterfacesInConfigDescriptor( 410 VOID 411 ) 412 { 413 return m_MismatchedInterfacesInConfigDescriptor; 414 } 415 416 VOID 417 CancelSentIo( 418 VOID 419 ); 420 421 BOOLEAN 422 IsEnabled( 423 VOID 424 ); 425 426 _Must_inspect_result_ 427 NTSTATUS 428 QueryUsbCapability( 429 __in 430 CONST GUID* CapabilityType, 431 __in 432 ULONG CapabilityBufferLength, 433 __drv_when(CapabilityBufferLength == 0, __out_opt) 434 __drv_when(CapabilityBufferLength != 0 && ResultLength == NULL, __out_bcount(CapabilityBufferLength)) 435 __drv_when(CapabilityBufferLength != 0 && ResultLength != NULL, __out_bcount_part_opt(CapabilityBufferLength, *ResultLength)) 436 PVOID CapabilityBuffer, 437 __out_opt 438 __drv_when(ResultLength != NULL,__deref_out_range(<=,CapabilityBufferLength)) 439 PULONG ResultLength 440 ); 441 442 __checkReturn 443 NTSTATUS 444 CreateUrb( 445 __in_opt 446 PWDF_OBJECT_ATTRIBUTES Attributes, 447 __out 448 WDFMEMORY* UrbMemory, 449 __deref_opt_out_bcount(sizeof(URB)) 450 PURB* Urb 451 ); 452 453 #ifdef _MSC_VER 454 #pragma warning(disable:28285) 455 #endif 456 __checkReturn 457 NTSTATUS 458 CreateIsochUrb( 459 __in_opt 460 PWDF_OBJECT_ATTRIBUTES Attributes, 461 __in 462 ULONG NumberOfIsochPackets, 463 __out 464 WDFMEMORY* UrbMemory, 465 __deref_opt_out_bcount(GET_ISOCH_URB_SIZE(NumberOfIsochPackets)) 466 PURB* Urb 467 ); 468 469 USBD_HANDLE GetUSBDHandle(VOID)470 GetUSBDHandle( 471 VOID 472 ) 473 { 474 return m_USBDHandle; 475 } 476 477 FX_URB_TYPE GetUrbType(VOID)478 GetUrbType( 479 VOID 480 ) 481 { 482 return m_UrbType; 483 } 484 485 FX_URB_TYPE 486 GetFxUrbTypeForRequest( 487 __in FxRequestBase* Request 488 ); 489 490 BOOLEAN 491 IsObjectDisposedOnRemove( 492 __in FxObject* Object 493 ); 494 495 protected: 496 ~FxUsbDevice( 497 VOID 498 ); 499 500 VOID 501 RemoveDeletedInterface( 502 __in FxUsbInterface* Interface 503 ); 504 505 // 506 // FxIoTarget overrides 507 // 508 virtual 509 _Must_inspect_result_ 510 NTSTATUS 511 Start( 512 VOID 513 ); 514 515 virtual 516 VOID 517 Stop( 518 __in WDF_IO_TARGET_SENT_IO_ACTION Action 519 ); 520 521 virtual 522 VOID 523 Purge( 524 __in WDF_IO_TARGET_PURGE_IO_ACTION Action 525 ); 526 // end FxIoTarget overrides 527 528 VOID 529 PipesGotoRemoveState( 530 __in BOOLEAN ForceRemovePipes 531 ); 532 533 static 534 VOID 535 _CleanupPipesRequests( 536 __in PLIST_ENTRY PendHead, 537 __in PSINGLE_LIST_ENTRY SentHead 538 ); 539 540 FxUsbInterface * 541 GetInterfaceFromNumber( 542 __in UCHAR InterfaceNumber 543 ); 544 545 _Must_inspect_result_ 546 NTSTATUS 547 GetInterfaceNumberFromInterface( 548 __in WDFUSBINTERFACE UsbInterface, 549 __out PUCHAR InterfaceNumber 550 ); 551 552 VOID 553 CleanupInterfacePipesAndDelete( 554 __in FxUsbInterface * UsbInterface 555 ); 556 _Acquires_lock_(_Global_critical_region_)557 _Acquires_lock_(_Global_critical_region_) 558 VOID 559 AcquireInterfaceIterationLock( 560 VOID 561 ) 562 { 563 m_InterfaceIterationLock.AcquireLock(GetDriverGlobals()); 564 } 565 _Releases_lock_(_Global_critical_region_)566 _Releases_lock_(_Global_critical_region_) 567 VOID 568 ReleaseInterfaceIterationLock( 569 VOID 570 ) 571 { 572 m_InterfaceIterationLock.ReleaseLock(GetDriverGlobals()); 573 } 574 575 ULONG 576 GetDefaultMaxTransferSize( 577 VOID 578 ); 579 580 VOID 581 FormatInterfaceSelectSettingUrb( 582 __in PURB Urb, 583 __in USHORT NumEndpoints, 584 __in UCHAR InterfaceNumber, 585 __in UCHAR SettingNumber 586 ); 587 588 virtual 589 BOOLEAN 590 Dispose( 591 VOID 592 ); 593 594 _Must_inspect_result_ 595 NTSTATUS 596 GetPortStatus( 597 __out PULONG PortStatus 598 ); 599 600 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 601 _Must_inspect_result_ 602 NTSTATUS 603 FxUsbDevice::SendSyncRequest( 604 __in FxSyncRequest* Request, 605 __in ULONGLONG Time 606 ); 607 608 _Must_inspect_result_ 609 NTSTATUS 610 SendSyncUmUrb( 611 __inout PUMURB Urb, 612 __in ULONGLONG Time, 613 __in_opt WDFREQUEST Request = NULL, 614 __in_opt PWDF_REQUEST_SEND_OPTIONS Options = NULL 615 ); 616 #endif 617 618 protected: 619 USBD_HANDLE m_USBDHandle; 620 621 USBD_PIPE_HANDLE m_ControlPipe; 622 623 FxUsbInterface ** m_Interfaces; 624 625 USBD_CONFIGURATION_HANDLE m_ConfigHandle; 626 627 USB_DEVICE_DESCRIPTOR m_DeviceDescriptor; 628 629 PUSB_CONFIGURATION_DESCRIPTOR m_ConfigDescriptor; 630 631 USBD_VERSION_INFORMATION m_UsbdVersionInformation; 632 633 PUSB_BUSIFFN_QUERY_BUS_TIME m_QueryBusTime; 634 635 PVOID m_BusInterfaceContext; 636 637 PINTERFACE_DEREFERENCE m_BusInterfaceDereference; 638 639 FxWaitLockInternal m_InterfaceIterationLock; 640 641 ULONG m_HcdPortCapabilities; 642 643 ULONG m_Traits; 644 645 BOOLEAN m_OnUSBD; 646 647 UCHAR m_NumInterfaces; 648 649 BOOLEAN m_MismatchedInterfacesInConfigDescriptor; 650 651 FX_URB_TYPE m_UrbType; 652 653 #if (FX_CORE_MODE == FX_CORE_USER_MODE) 654 private: 655 // 656 // Used to format the IWudfIrp for user-mode requests 657 // 658 IWudfFile* m_pHostTargetFile; 659 660 // 661 // Handle to the default USB interface exposed by WinUsb 662 // 663 WINUSB_INTERFACE_HANDLE m_WinUsbHandle; 664 #endif 665 }; 666 667 #endif // _FXUSBDEVICE_H_ 668