I want to create a kernel module that registers an interrupt handler for the keyboard.
The interrupt handler will output custom scancodes instead of the ones the user actually typed.
It doesn't work - after freeing the default handler, the output to the terminal is new line, instead of my scancodes.
Another strange thing, is that I checked with inb()
and the scancode from the keyboard is always '7a' with status "Released".
So I have two questions:
- What causes this strange behaviour?
- Why my scancodes are not printed?
Thanks in advance :)
Here is my code:
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/io.h>
MODULE_LICENSE("GPL");
#define KBD_IRQ 1 /* IRQ number for keyboard (i8042) */
#define KBD_DATA_REG 0x60 /* I/O port for keyboard data */
#define KBD_SCANCODE_MASK 0x7f
static int current_index = 0;
static int text_len = 2;
static int scancodes[2] = {0x15, 0x1e};
static irqreturn_t keyboard_intr_handler(int irq, void *dev)
{
printk(KERN_INFO "in interrupt handler\n");
char scancode = scancodes[current_index];
printk(KERN_INFO "got scancode %x\n", scancode);
current_index++;
if (text_len == current_index)
current_index = 0;
printk(KERN_INFO "gonna output scancode\n");
outb(KBD_DATA_REG, scancode);
printk(KERN_INFO "outputed scancode\n");
return IRQ_HANDLED;
}
static int __init my_register_interrupt(void)
{
struct irq_desc* desc = irq_to_desc(1);
struct irqaction *action, **action_ptr;
action_ptr = &desc->action;
action = *action_ptr;
free_irq(1, action->dev_id);
printk(KERN_INFO "in init\n");
if (request_irq(KBD_IRQ, keyboard_intr_handler, IRQF_SHARED,
"i8042", (void*) keyboard_intr_handler)) {
printk(KERN_ERR "my_device: cannot register IRQ 1\n");
return -EIO;
}
return 0;
}
static void __exit my_unregister_interrupt(void)
{
free_irq(1, (void*) keyboard_intr_handler);
}
module_init(my_register_interrupt);
module_exit(my_unregister_interrupt);
Thanks in advance!