以下这段代码能够在 X86 上很好的运行,他主要是重新分配键盘的 IRQ ,读取键盘的数据寄存器,安排队列的运行,最终打印出 scancode 的值和按键状态。 #include linux /kernel.h #include lin" name="description" />
MILY: 宋体">以下这段代码能够在X86上很好的运行,他主要是重新分配键盘的IRQ,读取键盘的数据寄存器,安排队列的运行,最终打印出scancode的值和按键状态。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/keyboard.h>
/* Bottom Half - 一旦内核模块认为它做任何事都是安全的时候这将被内核调用。 */
static void got_char(void *scancode)
{
printk("Scan Code %x %s.n",
(int) *((char *) scancode) & 0x
*((char *) scancode) & 0x80 ? "Released" : "Pressed");
}
/* 这个函数为键盘中断服务。它读取来自键盘的相关信息然后安排当内核认为bottom half安全的时候让它运行 */
void irq_handler(int irq,
void *dev_id,
struct pt_regs *regs)
{
/* 这些变量是静态的,因为它们需要对 bottom half 可见(通过指针)。 */
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);
/* 安排 bottom half 运行 */
#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);
}
/* 初始化模块--登记 IRQ 句柄 */
int init_module()
{
/* 既然键盘的句柄不能和我们的共存,在我们做事情前我们不得不关闭它(释放它的 IRQ)。
* 因为我们不知道它在哪儿,所以以后没有办法恢复它--因此当我们做完时计算机将被重新启动。
*/
free_irq(1, NULL);
/* 请求 IRQ 1,键盘的 IRQ,指向我们的 irq_handler。 */
return request_irq(
1, /* PC上的键盘的 IRQ 号 */
irq_handler, /* 我们的句柄 */
SA_SHIRQ,
/* SA_SHIRQ 意味着我们将另一个句柄用于这个 IRQ。
*
* SA_INTERRUPT 能使句柄为一个快速中断。
*/
"test_keyboard_irq_handler", NULL);
}
/* 清除 */
void cleanup_module()
{
/* 它在这儿只是为了完全。它是完全不相关的,因为我们没有办法恢复通常的键盘中断因此计算机完全没用 * 了,需要被重新启动。 */
free_irq(1, NULL);
}