Linux驱动——input子系统

一、input子系统基本框架

Linux内核为了两个目的:

  1. 简化纯输入类外设(如:键盘、鼠标、游戏杆、轨迹球、触摸屏。。。等等)的驱动开发

  2. 统一输入类外设产生的数据格式(struct input_event),更加方便应用层编程

设计了输入子系统

事件处理层:接收来自核心层上报的事件,并选择对应的handler(事件处理器 struct input_handler)去处理。内核维护着多个事件处理器对象,每个input_handler对象专门处理一类事件,所有产生同类事件的设备驱动共用同一个handler。

设备驱动层:主要实现获取硬件设备的数据信息(包括触摸屏被按下、按下位置、鼠标移动、键盘按下等等),并转换为核心层定义的规范事件后提交给核心层,该层每个设备对应一个struct input_dev对象,

核心层:负责连接设备驱动层和事件处理层,为设备驱动层提供输入设备驱动的接口(struct input_dev)以及输入设备驱动的注册函数(input_register_device),为事件处理层提供输入事件驱动的接口;通知事件处理层对事件进行处理。

二、驱动开发步骤

/*init或probe函数中:
1. 创建struct input_dev对象,使用input_allocate_device
2. 设置事件类型以及相关参数,使用set_bit
3. 注册struct input_dev对象,使用input_register_device
*/
​
/*exit或remove函数中:
1. 注销struct input_dev对象,使用input_unregister_device
2. 销毁struct input_dev对象,使用input_free_device
*/
​
/*上报事件两种事件上报方式:1. 对有中断支持的输入设备:在其中断处理函数(上半部或下半部)中上报事件2. 对无中断支持的输入设备:使用workqueue循环定时上报(struct delayed_work)主要函数:input_eventinput_report_absinput_sync
*/
​

相关接口:

/*_init*/
struct input_dev *input_allocate_device(void)//创建对象
​
void set_bit(struct input_dev *dev,unsigned long whichbits)//设置事件类型
​
void input_set_abs_params(struct input_dev *dev,unsigned int axis,int min,int max,int fuzz,int flat)//设置上报值的取值范围
​
int input_register_device(struct input_dev *dev)//注册input设备到内核
​
/*_exit*/
void input_unregister_device(struct input_dev *dev)
void input_free_device(struct input_dev *dev)
​
/*上报事件*/
void input_event(struct input_dev *,unsigned int t,unsigned int c,int v)
​
void input_report_key(struct input_dev *,unsigned int c,int v) //上报按键事件
void input_report_abs(struct input_dev *,unsigned int c,int v)//上报绝对坐标事件void input_sync(struct input_dev *)//上报完成后需要调用这些函数来通知系统处理完整事件
​
/*应用层数据类型*/
struct input_event {struct timeval time;       // 时间戳__u16 type;             // 事件类型__u16 code;             // 哪个分值__s32 value;            // 具体值      
};

三、fs4412key2-input版代码解析

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/platform_device.h>
#include<linux/device.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#include<linux/mm.h>
#include<linux/sched.h>
#include<linux/io.h>
#include<linux/slab.h>
#include<asm/atomic.h>
#include<linux/wait.h>
#include<linux/poll.h>
#include<linux/i2c.h>
#include<linux/input.h>
#include<linux/gpio.h>
#include<linux/interrupt.h>
#include<linux/of_gpio.h>
#include<linux/of_irq.h>
#include<linux/delay.h>
#include<linux/of.h>//函数声明,不声明会报错不知道是什么原因
struct device_node *of_find_node_by_path(const char *path);struct fs4412key2_dev{struct input_dev *pinput;int gpio;int irqno;};//自定义驱动结构体//定义全局指针
struct fs4412key2_dev *pdev = NULL;//中断处理函数,也就是当开发板摁下key2后执行的函数
irqreturn_t myfs4412key2_handle(int no,void *arg){struct fs4412key2_dev *pdev = (struct fs4412key2_dev *)arg;int status1 = 0;int status2 = 0;//读取引脚状态判断按键是否摁下,status2用来防抖status1 = gpio_get_value(pdev->gpio);mdelay(1);status2 = gpio_get_value(pdev->gpio);if(status1 != status2)return IRQ_NONE;if(status1){
//上报按键时间并通知系统来进行处理input_event(pdev->pinput,EV_KEY,KEY_2,0);input_sync(pdev->pinput);}else{input_event(pdev->pinput,EV_KEY,KEY_2,1);input_sync(pdev->pinput);}return IRQ_HANDLED;
}int __init fs4412key2_init(void){int ret = 0;struct device_node *pnode = NULL;//通过路径查找节点pnode = of_find_node_by_path("/mykey2_node");if(NULL == pnode){printk("find node failed\n");return -1;}pdev = (struct fs4412key2_dev *)kmalloc(sizeof(struct fs4412key2_dev),GFP_KERNEL);if(NULL == pdev){printk("kmalloc failed\n");return -1;}//提取gpio口pdev->gpio = of_get_named_gpio(pnode,"key2-gpio",0);
//获取中断号并进行映射pdev->irqno = irq_of_parse_and_map(pnode,0);pdev->pinput = input_allocate_device();set_bit(EV_KEY,pdev->pinput->evbit);set_bit(KEY_2,pdev->pinput->keybit);ret = input_register_device(pdev->pinput);
//申请中断ret = request_irq(pdev->irqno,myfs4412key2_handle,IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,"fs4412key2",pdev);if(ret){printk("request_irq failed\n");input_unregister_device(pdev->pinput);input_free_device(pdev->pinput);kfree(pdev);pdev = NULL;return -1;}return 0;}
void __exit fs4412key2_exit(void){free_irq(pdev->irqno,pdev); input_unregister_device(pdev->pinput);input_free_device(pdev->pinput);pdev->pinput = NULL;kfree(pdev);pdev = NULL;
}
#if 0
struct i2c_device_id fs4412key2_idt[] = {{"fs4412key2",0},{}
};
struct i2c_driver fs4412key2_dev = {.driver = {.name = "fs4412key2",.owner = THIS_MODULE,},.probe = fs4412key2_init,.remove = fs4412key2_exit,.id_table = fs4412key2_idt,};#endif//向内核注册一个i2c_driver对象
#if 0
int __init myfs4412key2_init(void){i2c_add_driver(&fs4412key2_dev);return 0;
}
//从内核注销一个i2c_driver对象
void __exit myfs4412key2_exit(void){i2c_del_driver(&fs4412key2_dev);
}
module_init(myfs4412key2_init);
module_exit(myfs4412key2_exit);
#else
//一个宏,同时完成注册和注销
//module_i2c_driver(fs4412key2_dev);
#endif
module_init(fs4412key2_init);
module_exit(fs4412key2_exit);MODULE_LICENSE("GPL");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/61069.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑马头条项目学习--Day3: 自媒体文章发布

Day3: 自媒体文章发布 Day3: 自媒体文章发布1) 素材管理-图片上传a) 前期微服务搭建b) 具体实现 2) 素材管理-图片列表a) 接口定义b) 具体实现 3) 素材管理-照片删除/收藏a) 图片删除a1) 接口定义a2) 代码实现 b) 收藏与取消b1) 接口定义b2) 代码实现 4) 文章管理-频道列表查询…

【C++】开源:gflags命令行参数解析库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍gflags命令行参数解析库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&…

【UE4 RTS】08-Setting up Game Clock

前言 本篇实现的效果是在游戏运行后能够记录当前的游戏时间&#xff08;年月日时分秒&#xff09;&#xff0c;并且可以通过修改变量从而改变游戏时间进行的快慢。 效果 步骤 1. 在Blueprints文件夹中新建如下两个文件夹&#xff0c;分别命名为“GameSettings”、“Player”…

递归神经网络简介

一、说明 说起递归神经网络&#xff0c;递归神经网络&#xff08;RNN&#xff09;主要包括以下几种类型&#xff1a; 简单的RNN&#xff08;Simple RNN&#xff09;&#xff1a;最基本的RNN类型&#xff0c;每个时刻的输出都与前面时刻的状态有关。 循环神经网络&#xff08;R…

软件第三方CMA、CNAS测试的目的和意义,信息化建设验收测试依据是什么?

在当今互联网时代&#xff0c;软件的第三方CMA、CNAS测试成为了软件行业的重要环节。那么&#xff0c;这个测试的目的和意义是什么呢?另外&#xff0c;信息化建设验收测试依据又是什么呢?    一、软件测试第三方CMA、CNAS测试的目的和意义 1、研究进展 随着软件行业的迅…

C++ 混合Python编程 及 Visual Studio配置

文章目录 需求配置环节明确安装的是64位Python安装目录 创建Console C ProjectCpp 调用 Python Demo 参考 需求 接手了一个C应用程序&#xff0c;解析csv和生成csv文件&#xff0c;但是如果要把多个csv文件合并成一个Excel&#xff0c;分布在不同的Sheet中&#xff0c;又想在一…

在Echarts中的tooltip上添加点击按钮

需求&#xff1a; 在Echarts的tooltips中添加点击按钮并可以鼠标悬停点击该按钮 功能实现&#xff1a; 在option中的tooltip添加enterable: true的属性&#xff0c;表示鼠标可以移入tooltip中再在formatter中添加 <button onclick"onTooltipsFun()" stylecursor:…

【Android】MVC,MVP,MVVM三种架构模式的区别

MVC 传统的代码架构模式&#xff0c;仅仅是对代码进行了分层&#xff0c;其中的C代表Controller&#xff0c;控制的意思 将代码划分为数据层&#xff0c;视图层&#xff0c;控制层&#xff0c;三层之间可以任意交互 MVP MVP是在MVC基础上改进而来的一种架构&#xff0c;其中的…

【深度学习注意力机制系列】—— CBAM注意力机制(附pytorch实现)

CBAM&#xff08;Convolutional Block Attention Module&#xff09;是一种用于增强卷积神经网络&#xff08;CNN&#xff09;性能的注意力机制模块。它由Sanghyun Woo等人在2018年的论文[1807.06521] CBAM: Convolutional Block Attention Module (arxiv.org)中提出。CBAM的主…

接口自动化测试框架及接口测试自动化主要知识点

接口自动化测试框架&#xff1a; 接口测试框架&#xff1a;使用最流行的Requests进行接口测试接口请求构造&#xff1a;常见的GET/POST/PUT/HEAD等HTTP请求构造 接口测试断言&#xff1a;状态码、返回内容等断言JSON/XML请求&#xff1a;发送json\xml请求JSON/XML响应断言&…

数据结构:各种结构函数参数辨析

&#xff08;一&#xff09;顺序表 1&#xff09;结构 typedef int SLDateType;typedef struct SeqList {SLDateType* data;int size;int capacity; }SeqList;SeqList ps { 0 }; 2&#xff09;函数参数 // 对数据的管理:增删查改 void SeqListInit(SeqList* ps); void Seq…

Linux系统目录结构介绍

Linux系统目录结构介绍 一、目录结构 Linux系统的目录结构是一颗倒状树&#xff1a; “/”表示最顶层的目录&#xff0c;叫做根目录。 &#xff08;1&#xff09;pwd可以显示当前所在的目录。 &#xff08;2&#xff09;cd可以切换当前的目录&#xff0c;例如&#xff0c;…