Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1005 lines
40 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. local.h
  5. Abstract
  6. Definitions that are private to the hid class driver code appear here.
  7. Author:
  8. Ervin P.
  9. Environment:
  10. Kernel mode only
  11. Revision History:
  12. --*/
  13. typedef struct _HID_DESCRIPTOR *PHID_DESCRIPTOR;
  14. typedef struct _HIDCLASS_COLLECTION *PHIDCLASS_COLLECTION;
  15. typedef struct _HIDCLASS_DEVICE_EXTENSION *PHIDCLASS_DEVICE_EXTENSION;
  16. typedef struct _HIDCLASS_DRIVER_EXTENSION *PHIDCLASS_DRIVER_EXTENSION;
  17. typedef struct _HIDCLASS_FILE_EXTENSION *PHIDCLASS_FILE_EXTENSION;
  18. typedef struct _HIDCLASS_PINGPONG *PHIDCLASS_PINGPONG;
  19. typedef struct _HIDCLASS_REPORT *PHIDCLASS_REPORT;
  20. typedef struct _FDO_EXTENSION *PFDO_EXTENSION;
  21. typedef struct _PDO_EXTENSION *PPDO_EXTENSION;
  22. #if DBG
  23. #define LockFileExtension( f, i ) \
  24. { \
  25. KeAcquireSpinLock( &(f)->ListSpinLock, (i) ); \
  26. (f)->ListSpinLockTaken = TRUE; \
  27. }
  28. #define UnlockFileExtension(f, i) \
  29. { \
  30. (f)->ListSpinLockTaken = FALSE; \
  31. KeReleaseSpinLock( &(f)->ListSpinLock, (i) ); \
  32. }
  33. VOID DbgLogIntStart();
  34. VOID DbgLogIntEnd();
  35. #define DBGLOG_INTSTART() DbgLogIntStart();
  36. #define DBGLOG_INTEND() DbgLogIntEnd();
  37. #else
  38. #define LockFileExtension(f, i) KeAcquireSpinLock(&(f)->ListSpinLock, (i));
  39. #define UnlockFileExtension(f, i) KeReleaseSpinLock(&(f)->ListSpinLock, (i));
  40. #define DBGLOG_INTSTART()
  41. #define DBGLOG_INTEND()
  42. #endif
  43. #define HIDCLASS_POOL_TAG 'CdiH'
  44. #define ALLOCATEPOOL(poolType, size) ExAllocatePoolWithTag((poolType), (size), HIDCLASS_POOL_TAG)
  45. #define ALLOCATEQUOTAPOOL(poolType, size) ExAllocatePoolWithQuotaTag((poolType), (size), HIDCLASS_POOL_TAG)
  46. //
  47. // On some busses, we can power down the bus, but not the system, in this case
  48. // we still need to allow the device to wake said bus, therefore
  49. // waitwake-supported should not rely on systemstate.
  50. //
  51. #define WAITWAKE_SUPPORTED(fdoExt) ((fdoExt)->deviceCapabilities.DeviceWake > PowerDeviceD0 && \
  52. (fdoExt)->deviceCapabilities.SystemWake > PowerSystemWorking)
  53. // #define WAITWAKE_ON(port) ((port)->WaitWakeIrp != 0)
  54. #define REMOTEWAKE_ON(port) \
  55. (InterlockedCompareExchangePointer(&(port)->remoteWakeIrp, NULL, NULL) != NULL)
  56. BOOLEAN
  57. HidpCheckRemoteWakeEnabled(
  58. IN PPDO_EXTENSION PdoExt
  59. );
  60. #define SHOULD_SEND_WAITWAKE(pdoExt) (!(pdoExt)->MouseOrKeyboard && \
  61. WAITWAKE_SUPPORTED(&(pdoExt)->deviceFdoExt->fdoExt) && \
  62. !REMOTEWAKE_ON(pdoExt) && \
  63. HidpCheckRemoteWakeEnabled(pdoExt))
  64. /*
  65. * String constants for use in compatible-id multi-string.
  66. */
  67. // 0123456789 123456789 1234
  68. #define HIDCLASS_COMPATIBLE_ID_STANDARD_NAME L"HID_DEVICE\0"
  69. #define HIDCLASS_COMPATIBLE_ID_GENERIC_NAME L"HID_DEVICE_UP:%04x_U:%04x\0"
  70. #define HIDCLASS_COMPATIBLE_ID_PAGE_OFFSET 14
  71. #define HIDCLASS_COMPATIBLE_ID_USAGE_OFFSET 21
  72. #define HIDCLASS_COMPATIBLE_ID_STANDARD_LENGTH 11
  73. #define HIDCLASS_COMPATIBLE_ID_GENERIC_LENGTH 26
  74. // 0123456789 123456789 123456
  75. #define HIDCLASS_SYSTEM_KEYBOARD L"HID_DEVICE_SYSTEM_KEYBOARD\0"
  76. #define HIDCLASS_SYSTEM_MOUSE L"HID_DEVICE_SYSTEM_MOUSE\0"
  77. #define HIDCLASS_SYSTEM_GAMING_DEVICE L"HID_DEVICE_SYSTEM_GAME\0"
  78. #define HIDCLASS_SYSTEM_CONTROL L"HID_DEVICE_SYSTEM_CONTROL\0"
  79. #define HIDCLASS_SYSTEM_CONSUMER_DEVICE L"HID_DEVICE_SYSTEM_CONSUMER\0"
  80. //
  81. // String constant used to find out if selective suspend
  82. // is supported on this device.
  83. //
  84. #define HIDCLASS_SELECTIVE_SUSPEND_ENABLED L"SelectiveSuspendEnabled\0"
  85. #define HIDCLASS_SELECTIVE_SUSPEND_ON L"SelectiveSuspendOn\0"
  86. #define HIDCLASS_REMOTE_WAKE_ENABLE L"RemoteWakeEnabled"
  87. #define NO_STATUS 0x80000000 // this will never be a STATUS_xxx constant in NTSTATUS.H
  88. #define HID_DEFAULT_IDLE_TIME 5 // in seconds
  89. //
  90. // Valid values for HIDCLASS_DEVICE_EXTENSION.state
  91. //
  92. enum deviceState {
  93. DEVICE_STATE_INITIALIZED = 1,
  94. DEVICE_STATE_STARTING,
  95. DEVICE_STATE_START_SUCCESS,
  96. DEVICE_STATE_START_FAILURE,
  97. DEVICE_STATE_STOPPING,
  98. DEVICE_STATE_STOPPED,
  99. DEVICE_STATE_REMOVING,
  100. DEVICE_STATE_REMOVED
  101. };
  102. enum collectionState {
  103. COLLECTION_STATE_UNINITIALIZED = 1,
  104. COLLECTION_STATE_INITIALIZED,
  105. COLLECTION_STATE_RUNNING,
  106. COLLECTION_STATE_STOPPING,
  107. COLLECTION_STATE_STOPPED,
  108. COLLECTION_STATE_REMOVING
  109. };
  110. //
  111. // _HIDCLASS_DRIVER_EXTENSION contains per-minidriver extension information
  112. // for the class driver. It is created upon a HidRegisterMinidriver() call.
  113. //
  114. typedef struct _HIDCLASS_DRIVER_EXTENSION {
  115. //
  116. // Pointer to the minidriver's driver object.
  117. //
  118. PDRIVER_OBJECT MinidriverObject;
  119. //
  120. // RegistryPath is a copy of the minidriver's RegistryPath that it
  121. // received as a DriverEntry() parameter.
  122. //
  123. UNICODE_STRING RegistryPath;
  124. //
  125. // DeviceExtensionSize is the size of the minidriver's per-device
  126. // extension.
  127. //
  128. ULONG DeviceExtensionSize;
  129. //
  130. // Dispatch routines for the minidriver. These are the only dispatch
  131. // routines that the minidriver should ever care about, no others will
  132. // be forwarded.
  133. //
  134. PDRIVER_DISPATCH MajorFunction[ IRP_MJ_MAXIMUM_FUNCTION + 1 ];
  135. /*
  136. * These are the minidriver's original entrypoints,
  137. * to which we chain.
  138. */
  139. PDRIVER_ADD_DEVICE AddDevice;
  140. PDRIVER_UNLOAD DriverUnload;
  141. //
  142. // Number of pointers to this structure that we've handed out
  143. //
  144. LONG ReferenceCount;
  145. //
  146. // Linkage onto our global list of driver extensions
  147. //
  148. LIST_ENTRY ListEntry;
  149. /*
  150. * Either all or none of the devices driven by a given minidriver are polled.
  151. */
  152. BOOLEAN DevicesArePolled;
  153. #if DBG
  154. ULONG Signature;
  155. #endif
  156. } HIDCLASS_DRIVER_EXTENSION;
  157. #if DBG
  158. #define HID_DRIVER_EXTENSION_SIG 'EdiH'
  159. #endif
  160. #define MIN_POLL_INTERVAL_MSEC 1
  161. #define MAX_POLL_INTERVAL_MSEC 10000
  162. #define DEFAULT_POLL_INTERVAL_MSEC 5
  163. //
  164. // HIDCLASS_COLLECTION is where we keep our per-collection information.
  165. //
  166. typedef struct _HIDCLASS_COLLECTION {
  167. ULONG CollectionNumber;
  168. ULONG CollectionIndex;
  169. //
  170. // NumOpens is a count of open handles against this collection.
  171. //
  172. ULONG NumOpens;
  173. // Number of pending reads for all clients on this collection.
  174. ULONG numPendingReads;
  175. //
  176. // FileExtensionList is the head of a list of file extensions, i.e.
  177. // open instances against this collection.
  178. //
  179. LIST_ENTRY FileExtensionList;
  180. KSPIN_LOCK FileExtensionListSpinLock;
  181. /*
  182. * For polled devices, we only read from the device
  183. * once every poll interval. We queue read IRPs
  184. * here until the poll timer expiration.
  185. *
  186. * Note: for a polled device, we keep a separate background
  187. * loop for each collection. This way, queued-up read IRPs
  188. * remain associated with the right collection.
  189. * Also, this will keep the number of reads we do on each
  190. * timer period roughly equal to the number of collections.
  191. */
  192. ULONG PollInterval_msec;
  193. KTIMER polledDeviceTimer;
  194. KDPC polledDeviceTimerDPC;
  195. LIST_ENTRY polledDeviceReadQueue;
  196. KSPIN_LOCK polledDeviceReadQueueSpinLock;
  197. /*
  198. * We save old reports on polled devices for
  199. * "opportunistic" readers who want to get a result right away.
  200. * The polledDataIsStale flag indicates that the saved report
  201. * is at least one poll interval old (so we should not use it).
  202. */
  203. PUCHAR savedPolledReportBuf;
  204. ULONG savedPolledReportLen;
  205. BOOLEAN polledDataIsStale;
  206. UNICODE_STRING SymbolicLinkName;
  207. UNICODE_STRING SymbolicLinkName_SystemControl;
  208. /*
  209. * HID collection information descriptor for this collection.
  210. */
  211. HID_COLLECTION_INFORMATION hidCollectionInfo;
  212. PHIDP_PREPARSED_DATA phidDescriptor;
  213. /*
  214. * This buffer is used to "cook" a raw report when it's been received.
  215. * This is only used for non-polled (interrupt) devices.
  216. */
  217. PUCHAR cookedInterruptReportBuf;
  218. /*
  219. * This is an IRP that we queue and complete
  220. * when a read report contains a power event.
  221. *
  222. * The powerEventIrp field retains an IRP
  223. * so it needs a spinlock to synchronize cancellation.
  224. */
  225. PIRP powerEventIrp;
  226. KSPIN_LOCK powerEventSpinLock;
  227. ULONG secureReadMode;
  228. KSPIN_LOCK secureReadLock;
  229. #if DBG
  230. ULONG Signature;
  231. #endif
  232. } HIDCLASS_COLLECTION;
  233. #if DBG
  234. #define HIDCLASS_COLLECTION_SIG 'EccH'
  235. #endif
  236. //
  237. // For HID devices that have at least one interrupt-style collection, we
  238. // try to keep a set of "ping-pong" report-read IRPs pending in the minidriver
  239. // in the event we get a report.
  240. //
  241. // HIDCLASS_PINGPONG contains a pointer to an IRP as well as an event
  242. // and status block. Each device has a pointer to an array of these structures,
  243. // the array size depending on the number of such IRPs we want to keep in
  244. // motion.
  245. //
  246. // Right now the default number is 2.
  247. //
  248. #define MIN_PINGPONG_IRPS 2
  249. //
  250. // Flags to indicate whether read completed synchronously or asynchronously
  251. //
  252. #define PINGPONG_START_READ 0x01
  253. #define PINGPONG_END_READ 0x02
  254. #define PINGPONG_IMMEDIATE_READ 0x03
  255. typedef struct _HIDCLASS_PINGPONG {
  256. #define PINGPONG_SIG (ULONG)'gnoP'
  257. ULONG sig;
  258. //
  259. // Read interlock value to protect us from running out of stack space
  260. //
  261. ULONG ReadInterlock;
  262. PIRP irp;
  263. PUCHAR reportBuffer;
  264. LONG weAreCancelling;
  265. KEVENT sentEvent; // When a read has been sent.
  266. KEVENT pumpDoneEvent; // When the read loop is finally exitting.
  267. PFDO_EXTENSION myFdoExt;
  268. /*
  269. * Timeout context for back-off algorithm applied to broken devices.
  270. */
  271. KTIMER backoffTimer;
  272. KDPC backoffTimerDPC;
  273. LARGE_INTEGER backoffTimerPeriod; // in negative 100-nsec units
  274. } HIDCLASS_PINGPONG;
  275. #if DBG
  276. #define HIDCLASS_REPORT_BUFFER_GUARD 'draG'
  277. #endif
  278. //
  279. // All possible idle states.
  280. //
  281. #define IdleUninitialized 0x0
  282. #define IdleDisabled 0x1
  283. #define IdleWaiting 0x2
  284. #define IdleIrpSent 0x3
  285. #define IdleCallbackReceived 0x4
  286. #define IdleComplete 0x5
  287. /*
  288. * Stores information about a Functional Device Object (FDO) which HIDCLASS attaches
  289. * to the top of the Physical Device Object (PDO) that it get from the minidriver below.
  290. */
  291. typedef struct _FDO_EXTENSION {
  292. //
  293. // Back pointer to the functional device object
  294. //
  295. PDEVICE_OBJECT fdo;
  296. //
  297. // HidDriverExtension is a pointer to our driver extension for the
  298. // minidriver that gave us the PDO.
  299. //
  300. PHIDCLASS_DRIVER_EXTENSION driverExt;
  301. //
  302. // Hid descriptor that we get from the device.
  303. //
  304. HID_DESCRIPTOR hidDescriptor; // 9 bytes
  305. //
  306. // The attributes of this hid device.
  307. //
  308. HID_DEVICE_ATTRIBUTES hidDeviceAttributes; // 0x20 bytes
  309. //
  310. // Pointer to and length of the raw report descriptor.
  311. //
  312. PUCHAR rawReportDescription;
  313. ULONG rawReportDescriptionLength;
  314. //
  315. // This device has one or more collections. We store the count and
  316. // pointer to an array of our HIDCLASS_COLLECTION structures (one per
  317. // collection) here.
  318. //
  319. PHIDCLASS_COLLECTION classCollectionArray;
  320. /*
  321. * This is initialized for us by HIDPARSE's HidP_GetCollectionDescription().
  322. * It includes an array of HIDP_COLLECTION_DESC structs corresponding
  323. * the classCollectionArray declared above.
  324. */
  325. HIDP_DEVICE_DESC deviceDesc; // 0x30 bytes
  326. BOOLEAN devDescInitialized;
  327. //
  328. // The maximum input size amongst ALL report types.
  329. //
  330. ULONG maxReportSize;
  331. //
  332. // For devices that have at least one interrupt collection, we keep
  333. // a couple of ping-pong IRPs and associated structures.
  334. // The ping-pong IRPs ferry data up from the USB hub.
  335. //
  336. ULONG numPingPongs;
  337. PHIDCLASS_PINGPONG pingPongs;
  338. //
  339. // OpenCount represents the number of file objects aimed at this device
  340. //
  341. ULONG openCount;
  342. /*
  343. * This is the number of IRPs still outstanding in the minidriver.
  344. */
  345. ULONG outstandingRequests;
  346. enum deviceState prevState;
  347. enum deviceState state;
  348. UNICODE_STRING name;
  349. /*
  350. * deviceRelations contains an array of client PDO pointers.
  351. *
  352. * As the HID bus driver, HIDCLASS produces this data structure to report
  353. * collection-PDOs to the system.
  354. */
  355. PDEVICE_RELATIONS deviceRelations;
  356. /*
  357. * This is an array of device extensions for the collection-PDOs of this
  358. * device-FDO.
  359. */
  360. PHIDCLASS_DEVICE_EXTENSION *collectionPdoExtensions;
  361. /*
  362. * This includes a
  363. * table mapping system power states to device power states.
  364. */
  365. DEVICE_CAPABILITIES deviceCapabilities;
  366. /*
  367. * Track both current system and device power state
  368. */
  369. SYSTEM_POWER_STATE systemPowerState;
  370. DEVICE_POWER_STATE devicePowerState;
  371. /*
  372. * Wait Wake Irp sent to parent PDO
  373. */
  374. PIRP waitWakeIrp;
  375. KSPIN_LOCK waitWakeSpinLock;
  376. BOOLEAN isWaitWakePending;
  377. /*
  378. * Queue of delayed requests due to the stack being in low power
  379. */
  380. KSPIN_LOCK collectionPowerDelayedIrpQueueSpinLock;
  381. LIST_ENTRY collectionPowerDelayedIrpQueue;
  382. ULONG numPendingPowerDelayedIrps;
  383. BOOLEAN isOutputOnlyDevice;
  384. //
  385. // Selective suspend idling context.
  386. //
  387. HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO idleCallbackInfo;
  388. LONG idleState;
  389. PULONG idleTimeoutValue;
  390. KSPIN_LOCK idleNotificationSpinLock;
  391. PIRP idleNotificationRequest;
  392. BOOLEAN idleCancelling;
  393. BOOLEAN idleEnabledInRegistry;
  394. BOOLEAN idleEnabled;
  395. KSPIN_LOCK idleSpinLock;
  396. KEVENT idleDoneEvent; // When the idle notification irp has been cancelled successfully.
  397. LONG numIdlePdos;
  398. /*
  399. * This is a list of WaitWake IRPs sent to the collection-PDOs
  400. * on this device, which we just save and complete when the
  401. * base device's WaitWake IRP completes.
  402. */
  403. LIST_ENTRY collectionWaitWakeIrpQueue;
  404. KSPIN_LOCK collectionWaitWakeIrpQueueSpinLock;
  405. struct _FDO_EXTENSION *nextFdoExt;
  406. /*
  407. * Device-specific flags (DEVICE_FLAG_xxx).
  408. */
  409. ULONG deviceSpecificFlags;
  410. /*
  411. * This is our storage space for the systemState IRP that we need to hold
  412. * on to and complete in DevicePowerRequestCompletion.
  413. */
  414. PIRP currentSystemStateIrp;
  415. /*
  416. * Unique number assigned to identify this HID bus.
  417. */
  418. ULONG BusNumber;
  419. //
  420. // WMI Information
  421. //
  422. WMILIB_CONTEXT WmiLibInfo;
  423. #if DBG
  424. WCHAR dbgDriverKeyName[64];
  425. #endif
  426. KSPIN_LOCK presentSpinLock;
  427. BOOLEAN isPresent;
  428. BOOLEAN presentReported;
  429. } FDO_EXTENSION;
  430. /*
  431. * Stores information about a Physical Device Object (PDO) which HIDCLASS creates
  432. * for each HID device-collection.
  433. */
  434. typedef struct _PDO_EXTENSION {
  435. enum collectionState prevState;
  436. enum collectionState state;
  437. ULONG collectionNum;
  438. ULONG collectionIndex;
  439. //
  440. // A remove lock to keep track of outstanding I/Os to prevent the device
  441. // object from leaving before such time as all I/O has been completed.
  442. //
  443. IO_REMOVE_LOCK removeLock;
  444. // represents a collection on the HID "bus"
  445. PDEVICE_OBJECT pdo;
  446. PUNICODE_STRING name;
  447. /*
  448. * This is a back-pointer to the original FDO's extension.
  449. */
  450. PHIDCLASS_DEVICE_EXTENSION deviceFdoExt;
  451. /*
  452. * Track both current system and device power state
  453. */
  454. SYSTEM_POWER_STATE systemPowerState;
  455. DEVICE_POWER_STATE devicePowerState;
  456. BOOLEAN remoteWakeEnabled;
  457. KSPIN_LOCK remoteWakeSpinLock;
  458. PIRP remoteWakeIrp;
  459. PIRP waitWakeIrp;
  460. /*
  461. * The status change function that was registered thru query interface
  462. * NOTE: Can currently only register one.
  463. */
  464. PHID_STATUS_CHANGE StatusChangeFn;
  465. PVOID StatusChangeContext;
  466. /*
  467. * Access protection information.
  468. * We count the number of opens for read and write on the collection.
  469. * We also count the number of opens which RESTRICT future
  470. * read/write opens on the collection.
  471. *
  472. * Note that desired access is independent of restriction.
  473. * A client may, for example, do an open-for-read-only but
  474. * (by not setting the FILE_SHARE_WRITE bit)
  475. * restrict other clients from doing an open-for-write.
  476. */
  477. ULONG openCount;
  478. ULONG opensForRead;
  479. ULONG opensForWrite;
  480. ULONG restrictionsForRead;
  481. ULONG restrictionsForWrite;
  482. ULONG restrictionsForAnyOpen;
  483. BOOLEAN MouseOrKeyboard;
  484. //
  485. // WMI Information
  486. //
  487. WMILIB_CONTEXT WmiLibInfo;
  488. } PDO_EXTENSION;
  489. /*
  490. * This contains info about either a device FDO or a device-collection PDO.
  491. * Some of the same functions process both, so we need one structure.
  492. */
  493. typedef struct _HIDCLASS_DEVICE_EXTENSION {
  494. /*
  495. * This is the public part of a HID FDO device extension, and
  496. * must be the first entry in this structure.
  497. */
  498. HID_DEVICE_EXTENSION hidExt; // size== 0x0C.
  499. /*
  500. * Determines whether this is a device extension for a device-FDO or a
  501. * device-collection-PDO; this resolves the following union.
  502. */
  503. BOOLEAN isClientPdo;
  504. /*
  505. * Include this signature for both debug and retail --
  506. * kenray's debug extensions look for this.
  507. */
  508. #define HID_DEVICE_EXTENSION_SIG 'EddH'
  509. ULONG Signature;
  510. union {
  511. FDO_EXTENSION fdoExt;
  512. PDO_EXTENSION pdoExt;
  513. };
  514. } HIDCLASS_DEVICE_EXTENSION;
  515. //
  516. // HIDCLASS_FILE_EXTENSION is private data we keep per file object.
  517. //
  518. typedef struct _HIDCLASS_FILE_EXTENSION {
  519. //
  520. // CollectionNumber is the ordinal of the collection in the device
  521. //
  522. ULONG CollectionNumber;
  523. PFDO_EXTENSION fdoExt;
  524. //
  525. // PendingIrpList is a list of READ IRPs currently waiting to be satisfied.
  526. //
  527. LIST_ENTRY PendingIrpList;
  528. //
  529. // ReportList is a list of reports waiting to be read on this handle.
  530. //
  531. LIST_ENTRY ReportList;
  532. //
  533. // FileList provides a way to link all of a collection's
  534. // file extensions together.
  535. //
  536. LIST_ENTRY FileList;
  537. //
  538. // Both PendingIrpList and ReportList are protected by the same spinlock,
  539. // ListSpinLock.
  540. //
  541. KSPIN_LOCK ListSpinLock;
  542. //
  543. // MaximumInputReportAge is only applicable for polled collections.
  544. // It represents the maximum acceptable input report age for this handle.
  545. // There is a value in the HIDCLASS_COLLECTION,
  546. // CurrentMaximumInputReportAge, that represents the current minimum value
  547. // of all of the file extensions open against the collection.
  548. //
  549. LARGE_INTEGER MaximumInputReportAge;
  550. //
  551. // CurrentInputReportQueueSize is the current size of the report input
  552. // queue.
  553. //
  554. ULONG CurrentInputReportQueueSize;
  555. /*
  556. * This is the maximum number of reports that will be queued for the file extension.
  557. * This starts at a default value and can be adjusted (within a fixed range) by an IOCTL.
  558. */
  559. ULONG MaximumInputReportQueueSize;
  560. #define MIN_INPUT_REPORT_QUEUE_SIZE MIN_PINGPONG_IRPS
  561. #define MAX_INPUT_REPORT_QUEUE_SIZE (MIN_INPUT_REPORT_QUEUE_SIZE*256)
  562. #define DEFAULT_INPUT_REPORT_QUEUE_SIZE (MIN_INPUT_REPORT_QUEUE_SIZE*16)
  563. //
  564. // Back pointer to the file object that this extension is for
  565. //
  566. PFILE_OBJECT FileObject;
  567. /*
  568. * File-attributes passed in irpSp->Parameters.Create.FileAttributes
  569. * when this open was made.
  570. */
  571. USHORT FileAttributes;
  572. ACCESS_MASK accessMask;
  573. USHORT shareMask;
  574. //
  575. // Closing is set when this file object is closing and will be removed
  576. // shortly. Don't queue any more reports or IRPs to this object
  577. // when this flag is set.
  578. //
  579. BOOLEAN Closing;
  580. //
  581. // DWORD allignment
  582. //
  583. BOOLEAN Reserved [2];
  584. /*
  585. * This flag indicates that this client does irregular, opportunistic
  586. * reads on the device, which is a polled device.
  587. * Instead of waiting for the background timer-driven read loop,
  588. * this client should have his reads completed immediately.
  589. */
  590. BOOLEAN isOpportunisticPolledDeviceReader;
  591. BOOLEAN isSecureOpen;
  592. ULONG SecureReadMode;
  593. /*
  594. * If a read fails, some clients reissue the read on the same thread.
  595. * If this happens repeatedly, we can run out of stack space.
  596. * So we keep track of the depth
  597. */
  598. #define INSIDE_READCOMPLETE_MAX 4
  599. ULONG insideReadCompleteCount;
  600. #if DBG
  601. BOOLEAN ListSpinLockTaken;
  602. ULONG dbgNumReportsDroppedSinceLastRead;
  603. ULONG Signature;
  604. #endif
  605. } HIDCLASS_FILE_EXTENSION;
  606. #if DBG
  607. #define HIDCLASS_FILE_EXTENSION_SIG 'efcH'
  608. #endif
  609. typedef struct {
  610. #define ASYNC_COMPLETE_CONTEXT_SIG 'cnsA'
  611. ULONG sig;
  612. PIO_WORKITEM workItem;
  613. PIRP irp;
  614. } ASYNC_COMPLETE_CONTEXT;
  615. //
  616. // HIDCLASS_REPORT is the structure we use to track a report returned from
  617. // the minidriver.
  618. //
  619. typedef struct _HIDCLASS_REPORT {
  620. //
  621. // ListEntry queues this report onto a file extension.
  622. //
  623. LIST_ENTRY ListEntry;
  624. ULONG reportLength;
  625. //
  626. // UnparsedReport is a data area for the unparsed report data as returned
  627. // from the minidriver. The lengths of all input reports for a given
  628. // class are the same, so we don't need to store the length in each
  629. // report.
  630. //
  631. UCHAR UnparsedReport[];
  632. } HIDCLASS_REPORT;
  633. typedef struct _HIDCLASS_WORK_ITEM_DATA {
  634. PIRP Irp;
  635. PDO_EXTENSION *PdoExt;
  636. PIO_WORKITEM Item;
  637. BOOLEAN RemoteWakeState;
  638. } HIDCLASS_WORK_ITEM_DATA, *PHIDCLASS_WORK_ITEM_DATA;
  639. //
  640. // Internal shared function prototypes
  641. //
  642. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
  643. NTSTATUS HidpAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject);
  644. VOID HidpDriverUnload(IN struct _DRIVER_OBJECT *minidriverObject);
  645. NTSTATUS HidpCallDriver(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
  646. NTSTATUS HidpCallDriverSynchronous(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp);
  647. NTSTATUS HidpCopyInputReportToUser(IN PHIDCLASS_FILE_EXTENSION fdoExtension, IN PUCHAR ReportData, IN OUT PULONG UserBufferLen, OUT PUCHAR UserBuffer);
  648. NTSTATUS HidpCreateSymbolicLink(IN PDO_EXTENSION *pdoExtension, IN ULONG collectionNum, IN BOOLEAN Create, IN PDEVICE_OBJECT Pdo);
  649. NTSTATUS HidpCreateClientPDOs(PHIDCLASS_DEVICE_EXTENSION hidClassExtension);
  650. ULONG HidpSetMaxReportSize(IN FDO_EXTENSION *fdoExtension);
  651. VOID EnqueueInterruptReport(PHIDCLASS_FILE_EXTENSION fileExtension, PHIDCLASS_REPORT report);
  652. PHIDCLASS_REPORT DequeueInterruptReport(PHIDCLASS_FILE_EXTENSION fileExtension, LONG maxLen);
  653. VOID HidpDestroyFileExtension(PHIDCLASS_COLLECTION collection, PHIDCLASS_FILE_EXTENSION FileExtension);
  654. VOID HidpFlushReportQueue(IN PHIDCLASS_FILE_EXTENSION FileExtension);
  655. NTSTATUS HidpGetCollectionDescriptor(IN FDO_EXTENSION *fdoExtension, IN ULONG collectionId, IN PVOID Buffer, IN OUT PULONG BufferSize);
  656. NTSTATUS HidpGetCollectionInformation(IN FDO_EXTENSION *fdoExtension, IN ULONG collectionNumber, IN PVOID Buffer, IN OUT PULONG BufferSize);
  657. NTSTATUS HidpGetDeviceDescriptor(FDO_EXTENSION *fdoExtension);
  658. BOOLEAN HidpStartIdleTimeout(FDO_EXTENSION *fdoExt, BOOLEAN DeviceStart);
  659. VOID HidpCancelIdleNotification(FDO_EXTENSION *fdoExt, BOOLEAN removing);
  660. VOID HidpIdleTimeWorker(PDEVICE_OBJECT DeviceObject, PIO_WORKITEM Item);
  661. VOID HidpIdleNotificationCallback(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension);
  662. NTSTATUS HidpRegisterDeviceForIdleDetection(PDEVICE_OBJECT DeviceObject, ULONG IdleTime, PULONG *);
  663. VOID HidpSetDeviceBusy(FDO_EXTENSION *fdoExt);
  664. NTSTATUS HidpCheckIdleState(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension,PIRP Irp);
  665. NTSTATUS HidpGetRawDeviceDescriptor(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, OUT PULONG RawDeviceDescriptorLength, OUT PUCHAR *RawDeviceDescriptor);
  666. NTSTATUS HidpInitializePingPongIrps(FDO_EXTENSION *fdoExtension);
  667. NTSTATUS HidpReallocPingPongIrps(FDO_EXTENSION *fdoExtension, ULONG newNumBufs);
  668. NTSTATUS HidpIrpMajorPnpComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  669. NTSTATUS HidpMajorHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  670. NTSTATUS HidpParseAndBuildLinks(FDO_EXTENSION *fdoExtension);
  671. NTSTATUS HidpFdoPowerCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  672. BOOLEAN EnqueueDriverExt(PHIDCLASS_DRIVER_EXTENSION driverExt);
  673. PHIDCLASS_DRIVER_EXTENSION RefDriverExt(IN PDRIVER_OBJECT MinidriverObject);
  674. PHIDCLASS_DRIVER_EXTENSION DerefDriverExt(IN PDRIVER_OBJECT MinidriverObject);
  675. NTSTATUS HidpStartAllPingPongs(FDO_EXTENSION *fdoExtension);
  676. ULONG HidiGetClassCollectionOrdinal(IN PHIDCLASS_COLLECTION ClassCollection);
  677. PHIDP_COLLECTION_DESC HidiGetHidCollectionByClassCollection(IN PHIDCLASS_COLLECTION ClassCollection);
  678. PHIDP_REPORT_IDS GetReportIdentifier(FDO_EXTENSION *fdoExtension, ULONG reportId);
  679. PHIDP_COLLECTION_DESC GetCollectionDesc(FDO_EXTENSION *fdoExtension, ULONG collectionId);
  680. PHIDCLASS_COLLECTION GetHidclassCollection(FDO_EXTENSION *fdoExtension, ULONG collectionId);
  681. //NTSTATUS HidpGetSetFeature(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp, IN ULONG controlCode, OUT BOOLEAN *sentIrp);
  682. NTSTATUS HidpGetSetReport(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp, IN ULONG controlCode, OUT BOOLEAN *sentIrp);
  683. NTSTATUS HidpGetDeviceString(IN FDO_EXTENSION *fdoExt, IN OUT PIRP Irp, IN ULONG stringId, IN ULONG languageId);
  684. NTSTATUS HidpGetPhysicalDescriptor(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  685. NTSTATUS HidpIrpMajorRead(IN PHIDCLASS_DEVICE_EXTENSION, IN OUT PIRP Irp);
  686. NTSTATUS HidpIrpMajorCreate(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  687. NTSTATUS HidpIrpMajorWrite(IN PHIDCLASS_DEVICE_EXTENSION, IN OUT PIRP Irp);
  688. NTSTATUS HidpIrpMajorPnp(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  689. NTSTATUS HidpPdoPnp(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  690. NTSTATUS HidpFdoPnp(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  691. NTSTATUS HidpIrpMajorPower(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  692. NTSTATUS HidpIrpMajorClose(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  693. NTSTATUS HidpIrpMajorDeviceControl(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  694. NTSTATUS HidpIrpMajorINTERNALDeviceControl(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  695. NTSTATUS HidpIrpMajorClose(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  696. NTSTATUS HidpIrpMajorDefault(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  697. NTSTATUS HidpInterruptReadComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  698. NTSTATUS HidpQueryDeviceRelations(IN PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, IN OUT PIRP Irp);
  699. NTSTATUS HidpQueryCollectionCapabilities(PDO_EXTENSION *pdoExt, IN OUT PIRP Irp);
  700. NTSTATUS HidpQueryIdForClientPdo(IN PHIDCLASS_DEVICE_EXTENSION hidClassExtension, IN OUT PIRP Irp);
  701. NTSTATUS HidpQueryInterface(IN PHIDCLASS_DEVICE_EXTENSION hidClassExtension, IN OUT PIRP Irp);
  702. PVOID MemDup(POOL_TYPE PoolType, PVOID dataPtr, ULONG length);
  703. BOOLEAN AllClientPDOsInitialized(FDO_EXTENSION *fdoExtension, BOOLEAN initialized);
  704. BOOLEAN AnyClientPDOsInitialized(FDO_EXTENSION *fdoExtension, BOOLEAN initialized);
  705. NTSTATUS ClientPdoCompletion(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, PIRP Irp);
  706. BOOLEAN HidpDeleteDeviceObjects(FDO_EXTENSION *fdoExt);
  707. VOID HidpCancelReadIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp);
  708. VOID CancelAllPingPongIrps(FDO_EXTENSION *fdoExt);
  709. VOID HidpCleanUpFdo(FDO_EXTENSION *fdoExt);
  710. NTSTATUS HidpRemoveDevice(FDO_EXTENSION *fdoExt, IN PIRP Irp);
  711. VOID HidpRemoveCollection(FDO_EXTENSION *fdoExt, PDO_EXTENSION *pdoExt, IN PIRP Irp);
  712. VOID HidpDestroyCollection(FDO_EXTENSION *fdoExt, PHIDCLASS_COLLECTION Collection);
  713. VOID CollectionPowerRequestCompletion(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus);
  714. VOID DevicePowerRequestCompletion(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus);
  715. NTSTATUS HidpQueryCapsCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  716. NTSTATUS HidpQueryDeviceCapabilities(IN PDEVICE_OBJECT PdoDeviceObject, IN PDEVICE_CAPABILITIES DeviceCapabilities);
  717. VOID DestroyPingPongs(FDO_EXTENSION *fdoExt);
  718. VOID CheckReportPowerEvent(FDO_EXTENSION *fdoExt, PHIDCLASS_COLLECTION collection, PUCHAR report, ULONG reportLen);
  719. BOOLEAN StartPollingLoop(FDO_EXTENSION *fdoExt, PHIDCLASS_COLLECTION hidCollection, BOOLEAN freshQueue);
  720. VOID StopPollingLoop(PHIDCLASS_COLLECTION hidCollection, BOOLEAN flushQueue);
  721. BOOLEAN ReadPolledDevice(PDO_EXTENSION *pdoExt, BOOLEAN isTimerDrivenRead);
  722. VOID PolledReadCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  723. VOID EnqueueFdoExt(FDO_EXTENSION *fdoExt);
  724. VOID DequeueFdoExt(FDO_EXTENSION *fdoExt);
  725. NTSTATUS AllocDeviceResources(FDO_EXTENSION *fdoExt);
  726. VOID FreeDeviceResources(FDO_EXTENSION *fdoExt);
  727. NTSTATUS AllocCollectionResources(FDO_EXTENSION *fdoExt, ULONG collectionNum);
  728. VOID FreeCollectionResources(FDO_EXTENSION *fdoExt, ULONG collectionNum);
  729. NTSTATUS InitializeCollection(FDO_EXTENSION *fdoExt, ULONG collectionIndex);
  730. NTSTATUS HidpStartCollectionPDO(FDO_EXTENSION *fdoExt, PDO_EXTENSION *pdoExt, PIRP Irp);
  731. NTSTATUS HidpStartDevice(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, PIRP Irp);
  732. PWCHAR SubstituteBusNames(PWCHAR oldIDs, FDO_EXTENSION *fdoExt, PDO_EXTENSION *pdoExt);
  733. PWSTR BuildCompatibleID(PHIDCLASS_DEVICE_EXTENSION hidClassExtension);
  734. PUNICODE_STRING MakeClientPDOName(PUNICODE_STRING fdoName, ULONG collectionId);
  735. VOID HidpPingpongBackoffTimerDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
  736. BOOLEAN WStrCompareN(PWCHAR str1, PWCHAR str2, ULONG maxChars);
  737. NTSTATUS SubmitWaitWakeIrp(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension);
  738. BOOLEAN HidpIsWaitWakePending(FDO_EXTENSION *fdoExt, BOOLEAN setIfNotPending);
  739. NTSTATUS HidpWaitWakeComplete(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus);
  740. NTSTATUS HidpGetIndexedString(IN FDO_EXTENSION *fdoExt, IN OUT PIRP Irp, IN ULONG stringIndex, IN ULONG languageId);
  741. VOID CompleteAllPendingReadsForCollection(PHIDCLASS_COLLECTION Collection);
  742. VOID CompleteAllPendingReadsForFileExtension(PHIDCLASS_COLLECTION Collection, PHIDCLASS_FILE_EXTENSION fileExtension);
  743. VOID CompleteAllPendingReadsForDevice(FDO_EXTENSION *fdoExt);
  744. BOOLEAN MyPrivilegeCheck(PIRP Irp);
  745. NTSTATUS QueuePowerEventIrp(PHIDCLASS_COLLECTION hidCollection, PIRP Irp);
  746. VOID PowerEventCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  747. NTSTATUS HidpPolledReadComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  748. NTSTATUS HidpPolledReadComplete_TimerDriven(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  749. VOID CollectionWaitWakeIrpCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  750. VOID CompleteAllCollectionWaitWakeIrps(FDO_EXTENSION *fdoExt, NTSTATUS status);
  751. VOID PowerDelayedCancelRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  752. NTSTATUS EnqueuePowerDelayedIrp(PHIDCLASS_DEVICE_EXTENSION HidDeviceExtension, PIRP Irp);
  753. PIRP DequeuePowerDelayedIrp(FDO_EXTENSION *fdoExt);
  754. ULONG DequeueAllPdoPowerDelayedIrps(PDO_EXTENSION *pdoExt, PLIST_ENTRY dequeue);
  755. VOID ReadDeviceFlagsFromRegistry(FDO_EXTENSION *fdoExt, PDEVICE_OBJECT pdo);
  756. LONG WStrNCmpI(PWCHAR s1, PWCHAR s2, ULONG n);
  757. ULONG LAtoX(PWCHAR wHexString);
  758. ULONG WStrNCpy(PWCHAR dest, PWCHAR src, ULONG n);
  759. NTSTATUS OpenSubkey(OUT PHANDLE Handle, IN HANDLE BaseHandle, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess);
  760. void HidpNumberToString(PWCHAR String, USHORT Number, USHORT stringLen);
  761. NTSTATUS GetHIDRawReportDescriptor(FDO_EXTENSION *fdoExt, PIRP irp, ULONG descriptorLen);
  762. VOID WorkItemCallback_CompleteIrpAsynchronously(PDEVICE_OBJECT DevObj,PVOID context);
  763. NTSTATUS EnqueueInterruptReadIrp(PHIDCLASS_COLLECTION collection, PHIDCLASS_FILE_EXTENSION fileExtension, PIRP Irp);
  764. PIRP DequeueInterruptReadIrp(PHIDCLASS_COLLECTION collection, PHIDCLASS_FILE_EXTENSION fileExtension);
  765. NTSTATUS EnqueuePolledReadIrp(PHIDCLASS_COLLECTION collection, PIRP Irp);
  766. PIRP DequeuePolledReadSystemIrp(PHIDCLASS_COLLECTION collection);
  767. PIRP DequeuePolledReadIrp(PHIDCLASS_COLLECTION collection);
  768. NTSTATUS HidpProcessInterruptReport(PHIDCLASS_COLLECTION collection, PHIDCLASS_FILE_EXTENSION FileExtension, PUCHAR Report, ULONG ReportLength, PIRP *irpToComplete);
  769. VOID HidpFreePowerEventIrp(PHIDCLASS_COLLECTION Collection);
  770. NTSTATUS HidpGetMsGenreDescriptor(IN FDO_EXTENSION *fdoExt, IN OUT PIRP Irp);
  771. NTSTATUS DllUnload(VOID);
  772. NTSTATUS DllInitialize (PUNICODE_STRING RegistryPath);
  773. VOID HidpPowerUpPdos(IN PFDO_EXTENSION fdoExt);
  774. NTSTATUS HidpDelayedPowerPoRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus);
  775. NTSTATUS HidpIrpMajorSystemControl(PHIDCLASS_DEVICE_EXTENSION DeviceObject, PIRP Irp);
  776. NTSTATUS HidpSetWmiDataItem(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG GuidIndex, ULONG InstanceIndex, ULONG DataItemId, ULONG BufferSize, PUCHAR Buffer);
  777. NTSTATUS HidpSetWmiDataBlock(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG GuidIndex, ULONG InstanceIndex, ULONG BufferSize, PUCHAR Buffer);
  778. NTSTATUS HidpQueryWmiDataBlock( PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG GuidIndex, ULONG InstanceIndex, ULONG InstanceCount, OUT PULONG InstanceLengthArray, ULONG BufferAvail, PUCHAR Buffer);
  779. NTSTATUS HidpQueryWmiRegInfo( PDEVICE_OBJECT DeviceObject, ULONG *RegFlags, PUNICODE_STRING InstanceName, PUNICODE_STRING *RegistryPath, PUNICODE_STRING MofResourceName, PDEVICE_OBJECT *Pdo);
  780. BOOLEAN HidpCreateRemoteWakeIrp (PDO_EXTENSION *PdoExt);
  781. void HidpCreateRemoteWakeIrpWorker (PDEVICE_OBJECT DeviceObject, PHIDCLASS_WORK_ITEM_DATA ItemData);
  782. NTSTATUS HidpToggleRemoteWake(PDO_EXTENSION *PdoExt, BOOLEAN RemoteWakeState);
  783. #if DBG
  784. VOID InitFdoExtDebugInfo(PHIDCLASS_DEVICE_EXTENSION hidclassExt);
  785. #endif
  786. extern ULONG HidpNextHidNumber;
  787. extern FDO_EXTENSION *allFdoExtensions;
  788. extern KSPIN_LOCK allFdoExtensionsSpinLock;
  789. PVOID
  790. HidpGetSystemAddressForMdlSafe(PMDL MdlAddress);