mirror of
https://github.com/reactos/reactos.git
synced 2024-06-16 09:31:51 +00:00
82d21c903e
svn path=/trunk/; revision=106
711 lines
17 KiB
C
711 lines
17 KiB
C
/*
|
|
** File: keyboard.c
|
|
** Description: ReactOS keyboard driver
|
|
** Current version: 0.0.4
|
|
** Last modified: 28 May 1998
|
|
**
|
|
* 31/08/98: Changed to interrupt driven model
|
|
* 29/06/98: NT interface by David Welch (welch@mcmail.com)
|
|
*
|
|
** Written by Victor Kirhenshtein (sauros@iname.com)
|
|
** Initial attempt by Jason Filby
|
|
**
|
|
** Some parts of this code are based on Linux keyboard driver
|
|
** written by Johan Myreen.
|
|
**
|
|
**
|
|
** KNOWN BUGS:
|
|
**
|
|
** * Repeat counter isn't supported
|
|
**
|
|
*/
|
|
|
|
#undef WIN32_LEAN_AND_MEAN
|
|
#include <internal/mmhal.h>
|
|
#include <internal/halio.h>
|
|
#include <ddk/ntddk.h>
|
|
#include <internal/string.h>
|
|
#include <defines.h>
|
|
|
|
#define NDEBUG
|
|
#include <internal/debug.h>
|
|
|
|
#include "keyboard.h"
|
|
|
|
/*
|
|
* Driver data
|
|
*/
|
|
|
|
static KEY_EVENT_RECORD kbdBuffer[KBD_BUFFER_SIZE];
|
|
static int bufHead,bufTail;
|
|
static int keysInBuffer;
|
|
static int extKey;
|
|
static BYTE ledStatus;
|
|
static BYTE capsDown,numDown,scrollDown;
|
|
static DWORD ctrlKeyState;
|
|
static KSPIN_LOCK kbdBufferLock;
|
|
static PKINTERRUPT KbdInterrupt;
|
|
static KDPC KbdDpc;
|
|
|
|
/*
|
|
* PURPOSE: Current irp being processed
|
|
*/
|
|
static PIRP CurrentIrp;
|
|
|
|
/*
|
|
* PURPOSE: Number of keys that have been read into the current irp's buffer
|
|
*/
|
|
static ULONG KeysRead;
|
|
static ULONG KeysRequired;
|
|
|
|
/*
|
|
* Virtual key codes table
|
|
*
|
|
* Comments:
|
|
* * PrtSc = VK_PRINT
|
|
* * Alt+PrtSc (SysRq) = VK_EXECUTE
|
|
* * Alt = VK_MENU
|
|
*/
|
|
|
|
static const WORD vkTable[128]=
|
|
{
|
|
/* 00 - 07 */ 0, VK_ESCAPE, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6,
|
|
/* 08 - 0F */ VK_7, VK_8, VK_9, VK_0, 189, 187, VK_BACK, VK_TAB,
|
|
/* 10 - 17 */ VK_Q, VK_W, VK_E, VK_R, VK_T, VK_Y, VK_U, VK_I,
|
|
/* 18 - 1F */ VK_O, VK_P, 219, 221, VK_RETURN, VK_CONTROL, VK_A, VK_S,
|
|
/* 20 - 27 */ VK_D, VK_F, VK_G, VK_H, VK_J, VK_K, VK_L, 186,
|
|
/* 28 - 2F */ 222, 192, VK_SHIFT, 220, VK_Z, VK_X, VK_C, VK_V,
|
|
/* 30 - 37 */ VK_B, VK_N, VK_M, 188, 190, 191, VK_SHIFT, VK_MULTIPLY,
|
|
/* 38 - 3F */ VK_MENU, VK_SPACE, VK_CAPITAL, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
|
|
/* 40 - 47 */ VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUMLOCK, VK_SCROLL, VK_HOME,
|
|
/* 48 - 4F */ VK_UP, VK_PRIOR, VK_SUBTRACT, VK_LEFT, VK_CLEAR, VK_RIGHT, VK_ADD, VK_END,
|
|
/* 50 - 57 */ VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE, VK_EXECUTE, 0, 0, VK_F11,
|
|
/* 58 - 5F */ VK_F12, 0, 0, 91, 92, 93, 0, 0,
|
|
/* 60 - 67 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 68 - 6F */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 70 - 77 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/* 78 - 7F */ 0, 0, 0, 0, 0, 0, 0, VK_PAUSE
|
|
};
|
|
static const WORD vkKeypadTable[13]= /* 47 - 53 */
|
|
{
|
|
VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_SUBTRACT,
|
|
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_ADD,
|
|
VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_DECIMAL
|
|
};
|
|
|
|
|
|
/*
|
|
* ASCII translation tables
|
|
*/
|
|
|
|
static const BYTE asciiTable1[10]=
|
|
{
|
|
')','!','@','#','$','%','^','&','*','('
|
|
};
|
|
static const BYTE asciiTable2[16]=
|
|
{
|
|
'0','1','2','3','4','5','6','7','8','9','*','+',0,'-','.','/'
|
|
};
|
|
static const BYTE asciiTable3[37]=
|
|
{
|
|
';','=',',','-','.','/','`', 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
'[', '\\', ']', '\''
|
|
};
|
|
static const BYTE asciiTable4[37]=
|
|
{
|
|
':','+','<','_','>','?','~', 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
'{', '|', '}', '"'
|
|
};
|
|
|
|
|
|
/*
|
|
* Write data to keyboard
|
|
*/
|
|
|
|
static void KbdWrite(int addr,BYTE data)
|
|
{
|
|
BYTE status;
|
|
|
|
do
|
|
{
|
|
status=inb_p(KBD_CTRL_PORT); // Wait until input buffer empty
|
|
} while(status & KBD_IBF);
|
|
outb_p(addr,data);
|
|
}
|
|
|
|
|
|
/*
|
|
* Read data from port 0x60
|
|
*/
|
|
|
|
static int KbdReadData(void)
|
|
{
|
|
int i;
|
|
BYTE status,data;
|
|
|
|
i=500000;
|
|
do
|
|
{
|
|
status=inb_p(KBD_CTRL_PORT);
|
|
if (!(status & KBD_OBF)) // Check if data available
|
|
continue;
|
|
data=inb_p(KBD_DATA_PORT);
|
|
if (status & (KBD_GTO | KBD_PERR)) // Check for timeout error
|
|
continue;
|
|
return data;
|
|
} while(--i);
|
|
return -1; // Timed out
|
|
}
|
|
|
|
|
|
/*
|
|
* Set keyboard LED's
|
|
*/
|
|
|
|
static void SetKeyboardLEDs(BYTE status)
|
|
{
|
|
KbdWrite(KBD_DATA_PORT,0xED);
|
|
if (KbdReadData()!=KBD_ACK) // Error
|
|
return;
|
|
KbdWrite(KBD_DATA_PORT,status);
|
|
KbdReadData();
|
|
}
|
|
|
|
|
|
/*
|
|
* Process scan code
|
|
*/
|
|
|
|
static void ProcessScanCode(BYTE scanCode,BOOL isDown)
|
|
{
|
|
switch(scanCode)
|
|
{
|
|
case 0x1D: // Ctrl
|
|
if (extKey)
|
|
{
|
|
if (isDown)
|
|
ctrlKeyState|=RIGHT_CTRL_PRESSED;
|
|
else
|
|
ctrlKeyState&=~RIGHT_CTRL_PRESSED;
|
|
}
|
|
else
|
|
{
|
|
if (isDown)
|
|
ctrlKeyState|=LEFT_CTRL_PRESSED;
|
|
else
|
|
ctrlKeyState&=~LEFT_CTRL_PRESSED;
|
|
}
|
|
break;
|
|
case 0x2A: // Left shift
|
|
case 0x36: // Right shift
|
|
if (isDown)
|
|
ctrlKeyState|=SHIFT_PRESSED;
|
|
else
|
|
ctrlKeyState&=~SHIFT_PRESSED;
|
|
break;
|
|
case 0x38: // Alt
|
|
if (extKey)
|
|
{
|
|
if (isDown)
|
|
ctrlKeyState|=RIGHT_ALT_PRESSED;
|
|
else
|
|
ctrlKeyState&=~RIGHT_ALT_PRESSED;
|
|
}
|
|
else
|
|
{
|
|
if (isDown)
|
|
ctrlKeyState|=LEFT_ALT_PRESSED;
|
|
else
|
|
ctrlKeyState&=~LEFT_ALT_PRESSED;
|
|
}
|
|
break;
|
|
case 0x3A: // CapsLock
|
|
if (ctrlKeyState & CTRL_PRESSED)
|
|
break;
|
|
if (isDown)
|
|
{
|
|
if (!capsDown)
|
|
{
|
|
capsDown=1;
|
|
if (ctrlKeyState & CAPSLOCK_ON)
|
|
{
|
|
ledStatus&=~KBD_LED_CAPS;
|
|
ctrlKeyState&=~CAPSLOCK_ON;
|
|
}
|
|
else
|
|
{
|
|
ledStatus|=KBD_LED_CAPS;
|
|
ctrlKeyState|=CAPSLOCK_ON;
|
|
}
|
|
SetKeyboardLEDs(ledStatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
capsDown=0;
|
|
}
|
|
break;
|
|
case 0x45: // NumLock
|
|
if (ctrlKeyState & CTRL_PRESSED)
|
|
break;
|
|
if (isDown)
|
|
{
|
|
if (!numDown)
|
|
{
|
|
numDown=1;
|
|
if (ctrlKeyState & NUMLOCK_ON)
|
|
{
|
|
ledStatus&=~KBD_LED_NUM;
|
|
ctrlKeyState&=~NUMLOCK_ON;
|
|
}
|
|
else
|
|
{
|
|
ledStatus|=KBD_LED_NUM;
|
|
ctrlKeyState|=NUMLOCK_ON;
|
|
}
|
|
SetKeyboardLEDs(ledStatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
numDown=0;
|
|
}
|
|
break;
|
|
case 0x46: // ScrollLock
|
|
if (ctrlKeyState & CTRL_PRESSED)
|
|
break;
|
|
if (isDown)
|
|
{
|
|
if (!scrollDown)
|
|
{
|
|
scrollDown=1;
|
|
if (ctrlKeyState & SCROLLLOCK_ON)
|
|
{
|
|
ledStatus&=~KBD_LED_SCROLL;
|
|
ctrlKeyState&=~SCROLLLOCK_ON;
|
|
}
|
|
else
|
|
{
|
|
ledStatus|=KBD_LED_SCROLL;
|
|
ctrlKeyState|=SCROLLLOCK_ON;
|
|
}
|
|
SetKeyboardLEDs(ledStatus);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
scrollDown=0;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Translate virtual key code to ASCII
|
|
*/
|
|
|
|
static BYTE VirtualToAscii(WORD keyCode,BOOL isDown)
|
|
{
|
|
if ((ctrlKeyState & ALT_PRESSED)&&(ctrlKeyState & CTRL_PRESSED))
|
|
return 0; // Ctrl+Alt+char always 0
|
|
if ((!isDown)&&(ctrlKeyState & ALT_PRESSED))
|
|
return 0; // Alt+char is 0 when key is released
|
|
|
|
if (ctrlKeyState & CTRL_PRESSED)
|
|
{
|
|
if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
|
|
return keyCode-VK_A+1;
|
|
switch(keyCode)
|
|
{
|
|
case VK_SPACE:
|
|
return ' ';
|
|
case VK_BACK:
|
|
return 127;
|
|
case VK_RETURN:
|
|
return 10;
|
|
case 219: /* [ */
|
|
if (ctrlKeyState & SHIFT_PRESSED)
|
|
return 0;
|
|
return 27;
|
|
case 220: /* \ */
|
|
if (ctrlKeyState & SHIFT_PRESSED)
|
|
return 0;
|
|
return 28;
|
|
case 221: /* ] */
|
|
if (ctrlKeyState & SHIFT_PRESSED)
|
|
return 0;
|
|
return 29;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
|
|
if (ctrlKeyState & CAPSLOCK_ON)
|
|
if (ctrlKeyState & SHIFT_PRESSED)
|
|
return keyCode-VK_A+'a';
|
|
else
|
|
return keyCode-VK_A+'A';
|
|
else
|
|
if (ctrlKeyState & SHIFT_PRESSED)
|
|
return keyCode-VK_A+'A';
|
|
else
|
|
return keyCode-VK_A+'a';
|
|
|
|
if ((keyCode>=VK_0)&&(keyCode<=VK_9))
|
|
if (ctrlKeyState & SHIFT_PRESSED)
|
|
return asciiTable1[keyCode-VK_0];
|
|
else
|
|
return keyCode-VK_0+'0';
|
|
|
|
if ((keyCode>=VK_NUMPAD0)&&(keyCode<=VK_DIVIDE))
|
|
return asciiTable2[keyCode-VK_NUMPAD0];
|
|
|
|
if ((keyCode>=186)&&(keyCode<=222))
|
|
if (ctrlKeyState & SHIFT_PRESSED)
|
|
return asciiTable4[keyCode-186];
|
|
else
|
|
return asciiTable3[keyCode-186];
|
|
|
|
switch(keyCode)
|
|
{
|
|
case VK_SPACE:
|
|
return ' ';
|
|
case VK_RETURN:
|
|
return 13;
|
|
case VK_BACK:
|
|
return 8;
|
|
case VK_TAB:
|
|
return 9;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Translate scan code to virtual key code
|
|
*/
|
|
|
|
static WORD ScanToVirtual(BYTE scanCode)
|
|
{
|
|
if ((scanCode>=0x47)&&(scanCode<=0x53)&&(ctrlKeyState & NUMLOCK_ON)&&
|
|
(!extKey)&&(!(ctrlKeyState & SHIFT_PRESSED)))
|
|
return vkKeypadTable[scanCode-0x47];
|
|
if ((scanCode==0x35)&&(extKey)) // Gray divide
|
|
return VK_DIVIDE;
|
|
if ((scanCode==0x37)&&(extKey)) // Print screen
|
|
return VK_PRINT;
|
|
return vkTable[scanCode];
|
|
}
|
|
|
|
|
|
/*
|
|
* Keyboard IRQ handler
|
|
*/
|
|
|
|
static VOID KbdDpcRoutine(PKDPC Dpc,
|
|
PVOID DeferredContext,
|
|
PVOID SystemArgument1,
|
|
PVOID SystemArgument2)
|
|
{
|
|
PIRP Irp = (PIRP)SystemArgument2;
|
|
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
|
|
|
|
CHECKPOINT;
|
|
DPRINT("KbdDpcRoutine(DeviceObject %x, Irp %x)\n",
|
|
DeviceObject,Irp);
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
IoStartNextPacket(DeviceObject,FALSE);
|
|
}
|
|
|
|
static unsigned int KeyboardHandler(unsigned int irq)
|
|
{
|
|
BYTE resp,thisKey;
|
|
BOOL isDown;
|
|
static BYTE lastKey;
|
|
|
|
CHECKPOINT;
|
|
|
|
// Read scan code
|
|
thisKey=inb_p(KBD_DATA_PORT);
|
|
if ((thisKey==0xE0)||(thisKey==0xE1)) // Extended key
|
|
{
|
|
extKey=1; // Wait for next byte
|
|
lastKey=thisKey;
|
|
return 0;
|
|
}
|
|
|
|
isDown=!(thisKey & 0x80);
|
|
thisKey&=0x7F;
|
|
|
|
// The keyboard maintains its own internal caps lock and num lock
|
|
// statuses. In caps lock mode E0 AA precedes make code and
|
|
// E0 2A follow break code. In num lock mode, E0 2A precedes
|
|
// make code and E0 AA follow break code. We maintain our own caps lock
|
|
// and num lock statuses, so we will just ignore these.
|
|
// Some keyboards have L-Shift/R-Shift modes instead of caps lock
|
|
// mode. If right shift pressed, E0 B6 / E0 36 pairs generated.
|
|
if (extKey & ((thisKey==0x2A)||(thisKey==0x36)))
|
|
{
|
|
extKey=0;
|
|
return 0;
|
|
}
|
|
|
|
// Check for PAUSE sequence
|
|
if (extKey && (lastKey==0xE1))
|
|
{
|
|
if (thisKey==0x1D)
|
|
lastKey=0xFF; // Sequence is OK
|
|
else
|
|
extKey=0;
|
|
return 0;
|
|
}
|
|
if (extKey && (lastKey==0xFF))
|
|
{
|
|
if (thisKey!=0x45)
|
|
{
|
|
extKey=0; // Bad sequence
|
|
return 0;
|
|
}
|
|
thisKey=0x7F; // Pseudo-code for PAUSE
|
|
}
|
|
|
|
ProcessScanCode(thisKey,isDown);
|
|
|
|
DPRINT("Key: '%c'\n",VirtualToAscii(ScanToVirtual(thisKey),isDown));
|
|
|
|
if (CurrentIrp!=NULL)
|
|
{
|
|
KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)
|
|
CurrentIrp->AssociatedIrp.SystemBuffer;
|
|
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(CurrentIrp);
|
|
|
|
CHECKPOINT;
|
|
|
|
rec[KeysRead].bKeyDown=isDown;
|
|
rec[KeysRead].wRepeatCount=1;
|
|
rec[KeysRead].wVirtualKeyCode=ScanToVirtual(thisKey);
|
|
rec[KeysRead].wVirtualScanCode=thisKey;
|
|
rec[KeysRead].AsciiChar=VirtualToAscii(rec->wVirtualKeyCode,isDown);
|
|
rec[KeysRead].dwControlKeyState=ctrlKeyState;
|
|
if (extKey)
|
|
{
|
|
rec[KeysRead].dwControlKeyState|=ENHANCED_KEY;
|
|
}
|
|
KeysRead++;
|
|
DPRINT("KeysRequired %d KeysRead %x\n",KeysRequired,KeysRead);
|
|
if (KeysRead==KeysRequired)
|
|
{
|
|
KeInsertQueueDpc(&KbdDpc,stk->DeviceObject,CurrentIrp);
|
|
CurrentIrp=NULL;
|
|
}
|
|
CHECKPOINT;
|
|
return(TRUE);
|
|
}
|
|
|
|
// Buffer is full ?
|
|
if (keysInBuffer==KBD_BUFFER_SIZE) // Buffer is full
|
|
{
|
|
extKey=0;
|
|
return 0;
|
|
}
|
|
kbdBuffer[bufHead].bKeyDown=isDown;
|
|
kbdBuffer[bufHead].wRepeatCount=1;
|
|
kbdBuffer[bufHead].wVirtualKeyCode=ScanToVirtual(thisKey);
|
|
kbdBuffer[bufHead].wVirtualScanCode=thisKey;
|
|
// kbdBuffer[bufHead].uChar.AsciiChar=TranslateScanCode(thisKey);
|
|
kbdBuffer[bufHead].AsciiChar=VirtualToAscii(kbdBuffer[bufHead].wVirtualKeyCode,isDown);
|
|
kbdBuffer[bufHead].dwControlKeyState=ctrlKeyState;
|
|
if (extKey)
|
|
kbdBuffer[bufHead].dwControlKeyState|=ENHANCED_KEY;
|
|
bufHead++;
|
|
bufHead&=KBD_WRAP_MASK; // Modulo KBD_BUFFER_SIZE
|
|
keysInBuffer++;
|
|
extKey=0;
|
|
}
|
|
|
|
|
|
//
|
|
// Initialize keyboard
|
|
//
|
|
static void KeyboardConnectInterrupt(void)
|
|
{
|
|
ULONG MappedIrq;
|
|
KIRQL Dirql;
|
|
KAFFINITY Affinity;
|
|
NTSTATUS Status;
|
|
|
|
MappedIrq = HalGetInterruptVector(Internal,
|
|
0,
|
|
0,
|
|
KEYBOARD_IRQ,
|
|
&Dirql,
|
|
&Affinity);
|
|
Status = IoConnectInterrupt(&KbdInterrupt,
|
|
KeyboardHandler,
|
|
NULL,
|
|
NULL,
|
|
MappedIrq,
|
|
Dirql,
|
|
Dirql,
|
|
0,
|
|
FALSE,
|
|
Affinity,
|
|
FALSE);
|
|
}
|
|
|
|
static int InitializeKeyboard(void)
|
|
{
|
|
// Initialize variables
|
|
bufHead=0;
|
|
bufTail=0;
|
|
keysInBuffer=0;
|
|
ledStatus=0;
|
|
capsDown=0;
|
|
numDown=0;
|
|
scrollDown=0;
|
|
ctrlKeyState=0;
|
|
extKey=0;
|
|
|
|
KeyboardConnectInterrupt();
|
|
KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Read data from keyboard buffer
|
|
*/
|
|
|
|
static void dummy(void)
|
|
{
|
|
}
|
|
|
|
BOOLEAN KbdSynchronizeRoutine(PVOID Context)
|
|
{
|
|
PIRP Irp = (PIRP)Context;
|
|
KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)
|
|
Irp->AssociatedIrp.SystemBuffer;
|
|
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
|
ULONG NrToRead = stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
|
|
int i;
|
|
|
|
DPRINT("NrToRead %d keysInBuffer %d\n",NrToRead,keysInBuffer);
|
|
NrToRead = min(NrToRead,keysInBuffer);
|
|
|
|
DPRINT("NrToRead %d stk->Parameters.Read.Length %d\n",
|
|
NrToRead,stk->Parameters.Read.Length);
|
|
DPRINT("sizeof(KEY_EVENT_RECORD) %d\n",sizeof(KEY_EVENT_RECORD));
|
|
for (i=0;i<NrToRead;i++)
|
|
{
|
|
memcpy(&rec[i],&kbdBuffer[bufTail],sizeof(KEY_EVENT_RECORD));
|
|
bufTail++;
|
|
bufTail&=KBD_WRAP_MASK;
|
|
keysInBuffer--;
|
|
}
|
|
if ((stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD))==NrToRead)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
KeysRequired=stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
|
|
KeysRead=NrToRead;
|
|
CurrentIrp=Irp;
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
VOID KbdStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
DPRINT("KeyboardStartIo(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
|
|
|
|
DPRINT("stk->Parameters.Read.Length %d\n",stk->Parameters.Read.Length);
|
|
DPRINT("KeysRequired %d\n",KeysRequired);
|
|
}
|
|
|
|
NTSTATUS KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("DeviceObject %x\n",DeviceObject);
|
|
DPRINT("Irp %x\n",Irp);
|
|
|
|
switch (stk->MajorFunction)
|
|
{
|
|
case IRP_MJ_CREATE:
|
|
case IRP_MJ_CLOSE:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IRP_MJ_READ:
|
|
DPRINT("Handling Read request\n");
|
|
if (KeSynchronizeExecution(KbdInterrupt,KbdSynchronizeRoutine,Irp))
|
|
{
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
DPRINT("Queueing packet\n");
|
|
IoStartPacket(DeviceObject,Irp,NULL,NULL);
|
|
Status = STATUS_PENDING;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
|
|
if (Status==STATUS_PENDING)
|
|
{
|
|
DPRINT("Marking irp pending\n");
|
|
IoMarkIrpPending(Irp);
|
|
}
|
|
else
|
|
{
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
}
|
|
DPRINT("Status %d\n",Status);
|
|
return(Status);
|
|
}
|
|
|
|
/*
|
|
* Module entry point
|
|
*/
|
|
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|
{
|
|
PDEVICE_OBJECT DeviceObject;
|
|
ANSI_STRING adevice_name;
|
|
UNICODE_STRING device_name;
|
|
|
|
DbgPrint("Keyboard Driver 0.0.4\n");
|
|
InitializeKeyboard();
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdDispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdDispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_READ] = KbdDispatch;
|
|
DriverObject->DriverStartIo = KbdStartIo;
|
|
|
|
RtlInitAnsiString(&adevice_name,"\\Device\\Keyboard");
|
|
RtlAnsiStringToUnicodeString(&device_name,&adevice_name,TRUE);
|
|
IoCreateDevice(DriverObject,0,&device_name,FILE_DEVICE_KEYBOARD,0,
|
|
TRUE,&DeviceObject);
|
|
DeviceObject->Flags = DO_BUFFERED_IO;
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|