IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 一、linux驱动开发-11.1-INPUT子系统 -> 正文阅读

[系统运维]一、linux驱动开发-11.1-INPUT子系统

一、前言

???????linux内核专门做了一个input子系统的框架来处理输入实践。输入设备的本质还是字符设备,只是在其基础上套上了input框架。

二、子系统

2.1、简介

???????input子系统就是管理输入的子系统,和pinctrl、gpio子系统一样,都是linux内核针对某一类设备而创建的框架,如下:

???????驱动编写只需要关注中间的驱动层、核心层、事件层,分工如下:

???????驱动层:输入设备的具体驱动程序,比如按键驱动程序,向内核层报告输入内容。
???????核心层:承上启下,为驱动层提供输入设备注册和操作接口。通知事件层对输入事件进行处理。
???????事件层:主要和用户空间进行交互

2.2、编写流程

???????input 核心层会向 Linux 内核注册一个字符设备,在drivers/input/input.c 这个文件,input.c 就是 input 输入子系统的核心层。

? ? ? ? 注册一个input类,系统启动后,就会在/sys/class目录下有一个input子目录。

???????input子系统的所有设备主设备号都为13,因此在使用input子系统处理输入设备的时候就不需要注册字符设备了,只需要向系统注册一个input_device即可。

2.2.1、注册input_dev

2.2.1.1、申请

???????input_dev表示input设备,定义在include/linux/input.h,使用input_allocate_device来申请。

/*
@return:申请到的input_dev
*/
struct input_dev *input_allocate_device(void)

???????如果要注销input设备,使用input_free_device来释放前面申请到的input_dev

/*
@dev:需要释放的input_dev
*/
void input_free_device(struct input_dev *dev)

2.2.1.2、初始化

???????需要初始化的内容主要为事件类型(evbit)和事件值(keybit)。

2.2.1.3、注册

? ? ? ?初始化完成后就需要向linux内核注册input_dev,

/*
@dev:要注册的input_dev

@return:0,成功
        <0,失败
*/
int input_register_device(struct input_dev *dev)

???????同样,注销驱动的时候也需要使用input_unregister_device函数来注销前面注册的input_dev,

/*
@dev:要注销的input_dev
*/
void input_unregister_device(struct input_dev *dev)

示例:

struct input_dev *inputdev;    //input结构体变量

static int __init xxx_init(void)
{
    //1、申请
    inputdev = input_allocate_device();     //申请input_dev
    inputdec->name = "test_input";          //设置input_dev名字

    //2、初始化
    /*********第一种设置事件和事件值的方法***********/
    __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);
    /************************************************/

    //3、注册
    input_register_device(inputdev);
}

static void __exit xxx_exit(void)
{
    //注销
    input_unregister_device(inputdev);

    //释放
    input_free_device(inputdev);
}

2.2.2、上报事件

???????向内核注册input_dev后,还得将获取到的具体输入值或者输入事件,上报给内核,比如在按键中断,定时中断中将按键值上报给内核,这样内核才能获取输入值。

不同的事件,其上报事件的API函数不同,下面是常见的:

/*
@description:上报指定的事件以及对应的值

@dev:需要上报的input_dev
@type:上报事件的类型,比如EV_KEY
@code:事件码,也就是注册的按键值,比如key_0
@value:事件值,比如1表示按键按下,0表示松开
*/
void input_event(struct input_dev *dev,
                 unsigned int type,
                 unsigned int code,
                 int value)

???????input_event 函数可以上报所有的事件类型和事件值,Linux 内核也提供了其他的针对具体事件的上报函数,这些函数其实都用到了 input_event 函数。比如上报按键所使用的input_report_key 函数:

static inline void input_report_key(struct input_dev *dev,
                                    unsigned int code, int value)
{
    input_event(dev, EV_KEY, code, !!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)
void input_report_ff_status(struct input_dev *dev, unsigned int code, int value)
void input_report_switch(struct input_dev *dev, unsigned int code, int value)
void input_mt_sync(struct input_dev *dev)

???????上报事件以后还需要使用input_sync函数来告诉内核input子系统上报结束:

/*
@dev:需要上报同步事件的input_dev
*/
void input_sync(struct input_dev *dev)

示例如下:

/* 用于按键消抖的定时器服务函数 */
void timer_function(unsigned long arg)
{
    unsigned char value;

    value = gpio_get_value(keydesc->gpio); /*  读取 IO  值 */
    if(value == 0){ /* 按下按键 */
        /*  上报按键值 */
        input_report_key(inputdev, KEY_0, 1); /*  最后一个参数 1 , 按下 */
        input_sync(inputdev); /* 同步事件 */
    } else { /* 按键松开 */
        input_report_key(inputdev, KEY_0, 0); /*  最后一个参数 0 , 松开 */
        input_sync(inputdev); /* 同步事件 */
    }
}

2.3、input_event结构体

????????Linux 内核使用 input_event 这个结构体来表示所有的输入事件,input_envent 结构体定义在include/uapi/linux/input.h 文件中,结构体内容如下

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-12-09 12:04:23  更:2021-12-09 12:06:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 4:45:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码