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.

815 lines
22 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. query.c
  5. Abstract:
  6. This module contains the code for Translating HID report packets.
  7. Environment:
  8. Kernel & user mode
  9. Revision History:
  10. Nov-96 : created by Kenneth Ray
  11. --*/
  12. #include <wtypes.h>
  13. #include "hidsdi.h"
  14. #include "hidparse.h"
  15. NTSTATUS __stdcall
  16. HidP_UsageListDifference (
  17. IN PUSAGE PreviousUsageList,
  18. IN PUSAGE CurrentUsageList,
  19. OUT PUSAGE BreakUsageList,
  20. OUT PUSAGE MakeUsageList,
  21. IN ULONG UsageListLength
  22. )
  23. /*++
  24. Routine Description:
  25. Please see hidpi.h for description
  26. Notes:
  27. --*/
  28. {
  29. ULONG i,j;
  30. ULONG test;
  31. ULONG b; // an index into MakeUsageList
  32. ULONG m; // an index into BreakUsageList
  33. USHORT usage;
  34. BOOLEAN found;
  35. b = m = 0;
  36. //
  37. // This assumes that UsageListLength will be a small number.
  38. // No keyboard today can generate more than 14 keys in one packet, and
  39. // there is no anticipation for other devices with greater than 14 usages
  40. // at once. For this reason the straight forward naive approach follows...
  41. //
  42. // These lists are not sorted.
  43. //
  44. //
  45. // Find the Old usages.
  46. //
  47. for (i=0; i<UsageListLength; i++) {
  48. usage = PreviousUsageList[i];
  49. if (0 == usage) {
  50. break; // Zeros Only at the end.
  51. }
  52. found = FALSE;
  53. for (j=0; j<UsageListLength; j++) {
  54. test = CurrentUsageList [j];
  55. if (0 == test) {
  56. break; // Zeros only at the end.
  57. }
  58. if (test == usage) {
  59. found = TRUE;
  60. break;
  61. }
  62. }
  63. if (!found) {
  64. BreakUsageList [b++] = usage;
  65. }
  66. }
  67. //
  68. // Find the New usages.
  69. //
  70. for (i=0; i<UsageListLength; i++) {
  71. usage = CurrentUsageList[i];
  72. if (0 == usage) {
  73. break; // Zeros Only at the end.
  74. }
  75. found = FALSE;
  76. for (j=0; j<UsageListLength; j++) {
  77. test = PreviousUsageList [j];
  78. if (0 == test) {
  79. break; // Zeros only at the end.
  80. }
  81. if (test == usage) {
  82. found = TRUE;
  83. break;
  84. }
  85. }
  86. if (!found) {
  87. MakeUsageList [m++] = usage;
  88. }
  89. }
  90. while (b < UsageListLength) {
  91. BreakUsageList [b++] = 0;
  92. }
  93. while (m < UsageListLength) {
  94. MakeUsageList [m++] = 0;
  95. }
  96. return HIDP_STATUS_SUCCESS;
  97. }
  98. NTSTATUS __stdcall
  99. HidP_UsageAndPageListDifference (
  100. IN PUSAGE_AND_PAGE PreviousUsageList,
  101. IN PUSAGE_AND_PAGE CurrentUsageList,
  102. OUT PUSAGE_AND_PAGE BreakUsageList,
  103. OUT PUSAGE_AND_PAGE MakeUsageList,
  104. IN ULONG UsageListLength
  105. )
  106. /*++
  107. Routine Description:
  108. Please see hidpi.h for description
  109. Notes:
  110. --*/
  111. {
  112. ULONG i,j;
  113. ULONG b; // an index into MakeUsageList
  114. ULONG m; // an index into BreakUsageList
  115. BOOLEAN found;
  116. USAGE_AND_PAGE usage;
  117. USAGE_AND_PAGE test;
  118. USAGE_AND_PAGE zero = {0,0};
  119. b = m = 0;
  120. //
  121. // This assumes that UsageListLength will be a small number.
  122. // No keyboard today can generate more than 14 keys in one packet, and
  123. // there is no anticipation for other devices with greater than 14 usages
  124. // at once. For this reason the straight forward naive approach follows...
  125. //
  126. // These lists are not sorted.
  127. //
  128. //
  129. // Find the Old usages.
  130. //
  131. for (i=0; i<UsageListLength; i++) {
  132. usage = PreviousUsageList[i];
  133. if (HidP_IsSameUsageAndPage (zero, usage)) {
  134. break; // Zeros Only at the end.
  135. }
  136. found = FALSE;
  137. for (j=0; j<UsageListLength; j++) {
  138. test = CurrentUsageList [j];
  139. if (HidP_IsSameUsageAndPage (zero, test)) {
  140. break; // Zeros only at the end.
  141. }
  142. if (HidP_IsSameUsageAndPage (test, usage)) {
  143. found = TRUE;
  144. break;
  145. }
  146. }
  147. if (!found) {
  148. BreakUsageList [b++] = usage;
  149. }
  150. }
  151. //
  152. // Find the New usages.
  153. //
  154. for (i=0; i<UsageListLength; i++) {
  155. usage = CurrentUsageList[i];
  156. if (HidP_IsSameUsageAndPage (zero, usage)) {
  157. break; // Zeros Only at the end.
  158. }
  159. found = FALSE;
  160. for (j=0; j<UsageListLength; j++) {
  161. test = PreviousUsageList [j];
  162. if (HidP_IsSameUsageAndPage (zero, test)) {
  163. break; // Zeros only at the end.
  164. }
  165. if (HidP_IsSameUsageAndPage (test, usage)) {
  166. found = TRUE;
  167. break;
  168. }
  169. }
  170. if (!found) {
  171. MakeUsageList [m++] = usage;
  172. }
  173. }
  174. while (b < UsageListLength) {
  175. BreakUsageList [b++] = zero;
  176. }
  177. while (m < UsageListLength) {
  178. MakeUsageList [m++] = zero;
  179. }
  180. return HIDP_STATUS_SUCCESS;
  181. }
  182. #define KPAD(_X_) 0x ## _X_ ## F0
  183. #define SHFT(_X_) 0x ## _X_ ## F1
  184. #define VEND(_X_) 0x ## _X_ ## F2
  185. #define PTSC(_X_) 0x ## _X_ ## F3
  186. #define NONE 0xFF
  187. //
  188. // A table to convert a Hid Keyboard usage into a scan code.
  189. // The scan codes from F0 ~ FF are special, they are used to indicate that
  190. // a secondary translation is required.
  191. // This secondary translation is done by way of the secondary translation
  192. // function found in the ScanCodeSubTable structure array below.
  193. //
  194. ULONG HidP_KeyboardToScanCodeTable [0x100] = {
  195. //
  196. // This is a straight lookup table
  197. //
  198. // + 00 + 01 + 02 + 03 + 04 + 05 + 06 + 07
  199. // + 08 + 09 + 0A + 0B + 0C + 0D + 0E + OF
  200. /*0x00*/ NONE, NONE, NONE, NONE, 0x1E, 0x30, 0x2E, 0x20,
  201. /*0x08*/ 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26,
  202. /*0x10*/ 0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1F, 0x14,
  203. /*0x18*/ 0x16, 0x2F, 0x11, 0x2D, 0x15, 0x2C, 0x02, 0x03,
  204. /*0x20*/ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
  205. /*0x28*/ 0x1C, 0x01, 0x0E, 0x0F, 0x39, 0x0C, 0x0D, 0x1A,
  206. /*0x30*/ 0x1B, 0x2B, 0x2B, 0x27, 0x28, 0x29, 0x33, 0x34,
  207. /*0x38*/ 0x35, SHFT(8), 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40,
  208. /*0x40*/ 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, PTSC(0),SHFT(9),
  209. /*0x48*/ 0x451DE1,KPAD(0), KPAD(1), KPAD(2), KPAD(3), KPAD(4), KPAD(5),KPAD(6),
  210. /*0x50*/ KPAD(7), KPAD(8), KPAD(9), SHFT(A), 0x35E0, 0x37, 0x4A, 0x4E,
  211. /*0x58*/ 0x1CE0, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47,
  212. /*0x60*/ 0x48, 0x49, 0x52, 0x53, 0x56, 0x5DE0, 0x5EE0, 0x59,
  213. /*0x68*/ 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
  214. /*0x70*/ 0x6C, 0x6D, 0x6E, 0x76, NONE, NONE, NONE, NONE,
  215. /*0x78*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  216. /*0x80*/ NONE, NONE, NONE, NONE, NONE, 0x7E, NONE, 0x73,
  217. /*0x88*/ 0x70, 0x7D, 0x79, 0x7B, 0x5C, NONE, NONE, NONE,
  218. /*0x90*/ VEND(0), VEND(1), 0x78, 0x77, 0x76, NONE, NONE, NONE,
  219. /*0x98*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  220. /*0xA0*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  221. /*0xA8*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  222. /*0xB0*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  223. /*0xB8*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  224. /*0xC0*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  225. /*0xC8*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  226. /*0xD0*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  227. /*0xD8*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  228. /*0xE0*/ SHFT(0), SHFT(1), SHFT(2), SHFT(3), SHFT(4), SHFT(5), SHFT(6),SHFT(7),
  229. /*0xE8*/ NONE, 0x5EE0, 0x5FE0, 0x63E0, NONE, NONE, NONE, NONE,
  230. /*KPAD*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  231. /*0xF8*/ NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
  232. };
  233. ULONG HidP_XlateKbdPadCodesSubTable[] = {
  234. /* + 00 + 01 + 02 + 03 + 04 + 05 + 06 + 07 */
  235. /* + 08 + 09 + 0A + 0B + 0C + 0D + 0E + OF */
  236. /*0x48*/ 0x52E0, 0x47E0, 0x49E0, 0x53E0, 0x4FE0, 0x51E0, 0x4DE0,
  237. /*0x50*/ 0x4BE0, 0x50E0, 0x48E0
  238. };
  239. ULONG HidP_XlateModifierCodesSubTable[] = {
  240. //
  241. // NOTE These modifier codes in this table are in a VERY SPECIAL order.
  242. // that is: they are in the order of appearence in the
  243. // _HIDP_KEYBOARD_SHIFT_STATE union.
  244. //
  245. // + 00 + 01 + 02 + 03 + 04 + 05 + 06 + 07
  246. // + 08 + 09 + 0A + 0B + 0C + 0D + 0E + OF
  247. // LCtrl LShft LAlt LGUI RCtrl RShft RAlt RGUI
  248. /*0xE0*/ 0x1D, 0x2A, 0x38, 0x5BE0, 0x1DE0, 0x36, 0x38E0, 0x5CE0,
  249. /*0x39 CAPS_LOCK*/ 0x3A,
  250. /*0x47 SCROLL_LOCK*/ 0x46,
  251. /*0x53 NUM_LOCK*/ 0x45
  252. // This table is set up so that indices into this table greater than 7
  253. // are sticky. HidP_ModifierCode uses this as an optimization for
  254. // updating the Modifier state table.
  255. //
  256. };
  257. ULONG HidP_BreakCodesAsMakeCodesTable[] = {
  258. //
  259. // Vendor scan codes that have the high bit set and are technically
  260. // break codes, but are sent as make codes. No break code will be sent.
  261. //
  262. // + 00 + 01 + 02 + 03 + 04 + 05 + 06 + 07
  263. // + 08 + 09 + 0A + 0B + 0C + 0D + 0E + OF
  264. /*0x90*/ 0xF2, 0xF1
  265. //
  266. };
  267. ULONG HidP_XlatePrtScrCodesSubTable[] = {
  268. /* + 00 + 01 + 02 + 03 + 04 + 05 + 06 + 07 */
  269. /* + 08 + 09 + 0A + 0B + 0C + 0D + 0E + OF */
  270. /*0x40*/ 0x37E0
  271. };
  272. HIDP_SCANCODE_SUBTABLE HidP_KeyboardSubTables[0x10] = {
  273. /* F0 */ {HidP_KeyboardKeypadCode, HidP_XlateKbdPadCodesSubTable},
  274. /* F1 */ {HidP_ModifierCode, HidP_XlateModifierCodesSubTable},
  275. /* F2 */ {HidP_VendorBreakCodesAsMakeCodes, HidP_BreakCodesAsMakeCodesTable},
  276. /* F3 */ {HidP_PrintScreenCode, HidP_XlatePrtScrCodesSubTable},
  277. /* F4 */ {NULL, NULL},
  278. /* F5 */ {NULL, NULL},
  279. /* F6 */ {NULL, NULL},
  280. /* F7 */ {NULL, NULL},
  281. /* F8 */ {NULL, NULL},
  282. /* F9 */ {NULL, NULL},
  283. /* FA */ {NULL, NULL},
  284. /* FB */ {NULL, NULL},
  285. /* FC */ {NULL, NULL},
  286. /* FD */ {NULL, NULL},
  287. /* FE */ {NULL, NULL},
  288. /* FF */ {NULL, NULL}
  289. };
  290. #define HIDP_CONSUMER_TABLE_SIZE 16
  291. ULONG HidP_ConsumerToScanCodeTable [HIDP_CONSUMER_TABLE_SIZE] = {
  292. //
  293. // This is an association table
  294. //
  295. // Usage -> Scancode
  296. //
  297. 0x0224, 0x6AE0, // WWW Back
  298. 0x0225, 0x69E0, // WWW Forward
  299. 0x0226, 0x68E0, // WWW Stop
  300. 0x0227, 0x67E0, // WWW Refresh
  301. 0x0221, 0x65E0, // WWW Search
  302. 0x022A, 0x66E0, // WWW Favorites
  303. 0x0223, 0x32E0, // WWW Home
  304. 0x018A, 0x6CE0 // Mail
  305. };
  306. HIDP_SCANCODE_SUBTABLE HidP_ConsumerSubTables [1] = {
  307. {NULL, NULL}
  308. };
  309. //
  310. //BOOLEAN
  311. //HidP_KbdPutKey (
  312. // ULONG Code,
  313. // HIDP_KEYBOARD_DIRECTION KeyAction,
  314. // PHIDP_INSERT_SCANCODES Insert,
  315. // PVOID Context)
  316. //
  317. // Add the scan codes to the callers buffer using the callback routine
  318. // Insert.
  319. //
  320. // If we find a zero in the list then we are done with no error
  321. // If we find a invalid code (anything that starts with an F, then
  322. // we have a problem. No where in current published i8042 specs is there
  323. // a scan code of F0 ~ FF.
  324. //
  325. // If we are breaking then we need to set the high byte.
  326. //
  327. BOOLEAN
  328. HidP_KbdPutKey (
  329. ULONG PassedCode,
  330. HIDP_KEYBOARD_DIRECTION KeyAction,
  331. PHIDP_INSERT_SCANCODES Insert,
  332. PVOID Context)
  333. {
  334. PUCHAR pCode = (PCHAR)&PassedCode;
  335. ULONG i;
  336. for (i = 0; i < sizeof(ULONG); i++) {
  337. //
  338. // Some swell keyboard vendors have added Fx charaters to their
  339. // keyboards which we now have to emulate.
  340. //
  341. // if ((0xF0 & *pCode) == 0xF0) {
  342. // return FALSE;
  343. // }
  344. if (0 == pCode[i]) {
  345. break;
  346. }
  347. if (HidP_Keyboard_Break == KeyAction) {
  348. pCode[i] |= 0x80;
  349. }
  350. }
  351. if (i) {
  352. (*Insert)(Context, pCode, i);
  353. }
  354. return TRUE;
  355. }
  356. NTSTATUS
  357. HidP_TranslateUsagesToI8042ScanCodes (
  358. PUSAGE ChangedUsageList, // Those usages that changed
  359. ULONG UsageListLength,
  360. HIDP_KEYBOARD_DIRECTION KeyAction,
  361. PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
  362. PHIDP_INSERT_SCANCODES InsertCodesProcedure,
  363. PVOID InsertCodesContext
  364. )
  365. /*++
  366. Routine Description:
  367. Please see hidpi.h for description
  368. Notes:
  369. --*/
  370. {
  371. PUSAGE usage;
  372. ULONG i;
  373. NTSTATUS status = HIDP_STATUS_SUCCESS;
  374. for (i = 0, usage = ChangedUsageList;
  375. i < UsageListLength;
  376. i++, usage++) {
  377. if (0 == *usage) {
  378. // No more interesting usages. Zero terminated if not max length.
  379. break;
  380. }
  381. status = HidP_TranslateUsage (*usage,
  382. KeyAction,
  383. ModifierState,
  384. HidP_StraightLookup,
  385. HidP_KeyboardToScanCodeTable,
  386. HidP_KeyboardSubTables,
  387. InsertCodesProcedure,
  388. InsertCodesContext);
  389. if (HIDP_STATUS_SUCCESS != status) {
  390. break;
  391. }
  392. }
  393. return status;
  394. }
  395. NTSTATUS __stdcall
  396. HidP_TranslateUsageAndPagesToI8042ScanCodes (
  397. PUSAGE_AND_PAGE ChangedUsageList, // Those usages that changed
  398. ULONG UsageListLength,
  399. HIDP_KEYBOARD_DIRECTION KeyAction,
  400. PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
  401. PHIDP_INSERT_SCANCODES InsertCodesProcedure,
  402. PVOID InsertCodesContext
  403. )
  404. /*++
  405. Routine Description:
  406. Please see hidpi.h for description
  407. Notes:
  408. --*/
  409. {
  410. PUSAGE_AND_PAGE usage;
  411. ULONG i;
  412. NTSTATUS status = HIDP_STATUS_SUCCESS;
  413. for (i = 0, usage = ChangedUsageList;
  414. i < UsageListLength;
  415. i++, usage++) {
  416. if (0 == usage->Usage) {
  417. break;
  418. }
  419. switch (usage->UsagePage) {
  420. case HID_USAGE_PAGE_KEYBOARD:
  421. status = HidP_TranslateUsage (usage->Usage,
  422. KeyAction,
  423. ModifierState,
  424. HidP_StraightLookup,
  425. HidP_KeyboardToScanCodeTable,
  426. HidP_KeyboardSubTables,
  427. InsertCodesProcedure,
  428. InsertCodesContext);
  429. break;
  430. case HID_USAGE_PAGE_CONSUMER:
  431. status = HidP_TranslateUsage (usage->Usage,
  432. KeyAction,
  433. ModifierState,
  434. HidP_AssociativeLookup,
  435. HidP_ConsumerToScanCodeTable,
  436. HidP_ConsumerSubTables,
  437. InsertCodesProcedure,
  438. InsertCodesContext);
  439. break;
  440. default:
  441. status = HIDP_STATUS_I8042_TRANS_UNKNOWN;
  442. }
  443. if (HIDP_STATUS_SUCCESS != status) {
  444. break;
  445. }
  446. }
  447. return status;
  448. }
  449. NTSTATUS __stdcall
  450. HidP_TranslateUsage (
  451. USAGE Usage,
  452. HIDP_KEYBOARD_DIRECTION KeyAction,
  453. PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
  454. PHIDP_LOOKUP_TABLE_PROC LookupTableProc,
  455. PULONG TranslationTable,
  456. PHIDP_SCANCODE_SUBTABLE SubTranslationTable,
  457. PHIDP_INSERT_SCANCODES InsertCodesProcedure,
  458. PVOID InsertCodesContext
  459. )
  460. /*++
  461. Routine Description:
  462. Notes:
  463. --*/
  464. {
  465. ULONG scancode;
  466. PHIDP_SCANCODE_SUBTABLE table;
  467. NTSTATUS status;
  468. scancode = (* LookupTableProc) (TranslationTable, Usage);
  469. if (0 == scancode) {
  470. return HIDP_STATUS_I8042_TRANS_UNKNOWN;
  471. }
  472. if ((ModifierState->LeftControl || ModifierState->RightControl) &&
  473. (scancode == 0x451DE1)) {
  474. //
  475. // The scancode of the pause key completely changes
  476. // if the control key is down.
  477. //
  478. scancode = 0x46E0;
  479. }
  480. if ((0xF0 & scancode) == 0xF0) {
  481. // Use a secondary table
  482. table = &SubTranslationTable [scancode & 0xF];
  483. if (table->ScanCodeFcn) {
  484. if ((*table->ScanCodeFcn) (table->Table,
  485. (UCHAR) ((scancode & 0xFF00) >> 8),
  486. InsertCodesProcedure,
  487. InsertCodesContext,
  488. KeyAction,
  489. ModifierState)) {
  490. ;
  491. } else {
  492. return HIDP_STATUS_I8042_TRANS_UNKNOWN;
  493. }
  494. } else {
  495. return HIDP_STATUS_I8042_TRANS_UNKNOWN;
  496. }
  497. } else {
  498. HidP_KbdPutKey (scancode,
  499. KeyAction,
  500. InsertCodesProcedure,
  501. InsertCodesContext);
  502. }
  503. return HIDP_STATUS_SUCCESS;
  504. }
  505. BOOLEAN
  506. HidP_KeyboardKeypadCode (
  507. IN ULONG * Table,
  508. IN UCHAR Index,
  509. IN PHIDP_INSERT_SCANCODES Insert,
  510. IN PVOID Context,
  511. IN HIDP_KEYBOARD_DIRECTION KeyAction,
  512. IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState
  513. )
  514. /*++
  515. Routine Description:
  516. Notes:
  517. --*/
  518. {
  519. //
  520. // The num lock key (if set then we add even more scan codes for these
  521. // keys)
  522. //
  523. ULONG DarrylRis_Magic_Code = 0x2AE0;
  524. BOOLEAN status = TRUE;
  525. if ((ModifierState->NumLock) && (HidP_Keyboard_Make == KeyAction) ) {
  526. status = HidP_KbdPutKey (DarrylRis_Magic_Code, KeyAction, Insert, Context);
  527. }
  528. if (!status) {
  529. return status;
  530. }
  531. status = HidP_KbdPutKey (Table[Index], KeyAction, Insert, Context);
  532. if (!status) {
  533. return status;
  534. }
  535. if ((ModifierState->NumLock) && (HidP_Keyboard_Break == KeyAction) ) {
  536. status = HidP_KbdPutKey (DarrylRis_Magic_Code, KeyAction, Insert, Context);
  537. }
  538. return status;
  539. }
  540. BOOLEAN
  541. HidP_ModifierCode (
  542. IN ULONG * Table,
  543. IN UCHAR Index,
  544. IN PHIDP_INSERT_SCANCODES Insert,
  545. IN PVOID Context,
  546. IN HIDP_KEYBOARD_DIRECTION KeyAction,
  547. IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState
  548. )
  549. /*++
  550. Routine Description:
  551. Notes:
  552. --*/
  553. {
  554. if (Index >> 3) {
  555. //
  556. // Indices greater than 8 are sticky.
  557. //
  558. switch (KeyAction) {
  559. case HidP_Keyboard_Make:
  560. if (!(ModifierState->ul & (1 << (Index+16)))) {
  561. //
  562. // Mark this as the first make.
  563. //
  564. ModifierState->ul |= (1 << (Index+16));
  565. //
  566. // Only toggle the state when this is the first make sent.
  567. //
  568. ModifierState->ul ^= (1 << Index);
  569. }
  570. break;
  571. case HidP_Keyboard_Break:
  572. //
  573. // Clear the fist make field.
  574. //
  575. ModifierState->ul &= ~(1 << (Index+16));
  576. break;
  577. }
  578. } else {
  579. switch (KeyAction) {
  580. case HidP_Keyboard_Make:
  581. // The key is now on
  582. ModifierState->ul |= (1 << Index);
  583. break;
  584. case HidP_Keyboard_Break:
  585. // The key is now off
  586. ModifierState->ul &= ~(1 << Index);
  587. break;
  588. }
  589. }
  590. return HidP_KbdPutKey (Table[Index], KeyAction, Insert, Context);
  591. }
  592. BOOLEAN
  593. HidP_VendorBreakCodesAsMakeCodes (
  594. IN ULONG * Table,
  595. IN UCHAR Index,
  596. IN PHIDP_INSERT_SCANCODES Insert,
  597. IN PVOID Context,
  598. IN HIDP_KEYBOARD_DIRECTION KeyAction,
  599. IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState
  600. )
  601. {
  602. //
  603. // Vendor scan codes that have the high bit set and are technically
  604. // break codes, but are sent as make codes. No break code will be sent.
  605. //
  606. UNREFERENCED_PARAMETER (ModifierState);
  607. switch (KeyAction) {
  608. case HidP_Keyboard_Make:
  609. return HidP_KbdPutKey (Table[Index], KeyAction, Insert, Context);
  610. case HidP_Keyboard_Break:
  611. // do Nothing
  612. return TRUE;
  613. default:
  614. return FALSE;
  615. }
  616. }
  617. BOOLEAN
  618. HidP_PrintScreenCode (
  619. IN ULONG * Table,
  620. IN UCHAR Index,
  621. IN PHIDP_INSERT_SCANCODES Insert,
  622. IN PVOID Context,
  623. IN HIDP_KEYBOARD_DIRECTION KeyAction,
  624. IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState
  625. )
  626. /*++
  627. Routine Description:
  628. Notes:
  629. --*/
  630. {
  631. BOOLEAN status = TRUE;
  632. //
  633. // Special casing for the printscreen key.
  634. //
  635. if (ModifierState->LeftAlt || ModifierState->RightAlt) {
  636. //
  637. // Alt key down.
  638. //
  639. status = HidP_KbdPutKey (0x54, KeyAction, Insert, Context);
  640. } else if (ModifierState->LeftShift || ModifierState->RightShift ||
  641. ModifierState->LeftControl || ModifierState->RightControl) {
  642. //
  643. // Shift or ctrl keys down.
  644. //
  645. status = HidP_KbdPutKey (Table[Index], KeyAction, Insert, Context);
  646. } else {
  647. //
  648. // No modifier keys down. Add some extra "padding" to the make and break.
  649. //
  650. ULONG DarrylRis_Magic_Code = 0x2AE0;
  651. if (HidP_Keyboard_Make == KeyAction) {
  652. status = HidP_KbdPutKey (DarrylRis_Magic_Code, KeyAction, Insert, Context);
  653. }
  654. if (!status) {
  655. return status;
  656. }
  657. status = HidP_KbdPutKey (Table[Index], KeyAction, Insert, Context);
  658. if (!status) {
  659. return status;
  660. }
  661. if (HidP_Keyboard_Break == KeyAction) {
  662. status = HidP_KbdPutKey (DarrylRis_Magic_Code, KeyAction, Insert, Context);
  663. }
  664. }
  665. return status;
  666. }
  667. ULONG
  668. HidP_StraightLookup (
  669. IN PULONG Table,
  670. IN ULONG Usage
  671. )
  672. {
  673. if (Usage > 0xFF) {
  674. // We have
  675. // have no translation for this usage.
  676. return 0;
  677. }
  678. return Table[Usage];
  679. }
  680. ULONG
  681. HidP_AssociativeLookup (
  682. IN PULONG Table,
  683. IN ULONG Usage
  684. )
  685. {
  686. ULONG i;
  687. for (i = 0; i < (HIDP_CONSUMER_TABLE_SIZE - 1); i+=2) {
  688. if (Usage == Table[i]) {
  689. return Table[i+1];
  690. }
  691. }
  692. return 0;
  693. }