input子系统

input子系统:
      像按键、键盘、鼠标、触摸屏、游戏摇杆等设备只有输入没有输出,而且在编程实现其对应的驱动程序时会有很多重复性的代码,内核的设计者将该部分代码抽象出来,驱动工程师只需要复用该部分代码,并且实现硬件相关的代码(中断号,中断触发条件),就可以可以很容易实现对应硬件的驱动程序 如何用复用input子系统中提供的通用函数功能模块, 要遵循以下步骤:
    核心数据结构
        struct input_dev
        {
            evbit//记录该设备将来会报告哪些事件
        }
    1)分配一个输入设备//定义一个input_dev类型变量
      input_allocate_device()
    2)设置input_dev
    
    3)注册input_dev
      input_register_device
    4)硬件操作
      注册中断服务程序
      延时去抖
      //保存按键值
    5)向input核心模块报告事件
      input_event(...)
    6)注销input_dev
      input_unregister_device
    7)释放输入设备
      input_free_device(...)

代码实例:

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/input.h>
  4 #include <linux/irq.h>
  5 #include <linux/interrupt.h>
  6 #include <asm/gpio.h>
  7 #include <plat/gpio-cfg.h>
  8 //定义按键硬件私有数据结构
  9 struct btn_resource {
 10     char *name; //名称
 11     int irq;    //中断号
 12     int gpio;   //GPIO编号
 13     int code;   //键值
 14 };
 15 
 16 //初始化开发板按键信息
 17 static struct btn_resource btn_info[] = {
 18     [0] = {
 19         .name = "KEY_L",
 20         .irq = IRQ_EINT(0),
 21         .gpio = S5PV210_GPH0(0),
 22         .code = KEY_L
 23     },
 24     [1] = {
 25         .name = "KEY_S",
 26         .irq = IRQ_EINT(1),
 27         .gpio = S5PV210_GPH0(1),
 28         .code = KEY_S
 29     },
 30     [2] = {
 31         .name = "KEY_ENTER",
 32         .irq = IRQ_EINT(2),
 33         .gpio = S5PV210_GPH0(2),
 34         .code = KEY_ENTER
 35     },
 36 };
 37 
 38 //定义input_dev指针
 39 static struct input_dev *btn_dev;
 40 
 41 //分配定时器
 42 static struct timer_list btn_timer;
 43 static struct btn_resource *pdata; 
 44 
 45 //定时器的处理函数
 46 static void btn_timer_func(unsigned long data)
 47 {
 48     unsigned int pinstate;
 49     
 50     //2.获取按键的状态
 51     pinstate = gpio_get_value(pdata->gpio);
 52 
 53     //3.上报按键信息给核心层然后唤醒休眠的进程
 54     if (pinstate == 1) { //松开
 55         //EV_KEY:上报按键类事件
 56         //pdata->code:具体键值
 57         //0:松开
 58         input_event(btn_dev, EV_KEY, pdata->code, 0);
 59         input_sync(btn_dev); //上报同步类事件
 60     } else {    //按下
 61         //EV_KEY:上报按键类事件
 62         //pdata->code:具体键值
 63         //1:按下
 64         input_event(btn_dev, EV_KEY, pdata->code, 1);
 65         input_sync(btn_dev);//上报同步类事件
 66     }
 67 }
 68 
 69 //中断处理函数
 70 static irqreturn_t button_isr(int irq, void *dev_id)
 71 {   
 72     //1.获取按键对应的数据项
 73     pdata = (struct btn_resource *)dev_id;
 74     
 75     //2.启动定时器,设置定时器的超时时间为10ms
 76     mod_timer(&btn_timer, jiffies + msecs_to_jiffies(10));
 77     return IRQ_HANDLED;
 78 }
 79 
 80 static int btn_init(void)
 81 {
 82     int i;
 83 
 84     //1.分配input_dev
 85     btn_dev = input_allocate_device();
 86     
 87     //2.初始化input_dev
 88     btn_dev->name = "wf_button";
 89     //2.1设置上报按键类事件
 90     set_bit(EV_KEY, btn_dev->evbit);
 91     //2.2设置上报重复类事件
 92     set_bit(EV_REP, btn_dev->evbit);
 93     //2.3设置上报按键类事件中的哪些键值
 94     for(i = 0; i < ARRAY_SIZE(btn_info); i++)
 95             set_bit(btn_info[i].code, btn_dev->keybit);
 96 
 97     //3.注册input_dev
 98     input_register_device(btn_dev);
 99     
100     //4.申请GPIO资源
101     //5.注册中断处理函数
102     for (i = 0; i < ARRAY_SIZE(btn_info); i++) {
103         gpio_request(btn_info[i].gpio, btn_info[i].name);
104         request_irq(btn_info[i].irq, button_isr/*中断处理函数*/,
105                 IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,/*下降沿和上升沿触发*/
106                 btn_info[i].name, &btn_info[i]/*给中断处理函数传递的参数*/);
107     }
108     
109     //6.初始化定时器 处理按键的毛刺
110     init_timer(&btn_timer);
111     
112     //6.1指定定时器的处理函数
113     btn_timer.function = btn_timer_func;
114     add_timer(&btn_timer);//将定时器添加到内核中
115     return 0;
116 }
117 
118 static void btn_exit(void)
119 {
120     int i;
121 
122     //1.释放中断,释放GPIO资源
123     for (i = 0; i < ARRAY_SIZE(btn_info); i++) {
124         gpio_free(btn_info[i].gpio);
125         free_irq(btn_info[i].irq, &btn_info[i]);
126     }
127 
128     //2.卸载input_dev
129     input_unregister_device(btn_dev);
130 
131     //3.释放input_dev内存
132     input_free_device(btn_dev);
133     
134     //4.删除定时器
135     del_timer(&btn_timer);
136 }
137 
138 module_init(btn_init);
139 module_exit(btn_exit);
140 MODULE_LICENSE("GPL");

测试代码:

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <linux/input.h> //input_event,标准键值等
 6 
 7 int main(int argc, char *argv[])
 8 {
 9     int fd;
10     struct input_event button;
11 
12     fd = open(argv[1], O_RDWR); //./btn_test /dev/input/event3
13     if (fd < 0) {
14         printf("open button failed.\n");
15         return -1;
16     }
17 
18     while(1) {
19         read(fd, &button, sizeof(button));
20         printf("type = %#x, code = %#x, value = %#x\n",
21                     button.type, button.code, button.value);
22     }
23 
24     close(fd);
25     return 0;
26 }

 

posted @ 2016-06-01 10:18  winfu  阅读(285)  评论(0编辑  收藏  举报