I've been attempting to write a driver that snoops data on they
keyboard as keyboard interrupts are raised on IRQ 1 (defined as
KEYBOARD_IRQ in /usr/src/include/ibm/interrupt.h). However, I register
my driver using irq 1 and i 0x1F (id 0xA is returned from the
sys_irqsetpolicy call), and I my driver never receives any HARD_INT
messages from the kernel when the keyboard is used.
The only driver I've successfully gotten to get HARD_INT messages from
the kernel was one that installed an ISR for IRQ 0 (CLOCK_IRQ in
/usr/src/include/ibm/interrupt.h).
Any help with this would be greatly appreciated, and I've pasted my
code below (builds with GCC 4.1.1 using G++).
Again... many many many thanks in advance, because I just can't figure
this out.
P.S.: Does the kernel only allow one ISR to attach itself for certain
IRQs such as the keyboard and allow multiple ISRs on other IRQs?
++++++ BEGIN PASTE ++++++
#define _SYSTEM 1
#define _MINIX 1
#include <minix/config.h>
#include <ibm/interrupt.h>
#include <ansi.h>
#include <minix/type.h>
#include <minix/sysutil.h>
#include <minix/com.h>
#include <minix/ipc.h>
#include <minix/syslib.h>
#include <fstream>
#include <stdlib.h>
#include <unistd.h>
using namespace std;
static const int IO_KEYBD_DATA= 0x60; // I/O data port for AT
keyboard.
static int i=0;
int main()
{
//int irq=CLOCK_IRQ;
//int id=irq+2;
int irq=KEYBOARD_IRQ;
int id=0x1F;
int ret = sys_irqsetpolicy(irq, 0, &id);
if (ret) {
panic("DRVR", "error setting policy", ret);
}
ret = sys_irqenable(&id);
if (ret) {
panic("DRVR", "error enabling interrupts", ret);
}
ofstream dout, sout;
dout.open("/tmp/keyboard.out");
dout << id << endl;
while (1) {
message m;
unsigned long dataByte=0;
ret = receive(ANY, &m);
if (ret) {
panic("DRVR", "error receiving packet", ret);
}
switch(m.m_type) {
case HARD_INT:
ret = sys_irqenable(&id);
if (ret) {
panic("DRVR", "error enabling interrupts", ret);
}
sout.open("/tmp/keybdStats.out");
sout << ++i << '\n';
sout.close();
/*
ret = sys_inb(IO_KEYBD_DATA, &dataByte);
if (ret) {
panic("DRVR", "error reading data.", ret);
}
*/
dout << dataByte;
dout.flush();
break;
default:
ret = sys_irqrmpolicy(irq, &id);
if (ret) {
panic("DRVR", "error removing policy", ret);
}
}
dout.close();
}
return 0;
}
Anyway, logging into the system using a VMware console solved the
problem. Now I have a basic driver that snoops the interrupts and
stores the keyboard scancodes it reads.
I thought I'd post this info for anyone that might be interested or
stuck in the future.