linux输入子系统点灯,按键实例 - Linux驱动子系统之输入子系统_Linux编程_Linux公社-Linux系统门户网站...

[概述]

介绍了基于输入子系统编写的简单按键驱动程序,对事件上报和输入设备初始化进行了详细分析。本驱动在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! 0b1331709591d260c1c78e86d0c51c18.png

你可能感兴趣的:(linux输入子系统点灯)