usrinput.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. usrinput.c
  5. Abstract:
  6. This module implements the User Input library.
  7. Author:
  8. Evan Green 16-Feb-2013
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "inputp.h"
  16. #include <minoca/lib/termlib.h>
  17. //
  18. // --------------------------------------------------------------------- Macros
  19. //
  20. //
  21. // This macros defines the set of keys that do not repeat when held.
  22. //
  23. #define USER_INPUT_IS_NO_REPEAT_KEY(_Key) \
  24. (((_Key) == KeyboardKeyPrintScreen) || \
  25. ((_Key) == KeyboardKeySysRq) || \
  26. ((_Key) == KeyboardKeyScrollLock) || \
  27. ((_Key) == KeyboardKeyBreak) || \
  28. ((_Key) == KeyboardKeyNumLock) || \
  29. ((_Key) == KeyboardKeyCapsLock) || \
  30. ((_Key) == KeyboardKeyLeftShift) || \
  31. ((_Key) == KeyboardKeyRightShift) || \
  32. ((_Key) == KeyboardKeyLeftAlt) || \
  33. ((_Key) == KeyboardKeyRightAlt) || \
  34. ((_Key) == KeyboardKeyApplication) || \
  35. ((_Key) == KeyboardKeyEscape))
  36. //
  37. // This macro defines the set of keys that should be repeated when held.
  38. //
  39. #define USER_INPUT_IS_REPEAT_KEY(_Key) !USER_INPUT_IS_NO_REPEAT_KEY(_Key)
  40. //
  41. // ---------------------------------------------------------------- Definitions
  42. //
  43. #define USER_INPUT_ALLOCATION_TAG 0x6E497355 // 'nIsU'
  44. //
  45. // Define how long to wait for the terminal buffer to clear up before throwing
  46. // the input away.
  47. //
  48. #define USER_INPUT_TERMINAL_WAIT_TIME 50
  49. //
  50. // Define the size of the terminal input buffer size.
  51. //
  52. #define TERMINAL_INPUT_BUFFER_SIZE 1024
  53. //
  54. // Define terminal keyboard flags.
  55. //
  56. #define TERMINAL_KEYBOARD_SHIFT 0x00000001
  57. #define TERMINAL_KEYBOARD_CONTROL 0x00000002
  58. #define TERMINAL_KEYBOARD_CAPS_LOCK 0x00000004
  59. #define TERMINAL_KEYBOARD_ALT 0x00000008
  60. #define TERMINAL_KEYBOARD_NUM_LOCK 0x00000010
  61. #define TERMINAL_KEYBOARD_SCROLL_LOCK 0x00000020
  62. #define KEYBOARD_REPEAT_DELAY (500 * MICROSECONDS_PER_MILLISECOND)
  63. #define KEYBOARD_REPEAT_RATE (50 * MICROSECONDS_PER_MILLISECOND)
  64. //
  65. // User input debug flags.
  66. //
  67. #define USER_INPUT_DEBUG_REGISTER 0x00000001
  68. #define USER_INPUT_DEBUG_EVENT 0x00000002
  69. #define USER_INPUT_DEBUG_REPEAT_EVENT 0x00000004
  70. #define USER_INPUT_DEBUG_DISABLE_REPEAT 0x00000008
  71. //
  72. // ------------------------------------------------------ Data Type Definitions
  73. //
  74. /*++
  75. Structure Description:
  76. This structure describes a user input device.
  77. Members:
  78. ListEntry - Stores pointers to the next and previous user input devices.
  79. Type - Stores the device type.
  80. Identifier - Stores the unique identifier assigned to the device.
  81. EventCount - Stores the number of events this device has generated.
  82. Device - Stores a pointer to the OS device associated with this context.
  83. DeviceContext - Stores a pointer to the OS device's private context for the
  84. device.
  85. RepeatEvent - Stores a pointer to the event that is to be replayed when the
  86. repeat work item runs.
  87. RepeatTimer - Stores a pointer to the key repeat timer. For keyboards only.
  88. RepeatDpc - Stores a pointer to the key repeat DPC. For keyboards only.
  89. RepeatWorkItem - Stores a pointer to the key repeat work item. For
  90. keyboards only.
  91. KeyboardInterface - Stores the interface to a user keyboard device.
  92. --*/
  93. struct _USER_INPUT_DEVICE {
  94. LIST_ENTRY ListEntry;
  95. USER_INPUT_DEVICE_TYPE Type;
  96. ULONG Identifier;
  97. ULONG EventCount;
  98. PDEVICE Device;
  99. PVOID DeviceContext;
  100. PUSER_INPUT_EVENT RepeatEvent;
  101. PKTIMER RepeatTimer;
  102. PDPC RepeatDpc;
  103. PWORK_ITEM RepeatWorkItem;
  104. union {
  105. USER_INPUT_KEYBOARD_DEVICE_INTERFACE KeyboardInterface;
  106. } U;
  107. };
  108. //
  109. // ----------------------------------------------- Internal Function Prototypes
  110. //
  111. VOID
  112. InUnloadDriver (
  113. PVOID Driver
  114. );
  115. KSTATUS
  116. InpProcessInputEvent (
  117. PUSER_INPUT_EVENT Event
  118. );
  119. KSTATUS
  120. InpProcessInputEventForTerminal (
  121. PUSER_INPUT_EVENT Event
  122. );
  123. VOID
  124. InpRepeatInputEventDpcRoutine (
  125. PDPC Dpc
  126. );
  127. VOID
  128. InpRepeatInputEventWorker (
  129. PVOID Parameter
  130. );
  131. VOID
  132. InpUpdateLedStateForTerminal (
  133. VOID
  134. );
  135. //
  136. // -------------------------------------------------------------------- Globals
  137. //
  138. PDRIVER InDriver = NULL;
  139. //
  140. // Define the next ID for a new user input device.
  141. //
  142. volatile ULONG InNextDeviceId = 1;
  143. //
  144. // Define the next event ID.
  145. //
  146. volatile ULONG InNextEventId = 1;
  147. //
  148. // Store a pointer to the global input pipe.
  149. //
  150. PIO_HANDLE InUserInputPipe;
  151. //
  152. // Store a pointer to the master side of the local terminal.
  153. //
  154. PIO_HANDLE InLocalTerminal;
  155. //
  156. // Store the current terminal keyboard mask.
  157. //
  158. volatile ULONG InTerminalKeyboardMask = 0;
  159. //
  160. // Stores a bitfield of enabled user input debug flags. See USER_INPUT_DEBUG_*
  161. // for definitions.
  162. //
  163. ULONG InDebugFlags = 0x0;
  164. //
  165. // Define user input type strings for debugging.
  166. //
  167. PSTR InDeviceTypeStrings[UserInputDeviceTypeCount] = {
  168. "INVALID",
  169. "Keyboard"
  170. };
  171. PSTR InEventTypeStrings[UserInputEventCount] = {
  172. "INVALID",
  173. "key down",
  174. "key up"
  175. };
  176. //
  177. // Store a list of user input devices and a lock to protect the list.
  178. //
  179. PQUEUED_LOCK InDeviceListLock;
  180. LIST_ENTRY InDeviceListHead;
  181. //
  182. // ------------------------------------------------------------------ Functions
  183. //
  184. KSTATUS
  185. DriverEntry (
  186. PDRIVER Driver
  187. )
  188. /*++
  189. Routine Description:
  190. This routine is the entry point for the user input library. It performs
  191. library wide initialization.
  192. Arguments:
  193. Driver - Supplies a pointer to the driver object.
  194. Return Value:
  195. STATUS_SUCCESS on success.
  196. Failure code on error.
  197. --*/
  198. {
  199. DRIVER_FUNCTION_TABLE FunctionTable;
  200. FILE_PERMISSIONS Permissions;
  201. PIO_HANDLE ReadSide;
  202. KSTATUS Status;
  203. ASSERT((InDriver == NULL) && (InUserInputPipe == NULL));
  204. InDriver = Driver;
  205. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  206. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  207. FunctionTable.Unload = InUnloadDriver;
  208. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  209. if (!KSUCCESS(Status)) {
  210. goto DriverEntryEnd;
  211. }
  212. //
  213. // Allocate a queued lock to protect the list of devices.
  214. //
  215. INITIALIZE_LIST_HEAD(&InDeviceListHead);
  216. InDeviceListLock = KeCreateQueuedLock();
  217. if (InDeviceListLock == NULL) {
  218. Status = STATUS_INSUFFICIENT_RESOURCES;
  219. goto DriverEntryEnd;
  220. }
  221. //
  222. // Create the global input pipe.
  223. // TODO: This would probably make more sense as a local socket.
  224. //
  225. Permissions = FILE_PERMISSION_USER_READ | FILE_PERMISSION_GROUP_READ |
  226. FILE_PERMISSION_OTHER_READ;
  227. Status = IoCreatePipe(TRUE,
  228. NULL,
  229. USER_INPUT_PIPE_NAME,
  230. sizeof(USER_INPUT_PIPE_NAME),
  231. 0,
  232. Permissions,
  233. &ReadSide,
  234. &InUserInputPipe);
  235. if (!KSUCCESS(Status)) {
  236. goto DriverEntryEnd;
  237. }
  238. //
  239. // Close the read side of the pipe.
  240. //
  241. IoClose(ReadSide);
  242. //
  243. // Get the master side of the local terminal.
  244. //
  245. Status = IoOpenLocalTerminalMaster(&InLocalTerminal);
  246. if (!KSUCCESS(Status)) {
  247. goto DriverEntryEnd;
  248. }
  249. //
  250. // Start with number lock enabled.
  251. //
  252. InTerminalKeyboardMask = TERMINAL_KEYBOARD_NUM_LOCK;
  253. Status = STATUS_SUCCESS;
  254. DriverEntryEnd:
  255. return Status;
  256. }
  257. USER_INPUT_API
  258. HANDLE
  259. InRegisterInputDevice (
  260. PUSER_INPUT_DEVICE_DESCRIPTION Description
  261. )
  262. /*++
  263. Routine Description:
  264. This routine registers a new user input device.
  265. Arguments:
  266. Description - Supplies a pointer to the description of the user input
  267. device being registered.
  268. Return Value:
  269. Returns a handle to the user input device on success.
  270. INVALID_HANDLE on failure.
  271. --*/
  272. {
  273. PUSER_INPUT_DEVICE InputDevice;
  274. ULONG LedState;
  275. PUSER_INPUT_EVENT RepeatEvent;
  276. KSTATUS Status;
  277. InputDevice = INVALID_HANDLE;
  278. if (Description == NULL) {
  279. Status = STATUS_INVALID_PARAMETER;
  280. goto RegisterInputDeviceEnd;
  281. }
  282. if (Description->Type >= UserInputDeviceTypeCount) {
  283. Status = STATUS_INVALID_PARAMETER;
  284. goto RegisterInputDeviceEnd;
  285. }
  286. //
  287. // Check the interface version before proceeding.
  288. //
  289. if ((Description->Type == UserInputDeviceKeyboard) &&
  290. (Description->InterfaceVersion !=
  291. USER_INPUT_KEYBOARD_DEVICE_INTERFACE_VERSION)) {
  292. Status = STATUS_VERSION_MISMATCH;
  293. goto RegisterInputDeviceEnd;
  294. }
  295. //
  296. // Create the new input device.
  297. //
  298. InputDevice = MmAllocateNonPagedPool(sizeof(USER_INPUT_DEVICE),
  299. USER_INPUT_ALLOCATION_TAG);
  300. if (InputDevice == NULL) {
  301. Status = STATUS_INSUFFICIENT_RESOURCES;
  302. goto RegisterInputDeviceEnd;
  303. }
  304. RtlZeroMemory(InputDevice, sizeof(USER_INPUT_DEVICE));
  305. InputDevice->Type = Description->Type;
  306. InputDevice->Identifier = RtlAtomicAdd32(&InNextDeviceId, 1);
  307. InputDevice->Device = Description->Device;
  308. InputDevice->DeviceContext = Description->DeviceContext;
  309. //
  310. // Copy the keyboard interface and create the keyboard repeat input event,
  311. // timer, DPC, and work item.
  312. //
  313. if (InputDevice->Type == UserInputDeviceKeyboard) {
  314. RtlCopyMemory(&(InputDevice->U.KeyboardInterface),
  315. &(Description->U.KeyboardInterface),
  316. sizeof(USER_INPUT_KEYBOARD_DEVICE_INTERFACE));
  317. RepeatEvent = MmAllocateNonPagedPool(sizeof(USER_INPUT_EVENT),
  318. USER_INPUT_ALLOCATION_TAG);
  319. if (RepeatEvent == NULL) {
  320. Status = STATUS_INSUFFICIENT_RESOURCES;
  321. goto RegisterInputDeviceEnd;
  322. }
  323. RepeatEvent->U.Key = KeyboardKeyInvalid;
  324. InputDevice->RepeatEvent = RepeatEvent;
  325. InputDevice->RepeatTimer = KeCreateTimer(USER_INPUT_ALLOCATION_TAG);
  326. if (InputDevice->RepeatTimer == NULL) {
  327. Status = STATUS_INSUFFICIENT_RESOURCES;
  328. goto RegisterInputDeviceEnd;
  329. }
  330. InputDevice->RepeatDpc = KeCreateDpc(InpRepeatInputEventDpcRoutine,
  331. InputDevice);
  332. if (InputDevice->RepeatDpc == NULL) {
  333. Status = STATUS_INSUFFICIENT_RESOURCES;
  334. goto RegisterInputDeviceEnd;
  335. }
  336. InputDevice->RepeatWorkItem = KeCreateWorkItem(
  337. NULL,
  338. WorkPriorityNormal,
  339. InpRepeatInputEventWorker,
  340. InputDevice,
  341. USER_INPUT_ALLOCATION_TAG);
  342. if (InputDevice->RepeatWorkItem == NULL) {
  343. Status = STATUS_INSUFFICIENT_RESOURCES;
  344. goto RegisterInputDeviceEnd;
  345. }
  346. }
  347. //
  348. // Insert the device into the list lock. While the lock is held, set the
  349. // current LED state for any newly arrived keyboard. The terminal updates
  350. // the LED state underneath the list lock to reach all devices, so it must
  351. // be done under the lock here as well.
  352. //
  353. KeAcquireQueuedLock(InDeviceListLock);
  354. if ((InputDevice->Type == UserInputDeviceKeyboard) &&
  355. (InputDevice->U.KeyboardInterface.SetLedState != NULL)) {
  356. LedState = 0;
  357. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_NUM_LOCK) != 0) {
  358. LedState |= USER_INPUT_KEYBOARD_LED_NUM_LOCK;
  359. }
  360. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_CAPS_LOCK) != 0) {
  361. LedState |= USER_INPUT_KEYBOARD_LED_CAPS_LOCK;
  362. }
  363. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_SCROLL_LOCK) != 0) {
  364. LedState |= USER_INPUT_KEYBOARD_LED_SCROLL_LOCK;
  365. }
  366. InputDevice->U.KeyboardInterface.SetLedState(InputDevice->Device,
  367. InputDevice->DeviceContext,
  368. LedState);
  369. }
  370. INSERT_BEFORE(&(InputDevice->ListEntry), &InDeviceListHead);
  371. KeReleaseQueuedLock(InDeviceListLock);
  372. if ((InDebugFlags & USER_INPUT_DEBUG_REGISTER) != 0) {
  373. RtlDebugPrint("USIN: Registered %s Device (0x%08x), identifier: "
  374. "0x%08x.\n",
  375. InDeviceTypeStrings[InputDevice->Type],
  376. InputDevice,
  377. InputDevice->Identifier);
  378. }
  379. Status = STATUS_SUCCESS;
  380. RegisterInputDeviceEnd:
  381. if (!KSUCCESS(Status)) {
  382. if (InputDevice != INVALID_HANDLE) {
  383. if (InputDevice != NULL) {
  384. InDestroyInputDevice(InputDevice);
  385. }
  386. InputDevice = INVALID_HANDLE;
  387. }
  388. }
  389. return (HANDLE)InputDevice;
  390. }
  391. USER_INPUT_API
  392. VOID
  393. InDestroyInputDevice (
  394. HANDLE Handle
  395. )
  396. /*++
  397. Routine Description:
  398. This routine tears down state associated with a user input device created
  399. when the device was registered.
  400. Arguments:
  401. Handle - Supplies the handle to the registered device. When this function
  402. returns, the handle will be invalid.
  403. Return Value:
  404. None.
  405. --*/
  406. {
  407. PUSER_INPUT_DEVICE InputDevice;
  408. InputDevice = (PUSER_INPUT_DEVICE)Handle;
  409. KeAcquireQueuedLock(InDeviceListLock);
  410. LIST_REMOVE(&(InputDevice->ListEntry));
  411. KeReleaseQueuedLock(InDeviceListLock);
  412. if (InputDevice->RepeatEvent != NULL) {
  413. MmFreeNonPagedPool(InputDevice->RepeatEvent);
  414. }
  415. if (InputDevice->RepeatTimer != NULL) {
  416. KeDestroyTimer(InputDevice->RepeatTimer);
  417. }
  418. if (InputDevice->RepeatDpc != NULL) {
  419. KeDestroyDpc(InputDevice->RepeatDpc);
  420. }
  421. if (InputDevice->RepeatWorkItem != NULL) {
  422. KeDestroyWorkItem(InputDevice->RepeatWorkItem);
  423. }
  424. if ((InDebugFlags & USER_INPUT_DEBUG_REGISTER) != 0) {
  425. RtlDebugPrint("USIN: Destroyed %s Device (0x%08x), identifier: "
  426. "0x%08x.\n",
  427. InDeviceTypeStrings[InputDevice->Type],
  428. InputDevice,
  429. InputDevice->Identifier);
  430. }
  431. MmFreeNonPagedPool(InputDevice);
  432. return;
  433. }
  434. USER_INPUT_API
  435. KSTATUS
  436. InReportInputEvent (
  437. HANDLE Handle,
  438. PUSER_INPUT_EVENT Event
  439. )
  440. /*++
  441. Routine Description:
  442. This routine processes a new input event from the given device. This
  443. routine must be called at low level. The caller is expected to synchronize
  444. calls to report input for a device.
  445. Arguments:
  446. Handle - Supplies the handle to the registered device reporting the event.
  447. Event - Supplies a pointer to the event that occurred. The caller must
  448. supply this buffer, but it will only be used for the duration of the
  449. routine (a copy will be made). The caller must fill out the event type
  450. and union, and should expect all other fields to be overwritten.
  451. Return Value:
  452. STATUS_SUCCESS on success.
  453. STATUS_BUFFER_FULL if the input pipe is full of events and this one was
  454. dropped.
  455. --*/
  456. {
  457. ULONGLONG DueTime;
  458. PUSER_INPUT_DEVICE InputDevice;
  459. ULONGLONG Period;
  460. BOOL Repeat;
  461. KSTATUS Status;
  462. InputDevice = (PUSER_INPUT_DEVICE)Handle;
  463. ASSERT(KeGetRunLevel() == RunLevelLow);
  464. Event->EventIdentifier = RtlAtomicAdd32(&InNextEventId, 1);
  465. Event->DeviceIdentifier = InputDevice->Identifier;
  466. Event->DeviceType = InputDevice->Type;
  467. //
  468. // Handle the repeat event for any keyboard devices.
  469. //
  470. Repeat = FALSE;
  471. if (Event->DeviceType == UserInputDeviceKeyboard) {
  472. //
  473. // Bring the repeat timer, DPC, and work item to a halt. Cancelling a
  474. // periodic timer only guarantees that the timer will not fire again.
  475. // Not much can be said about the associated DPC. So, flush it. If it
  476. // is queued, this will busy spin until it's done running, but it
  477. // shouldn't take too long.
  478. //
  479. if (InputDevice->RepeatEvent->U.Key != KeyboardKeyInvalid) {
  480. KeCancelTimer(InputDevice->RepeatTimer);
  481. KeFlushDpc(InputDevice->RepeatDpc);
  482. //
  483. // With the timer cancelled and DPC flushed, there is still the
  484. // work item to worry about. Try to cancel it. And if that fails,
  485. // flush it.
  486. //
  487. Status = KeCancelWorkItem(InputDevice->RepeatWorkItem);
  488. if (Status == STATUS_TOO_LATE) {
  489. KeFlushWorkItem(InputDevice->RepeatWorkItem);
  490. }
  491. }
  492. //
  493. // If this is a key down, then the new key becomes the repeat key if it
  494. // should be repeated. Otherwise the repeat remains cancelled.
  495. //
  496. if (Event->EventType == UserInputEventKeyDown) {
  497. if (USER_INPUT_IS_REPEAT_KEY(Event->U.Key) != FALSE) {
  498. RtlCopyMemory(InputDevice->RepeatEvent,
  499. Event,
  500. sizeof(USER_INPUT_EVENT));
  501. Repeat = TRUE;
  502. } else {
  503. InputDevice->RepeatEvent->U.Key = KeyboardKeyInvalid;
  504. }
  505. //
  506. // If this is a key up, do not restart the repeat if this is a key up
  507. // on the repeat key. Otherwise restart the repeat if there is a valid
  508. // repeat event.
  509. //
  510. } else {
  511. ASSERT(Event->EventType == UserInputEventKeyUp);
  512. if (Event->U.Key == InputDevice->RepeatEvent->U.Key) {
  513. InputDevice->RepeatEvent->U.Key = KeyboardKeyInvalid;
  514. } else if (InputDevice->RepeatEvent->U.Key != KeyboardKeyInvalid) {
  515. Repeat = TRUE;
  516. }
  517. }
  518. }
  519. ASSERT(Event->EventType < UserInputEventCount);
  520. Status = InpProcessInputEvent(Event);
  521. //
  522. // If there is an active keyboard repeat event, then queue it.
  523. //
  524. if ((Repeat != FALSE) &&
  525. ((InDebugFlags & USER_INPUT_DEBUG_DISABLE_REPEAT) == 0)) {
  526. ASSERT(Event->DeviceType == UserInputDeviceKeyboard);
  527. DueTime = HlQueryTimeCounter();
  528. DueTime += KeConvertMicrosecondsToTimeTicks(KEYBOARD_REPEAT_DELAY);
  529. Period = KeConvertMicrosecondsToTimeTicks(KEYBOARD_REPEAT_RATE);
  530. KeQueueTimer(InputDevice->RepeatTimer,
  531. TimerQueueSoftWake,
  532. DueTime,
  533. Period,
  534. 0,
  535. InputDevice->RepeatDpc);
  536. }
  537. if ((InDebugFlags & USER_INPUT_DEBUG_EVENT) != 0) {
  538. RtlDebugPrint("USIN: %s %s event processed with status 0x%08x: event "
  539. "0x%08x, device 0x%08x, ",
  540. InDeviceTypeStrings[Event->DeviceType],
  541. InEventTypeStrings[Event->EventType],
  542. Status,
  543. Event->EventIdentifier,
  544. Event->DeviceIdentifier);
  545. switch (Event->DeviceType) {
  546. case UserInputDeviceKeyboard:
  547. RtlDebugPrint("key %d.\n", Event->U.Key);
  548. break;
  549. default:
  550. RtlDebugPrint("no data.\n");
  551. break;
  552. }
  553. }
  554. return Status;
  555. }
  556. //
  557. // --------------------------------------------------------- Internal Functions
  558. //
  559. VOID
  560. InUnloadDriver (
  561. PVOID Driver
  562. )
  563. /*++
  564. Routine Description:
  565. This routine is called before a driver is about to be unloaded from memory.
  566. The driver should take this opportunity to free any resources it may have
  567. set up in the driver entry routine.
  568. Arguments:
  569. Driver - Supplies a pointer to the driver being torn down.
  570. Return Value:
  571. None.
  572. --*/
  573. {
  574. if (InUserInputPipe != NULL) {
  575. IoClose(InUserInputPipe);
  576. InUserInputPipe = NULL;
  577. }
  578. if (InLocalTerminal != NULL) {
  579. IoClose(InLocalTerminal);
  580. InLocalTerminal = NULL;
  581. }
  582. if (InDeviceListLock != NULL) {
  583. KeDestroyQueuedLock(InDeviceListLock);
  584. InDeviceListLock = NULL;
  585. }
  586. return;
  587. }
  588. KSTATUS
  589. InpProcessInputEvent (
  590. PUSER_INPUT_EVENT Event
  591. )
  592. /*++
  593. Routine Description:
  594. This routine processes an input event, sending it on to the terminal and
  595. the user input pipe.
  596. Arguments:
  597. Event - Supplies a pointer to a user input event.
  598. Return Value:
  599. Status code.
  600. --*/
  601. {
  602. UINTN BytesWritten;
  603. PIO_BUFFER IoBuffer;
  604. KSTATUS Status;
  605. //
  606. // Potentially convert this event into some terminal characters.
  607. //
  608. InpProcessInputEventForTerminal(Event);
  609. //
  610. // Create an I/O buffer for the write.
  611. //
  612. Status = MmCreateIoBuffer(Event,
  613. sizeof(USER_INPUT_EVENT),
  614. IO_BUFFER_FLAG_KERNEL_MODE_DATA,
  615. &IoBuffer);
  616. if (!KSUCCESS(Status)) {
  617. goto ProcessInputEventEnd;
  618. }
  619. //
  620. // Write the event out for anyone listening.
  621. //
  622. Status = IoWrite(InUserInputPipe,
  623. IoBuffer,
  624. sizeof(USER_INPUT_EVENT),
  625. 0,
  626. 0,
  627. &BytesWritten);
  628. ASSERT((BytesWritten == 0) || (BytesWritten == sizeof(USER_INPUT_EVENT)));
  629. if (!KSUCCESS(Status)) {
  630. goto ProcessInputEventEnd;
  631. }
  632. ProcessInputEventEnd:
  633. if (IoBuffer != NULL) {
  634. MmFreeIoBuffer(IoBuffer);
  635. }
  636. return Status;
  637. }
  638. KSTATUS
  639. InpProcessInputEventForTerminal (
  640. PUSER_INPUT_EVENT Event
  641. )
  642. /*++
  643. Routine Description:
  644. This routine processes a new input event and writes it out to the terminal
  645. if applicable. This routine must be called at low level.
  646. Arguments:
  647. Event - Supplies a pointer to the event that occurred.
  648. Return Value:
  649. STATUS_SUCCESS on success.
  650. STATUS_BUFFER_FULL if the input pipe is full of events and this one was
  651. dropped.
  652. --*/
  653. {
  654. UINTN BytesWritten;
  655. ULONG CharacterCount;
  656. CHAR Characters[TERMINAL_MAX_KEY_CHARACTERS + 1];
  657. ULONG ControlMask;
  658. PIO_BUFFER IoBuffer;
  659. CHAR RegularCharacter;
  660. BOOL Result;
  661. KSTATUS Status;
  662. TERMINAL_KEY_DATA TerminalKey;
  663. BOOL UpdateLedState;
  664. ControlMask = 0;
  665. CharacterCount = 0;
  666. RegularCharacter = 0;
  667. if (Event->DeviceType != UserInputDeviceKeyboard) {
  668. return STATUS_SUCCESS;
  669. }
  670. TerminalKey.Flags = 0;
  671. TerminalKey.Key = TerminalKeyInvalid;
  672. //
  673. // First handle key up events. There is nothing to write to the terminal
  674. // for such events, but the control key mask may need to change.
  675. //
  676. if (Event->EventType == UserInputEventKeyUp) {
  677. switch (Event->U.Key) {
  678. case KeyboardKeyLeftControl:
  679. case KeyboardKeyRightControl:
  680. ControlMask = TERMINAL_KEYBOARD_CONTROL;
  681. break;
  682. case KeyboardKeyLeftShift:
  683. case KeyboardKeyRightShift:
  684. ControlMask = TERMINAL_KEYBOARD_SHIFT;
  685. break;
  686. case KeyboardKeyLeftAlt:
  687. case KeyboardKeyRightAlt:
  688. ControlMask = TERMINAL_KEYBOARD_ALT;
  689. break;
  690. default:
  691. break;
  692. }
  693. if (ControlMask != 0) {
  694. RtlAtomicAnd32(&InTerminalKeyboardMask, ~ControlMask);
  695. }
  696. return STATUS_SUCCESS;
  697. //
  698. // Events other than key down and key up are ignored.
  699. //
  700. } else if (Event->EventType != UserInputEventKeyDown) {
  701. return STATUS_SUCCESS;
  702. }
  703. //
  704. // Handle key down events.
  705. //
  706. UpdateLedState = FALSE;
  707. IoBuffer = NULL;
  708. switch (Event->U.Key) {
  709. case KeyboardKeyLeftControl:
  710. case KeyboardKeyRightControl:
  711. ControlMask = TERMINAL_KEYBOARD_CONTROL;
  712. break;
  713. case KeyboardKeyLeftShift:
  714. case KeyboardKeyRightShift:
  715. ControlMask = TERMINAL_KEYBOARD_SHIFT;
  716. break;
  717. case KeyboardKeyLeftAlt:
  718. case KeyboardKeyRightAlt:
  719. ControlMask = TERMINAL_KEYBOARD_ALT;
  720. break;
  721. case KeyboardKeyNumLock:
  722. RtlAtomicXor32(&InTerminalKeyboardMask, TERMINAL_KEYBOARD_NUM_LOCK);
  723. UpdateLedState = TRUE;
  724. break;
  725. case KeyboardKeyScrollLock:
  726. RtlAtomicXor32(&InTerminalKeyboardMask, TERMINAL_KEYBOARD_SCROLL_LOCK);
  727. UpdateLedState = TRUE;
  728. break;
  729. case KeyboardKeyCapsLock:
  730. RtlAtomicXor32(&InTerminalKeyboardMask, TERMINAL_KEYBOARD_CAPS_LOCK);
  731. UpdateLedState = TRUE;
  732. break;
  733. case KeyboardKeyUp:
  734. TerminalKey.Key = TerminalKeyUp;
  735. break;
  736. case KeyboardKeyDown:
  737. TerminalKey.Key = TerminalKeyDown;
  738. break;
  739. case KeyboardKeyLeft:
  740. TerminalKey.Key = TerminalKeyLeft;
  741. break;
  742. case KeyboardKeyRight:
  743. TerminalKey.Key = TerminalKeyRight;
  744. break;
  745. case KeyboardKeyPageUp:
  746. TerminalKey.Key = TerminalKeyPageUp;
  747. break;
  748. case KeyboardKeyPageDown:
  749. TerminalKey.Key = TerminalKeyPageDown;
  750. break;
  751. case KeyboardKeyHome:
  752. TerminalKey.Key = TerminalKeyHome;
  753. break;
  754. case KeyboardKeyEnd:
  755. TerminalKey.Key = TerminalKeyEnd;
  756. break;
  757. case KeyboardKeyInsert:
  758. TerminalKey.Key = TerminalKeyInsert;
  759. break;
  760. case KeyboardKeyDelete:
  761. TerminalKey.Key = TerminalKeyDelete;
  762. break;
  763. case KeyboardKeyKeypad0:
  764. case KeyboardKeyKeypad1:
  765. case KeyboardKeyKeypad2:
  766. case KeyboardKeyKeypad3:
  767. case KeyboardKeyKeypad4:
  768. case KeyboardKeyKeypad5:
  769. case KeyboardKeyKeypad6:
  770. case KeyboardKeyKeypad7:
  771. case KeyboardKeyKeypad8:
  772. case KeyboardKeyKeypad9:
  773. case KeyboardKeyKeypadPeriod:
  774. //
  775. // If the number lock is off or the shift key is pressed, then the
  776. // above keypad values turn into special or cursor codes.
  777. //
  778. if (((InTerminalKeyboardMask & TERMINAL_KEYBOARD_NUM_LOCK) == 0) ||
  779. ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_SHIFT) != 0)) {
  780. switch (Event->U.Key) {
  781. case KeyboardKeyKeypad0:
  782. TerminalKey.Key = TerminalKeyInsert;
  783. break;
  784. case KeyboardKeyKeypad1:
  785. TerminalKey.Key = TerminalKeyEnd;
  786. break;
  787. case KeyboardKeyKeypad2:
  788. TerminalKey.Key = TerminalKeyDown;
  789. break;
  790. case KeyboardKeyKeypad3:
  791. TerminalKey.Key = TerminalKeyPageDown;
  792. break;
  793. case KeyboardKeyKeypad4:
  794. TerminalKey.Key = TerminalKeyLeft;
  795. break;
  796. case KeyboardKeyKeypad5:
  797. break;
  798. case KeyboardKeyKeypad6:
  799. TerminalKey.Key = TerminalKeyRight;
  800. break;
  801. case KeyboardKeyKeypad7:
  802. TerminalKey.Key = TerminalKeyHome;
  803. break;
  804. case KeyboardKeyKeypad8:
  805. TerminalKey.Key = TerminalKeyUp;
  806. break;
  807. case KeyboardKeyKeypad9:
  808. TerminalKey.Key = TerminalKeyPageUp;
  809. break;
  810. case KeyboardKeyKeypadPeriod:
  811. TerminalKey.Key = TerminalKeyDelete;
  812. break;
  813. default:
  814. ASSERT(FALSE);
  815. break;
  816. }
  817. //
  818. // Otherwise get the regular character. Caps Lock has no effect on the
  819. // keypad, so this cannot drop down into the regular case.
  820. //
  821. } else {
  822. RegularCharacter = InKeyboardCharacters[Event->U.Key];
  823. }
  824. break;
  825. //
  826. // Process a normal character.
  827. //
  828. default:
  829. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_SHIFT) != 0) {
  830. RegularCharacter = InShiftedKeyboardCharacters[Event->U.Key];
  831. } else {
  832. RegularCharacter = InKeyboardCharacters[Event->U.Key];
  833. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_CAPS_LOCK) != 0) {
  834. RegularCharacter = RtlConvertCharacterToUpperCase(
  835. RegularCharacter);
  836. }
  837. }
  838. //
  839. // Do it differently if a control key is down.
  840. //
  841. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_CONTROL) != 0) {
  842. RegularCharacter =
  843. RtlConvertCharacterToUpperCase(RegularCharacter);
  844. if ((RegularCharacter >= '@') && (RegularCharacter <= '_')) {
  845. RegularCharacter -= '@';
  846. } else {
  847. RegularCharacter = 0;
  848. }
  849. }
  850. break;
  851. }
  852. //
  853. // Update the keyboard mask if a control value changed.
  854. //
  855. if (ControlMask != 0) {
  856. RtlAtomicOr32(&InTerminalKeyboardMask, ControlMask);
  857. }
  858. //
  859. // Update the LED state if it changed.
  860. //
  861. if (UpdateLedState != FALSE) {
  862. InpUpdateLedStateForTerminal();
  863. }
  864. if (TerminalKey.Key != TerminalKeyInvalid) {
  865. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_ALT) != 0) {
  866. TerminalKey.Flags |= TERMINAL_KEY_FLAG_ALT;
  867. }
  868. Result = TermCreateInputSequence(&TerminalKey,
  869. Characters,
  870. sizeof(Characters));
  871. if (Result != FALSE) {
  872. Characters[sizeof(Characters) - 1] = '\0';
  873. CharacterCount = RtlStringLength(Characters);
  874. } else {
  875. CharacterCount = 0;
  876. }
  877. } else if (RegularCharacter != 0) {
  878. Characters[0] = RegularCharacter;
  879. CharacterCount = 1;
  880. }
  881. ASSERT(Event->EventType == UserInputEventKeyDown);
  882. if (CharacterCount != 0) {
  883. if (InLocalTerminal != NULL) {
  884. Status = MmCreateIoBuffer(Characters,
  885. CharacterCount,
  886. IO_BUFFER_FLAG_KERNEL_MODE_DATA,
  887. &IoBuffer);
  888. if (!KSUCCESS(Status)) {
  889. goto ProcessInputEventForTerminalEnd;
  890. }
  891. Status = IoWrite(InLocalTerminal,
  892. IoBuffer,
  893. CharacterCount,
  894. 0,
  895. USER_INPUT_TERMINAL_WAIT_TIME,
  896. &BytesWritten);
  897. if (Status == STATUS_TOO_LATE) {
  898. RtlDebugPrint("Shutting down user input on local terminal.\n");
  899. IoClose(InLocalTerminal);
  900. InLocalTerminal = NULL;
  901. }
  902. }
  903. }
  904. Status = STATUS_SUCCESS;
  905. ProcessInputEventForTerminalEnd:
  906. if (IoBuffer != NULL) {
  907. MmFreeIoBuffer(IoBuffer);
  908. }
  909. return Status;
  910. }
  911. VOID
  912. InpRepeatInputEventDpcRoutine (
  913. PDPC Dpc
  914. )
  915. /*++
  916. Routine Description:
  917. This routine implements the DPC routine that fires when the user input
  918. repeat event timer expires. It queues the work item.
  919. Arguments:
  920. Dpc - Supplies a pointer to the DPC that is running.
  921. Return Value:
  922. None.
  923. --*/
  924. {
  925. PUSER_INPUT_DEVICE InputDevice;
  926. InputDevice = (PUSER_INPUT_DEVICE)Dpc->UserData;
  927. KeQueueWorkItem(InputDevice->RepeatWorkItem);
  928. return;
  929. }
  930. VOID
  931. InpRepeatInputEventWorker (
  932. PVOID Parameter
  933. )
  934. /*++
  935. Routine Description:
  936. This routine completes work for repeated user input events.
  937. Arguments:
  938. Parameter - Supplies a pointer to the user input device who owns the repeat
  939. event.
  940. Return Value:
  941. None.
  942. --*/
  943. {
  944. PUSER_INPUT_DEVICE InputDevice;
  945. PUSER_INPUT_EVENT RepeatEvent;
  946. KSTATUS Status;
  947. InputDevice = (PUSER_INPUT_DEVICE)Parameter;
  948. RepeatEvent = InputDevice->RepeatEvent;
  949. RepeatEvent->EventIdentifier = RtlAtomicAdd32(&InNextEventId, 1);
  950. Status = InpProcessInputEvent(RepeatEvent);
  951. //
  952. // Display optional debug information.
  953. //
  954. if ((InDebugFlags & USER_INPUT_DEBUG_REPEAT_EVENT) != 0) {
  955. RtlDebugPrint("USIN: REPEAT %s %s event processed with status 0x%08x: "
  956. "event 0x%08x, device 0x%08x, ",
  957. InDeviceTypeStrings[RepeatEvent->DeviceType],
  958. InEventTypeStrings[RepeatEvent->EventType],
  959. Status,
  960. RepeatEvent->EventIdentifier,
  961. RepeatEvent->DeviceIdentifier);
  962. switch (InputDevice->RepeatEvent->DeviceType) {
  963. case UserInputDeviceKeyboard:
  964. RtlDebugPrint("key %d.\n", RepeatEvent->U.Key);
  965. break;
  966. default:
  967. RtlDebugPrint("no data.\n");
  968. break;
  969. }
  970. }
  971. return;
  972. }
  973. VOID
  974. InpUpdateLedStateForTerminal (
  975. VOID
  976. )
  977. /*++
  978. Routine Description:
  979. This routine updates the LED state for all terminal devices (i.e.
  980. keyboards).
  981. Arguments:
  982. None.
  983. Return Value:
  984. None.
  985. --*/
  986. {
  987. PLIST_ENTRY CurrentEntry;
  988. PUSER_INPUT_DEVICE Device;
  989. ULONG LedState;
  990. //
  991. // Acquire the device list lock and get the LED state by parsing the
  992. // terminal mask. It is OK if the terminal mask changes while reading, the
  993. // event that caused the change will have to wait on the device list lock
  994. // and will set the most up to date LED state.
  995. //
  996. LedState = 0;
  997. KeAcquireQueuedLock(InDeviceListLock);
  998. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_NUM_LOCK) != 0) {
  999. LedState |= USER_INPUT_KEYBOARD_LED_NUM_LOCK;
  1000. }
  1001. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_CAPS_LOCK) != 0) {
  1002. LedState |= USER_INPUT_KEYBOARD_LED_CAPS_LOCK;
  1003. }
  1004. if ((InTerminalKeyboardMask & TERMINAL_KEYBOARD_SCROLL_LOCK) != 0) {
  1005. LedState |= USER_INPUT_KEYBOARD_LED_SCROLL_LOCK;
  1006. }
  1007. //
  1008. // Iterate over the list of user input devices and set the LED state.
  1009. //
  1010. CurrentEntry = InDeviceListHead.Next;
  1011. while (CurrentEntry != &InDeviceListHead) {
  1012. Device = LIST_VALUE(CurrentEntry, USER_INPUT_DEVICE, ListEntry);
  1013. CurrentEntry = CurrentEntry->Next;
  1014. if (Device->Type != UserInputDeviceKeyboard) {
  1015. continue;
  1016. }
  1017. if (Device->U.KeyboardInterface.SetLedState != NULL) {
  1018. Device->U.KeyboardInterface.SetLedState(Device->Device,
  1019. Device->DeviceContext,
  1020. LedState);
  1021. }
  1022. }
  1023. KeReleaseQueuedLock(InDeviceListLock);
  1024. return;
  1025. }