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