linux输入子系统

本篇文章通过按键驱动为例讲解输入子系统的开发流程。

输入子系统由驱动层、输入子系统核心、事件处理层三部分组成。一个输入事件,如鼠标移动、键盘按下等通过Driver->Inputcore->Event handler->userspace的顺序到达用户控件的应用程序。

用于报告EV_KEY,EV_REL,EV_ABS事件的函数分别为
void input_report_key(struct input_dev *dev,unsigned int code,int value)
void input_report_rel(struct input_dev *dev,unsigned int code,int value)
void input_report_abs(struct input_dev *dev,unsigned int code,int value)

以上函数调用input_event函数上报事件。

set_bit告诉input输入子系统支持哪些事件,哪些按键。

事件类型包括EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等。

变量定义及初始化
struct pin_desc{
     int irq;
     char *name;
     unsigned int pin;
     unsigned int key_val;
};

struct pin_desc pins_desc[4] = {
     {IRQ_EINT0,  "S2", S3C2410_GPF0,   KEY_L},
     {IRQ_EINT2,  "S3", S3C2410_GPF2,   KEY_S},
     {IRQ_EINT11, "S4", S3C2410_GPG3,   KEY_ENTER},
     {IRQ_EINT19, "S5",  S3C2410_GPG11, KEY_LEFTSHIFT},
};
static struct input_dev *buttons_dev;

static struct pin_desc *irq_pd;
static struct timer_list buttons_timer;

1.分配input_dev结构体

buttons_dev = input_allocate_device();

2.设置

2.1设置能产生哪类事件
set_bit(EV_KEY, buttons_dev->evbit);//按键类事件
set_bit(EV_REP, buttons_dev->evbit);//重复类事件
2.2设置能产生这类操作里的哪些事件
set_bit(KEY_L, buttons_dev->keybit);
set_bit(KEY_S, buttons_dev->keybit);
set_bit(KEY_ENTER, buttons_dev->keybit);
set_bit(KEY_LEFTSHIFT, buttons_dev->keybit);
3.注册
input_register_device(buttons_dev);
4.初始化定时器,用于消除按键的抖动
init_timer(&buttosn_timer);
buttons_timer.function = buttons_timer_function;
add_timer(&buttons_timer);
5.申请按键中断
for (i=0;i<4;i++) {
      request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);
}

6.中断处理函数,在中断中保存当前按下按键的信息,并打开定时器

static irqreturn_t buttons_irq(int irq, void *dev_id)
{
     irq_pd = (struct pin_desc*)dev_id;
     mod_timer(&buttons_timer, jiffies + HZ/100);
     return IRQ_RETVAL(IRQ_HANDLed);
}
7.定时器中断,用于消除按键抖动,上报事件
static void buttons_timer_function(unsigned long data)
{
     struct pin_desc *pindesc = irq_pd;
     unsigned int pinval;
 
     if (!pindesc) {
          return;
     }
     pinval = s3c2410_gpio_getpin(pindesc->pin);
     if (pinval) {
          /* 松开 */
          input_event(buttons_dev, EV_KEY, pindesc->key_val, 0);//上报事件
          input_sync(buttons_dev);                //同步用于告诉input core子系统报告结束
     } else {
          /* 按下 */
          input_event(buttons_dev, EV_KEY, pindesc->key, 1);
          input_sync(buttons_dev);
     }
}
posted @ 2014-07-01 20:21  zpehome  阅读(291)  评论(0编辑  收藏  举报