Hi,
My modified i8042prt driver works.
I have used I8xQueueCurrentKeyboardInput, because I don’t want to manage own
keyboard queue and this function can be called easy.
I know that this function is a callback function, it can be called from a
filter driver too. (So I can do everything in a filter driver).
My code fragments can be found in the end of this mail.I am happy now.
But I have a problem:
I want to use my keyboard in two cases:
1st) Standard keyboard and my keyboard connects to the PC in the same time
2nd) Only my keyboard connects.
The first case is OK.
In the second case there is Blue Screen Of Death.Of course the keyboard
driver not start because it didn’t detect any keyboard, but my code starts
(?).
What can I do?
a) I can move everything to a filter driver. Does the filter driver work in
the 2nd) case?
b) I can try to modify i8042prt: The driver starts in the 2nd) case too, but
in this case it doesn’t touch the original (standard) keyboard hardware
(because there is no original keyboard hardware). How can I do it?
c) There will be two port driver in the device stack: i8042prt, and mine. It
seems to be complicated.
Please help!
Thanks in advance,
Ferenc
MY CODE:
There are scan codes in the dual-port RAM mapped to the memory space.
These scan codes come from my keyboard.
I scan it (I sample it) in every 50 ms and if I find changes then I generate
keyboard messages.
I have added some extra member in COMMON_DATA:
typedef struct COMMON_DATA {
// Variables for setting the timer
KDPC pollingDPC;
KTIMER pollingTimer;
LARGE_INTEGER pollingInterval;
// The timer starts only once
UCHAR not_first;
// I can get three scan codes from my keyboard in the same time via
a dual-port RAM.
// This pointer points to the 1st one.
PUCHAR DualRam;
// I sampling the keyboard in every 50ms. These 3 bytes are read in
the previous sample
UCHAR old_keys[3];
// …
} *PCOMMON_DATA;
My extra lines in I8xAddDevice:
PHYSICAL_ADDRESS physAddr_dual;
// …
// Setup of the timer
commonData->pollingInterval = RtlConvertLongToLargeInteger(-10000000);
KeInitializeTimer(&commonData->pollingTimer);
KeInitializeDpc(&commonData->pollingDPC,PollingTimerDpc,(PVOID)device);
// Initialisation of not_first
commonData->not_first = 0;
//The scancodes are transported by the dual-port RAM.
//The physical address of the dual port RAM is 0x000b0000.
//My driver uses the 1st three bytes
physAddr_dual.LowPart = 0x000b0000;
physAddr_dual.HighPart = 0x00000000;
commonData->DualRam = MmMapIoSpace(physAddr_dual,3,MmNonCached);
Extra lines I8042KeyboardInterruptService (I know that this routine is not
the best place for these lines):
PCOMMON_DATA commonData;
// …
commonData = GET_COMMON_DATA(deviceExtension);
// I start the timer only once
if (!commonData->not_first)
{
KeSetTimerEx(&commonData->pollingTimer,commonData->pollingInterval,50,&commo
nData->pollingDPC);
commonData->not_first = 1;
}
My PollingTimerDpc routine runs in every 50msec.:
VOID PollingTimerDpc(IN PKDPC pDpc, IN PVOID pContext, IN PVOID SysArg1, IN
PVOID SysArg2)
{
//My keyboard has special scancodes, so I have to translate it
static UCHAR NctToScanTbl[113] = {
0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x00,0x00,0x00,0x00,0x00,0
x00,
0x1e,0x30,0x2e,0x20,0x12,0x21,0x22,0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,0
x19,
0x10,0x13,0x1f,0x14,0x16,0x2f,0x11,0x2d,0x15,0x2c,0x39,0x2a,0x00,0x00,0x00,0
x00,
0x08,0x09,0x0a,0x05,0x06,0x07,0x02,0x03,0x04,0x0c,0x0b,0x0d,0x00,0x00,0x00,0
x00,
0x29,0x0e,0x57,0x58,0x01,0x0f,0x1a,0x1b,0x2b,0x3a,0x27,0x28,0x1c,0x00,0x33,0
x34,
0x35,0x00,0x00,0x1d,0x00,0x38,0x00,0x00,0x36,0x38,0x00,0x1d,0x00,0x00,0x00,0
x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0
x00};
PDEVICE_OBJECT DeviceObject;
PPORT_KEYBOARD_EXTENSION deviceExtension;
PKEYBOARD_INPUT_DATA input;
UCHAR i,j;
UCHAR in_the_list;
UCHAR myscan;
PCOMMON_DATA commonData;
DeviceObject = (PDEVICE_OBJECT) pContext;
deviceExtension = (PPORT_KEYBOARD_EXTENSION)
DeviceObject->DeviceExtension;
commonData = GET_COMMON_DATA(DeviceObject->DeviceExtension);
// I check the scancodes in old_keys.
// If I don’t find one of them then I send “key up” message
for (i=0; i<=2; i++)
{
for (j=0, in_the_list=0; j<=2; j++)
{
if (commonData->old_keys[i] == *(commonData->DualRam + j))
in_the_list = 1;
}
if (! in_the_list )
{
myscan = NctToScanTbl[commonData->old_keys[i]];
if (!myscan)
{
// I send “key up”
input = &deviceExtension->CurrentInput;
input->MakeCode = myscan;
input->Flags = KEY_BREAK;
I8xQueueCurrentKeyboardInput(DeviceObject);
}
}
}
// I compare the 3 byte in the “DualRam” with the previous sample
// If there is new scan code in the “DualRam” then I send “key down”
message
for (i=0; i<=2; i++)
{
for (j=0, in_the_list =0; j<=2; j++)
{
if (commonData->old_keys[j] == *(commonData->DualRam + i))
in_the_list = 1;
}
if (! in_the_list )
{
myscan = NctToScanTbl[*(commonData->DualRam + i)];
if (!myscan)
{
// I send “key down”
input = &deviceExtension->CurrentInput;
input->MakeCode = NctToScanTbl[*(commonData->DualRam +
i)];
input->Flags = KEY_MAKE;
I8xQueueCurrentKeyboardInput(DeviceObject);
}
}
}
// I save the new sample
commonData->old_keys[0] = *(commonData->DualRam + 0);
commonData->old_keys[1] = *(commonData->DualRam + 1);
commonData->old_keys[2] = *(commonData->DualRam + 2);
}
----- Original Message -----
From: “Doron Holan”
To: “NT Developers Interest List”
Sent: Wednesday, January 08, 2003 8:21 PM
Subject: [ntdev] RE: i8042prt example installation
you can’t just copy it into %windir%\system32\drivers as I am guessing you
found out. Furthermore, you can’t really use the add new hardware wizard or
device manager to add your driver b/c you don’t want to write an INF.
To install your driver (and thereby bypassing the shipping i8042prt.sys, I
would
1 change the sources file in the example to give the binary another name,
say my8042.sys.
2 open hklm\system\currentcontrolset\services\i8042prt and change the
ImagePath value from “System32\DRIVERS\i8042prt.sys” to
“System32\DRIVERS\my8042.sys”
3 reboot
be careful here to either have a back up build or some other form of
recovery since your driver will always be loaded during boot (assuming there
are ps2 devices on your machine). If you do get stuck, goto your backup
build and copy i8042prt.sys to my8042.sys to recover.
D
(also, please note that you are not supposed to ship an 8042 replacement.
If you want to add 8042 added features, you should use a device upper filter
driver (see kbdfiltr in the ddk)).