|
发表于 2004-11-20 13:53:32
|
显示全部楼层
这是一本新书《嵌入式Linux应用开发详解》上的源码程序,另外你还可以参考一下“置顶:入门的朋友一起来读这本书啦!”邹思轶写的那本书里面也有相关介绍。
[php]
/*键盘驱动范例 keybd.c*/
/* Copyright (C) 1998 by Ori Pomerantz */
/*必要头文件*/
/*标准头文件*/
#include <linux/kernel.h> /*内核工作*/
#include <linux/module.h> /*明确指定是模块*/
/*处理 CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/sched.h>
#include <linux/tqueue.h>
/* 在程序中将用到中断 */
#include <linux/interrupt.h>
#include <asm/io.h>
/*在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" : "ressed");
}
/*这个函数为键盘中断服务。它读取来自键盘的相关信息,然后安排到当内核认为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);
}
[/php] |
|