[概述]
介绍了基于输入子系统编写的简单按键驱动程序,对事件上报和输入设备初始化进行了详细分析。本驱动在mini2440开发板上能正常work。
[必要头文件和宏]
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEV_NAME "KEY1"
#define S3C2440 1
#if S3C2440 /*s3c2440 */
# defineBUTTON_IRQ IRQ_EINT8
#endif
staticstructinput_dev *button_dev;
[中断服务程序]
staticirqreturn_t button_interrupt(intirq,void*p)
{
/*get pin value */
intval = s3c2410_gpio_getpin(S3C2410_GPG(0));
/* val must a variable */
input_report_key(button_dev,KEY_1, val);
input_sync(button_dev);
returnIRQ_RETVAL(IRQ_HANDLED);
}
中断服务程序主要工作是将获得的按键值上报给input核心层;然后核心层对数据进行处理后上报给input处理层。
我们通过source insight,以按键事件为例来具体分析一下上报流程:
Input_report_key() -> input_event()->input_handle_event() ->input_pass_event() -> evdev_event() ->evdev_pass_event()
执行client->buffer[client->head++] = *event;这个赋值语句后,才把事件信息上报到用户空间的buffer中。
input_sync(button_dev)函数用来同步,比如触摸屏需要上报X坐标和Y坐标,然后在调用Input_sync函数,表示这是一组坐标值,否则会造成混乱。
值得注意的是,无论你下层发生了什么事件,www.linuxidc.com不管是按键,还是触摸屏,还是鼠标,事件信息都会以统一的格式发送到用户空间的buffer中,以供应用程序读取,这个统一的格式就是struct input_event
structinput_event {
structtimeval time;
__u16type;
__u16code;
__s32value;
};
Time 表示按键时间;
Type 表示事件类型;
Code 表示事件代码;
Value 表示事件值,按键事件等;
[模块初始化函数]
staticint__init button_init(void)
{
interr;
if(request_irq(BUTTON_IRQ, button_interrupt,
IRQ_TYPE_EDGE_BOTH,DEV_NAME, NULL) {
printk(KERN_ERR"cannotallocate irq");
return- EBUSY;
}
button_dev= input_allocate_device();
if(button_dev == NULL) {
printk(KERN_ERR"notenough memory\n");
err= - ENOMEM;
gotoerr_free_irq;
}
set_bit(EV_KEY,button_dev->evbit);
set_bit(KEY_1,button_dev->keybit);
err= input_register_device(button_dev);
if(err) {
printk(KERN_ERR"failedto register device\n");
gotoerr_free_dev;
}
printk("initialized\n");
return0;
err_free_dev:
input_free_device(button_dev);
err_free_irq:
free_irq(BUTTON_IRQ,&dev_id);
returnerr;
}
我们模块初始化函数做了两个工作:
1、 申请中断request_irq(BUTTON_IRQ,button_interrupt,
IRQ_TYPE_EDGE_BOTH,DEV_NAME, NULL)
BUTTON_IRQ 申请的中断号;
IRQ_TYPE_EDGE_BOTH 表示边沿触发方式;
DEV_NAME 申请中断的设备名;
第四个参数 用于共享中断,唯一的,用来判断共享中断线上究竟是哪个设备产生了中断。
2、 注册input设备
input_allocate_device函数用来分配一个input_dev结构体;
set_bit(EV_KEY,button_dev->evbit);
set_bit(KEY_1,button_dev->keybit);
用来设置设备支持的事件类型和按键代码,事件类型和代码定义在linux/input.h中;
input_register_device(button_dev) 函数把input设备注册到输入子系统中。
[模块卸载函数]
staticvoid__exit button_exit(void)
{
input_unregister_device(button_dev);
free_irq(BUTTON_IRQ,NULL);
}
module_init(button_init);
module_exit(button_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("CJOK ");
if you have any questions, please contact me or leave a comment, we will exchange views, it's good for us, so great!