Use free Windows DDK and compile with latest MinGW releases.
[reactos.git] / reactos / drivers / input / keyboard / keyboard.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: services/dd/keyboard/keyboard.c
5 * PURPOSE: Keyboard driver
6 * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
7 * Jason Filby (jasonfilby@yahoo.com)
8 */
9
10 /* INCLUDES ****************************************************************/
11
12 #define NTOS_KERNEL_MODE
13 #include <ntos.h>
14 #include <ntos/keyboard.h>
15 #include <ddk/ntddkbd.h>
16 #include <ddk/ntdd8042.h>
17 #include <string.h>
18 #include <ntos/minmax.h>
19
20 #define NDEBUG
21 #include <debug.h>
22
23 #include "keyboard.h"
24
25 /* GLOBALS *******************************************************************/
26
27 /*
28 * Driver data
29 */
30
31 static KEY_EVENT_RECORD kbdBuffer[KBD_BUFFER_SIZE];
32 static int bufHead,bufTail;
33 static int keysInBuffer;
34 static int extKey;
35 static BYTE ledStatus;
36 static BYTE capsDown,numDown,scrollDown;
37 static DWORD ctrlKeyState;
38 static PKINTERRUPT KbdInterrupt;
39 static KDPC KbdDpc;
40 static BOOLEAN AlreadyOpened = FALSE;
41
42 /*
43 * PURPOSE: Current irp being processed
44 */
45 static PIRP CurrentIrp;
46
47 /*
48 * PURPOSE: Number of keys that have been read into the current irp's buffer
49 */
50 static ULONG KeysRead;
51 static ULONG KeysRequired;
52
53 /*
54 * Virtual key codes table
55 *
56 * Comments:
57 * * PrtSc = VK_PRINT
58 * * Alt+PrtSc (SysRq) = VK_EXECUTE
59 * * Alt = VK_MENU
60 */
61
62 static const WORD vkTable[128]=
63 {
64 /* 00 - 07 */ 0, VK_ESCAPE, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6,
65 /* 08 - 0F */ VK_7, VK_8, VK_9, VK_0, 189, 187, VK_BACK, VK_TAB,
66 /* 10 - 17 */ VK_Q, VK_W, VK_E, VK_R, VK_T, VK_Y, VK_U, VK_I,
67 /* 18 - 1F */ VK_O, VK_P, 219, 221, VK_RETURN, VK_CONTROL, VK_A, VK_S,
68 /* 20 - 27 */ VK_D, VK_F, VK_G, VK_H, VK_J, VK_K, VK_L, 186,
69 /* 28 - 2F */ 222, 192, VK_SHIFT, 220, VK_Z, VK_X, VK_C, VK_V,
70 /* 30 - 37 */ VK_B, VK_N, VK_M, 188, 190, 191, VK_SHIFT, VK_MULTIPLY,
71 /* 38 - 3F */ VK_MENU, VK_SPACE, VK_CAPITAL, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
72 /* 40 - 47 */ VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUMLOCK, VK_SCROLL, VK_HOME,
73 /* 48 - 4F */ VK_UP, VK_PRIOR, VK_SUBTRACT, VK_LEFT, VK_CLEAR, VK_RIGHT, VK_ADD, VK_END,
74 /* 50 - 57 */ VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE, VK_EXECUTE, 0, 0, VK_F11,
75 /* 58 - 5F */ VK_F12, 0, 0, 91, 92, 93, 0, 0,
76 /* 60 - 67 */ 0, 0, 0, 0, 0, 0, 0, 0,
77 /* 68 - 6F */ 0, 0, 0, 0, 0, 0, 0, 0,
78 /* 70 - 77 */ 0, 0, 0, 0, 0, 0, 0, 0,
79 /* 78 - 7F */ 0, 0, 0, 0, 0, 0, 0, VK_PAUSE
80 };
81 static const WORD vkKeypadTable[13]= /* 47 - 53 */
82 {
83 VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_SUBTRACT,
84 VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_ADD,
85 VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_DECIMAL
86 };
87
88
89 /*
90 * ASCII translation tables
91 */
92
93 static const BYTE asciiTable1[10]=
94 {
95 ')','!','@','#','$','%','^','&','*','('
96 };
97 static const BYTE asciiTable2[16]=
98 {
99 '0','1','2','3','4','5','6','7','8','9','*','+',0,'-','.','/'
100 };
101 static const BYTE asciiTable3[37]=
102 {
103 ';','=',',','-','.','/','`', 0, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 '[', '\\', ']', '\''
106 };
107 static const BYTE asciiTable4[37]=
108 {
109 ':','+','<','_','>','?','~', 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 '{', '|', '}', '"'
112 };
113
114 VOID STDCALL
115 KdSystemDebugControl(ULONG Code);
116
117 static LONG DoSystemDebug = -1;
118 static BOOLEAN InSysRq = FALSE;
119
120 /* FUNCTIONS *****************************************************************/
121
122 static void KbdWrite(int addr,BYTE data)
123 /*
124 * FUNCTION: Write data to keyboard
125 */
126 {
127 BYTE status;
128
129 do
130 {
131 status=READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT); // Wait until input buffer empty
132 } while(status & KBD_IBF);
133 WRITE_PORT_UCHAR((PUCHAR)addr,data);
134 }
135
136 static int KbdReadData(void)
137 /*
138 * FUNCTION: Read data from port 0x60
139 */
140 {
141 int i;
142 BYTE status,data;
143
144 i=500000;
145 do
146 {
147 status=READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT);
148 if (!(status & KBD_OBF)) // Check if data available
149 continue;
150 data=READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT);
151 if (status & (KBD_GTO | KBD_PERR)) // Check for timeout error
152 continue;
153 return data;
154 } while(--i);
155 return -1; // Timed out
156 }
157
158
159 /*
160 * Set keyboard LED's
161 */
162
163 static void SetKeyboardLEDs(BYTE status)
164 {
165 KbdWrite(KBD_DATA_PORT,0xED);
166 if (KbdReadData()!=KBD_ACK) // Error
167 return;
168 KbdWrite(KBD_DATA_PORT,status);
169 KbdReadData();
170 }
171
172
173 /*
174 * Process scan code
175 */
176
177 static void ProcessScanCode(BYTE scanCode,BOOL isDown)
178 {
179 switch(scanCode)
180 {
181 case 0x1D: // Ctrl
182 if (extKey)
183 {
184 if (isDown)
185 ctrlKeyState|=RIGHT_CTRL_PRESSED;
186 else
187 ctrlKeyState&=~RIGHT_CTRL_PRESSED;
188 }
189 else
190 {
191 if (isDown)
192 ctrlKeyState|=LEFT_CTRL_PRESSED;
193 else
194 ctrlKeyState&=~LEFT_CTRL_PRESSED;
195 }
196 break;
197 case 0x2A: // Left shift
198 case 0x36: // Right shift
199 if (isDown)
200 ctrlKeyState|=SHIFT_PRESSED;
201 else
202 ctrlKeyState&=~SHIFT_PRESSED;
203 break;
204 case 0x38: // Alt
205 if (extKey)
206 {
207 if (isDown)
208 ctrlKeyState|=RIGHT_ALT_PRESSED;
209 else
210 ctrlKeyState&=~RIGHT_ALT_PRESSED;
211 }
212 else
213 {
214 if (isDown)
215 ctrlKeyState|=LEFT_ALT_PRESSED;
216 else
217 ctrlKeyState&=~LEFT_ALT_PRESSED;
218 }
219 break;
220 case 0x3A: // CapsLock
221 if (ctrlKeyState & CTRL_PRESSED)
222 break;
223 if (isDown)
224 {
225 if (!capsDown)
226 {
227 capsDown=1;
228 if (ctrlKeyState & CAPSLOCK_ON)
229 {
230 ledStatus&=~KBD_LED_CAPS;
231 ctrlKeyState&=~CAPSLOCK_ON;
232 }
233 else
234 {
235 ledStatus|=KBD_LED_CAPS;
236 ctrlKeyState|=CAPSLOCK_ON;
237 }
238 SetKeyboardLEDs(ledStatus);
239 }
240 }
241 else
242 {
243 capsDown=0;
244 }
245 break;
246 case 0x45: // NumLock
247 if (ctrlKeyState & CTRL_PRESSED)
248 break;
249 if (isDown)
250 {
251 if (!numDown)
252 {
253 numDown=1;
254 if (ctrlKeyState & NUMLOCK_ON)
255 {
256 ledStatus&=~KBD_LED_NUM;
257 ctrlKeyState&=~NUMLOCK_ON;
258 }
259 else
260 {
261 ledStatus|=KBD_LED_NUM;
262 ctrlKeyState|=NUMLOCK_ON;
263 }
264 SetKeyboardLEDs(ledStatus);
265 }
266 }
267 else
268 {
269 numDown=0;
270 }
271 break;
272 case 0x46: // ScrollLock
273 if (ctrlKeyState & CTRL_PRESSED)
274 break;
275 if (isDown)
276 {
277 if (!scrollDown)
278 {
279 scrollDown=1;
280 if (ctrlKeyState & SCROLLLOCK_ON)
281 {
282 ledStatus&=~KBD_LED_SCROLL;
283 ctrlKeyState&=~SCROLLLOCK_ON;
284 }
285 else
286 {
287 ledStatus|=KBD_LED_SCROLL;
288 ctrlKeyState|=SCROLLLOCK_ON;
289 }
290 SetKeyboardLEDs(ledStatus);
291 }
292 }
293 else
294 {
295 scrollDown=0;
296 }
297 break;
298 default:
299 break;
300 }
301 }
302
303
304 /*
305 * Translate virtual key code to ASCII
306 */
307
308 static BYTE VirtualToAscii(WORD keyCode,BOOL isDown)
309 {
310 if ((ctrlKeyState & ALT_PRESSED)&&(ctrlKeyState & CTRL_PRESSED))
311 return 0; // Ctrl+Alt+char always 0
312 if ((!isDown)&&(ctrlKeyState & ALT_PRESSED))
313 return 0; // Alt+char is 0 when key is released
314
315 if (ctrlKeyState & CTRL_PRESSED)
316 {
317 if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
318 return keyCode-VK_A+1;
319 switch(keyCode)
320 {
321 case VK_SPACE:
322 return ' ';
323 case VK_BACK:
324 return 127;
325 case VK_RETURN:
326 return '\r';
327 case 219: /* [ */
328 if (ctrlKeyState & SHIFT_PRESSED)
329 return 0;
330 return 27;
331 case 220: /* \ */
332 if (ctrlKeyState & SHIFT_PRESSED)
333 return 0;
334 return 28;
335 case 221: /* ] */
336 if (ctrlKeyState & SHIFT_PRESSED)
337 return 0;
338 return 29;
339 default:
340 return 0;
341 }
342 }
343
344 if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
345 {
346 if (ctrlKeyState & CAPSLOCK_ON)
347 if (ctrlKeyState & SHIFT_PRESSED)
348 return keyCode-VK_A+'a';
349 else
350 return keyCode-VK_A+'A';
351 else
352 if (ctrlKeyState & SHIFT_PRESSED)
353 return keyCode-VK_A+'A';
354 else
355 return keyCode-VK_A+'a';
356 }
357
358 if ((keyCode>=VK_0)&&(keyCode<=VK_9))
359 {
360 if (ctrlKeyState & SHIFT_PRESSED)
361 return asciiTable1[keyCode-VK_0];
362 else
363 return keyCode-VK_0+'0';
364 }
365
366 if ((keyCode>=VK_NUMPAD0)&&(keyCode<=VK_DIVIDE))
367 return asciiTable2[keyCode-VK_NUMPAD0];
368
369 if ((keyCode>=186)&&(keyCode<=222))
370 {
371 if (ctrlKeyState & SHIFT_PRESSED)
372 return asciiTable4[keyCode-186];
373 else
374 return asciiTable3[keyCode-186];
375 }
376
377 switch(keyCode)
378 {
379 case VK_SPACE:
380 return ' ';
381 case VK_RETURN:
382 return '\r';
383 case VK_BACK:
384 return 8;
385 case VK_TAB:
386 return 9;
387 }
388 return 0;
389 }
390
391
392 /*
393 * Translate scan code to virtual key code
394 */
395
396 static WORD ScanToVirtual(BYTE scanCode)
397 {
398 if ((scanCode>=0x47)&&(scanCode<=0x53)&&(ctrlKeyState & NUMLOCK_ON)&&
399 (!extKey)&&(!(ctrlKeyState & SHIFT_PRESSED)))
400 return vkKeypadTable[scanCode-0x47];
401 if ((scanCode==0x35)&&(extKey)) // Gray divide
402 return VK_DIVIDE;
403 if ((scanCode==0x37)&&(extKey)) // Print screen
404 return VK_PRINT;
405 return vkTable[scanCode];
406 }
407
408
409 /*
410 * Keyboard IRQ handler
411 */
412
413 static VOID STDCALL
414 KbdDpcRoutine(PKDPC Dpc,
415 PVOID DeferredContext,
416 PVOID SystemArgument1,
417 PVOID SystemArgument2)
418 {
419 PIRP Irp = (PIRP)SystemArgument2;
420 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
421
422 if (SystemArgument1 == NULL && DoSystemDebug != -1)
423 {
424 KdSystemDebugControl(DoSystemDebug);
425 DoSystemDebug = -1;
426 return;
427 }
428
429 CHECKPOINT;
430 DPRINT("KbdDpcRoutine(DeviceObject %x, Irp %x)\n",
431 DeviceObject,Irp);
432 Irp->IoStatus.Status = STATUS_SUCCESS;
433 Irp->IoStatus.Information = 0;
434 IoCompleteRequest(Irp,IO_NO_INCREMENT);
435 IoStartNextPacket(DeviceObject,FALSE);
436 }
437
438 static BOOLEAN STDCALL
439 KeyboardHandler(PKINTERRUPT Interrupt,
440 PVOID Context)
441 {
442 BYTE thisKey;
443 BOOL isDown;
444 static BYTE lastKey;
445 CHAR Status;
446 PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context;
447 PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
448
449 CHECKPOINT;
450
451 /*
452 * Check status
453 */
454 Status = READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT);
455 if (!(Status & KBD_OBF))
456 {
457 return (FALSE);
458 }
459
460 // Read scan code
461 thisKey=READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT);
462
463 // Call hook routine. May change scancode value.
464 if (deviceExtension->IsrHookCallback) {
465 BOOLEAN cont = FALSE, ret;
466 //BUG BUG: rewrite to have valid CurrentScanState!!!
467 ret = (*deviceExtension->IsrHookCallback)(
468 deviceObject,
469 NULL,//&deviceExtension->CurrentInput,
470 NULL,//&deviceExtension->CurrentOutput,
471 Status,
472 &thisKey, //&scanCode,
473 &cont,
474 NULL //&deviceExtension->CurrentScanState
475 );
476
477 if (!cont) {
478 return ret;
479 }
480 }
481
482
483 if ((thisKey==0xE0)||(thisKey==0xE1)) // Extended key
484 {
485 extKey=1; // Wait for next byte
486 lastKey=thisKey;
487 return FALSE;
488 }
489
490 isDown=!(thisKey & 0x80);
491 thisKey&=0x7F;
492
493 // The keyboard maintains its own internal caps lock and num lock
494 // statuses. In caps lock mode E0 AA precedes make code and
495 // E0 2A follow break code. In num lock mode, E0 2A precedes
496 // make code and E0 AA follow break code. We maintain our own caps lock
497 // and num lock statuses, so we will just ignore these.
498 // Some keyboards have L-Shift/R-Shift modes instead of caps lock
499 // mode. If right shift pressed, E0 B6 / E0 36 pairs generated.
500 if (extKey & ((thisKey==0x2A)||(thisKey==0x36)))
501 {
502 extKey=0;
503 return FALSE;
504 }
505
506 // Check for PAUSE sequence
507 if (extKey && (lastKey==0xE1))
508 {
509 if (thisKey==0x1D)
510 lastKey=0xFF; // Sequence is OK
511 else
512 extKey=0;
513 return FALSE;
514 }
515 if (extKey && (lastKey==0xFF))
516 {
517 if (thisKey!=0x45)
518 {
519 extKey=0; // Bad sequence
520 return FALSE;
521 }
522 thisKey=0x7F; // Pseudo-code for PAUSE
523 }
524
525 ProcessScanCode(thisKey,isDown);
526
527 // DbgPrint("Key: %c\n",VirtualToAscii(ScanToVirtual(thisKey),isDown));
528 // DbgPrint("Key: %x\n",ScanToVirtual(thisKey));
529 if (ScanToVirtual(thisKey) == VK_TAB && isDown)
530 {
531 InSysRq = TRUE;
532 }
533 else if (ScanToVirtual(thisKey) == VK_TAB && !isDown)
534 {
535 InSysRq = FALSE;
536 }
537 else if (InSysRq == TRUE && ScanToVirtual(thisKey) >= VK_A &&
538 ScanToVirtual(thisKey) <= VK_Z && isDown)
539 {
540 DoSystemDebug = ScanToVirtual(thisKey) - VK_A;
541 KeInsertQueueDpc(&KbdDpc, NULL, NULL);
542 return(TRUE);
543 }
544
545 if (CurrentIrp!=NULL)
546 {
547 KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)
548 CurrentIrp->AssociatedIrp.SystemBuffer;
549 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(CurrentIrp);
550
551 CHECKPOINT;
552
553 rec[KeysRead].bKeyDown=isDown;
554 rec[KeysRead].wRepeatCount=1;
555 rec[KeysRead].wVirtualKeyCode=ScanToVirtual(thisKey);
556 rec[KeysRead].wVirtualScanCode=thisKey;
557 rec[KeysRead].uChar.AsciiChar=VirtualToAscii(rec->wVirtualKeyCode,isDown);
558 rec[KeysRead].dwControlKeyState=ctrlKeyState;
559 if (extKey)
560 {
561 rec[KeysRead].dwControlKeyState|=ENHANCED_KEY;
562 }
563 KeysRead++;
564 DPRINT("KeysRequired %d KeysRead %x\n",KeysRequired,KeysRead);
565 if (KeysRead==KeysRequired)
566 {
567 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) Context;
568 KeInsertQueueDpc(&KbdDpc,DeviceObject,CurrentIrp);
569 CurrentIrp=NULL;
570 }
571 CHECKPOINT;
572 return TRUE;
573 }
574
575 // Buffer is full ?
576 if (keysInBuffer==KBD_BUFFER_SIZE) // Buffer is full
577 {
578 extKey=0;
579 return(TRUE);
580 }
581 kbdBuffer[bufHead].bKeyDown=isDown;
582 kbdBuffer[bufHead].wRepeatCount=1;
583 kbdBuffer[bufHead].wVirtualKeyCode=ScanToVirtual(thisKey);
584 kbdBuffer[bufHead].wVirtualScanCode=thisKey;
585 kbdBuffer[bufHead].uChar.UnicodeChar=0;
586 // kbdBuffer[bufHead].uChar.AsciiChar=TranslateScanCode(thisKey);
587 kbdBuffer[bufHead].uChar.AsciiChar=VirtualToAscii(kbdBuffer[bufHead].wVirtualKeyCode,isDown);
588 kbdBuffer[bufHead].dwControlKeyState=ctrlKeyState;
589 if (extKey)
590 kbdBuffer[bufHead].dwControlKeyState|=ENHANCED_KEY;
591 bufHead++;
592 bufHead&=KBD_WRAP_MASK; // Modulo KBD_BUFFER_SIZE
593 keysInBuffer++;
594 extKey=0;
595 return TRUE;
596 }
597
598
599 //
600 // Initialize keyboard
601 //
602 static void KeyboardConnectInterrupt(PDEVICE_OBJECT DeviceObject)
603 {
604 ULONG MappedIrq;
605 KIRQL Dirql;
606 KAFFINITY Affinity;
607 NTSTATUS Status;
608
609 MappedIrq = HalGetInterruptVector(Internal,
610 0,
611 0,
612 KEYBOARD_IRQ,
613 &Dirql,
614 &Affinity);
615 Status = IoConnectInterrupt(&KbdInterrupt,
616 KeyboardHandler,
617 (PVOID)DeviceObject,
618 NULL,
619 MappedIrq,
620 Dirql,
621 Dirql,
622 0,
623 FALSE,
624 Affinity,
625 FALSE);
626 }
627
628 VOID
629 KbdClearInput(VOID)
630 {
631 ULONG i;
632 CHAR Status;
633
634 for (i = 0; i < 100; i++)
635 {
636 Status = READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT);
637 if (!(Status & KBD_OBF))
638 {
639 return;
640 }
641 (VOID)READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT);
642 }
643 }
644
645 static int InitializeKeyboard(PDEVICE_OBJECT DeviceObject)
646 {
647 // Initialize variables
648 bufHead=0;
649 bufTail=0;
650 keysInBuffer=0;
651 ledStatus=0;
652 capsDown=0;
653 numDown=0;
654 scrollDown=0;
655 ctrlKeyState=0;
656 extKey=0;
657
658 KbdClearInput();
659 KeyboardConnectInterrupt(DeviceObject);
660 KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL);
661 return 0;
662 }
663
664 /*
665 * Read data from keyboard buffer
666 */
667 BOOLEAN STDCALL
668 KbdSynchronizeRoutine(PVOID Context)
669 {
670 PIRP Irp = (PIRP)Context;
671 KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)Irp->AssociatedIrp.SystemBuffer;
672 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
673 ULONG NrToRead = stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
674 int i;
675
676 DPRINT("NrToRead %d keysInBuffer %d\n",NrToRead,keysInBuffer);
677 NrToRead = min(NrToRead,keysInBuffer);
678
679 DPRINT("NrToRead %d stk->Parameters.Read.Length %d\n",
680 NrToRead,stk->Parameters.Read.Length);
681 DPRINT("sizeof(KEY_EVENT_RECORD) %d\n",sizeof(KEY_EVENT_RECORD));
682 for (i=0;i<NrToRead;i++)
683 {
684 memcpy(&rec[i],&kbdBuffer[bufTail],sizeof(KEY_EVENT_RECORD));
685 bufTail++;
686 bufTail&=KBD_WRAP_MASK;
687 keysInBuffer--;
688 }
689 if ((stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD))==NrToRead)
690 {
691 return(TRUE);
692 }
693
694 KeysRequired=stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
695 KeysRead=NrToRead;
696 CurrentIrp=Irp;
697
698 return(FALSE);
699 }
700
701 VOID STDCALL KbdStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
702 {
703 #ifndef NDEBUG
704 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
705 #endif
706
707 DPRINT("KeyboardStartIo(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
708
709 if (KeSynchronizeExecution(KbdInterrupt, KbdSynchronizeRoutine, Irp))
710 {
711 Irp->IoStatus.Status = STATUS_SUCCESS;
712 Irp->IoStatus.Information = 0;
713 IoCompleteRequest(Irp, IO_NO_INCREMENT);
714 IoStartNextPacket(DeviceObject, FALSE);
715 }
716
717 DPRINT("stk->Parameters.Read.Length %d\n",stk->Parameters.Read.Length);
718 DPRINT("KeysRequired %d\n",KeysRequired);
719 }
720
721 NTSTATUS KbdInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
722 {
723 PIO_STACK_LOCATION stk;
724 PINTERNAL_I8042_HOOK_KEYBOARD hookKeyboard;
725 PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
726 NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
727
728 Irp->IoStatus.Information = 0;
729 stk = IoGetCurrentIrpStackLocation(Irp);
730
731 switch (stk->Parameters.DeviceIoControl.IoControlCode)
732 {
733 /*-----------------11/29/2001 4:12PM----------------
734 * This internal ioctrl belongs in i8042 driver. Should be
735 * moved to the appropriate driver later.
736 * --------------------------------------------------*/
737 case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:
738
739 if (stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(INTERNAL_I8042_HOOK_KEYBOARD))
740 {
741 DPRINT(("Keyboard IOCTL_INTERNAL_I8042_HOOK_KEYBOARD invalid buffer size\n"));
742 status = STATUS_INVALID_PARAMETER;
743 }
744 else {
745 //
746 // Copy the values if they are filled in
747 //
748 hookKeyboard = (PINTERNAL_I8042_HOOK_KEYBOARD)
749 stk->Parameters.DeviceIoControl.Type3InputBuffer;
750
751 DevExt->HookContext = hookKeyboard->Context;
752 if (hookKeyboard->InitializationRoutine) {
753 DbgPrint("Keyboard: InitializationHookCallback NOT IMPLEMENTED\n");
754 DevExt->InitializationHookCallback =
755 hookKeyboard->InitializationRoutine;
756 }
757
758 if (hookKeyboard->IsrRoutine) {
759 DevExt->IsrHookCallback = hookKeyboard->IsrRoutine;
760 }
761
762 status = STATUS_SUCCESS;
763 }
764 break;
765 default:
766 status = STATUS_INVALID_DEVICE_REQUEST;
767 break;
768 }
769
770 Irp->IoStatus.Status = status;
771 IoCompleteRequest(Irp, IO_NO_INCREMENT);
772 return status;
773 }
774
775 NTSTATUS STDCALL KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
776 {
777 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
778 NTSTATUS Status;
779
780 DPRINT("DeviceObject %x\n",DeviceObject);
781 DPRINT("Irp %x\n",Irp);
782
783 DPRINT("IRP_MJ_CREATE %d stk->MajorFunction %d\n",
784 IRP_MJ_CREATE, stk->MajorFunction);
785 DPRINT("AlreadyOpened %d\n",AlreadyOpened);
786
787 switch (stk->MajorFunction)
788 {
789 case IRP_MJ_CREATE:
790 if (AlreadyOpened == TRUE)
791 {
792 CHECKPOINT;
793 // Status = STATUS_UNSUCCESSFUL;
794 Status = STATUS_SUCCESS;
795 }
796 else
797 {
798 CHECKPOINT;
799 Status = STATUS_SUCCESS;
800 AlreadyOpened = TRUE;
801 }
802 break;
803
804 case IRP_MJ_CLOSE:
805 Status = STATUS_SUCCESS;
806 break;
807
808 case IRP_MJ_READ:
809 DPRINT("Handling Read request\n");
810 DPRINT("Queueing packet\n");
811 IoMarkIrpPending(Irp);
812 IoStartPacket(DeviceObject,Irp,NULL,NULL);
813 return(STATUS_PENDING);
814
815 default:
816 Status = STATUS_NOT_IMPLEMENTED;
817 break;
818 }
819
820 Irp->IoStatus.Status = Status;
821 Irp->IoStatus.Information = 0;
822 IoCompleteRequest(Irp,IO_NO_INCREMENT);
823 DPRINT("Status %d\n",Status);
824 return(Status);
825 }
826
827 NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
828 PUNICODE_STRING RegistryPath)
829 /*
830 * FUNCTION: Module entry point
831 */
832 {
833 PDEVICE_OBJECT DeviceObject;
834 UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\Keyboard");
835 UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\Keyboard");
836
837 DPRINT("Keyboard Driver 0.0.4\n");
838
839 DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdDispatch;
840 DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdDispatch;
841 DriverObject->MajorFunction[IRP_MJ_READ] = KbdDispatch;
842 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = KbdInternalDeviceControl;
843
844 DriverObject->DriverStartIo = KbdStartIo;
845
846 IoCreateDevice(DriverObject,
847 sizeof(DEVICE_EXTENSION),
848 &DeviceName,
849 FILE_DEVICE_KEYBOARD,
850 0,
851 TRUE,
852 &DeviceObject);
853
854 RtlZeroMemory(DeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
855
856 DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
857 InitializeKeyboard( DeviceObject );
858
859 IoCreateSymbolicLink(&SymlinkName, &DeviceName);
860
861 return(STATUS_SUCCESS);
862 }