Source code of Windows XP (NT5)
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.

666 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. KBDHID.H
  5. Abstract:
  6. This module contains the PRIVATE (driver-only) definitions for the
  7. code that implements this sample client driver.
  8. Note: This is not a WDM driver as it will not run on Memphis (you need a
  9. vxd mapper to do keyboards for Memphis) and it uses event logs
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. Nov-96 : created by Kenneth D. Ray
  14. --*/
  15. #ifndef _KBDHID_H
  16. #define _KBDHID_H
  17. #include "ntddk.h"
  18. #include "hidusage.h"
  19. #include "hidpi.h"
  20. #include "ntddkbd.h"
  21. #include "kbdmou.h"
  22. #include "kbdhidm.h"
  23. #include "wmilib.h"
  24. //
  25. // Sometimes we allocate a bunch of structures together and need to split the
  26. // allocation among these different structures. Use this macro to get the
  27. // lengths of the different structures aligned properly
  28. //
  29. #if defined(_WIN64)
  30. // Round the
  31. #define ALIGNPTRLEN(x) ((x + 0x7) >> 3) << 3
  32. #else // defined(_WIN64)
  33. #define ALIGNPTRLEN(x) x
  34. #endif // defined(_WIN64)
  35. //
  36. // allow a device parameter in the dev node to override the reported keyboard
  37. // type, with a value of this name.
  38. //
  39. #define KEYBOARD_TYPE_OVERRIDE L"KeyboardTypeOverride"
  40. #define KEYBOARD_SUBTYPE_OVERRIDE L"KeyboardSubtypeOverride"
  41. #define KEYBOARD_NUMBER_TOTAL_KEYS_OVERRIDE L"KeyboardNumberTotalKeysOverride"
  42. #define KEYBOARD_NUMBER_FUNCTION_KEYS_OVERRIDE L"KeyboardNumberFunctionKeysOverride"
  43. #define KEYBOARD_NUMBER_INDICATORS_OVERRIDE L"KeyboardNumberIndicatorsOverride"
  44. //
  45. // Only allocate with a pool tag. Remember that NT and 95 are little endian
  46. // systmes.
  47. //
  48. #define KBDHID_POOL_TAG (ULONG) 'lCdH'
  49. #undef ExAllocatePool
  50. #define ExAllocatePool(type, size) \
  51. ExAllocatePoolWithTag (type, size, KBDHID_POOL_TAG);
  52. //
  53. // Registry ProblemFlags masks. [DAN]
  54. //
  55. #define PROBLEM_CHATTERY_KEYBOARD 0x00000001
  56. #define KEYBOARD_HW_CHATTERY_FIX 1 // [DAN]
  57. #if KEYBOARD_HW_CHATTERY_FIX // [DAN]
  58. //
  59. // Delay between StartRead calls for chattery keyboards.
  60. //
  61. // Note that the StartRead delay for chattery keyboards must be no greater
  62. // than KEYBOARD_TYPEMATIC_DELAY_MINIMUM milliseconds (250), otherwise the
  63. // keys on the keyboard will auto-repeat unexpectedly.
  64. //
  65. // 50ms will satisfy 212 words/minute (one word = 5 keystrokes), the world's
  66. // fastest typing speed as recorded in the 23rd Guiness Book of World Record.
  67. //
  68. #define DEFAULT_START_READ_DELAY (50 * 10000) // 50 miliseconds.
  69. #endif
  70. //
  71. // Declarations. [DAN]
  72. //
  73. #define HID_KEYBOARD_NUMBER_OF_FUNCTION_KEYS 12 // 12 "known" func-key usages
  74. #define HID_KEYBOARD_NUMBER_OF_KEYS_TOTAL 101 // 101 "known" key usages
  75. #define HID_KEYBOARD_IDENTIFIER_TYPE 81
  76. //
  77. // Flags to indicate whether read completed synchronously or asynchronously
  78. //
  79. #define KBDHID_START_READ 0x01
  80. #define KBDHID_END_READ 0x02
  81. #define KBDHID_IMMEDIATE_READ 0x03
  82. //
  83. // Statically allocate the (known) scancode-to-indicator-light mapping.
  84. // This information is returned by the
  85. // IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION device control request.
  86. //
  87. #define HID_KEYBOARD_NUMBER_OF_INDICATORS 3
  88. //
  89. // Default keyboard scan code mode (lifted from I8042PRT.H). [DAN]
  90. //
  91. #define HID_KEYBOARD_SCAN_CODE_SET 0x01
  92. //
  93. // Minimum, maximum, and default values for keyboard typematic rate and delay
  94. // (lifted from I8042PRT.H). [DAN]
  95. //
  96. #define HID_KEYBOARD_TYPEMATIC_RATE_MINIMUM 2
  97. #define HID_KEYBOARD_TYPEMATIC_RATE_MAXIMUM 30
  98. #define HID_KEYBOARD_TYPEMATIC_RATE_DEFAULT 30
  99. #define HID_KEYBOARD_TYPEMATIC_DELAY_MINIMUM 250
  100. #define HID_KEYBOARD_TYPEMATIC_DELAY_MAXIMUM 1000
  101. #define HID_KEYBOARD_TYPEMATIC_DELAY_DEFAULT 250
  102. static const INDICATOR_LIST IndicatorList[HID_KEYBOARD_NUMBER_OF_INDICATORS] = {
  103. {0x3A, KEYBOARD_CAPS_LOCK_ON},
  104. {0x45, KEYBOARD_NUM_LOCK_ON},
  105. {0x46, KEYBOARD_SCROLL_LOCK_ON}
  106. };
  107. //
  108. // Debugging levels
  109. //
  110. #define DBG_STARTUP_SHUTDOWN_MASK 0x0000000F
  111. #define DBG_SS_NOISE 0x00000001
  112. #define DBG_SS_TRACE 0x00000002
  113. #define DBG_SS_INFO 0x00000004
  114. #define DBG_SS_ERROR 0x00000008
  115. #define DBG_CALL_MASK 0x000000F0
  116. #define DBG_CALL_NOISE 0x00000010
  117. #define DBG_CALL_TRACE 0x00000020
  118. #define DBG_CALL_INFO 0x00000040
  119. #define DBG_CALL_ERROR 0x00000080
  120. #define DBG_IOCTL_MASK 0x00000F00
  121. #define DBG_IOCTL_NOISE 0x00000100
  122. #define DBG_IOCTL_TRACE 0x00000200
  123. #define DBG_IOCTL_INFO 0x00000400
  124. #define DBG_IOCTL_ERROR 0x00000800
  125. #define DBG_READ_MASK 0x0000F000
  126. #define DBG_READ_NOISE 0x00001000
  127. #define DBG_READ_TRACE 0x00002000
  128. #define DBG_READ_INFO 0x00004000
  129. #define DBG_READ_ERROR 0x00008000
  130. #define DBG_CREATE_CLOSE_MASK 0x000F0000
  131. #define DBG_CC_NOISE 0x00010000
  132. #define DBG_CC_TRACE 0x00020000
  133. #define DBG_CC_INFO 0x00040000
  134. #define DBG_CC_ERROR 0x00080000
  135. #define DBG_POWER_MASK 0x00F00000
  136. #define DBG_POWER_NOISE 0x00100000
  137. #define DBG_POWER_TRACE 0x00200000
  138. #define DBG_POWER_INFO 0x00400000
  139. #define DBG_POWER_ERROR 0x00800000
  140. #define DBG_PNP_MASK 0x0F000000
  141. #define DBG_PNP_NOISE 0x01000000
  142. #define DBG_PNP_TRACE 0x02000000
  143. #define DBG_PNP_INFO 0x04000000
  144. #define DBG_PNP_ERROR 0x08000000
  145. #define DBG_CANCEL_MASK 0xF0000000
  146. #define DBG_CANCEL_NOISE 0x10000000
  147. #define DBG_CANCEL_TRACE 0x20000000
  148. #define DBG_CANCEL_INFO 0x40000000
  149. #define DBG_CANCEL_ERROR 0x80000000
  150. #define DEFAULT_DEBUG_OUTPUT_LEVEL 0x88888888
  151. #if DBG
  152. #define Print(_l_, _x_) \
  153. if (Globals.DebugLevel & (_l_)) { \
  154. DbgPrint ("KbdHid: "); \
  155. DbgPrint _x_; \
  156. }
  157. #define TRAP() DbgBreakPoint()
  158. #else
  159. #define Print(_l_,_x_)
  160. #define TRAP()
  161. #endif
  162. #define MAX(_A_,_B_) (((_A_) < (_B_)) ? (_B_) : (_A_))
  163. #define MIN(_A_,_B_) (((_A_) < (_B_)) ? (_A_) : (_B_))
  164. //
  165. // Define the keyboard scan code input states.
  166. //
  167. typedef enum _KEYBOARD_SCAN_STATE {
  168. Normal,
  169. GotE0,
  170. GotE1
  171. } KEYBOARD_SCAN_STATE;
  172. //
  173. // Structures;
  174. //
  175. typedef struct _GLOBALS {
  176. #if DBG
  177. //
  178. // The level of trace output sent to the debugger. See HidCli_KdPrint above.
  179. //
  180. ULONG DebugLevel;
  181. #endif
  182. //
  183. // Pointer to this driver's null-terminated registry path.
  184. //
  185. UNICODE_STRING RegistryPath;
  186. //
  187. // Unit ID given to the keyboard class driver
  188. //
  189. ULONG UnitId;
  190. } GLOBALS;
  191. extern GLOBALS Globals;
  192. /*
  193. * The UsageMappingList is used to keep track of mappings
  194. * from incorrect to correct usage values (for broken keyboards).
  195. */
  196. typedef struct UsageMappingList {
  197. USHORT sourceUsage, mappedUsage;
  198. struct UsageMappingList *next;
  199. } UsageMappingList;
  200. typedef struct _DEVICE_EXTENSION
  201. {
  202. //
  203. // A back pointer to the device extension.
  204. //
  205. PDEVICE_OBJECT Self;
  206. //
  207. // The top of the stack before this filter was added. AKA the location
  208. // to which all IRPS should be directed.
  209. //
  210. PDEVICE_OBJECT TopOfStack;
  211. //
  212. // "THE PDO" (ejected by Hidclass)
  213. //
  214. PDEVICE_OBJECT PDO;
  215. //
  216. // Flag indicating permission to send callbacks to the mouse class driver.
  217. //
  218. LONG EnableCount;
  219. //
  220. // Read interlock value to protect us from running out of stack space
  221. //
  222. ULONG ReadInterlock;
  223. //
  224. // Event used to synchronize the completion of the read irp and the close irp
  225. //
  226. KEVENT ReadCompleteEvent;
  227. //
  228. // Event used to indicate that a read irp has been sent and is now cancelable.
  229. //
  230. KEVENT ReadSentEvent;
  231. //
  232. // Has the device been taken out from under us?
  233. // Has it been started?
  234. //
  235. BOOLEAN Started;
  236. BOOLEAN ShuttingDown;
  237. BOOLEAN Initialized;
  238. USHORT UnitId;
  239. // Make this look like mouhid.h
  240. ULONG Reserved;
  241. //
  242. // Write and Feature Irps get passed straight down, but read Irps do not.
  243. // For this reason we keep around a read Irp, which we created.
  244. //
  245. PIRP ReadIrp;
  246. //
  247. // A pointer to the HID extension.
  248. //
  249. struct _HID_EXTENSION * HidExtension;
  250. //
  251. // Flags indicating problems with the keyboard HID device (such as
  252. // a chattery keyboard). [DAN]
  253. //
  254. ULONG ProblemFlags;
  255. //
  256. // A file pointer to be used for reading
  257. //
  258. PFILE_OBJECT ReadFile;
  259. //
  260. // Pointer to the mouse class device object and callback routine
  261. // above us, Used as the first parameter and the MouseClassCallback().
  262. // routine itself.
  263. //
  264. CONNECT_DATA ConnectData;
  265. //
  266. // Remove Lock object to project IRP_MN_REMOVE_DEVICE
  267. //
  268. IO_REMOVE_LOCK RemoveLock;
  269. //
  270. // A fast mutex to prevent Create from trouncing close, as one starts the
  271. // read loop and the other shuts it down.
  272. //
  273. FAST_MUTEX CreateCloseMutex;
  274. //
  275. // An event to halt the deletion of a device until it is ready to go.
  276. //
  277. KEVENT StartEvent;
  278. //
  279. // A place to store a single data packet so that we might hand it to the
  280. // keyclass driver.
  281. //
  282. KEYBOARD_INPUT_DATA InputData;
  283. KEYBOARD_SCAN_STATE ScanState;
  284. //
  285. // The attributes of this keyboard port [DAN]
  286. //
  287. KEYBOARD_ATTRIBUTES Attributes;
  288. //
  289. // The extended ID attributes of this keyboard port
  290. //
  291. KEYBOARD_ID_EX IdEx;
  292. //
  293. // The current state of the indicator lights [DAN]
  294. //
  295. KEYBOARD_INDICATOR_PARAMETERS Indicators;
  296. //
  297. // The typematic parameters [DAN]
  298. //
  299. KEYBOARD_TYPEMATIC_PARAMETERS Typematic;
  300. //
  301. // A timer DPC to do the autorepeat.
  302. //
  303. KDPC AutoRepeatDPC;
  304. KTIMER AutoRepeatTimer;
  305. LARGE_INTEGER AutoRepeatDelay;
  306. LONG AutoRepeatRate;
  307. #if KEYBOARD_HW_CHATTERY_FIX
  308. // Added new DPC routine to schedule intermittent StartReads.
  309. KDPC InitiateStartReadDPC;
  310. KTIMER InitiateStartReadTimer;
  311. LARGE_INTEGER InitiateStartReadDelay;
  312. BOOLEAN InitiateStartReadUserNotified;
  313. #endif
  314. //
  315. // An attachment point for the global list o devices
  316. //
  317. LIST_ENTRY Link;
  318. //
  319. // WMI Information
  320. //
  321. WMILIB_CONTEXT WmiLibInfo;
  322. UsageMappingList *usageMapping;
  323. KSPIN_LOCK usageMappingSpinLock;
  324. } DEVICE_EXTENSION, * PDEVICE_EXTENSION;
  325. typedef struct _HID_EXTENSION {
  326. //
  327. // The preparsed data associated with this hid device.
  328. //
  329. PHIDP_PREPARSED_DATA Ppd;
  330. //
  331. // The capabilities of this hid device
  332. //
  333. HIDP_CAPS Caps;
  334. //
  335. // The maximum number of usages that can be returned from a single read
  336. // report.
  337. ULONG MaxUsages;
  338. //
  339. // A place to keep the modifier keys. Used by the parser to translate from
  340. // usages to i8042 codes.
  341. //
  342. HIDP_KEYBOARD_MODIFIER_STATE ModifierState;
  343. //
  344. // We need a place to put the current packet, being retreived or sent for
  345. // input, output, or feature.
  346. // In addition to a place to put the usages (keys pressed) returned from the
  347. // keyboard, and a place to put the new strokes from the keyboard.
  348. //
  349. // Global buffers mean, of course, we cannot have overlapping read
  350. // requests.
  351. //
  352. // Pointers into the buffer contained below.
  353. PCHAR InputBuffer;
  354. PUSAGE_AND_PAGE PreviousUsageList;
  355. PUSAGE_AND_PAGE CurrentUsageList;
  356. PUSAGE_AND_PAGE BreakUsageList;
  357. PUSAGE_AND_PAGE MakeUsageList;
  358. PUSAGE_AND_PAGE OldMakeUsageList;
  359. PUSAGE_AND_PAGE ScrapBreakUsageList;
  360. //
  361. // An MDL describing the below contained buffer.
  362. //
  363. PMDL InputMdl;
  364. //
  365. // A buffer to hold an Input packet, Output packet, the Maximum Usages
  366. // posible from a single hid packet, and
  367. //
  368. CHAR Buffer[];
  369. } HID_EXTENSION, * PHID_EXTENSION;
  370. //
  371. // Prototypes
  372. //
  373. VOID
  374. KbdHid_AutoRepeat (
  375. IN PKDPC DPC,
  376. IN PDEVICE_EXTENSION Data,
  377. IN PVOID SystemArgument1,
  378. IN PVOID SystemArgument2
  379. );
  380. #if KEYBOARD_HW_CHATTERY_FIX
  381. VOID
  382. KbdHid_InitiateStartRead (
  383. IN PKDPC DPC,
  384. IN PDEVICE_EXTENSION Data,
  385. IN PVOID SystemArgument1,
  386. IN PVOID SystemArgument2
  387. );
  388. #endif
  389. NTSTATUS
  390. KbdHid_StartRead (
  391. PDEVICE_EXTENSION Data
  392. );
  393. NTSTATUS
  394. DriverEntry(
  395. IN PDRIVER_OBJECT DriverObject,
  396. IN PUNICODE_STRING RegistryPath
  397. );
  398. NTSTATUS
  399. KbdHid_AddDevice (
  400. IN PDRIVER_OBJECT KbdHidDriver, // The kbd Driver object.
  401. IN PDEVICE_OBJECT PDO
  402. );
  403. NTSTATUS
  404. KbdHid_Close (
  405. IN PDEVICE_OBJECT DeviceObject,
  406. IN PIRP Irp
  407. );
  408. NTSTATUS
  409. KbdHid_Create (
  410. IN PDEVICE_OBJECT DeviceObject,
  411. IN PIRP Irp
  412. );
  413. NTSTATUS
  414. KbdHid_SetLedIndicators (
  415. PDEVICE_EXTENSION Data,
  416. PKEYBOARD_INDICATOR_PARAMETERS Parameters,
  417. PIRP Irp
  418. );
  419. NTSTATUS
  420. KbdHid_CallHidClass(
  421. IN PDEVICE_EXTENSION Data,
  422. IN ULONG Ioctl,
  423. PVOID InputBuffer,
  424. ULONG InputBufferLength,
  425. PVOID OutputBuffer,
  426. ULONG OutputBufferLength
  427. );
  428. BOOLEAN
  429. KbdHid_InsertCodesIntoQueue (
  430. PDEVICE_EXTENSION Data,
  431. PCHAR NewCodes,
  432. ULONG Length
  433. );
  434. VOID
  435. KbdHid_UpdateRegistryProblemFlags(
  436. IN PDEVICE_EXTENSION Data
  437. );
  438. VOID
  439. KbdHid_UpdateRegistryProblemFlagsCallback (
  440. IN PDEVICE_OBJECT DeviceObject,
  441. IN PIO_WORKITEM Item
  442. );
  443. VOID
  444. KbdHid_LogError(
  445. IN PDRIVER_OBJECT DriverObject,
  446. IN NTSTATUS ErrorCode,
  447. IN PWSTR ErrorInsertionString OPTIONAL
  448. );
  449. NTSTATUS
  450. KbdHid_StartDevice (
  451. IN PDEVICE_EXTENSION Data
  452. );
  453. NTSTATUS
  454. KbdHid_PnP (
  455. IN PDEVICE_OBJECT DeviceObject,
  456. IN PIRP Irp
  457. );
  458. NTSTATUS
  459. KbdHid_Power (
  460. IN PDEVICE_OBJECT DeviceObject,
  461. IN PIRP Irp
  462. );
  463. NTSTATUS
  464. KbdHid_PnPComplete (
  465. IN PDEVICE_OBJECT DeviceObject,
  466. IN PIRP Irp,
  467. IN PVOID Context
  468. );
  469. NTSTATUS
  470. KbdHid_GetRegistryParameters ();
  471. VOID
  472. KbdHid_Unload(
  473. IN PDRIVER_OBJECT Driver
  474. );
  475. NTSTATUS
  476. KbdHid_IOCTL (
  477. IN PDEVICE_OBJECT DeviceObject,
  478. IN PIRP Irp
  479. );
  480. NTSTATUS
  481. KbdHid_Flush (
  482. IN PDEVICE_OBJECT DeviceObject,
  483. IN PIRP Irp
  484. );
  485. NTSTATUS
  486. KbdHid_Power (
  487. IN PDEVICE_OBJECT DeviceObject,
  488. IN PIRP Irp
  489. );
  490. NTSTATUS
  491. KbdHid_PassThrough (
  492. IN PDEVICE_OBJECT DeviceObject,
  493. IN PIRP Irp
  494. );
  495. NTSTATUS
  496. KbdHid_SystemControl(
  497. IN PDEVICE_OBJECT DeviceObject,
  498. IN PIRP Irp
  499. );
  500. NTSTATUS
  501. KbdHid_SetWmiDataItem(
  502. IN PDEVICE_OBJECT DeviceObject,
  503. IN PIRP Irp,
  504. IN ULONG GuidIndex,
  505. IN ULONG InstanceIndex,
  506. IN ULONG DataItemId,
  507. IN ULONG BufferSize,
  508. IN PUCHAR Buffer
  509. );
  510. NTSTATUS
  511. KbdHid_SetWmiDataBlock(
  512. IN PDEVICE_OBJECT DeviceObject,
  513. IN PIRP Irp,
  514. IN ULONG GuidIndex,
  515. IN ULONG InstanceIndex,
  516. IN ULONG BufferSize,
  517. IN PUCHAR Buffer
  518. );
  519. NTSTATUS
  520. KbdHid_QueryWmiDataBlock(
  521. IN PDEVICE_OBJECT DeviceObject,
  522. IN PIRP Irp,
  523. IN ULONG GuidIndex,
  524. IN ULONG InstanceIndex,
  525. IN ULONG InstanceCount,
  526. IN OUT PULONG InstanceLengthArray,
  527. IN ULONG BufferAvail,
  528. OUT PUCHAR Buffer
  529. );
  530. NTSTATUS
  531. KbdHid_QueryWmiRegInfo(
  532. IN PDEVICE_OBJECT DeviceObject,
  533. OUT ULONG *RegFlags,
  534. OUT PUNICODE_STRING InstanceName,
  535. OUT PUNICODE_STRING *RegistryPath,
  536. OUT PUNICODE_STRING MofResourceName,
  537. OUT PDEVICE_OBJECT *Pdo
  538. );
  539. VOID LoadKeyboardUsageMappingList(PDEVICE_EXTENSION devExt);
  540. VOID FreeKeyboardUsageMappingList(PDEVICE_EXTENSION devExt);
  541. USHORT MapUsage(PDEVICE_EXTENSION devExt, USHORT kbdUsage);
  542. NTSTATUS OpenSubkey(OUT PHANDLE Handle, IN HANDLE BaseHandle, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess);
  543. ULONG LAtoX(PWCHAR wHexString);
  544. extern WMIGUIDREGINFO KbdHid_WmiGuidList[2];
  545. #endif // _KBDHID_H