Энциклопедия разработчика модулей ядра Linux | страница 42
Этот код связывает себя с IRQ 1, который является IRQ клавиатуры, управляемой в архитектуре Intel. При получении прерывания от клавиатуры, он читает состояние клавиатуры (inb(0x64)) и скэн-кода, который является значением, возвращенным клавиатурой. Затем, как только ядро думает, что это выполнимо, выполняется got_char, который дает код используемой клавиши (первые семь битов скэн-кода) и была ли она нажата (если 8-ой бит нулевой) или отпущена (если он равен единице).
>/* intrpt.c - An interrupt handler. */
>/* Copyright (C) 1998 by Ori Pomerantz */
>/* The necessary header files */
>/* Standard in kernel modules */
>#include
>#include
>/* Deal with CONFIG_MODVERSIONS */
>#if CONFIG_MODVERSIONS==1
>#define MODVERSIONS
>#include
>#endif
>#include
>#include
>/* We want an interrupt */
>#include
>#include
>/* In 2.2.3 /usr/include/linux/version.h includes a
>* macro for this, but 2.0.35 doesn't - so I add it
>* here if necessary. */
>#ifndef KERNEL_VERSION
>#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
>#endif
>/* Bottom Half - this will get called by the kernel
>* as soon as it's safe to do everything normally
>* allowed by kernel modules. */
>static void got_char(void *scancode) {
> printk("Scan Code %x %s.\n", (int) *((char *) scancode) & 0x7F, *((char *) scancode) & 0x80 ? "Released" : "Pressed");
>}
>/* This function services keyboard interrupts. It reads
>* the relevant information from the keyboard and then
>* scheduales the bottom half to run when the kernel
>* considers it safe. */
>void irq_handler(int irq, void *dev_id, struct pt_regs *regs) {
> /* This variables are static because they need to be
> * accessible (through pointers) to the bottom
> * half routine. */
> static unsigned char scancode;
> static struct tq_struct task = {NULL, 0, got_char, &scancode};
> unsigned char status;
> /* Read keyboard status */
> status = inb(0x64);
> scancode = inb(0x60);
> /* Scheduale bottom half to run */
>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
> queue_task(&task, &tq_immediate);
>#else
> queue_task_irq(&task, &tq_immediate);
>#endif
> mark_bh(IMMEDIATE_BH);
>}
>/* Initialize the module - register the IRQ handler */
>int init_module() {
> /* Since the keyboard handler won't co-exist with
> * another handler, such as us, we have to disable
> * it (free its IRQ) before we do anything. Since we