当前位置: 首页 > news >正文

【IMX6ULL驱动学习】INPUT子系统

13. INPUT子系统

13.1. INPUT子系统框架

  • INPUT子系统和pinctrlgpio子系统类似,都是 Linux 内核针对某一类设备而创建的框架。INPUT子系统针对的是输入设备,比如键盘、鼠标、触摸屏等。
    请添加图片描述

INPUT子系统主要包含以下几个部分

  1. 内核空间-驱动层:探测输入设备,初始化硬件,轮询输入事件,并将采集到的数据初始化为INPUT子系统的标准事件,调用input_event(), input_report_key()等函数将事件上报给INPUT子系统
  2. 内核空间-核心层:提供API,定义标准的输入事件
  3. 内核空间-事件层:创建INPUT设备节点,实现文件操作接口readwriteioctl等函数,供用户空间程序访问,将从核心层得到的事件转换为用户空间的标准数据格式
  4. 用户空间:调用openreadioctl等函数访问INPUT设备节点,获取输入事件

13.2. INPUT子系统驱动编写

在核心层,INPUT子系统已经注册了一个字符设备,并得到了一个主设备号,在驱动文件中,就不需要专门给INPUT子系统创建字符设备和设备节点了,只需要构建input_dev结构体变量,设置好设备的属性,然后通过input_register_device函数将设备注册到INPUT子系统即可

13.2.1. 构建input_dev结构体变量

  1. 构建数据结构,存放驱动运行所需的所有数据
    struct input_dev {const char *name;const char *phys;const char *uniq;struct input_id id;unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];unsigned long evbit[BITS_TO_LONGS(EV_CNT)];    /* 事件类型的位图 */unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; /* 按键值的位图 */unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; /* 相对坐标的位图 */unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; /* 绝对坐标的位图 */unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; /* 杂项事件的位图 */unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; /* LED 相关的位图 */unsigned long sndbit[BITS_TO_LONGS(SND_CNT)]; /* sound 有关的位图 */unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];  /* 压力反馈的位图 */unsigned long swbit[BITS_TO_LONGS(SW_CNT)];  /* 开关状态的位图 */bool devres_managed;
    };
    
    其中evbit表示设备支持的事件类型,keybit表示设备支持的按键值,relbit表示设备支持的相对坐标,absbit表示设备支持的绝对坐标等。evbit可选的事件类型如下
    #define EV_SYN   0x00    /* 同步事件 */
    #define EV_KEY   0x01    /* 按键事件 */
    #define EV_REL   0x02    /* 相对坐标事件 */
    #define EV_ABS   0x03    /* 绝对坐标事件 */
    #define EV_MSC   0x04    /* 杂项(其他)事件 */
    #define EV_SW    0x05    /* 开关事件 */
    #define EV_LED   0x11    /* LED */
    #define EV_SND   0x12    /* sound(声音) */
    #define EV REP   0x14    /* 重复事件 */
    #define EV_FF    0x15    /* 压力事件 */
    #define EV_PWR   0x16    /* 电源事件 */
    #define EV_FF_STATUS 0x17 /* 压力状态事件 */
    
    如果需要使用某个事件,就需要向INPUT子系统注册这个事件,比如要使用到按键,按键的按键值可选值如下**(所有事件通用)**
    #define KEY_RESERVED 0
    #define KEY_ESC 1
    #define KEY_1 2
    #define KEY_2 3
    #define KEY_3 4
    #define KEY_4 5
    #define KEY_5 6
    #define KEY_6 7
    #define KEY_7 8
    #define KEY_8 9
    #define KEY_9 10
    #define KEY_0 11...
    #define BTN_TRIGGER_HAPPY39 0x2e6
    #define BTN_TRIGGER_HAPPY40 0x2e7
    
    按键事件需要注册EV_KEY 事件,如果要使用连按功能的话还需要注册 EV_REP 事件,以下有三种注册方式
    /************* 第一种设置事件和事件值的方法 *************/
    __set_bit(EV_KEY, inputdev->evbit);    /* 设置产生按键事件 */
    __set_bit(EV_REP, inputdev->evbit);    /* 重复事件 */
    __set_bit(KEY_0, inputdev->keybit);    /* 设置产生哪些按键值 *//************* 第二种设置事件和事件值的方法 *************/
    keyinputdev.inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
    keyinputdev.inputdev->keybit[BIT_WORD(KEY_0)] |= BIT_MASK(KEY_0);/************* 第三种设置事件和事件值的方法 *************/
    keyinputdev.inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
    input_set_capability(keyinputdev.inputdev, EV_KEY, KEY_0);/* 注册 input_dev */
    input_register_device(inputdev);
    
    完整的驱动文件中,构建input_dev结构体变量的代码如下
    struct input_dev *inputdev;  /* 定义一个input_dev结构体指针 */
    static __init xxx_init(Void){int ret;.../* 1. 分配input_dev结构体 */inputdev = input_allocate_device();if(!inputdev){printk("input_allocate_device err\n");return -ENOMEM;}/* 2. 设置设备属性 */inputdev->name = "my_input";  /* 设备名称 *//* 3. 设置事件类型和事件值 */inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); /* 设置产生按键事件和重复事件 */inputdev->keybit[BIT_WORD(KEY_0)] |= BIT_MASK(KEY_0);     /* 设置产生哪些按键值 *//* 4. 注册 input_dev */ret = input_register_device(inputdev);if(ret){printk("input_register_device err\n");input_free_device(inputdev);}		return 0;
    }
    static __exit xxx_exit(void){/* 注销 input_dev */input_unregister_device(inputdev);/* 释放 input_dev 结构体 */input_free_device(inputdev);
    }
    

13.2.2. 上报事件

注册完input_dev结构体变量后,只是构建了一个可能发生事件的框架,当事件真正发生,需要调用API进行上报

  1. input_event函数

    void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
    
    • dev:input_dev结构体变量
    • type:事件类型,比如EV_KEY,EV_REL等
    • code:事件值,比如KEY_0,REL_X等
    • value:事件值的状态,比如按下为1,松开为0,保持为2

    input_event 函数可以上报所有的事件类型和事件值,比如检测到了按下按键KEY_0,可以调用以下代码上报事件

    input_event(inputdev, EV_KEY, KEY_0, 1); /* 按下 */
    input_event(inputdev, EV_SYN, SYN_REPORT, 0); /* 同步 */
    

    还有其他上报函数针对特定事件,但都是调用input_event函数实现的

  2. input_sync函数

    void input_sync(struct input_dev *dev);
    
    • dev:input_dev结构体变量

    input_sync函数用于同步事件,因为一次上报的事件不一定只有一件事,可能有多件事,比如按下按键KEY_0,同时移动鼠标,这时需要调用input_event函数上报多次事件,最后调用input_sync函数进行同步,告知内核,此次事件上报结束。

http://www.dtcms.com/a/446378.html

相关文章:

  • 上海做网站建设公司代理注册公司流程和费用
  • spring6学习笔记
  • 资料代做网站网站建设维护合同
  • 【Linux】 开启关闭MediaMTX服务
  • 网站qq启动链接怎么做宁波seo网络推广定制多少钱
  • 下载站用什么cms公众号微网站建设
  • 南阳做网站 汉狮公司wordpress游客
  • 网站建设比较好的律所无锡专业网站营销
  • 建设网站要注意哪些成都网站关键词
  • 违规管理系统后端接口文档
  • 月票车本地数据API后端实现文档
  • Scrapy 中间件详解:自定义下载器与爬虫的 “拦截器”
  • jQuery Mobile 过渡
  • 网站外链优化抖音代运营协议书范本
  • Java 变量命名规则
  • 经营网站挣钱网页制作三剑客是什么
  • mysql主从配置(保姆级)
  • 高端建设网站公司哪个网站可以做设计比赛
  • 陵水网站建设装修设计公司网络下载软件
  • 数据结构与算法篇--结构不变式--动态数组
  • 做企业网站前期需要准备什么网站做定制还是固定模板
  • 模板引擎驱动的动态计划书生成系统
  • 网站建设与维护好学吗做网站优化有什么方法
  • BLDCPMSM电机控制器硬件设计工程(四)控制器功率模块IGBT和SIC MOS介绍及驱动方案
  • opencart做视频网站哪些php网站
  • 追踪 - 两张图片引发的地理位置暴露
  • 基于「YOLO目标检测 + 多模态AI分析」的光伏板缺陷检测分析系统(vue+flask+模型训练+AI算法)
  • 【Misc】CTFSHOW 入门 wp
  • 网站优化分析杭州网站建设公司
  • 每日一个C语言知识:C语言基础语法