Обработчик прерываний клавиатуры, который выводит пользовательские коды сканирования, не работает - linux - PullRequest
0 голосов
/ 19 марта 2020

Я хочу создать модуль ядра, который регистрирует обработчик прерываний для клавиатуры. Обработчик прерываний будет выводить пользовательские коды сканирования вместо тех, которые пользователь фактически набрал. Это не работает - после освобождения обработчика по умолчанию на терминал выводится новая строка вместо моих кодов сканирования. Еще одна странная вещь: я проверил с помощью inb(), и скан-код с клавиатуры всегда равен «7а» со статусом «Выпущено».
Поэтому у меня есть два вопроса:

  1. Что вызывает это странное поведение?
  2. Почему мои скан-коды не печатаются?

Заранее спасибо:)

Вот мой код:

#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);

Заранее спасибо!

...