Энциклопедия разработчика модулей ядра Linux | страница 42



Этот код связывает себя с IRQ 1, который является IRQ клавиатуры, управляемой в архитектуре Intel. При получении прерывания от клавиатуры, он читает состояние клавиатуры (inb(0x64)) и скэн-кода, который является значением, возвращенным клавиатурой. Затем, как только ядро думает, что это выполнимо, выполняется got_char, который дает код используемой клавиши (первые семь битов скэн-кода) и была ли она нажата (если 8-ой бит нулевой) или отпущена (если он равен единице).

intrpt.c

>/* intrpt.c - An interrupt handler. */

>/* Copyright (C) 1998 by Ori Pomerantz */


>/* The necessary header files */

>/* Standard in kernel modules */

>#include    /* We're doing kernel work */

>#include    /* Specifically, a module */


>/* 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