936b4df987cdb9654a3228d507d9788bb6acd742
[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
440 CHECKPOINT;
441
442 // Read scan code
443 thisKey=READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT);
444 if ((thisKey==0xE0)||(thisKey==0xE1)) // Extended key
445 {
446 extKey=1; // Wait for next byte
447 lastKey=thisKey;
448 return FALSE;
449 }
450
451 isDown=!(thisKey & 0x80);
452 thisKey&=0x7F;
453
454 // The keyboard maintains its own internal caps lock and num lock
455 // statuses. In caps lock mode E0 AA precedes make code and
456 // E0 2A follow break code. In num lock mode, E0 2A precedes
457 // make code and E0 AA follow break code. We maintain our own caps lock
458 // and num lock statuses, so we will just ignore these.
459 // Some keyboards have L-Shift/R-Shift modes instead of caps lock
460 // mode. If right shift pressed, E0 B6 / E0 36 pairs generated.
461 if (extKey & ((thisKey==0x2A)||(thisKey==0x36)))
462 {
463 extKey=0;
464 return FALSE;
465 }
466
467 // Check for PAUSE sequence
468 if (extKey && (lastKey==0xE1))
469 {
470 if (thisKey==0x1D)
471 lastKey=0xFF; // Sequence is OK
472 else
473 extKey=0;
474 return FALSE;
475 }
476 if (extKey && (lastKey==0xFF))
477 {
478 if (thisKey!=0x45)
479 {
480 extKey=0; // Bad sequence
481 return FALSE;
482 }
483 thisKey=0x7F; // Pseudo-code for PAUSE
484 }
485
486 ProcessScanCode(thisKey,isDown);
487
488 // DbgPrint("Key: %c\n",VirtualToAscii(ScanToVirtual(thisKey),isDown));
489 // DbgPrint("Key: %x\n",ScanToVirtual(thisKey));
490 if (ScanToVirtual(thisKey) == VK_PRINT && isDown)
491 {
492 InSysRq = TRUE;
493 }
494 else if (ScanToVirtual(thisKey) == VK_PRINT && !isDown)
495 {
496 InSysRq = FALSE;
497 }
498 else if (InSysRq == TRUE && ScanToVirtual(thisKey) >= VK_A &&
499 ScanToVirtual(thisKey) <= VK_Z && isDown)
500 {
501 DoSystemDebug = ScanToVirtual(thisKey) - VK_A;
502 KeInsertQueueDpc(&KbdDpc, NULL, NULL);
503 return(TRUE);
504 }
505
506 if (CurrentIrp!=NULL)
507 {
508 KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)
509 CurrentIrp->AssociatedIrp.SystemBuffer;
510 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(CurrentIrp);
511
512 CHECKPOINT;
513
514 rec[KeysRead].bKeyDown=isDown;
515 rec[KeysRead].wRepeatCount=1;
516 rec[KeysRead].wVirtualKeyCode=ScanToVirtual(thisKey);
517 rec[KeysRead].wVirtualScanCode=thisKey;
518 rec[KeysRead].uChar.AsciiChar=VirtualToAscii(rec->wVirtualKeyCode,isDown);
519 rec[KeysRead].dwControlKeyState=ctrlKeyState;
520 if (extKey)
521 {
522 rec[KeysRead].dwControlKeyState|=ENHANCED_KEY;
523 }
524 KeysRead++;
525 DPRINT("KeysRequired %d KeysRead %x\n",KeysRequired,KeysRead);
526 if (KeysRead==KeysRequired)
527 {
528 KeInsertQueueDpc(&KbdDpc,stk->DeviceObject,CurrentIrp);
529 CurrentIrp=NULL;
530 }
531 CHECKPOINT;
532 return TRUE;
533 }
534
535 // Buffer is full ?
536 if (keysInBuffer==KBD_BUFFER_SIZE) // Buffer is full
537 {
538 extKey=0;
539 return(TRUE);
540 }
541 kbdBuffer[bufHead].bKeyDown=isDown;
542 kbdBuffer[bufHead].wRepeatCount=1;
543 kbdBuffer[bufHead].wVirtualKeyCode=ScanToVirtual(thisKey);
544 kbdBuffer[bufHead].wVirtualScanCode=thisKey;
545 kbdBuffer[bufHead].uChar.UnicodeChar=0;
546 // kbdBuffer[bufHead].uChar.AsciiChar=TranslateScanCode(thisKey);
547 kbdBuffer[bufHead].uChar.AsciiChar=VirtualToAscii(kbdBuffer[bufHead].wVirtualKeyCode,isDown);
548 kbdBuffer[bufHead].dwControlKeyState=ctrlKeyState;
549 if (extKey)
550 kbdBuffer[bufHead].dwControlKeyState|=ENHANCED_KEY;
551 bufHead++;
552 bufHead&=KBD_WRAP_MASK; // Modulo KBD_BUFFER_SIZE
553 keysInBuffer++;
554 extKey=0;
555 return TRUE;
556 }
557
558
559 //
560 // Initialize keyboard
561 //
562 static void KeyboardConnectInterrupt(void)
563 {
564 ULONG MappedIrq;
565 KIRQL Dirql;
566 KAFFINITY Affinity;
567 NTSTATUS Status;
568
569 MappedIrq = HalGetInterruptVector(Internal,
570 0,
571 0,
572 KEYBOARD_IRQ,
573 &Dirql,
574 &Affinity);
575 Status = IoConnectInterrupt(&KbdInterrupt,
576 KeyboardHandler,
577 NULL,
578 NULL,
579 MappedIrq,
580 Dirql,
581 Dirql,
582 0,
583 FALSE,
584 Affinity,
585 FALSE);
586 }
587
588 static int InitializeKeyboard(void)
589 {
590 // Initialize variables
591 bufHead=0;
592 bufTail=0;
593 keysInBuffer=0;
594 ledStatus=0;
595 capsDown=0;
596 numDown=0;
597 scrollDown=0;
598 ctrlKeyState=0;
599 extKey=0;
600
601 KeyboardConnectInterrupt();
602 KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL);
603 return 0;
604 }
605
606 /*
607 * Read data from keyboard buffer
608 */
609 BOOLEAN KbdSynchronizeRoutine(PVOID Context)
610 {
611 PIRP Irp = (PIRP)Context;
612 KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)Irp->AssociatedIrp.SystemBuffer;
613 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
614 ULONG NrToRead = stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
615 int i;
616
617 DPRINT("NrToRead %d keysInBuffer %d\n",NrToRead,keysInBuffer);
618 NrToRead = min(NrToRead,keysInBuffer);
619
620 DPRINT("NrToRead %d stk->Parameters.Read.Length %d\n",
621 NrToRead,stk->Parameters.Read.Length);
622 DPRINT("sizeof(KEY_EVENT_RECORD) %d\n",sizeof(KEY_EVENT_RECORD));
623 for (i=0;i<NrToRead;i++)
624 {
625 memcpy(&rec[i],&kbdBuffer[bufTail],sizeof(KEY_EVENT_RECORD));
626 bufTail++;
627 bufTail&=KBD_WRAP_MASK;
628 keysInBuffer--;
629 }
630 if ((stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD))==NrToRead)
631 {
632 return(TRUE);
633 }
634
635 KeysRequired=stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
636 KeysRead=NrToRead;
637 CurrentIrp=Irp;
638
639 return(FALSE);
640 }
641
642 VOID STDCALL KbdStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
643 {
644 #ifndef NDEBUG
645 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
646 #endif
647
648 DPRINT("KeyboardStartIo(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
649
650 if (KeSynchronizeExecution(KbdInterrupt, KbdSynchronizeRoutine, Irp))
651 {
652 Irp->IoStatus.Status = STATUS_SUCCESS;
653 Irp->IoStatus.Information = 0;
654 IoCompleteRequest(Irp, IO_NO_INCREMENT);
655 IoStartNextPacket(DeviceObject, FALSE);
656 }
657
658 DPRINT("stk->Parameters.Read.Length %d\n",stk->Parameters.Read.Length);
659 DPRINT("KeysRequired %d\n",KeysRequired);
660 }
661
662 NTSTATUS STDCALL KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
663 {
664 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
665 NTSTATUS Status;
666
667 DPRINT("DeviceObject %x\n",DeviceObject);
668 DPRINT("Irp %x\n",Irp);
669
670 DPRINT("IRP_MJ_CREATE %d stk->MajorFunction %d\n",
671 IRP_MJ_CREATE, stk->MajorFunction);
672 DPRINT("AlreadyOpened %d\n",AlreadyOpened);
673
674 switch (stk->MajorFunction)
675 {
676 case IRP_MJ_CREATE:
677 if (AlreadyOpened == TRUE)
678 {
679 CHECKPOINT;
680 // Status = STATUS_UNSUCCESSFUL;
681 Status = STATUS_SUCCESS;
682 }
683 else
684 {
685 CHECKPOINT;
686 Status = STATUS_SUCCESS;
687 AlreadyOpened = TRUE;
688 }
689 break;
690
691 case IRP_MJ_CLOSE:
692 Status = STATUS_SUCCESS;
693 break;
694
695 case IRP_MJ_READ:
696 DPRINT("Handling Read request\n");
697 DPRINT("Queueing packet\n");
698 IoMarkIrpPending(Irp);
699 IoStartPacket(DeviceObject,Irp,NULL,NULL);
700 return(STATUS_PENDING);
701
702 default:
703 Status = STATUS_NOT_IMPLEMENTED;
704 break;
705 }
706
707 Irp->IoStatus.Status = Status;
708 Irp->IoStatus.Information = 0;
709 IoCompleteRequest(Irp,IO_NO_INCREMENT);
710 DPRINT("Status %d\n",Status);
711 return(Status);
712 }
713
714 NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
715 PUNICODE_STRING RegistryPath)
716 /*
717 * FUNCTION: Module entry point
718 */
719 {
720 PDEVICE_OBJECT DeviceObject;
721 UNICODE_STRING DeviceName;
722 UNICODE_STRING SymlinkName;
723
724 DbgPrint("Keyboard Driver 0.0.4\n");
725 InitializeKeyboard();
726
727 DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdDispatch;
728 DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdDispatch;
729 DriverObject->MajorFunction[IRP_MJ_READ] = KbdDispatch;
730 DriverObject->DriverStartIo = KbdStartIo;
731
732 RtlInitUnicodeString(&DeviceName, L"\\Device\\Keyboard");
733 IoCreateDevice(DriverObject,
734 0,
735 &DeviceName,
736 FILE_DEVICE_KEYBOARD,
737 0,
738 TRUE,
739 &DeviceObject);
740 DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
741
742 RtlInitUnicodeString(&SymlinkName, L"\\??\\Keyboard");
743 IoCreateSymbolicLink(&SymlinkName, &DeviceName);
744
745 return(STATUS_SUCCESS);
746 }