www.pudn.com > 嵌入式linux9应用开发祥解.rar > keyboard.C
/*键盘驱动范例 keybd.c*/ /* Copyright (C) 1998 by Ori Pomerantz */ /*必要头文件*/ /*标准头文件*/ #include/*内核工作*/ #include /*明确指定是模块*/ /*处理 CONFIG_MODVERSIONS */ #if CONFIG_MODVERSIONS==1 #define MODVERSIONS #include #endif #include #include /* 在程序中将用到中断 */ #include #include /*在2.2.3 版/usr/include/linux/version.h 中包含这个宏 * 但 2.0.35 版不包含-因此在这加入以被需要*/ #ifndef KERNEL_VERSION #define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) #endif /*Bottom Half - 一旦内核模块认为它做任何事都是安全的时候这将被内核调用*/ static void got_char(void *scancode) { printk("Scan Code %x %s.\n", (int) *((char *) scancode) & 0x7F, *((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; /*读取键盘状态*/ 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); }