• 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.
    ");
    15         return -1;
    16     }
    17 
    18     while(1) {
    19         read(fd, &button, sizeof(button));
    20         printf("type = %#x, code = %#x, value = %#x
    ",
    21                     button.type, button.code, button.value);
    22     }
    23 
    24     close(fd);
    25     return 0;
    26 }
  • 相关阅读:
    使用 Python 编码和解码 JSON 对象
    搞定github下载加速
    git错误:fatal: Could not read from remote repository.解决
    webstorm安装配置
    node.js下载安装
    IDEA安装小配置
    JAVA软件安装
    关于升级一般软件的一些想法
    linux 的 逻辑卷管理
    记一次内核升级。
  • 原文地址:https://www.cnblogs.com/winfu/p/5548703.html
Copyright © 2020-2023  润新知