:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / 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 #include <ddk/ntddkbd.h>
18 #include <ddk/ntdd8042.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 }