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