Linux驱动——input子系统

news2024/11/29 0:34:42

一、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_event
    input_report_abs
    input_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.coloradmin.cn/o/858011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将你的计算机变身为果园守护者:与本地树莓派建立连结的乐趣探索!!

如何连接本地树莓派 文章目录 如何连接本地树莓派前言1. 操作流程2. 打开树莓派SSH功能3. 确认树莓派信息后 安装相应SSH客户端 &#x1f341; 小结 &#x1f341; 前言 树莓派作为一款以教育为目的推出的硬件系统&#xff0c;也是超低功耗的微型“准系统”&#xff0c;能够提…

Redis的RDB持久化

Redis是一个键值对数据库服务器&#xff0c;服务器中通常包含着任意个非空数据库&#xff0c;而每个非空数据库中又可以包含任意个键值对&#xff0c;为了方便起见&#xff0c;我们将服务器中的非空数据库以及它们的键值对统称为数据库状态。 举个例子&#xff0c;下图展示了一…

模仿学习(行为克隆,逆强化学习,生成式对抗模仿学习)

目录 1.模仿学习 1.1先说强化学习 1.2再说逆强化学习 1.3最后说生成对抗模仿学习 1.3.1先说GAN 1.3.2再说生成对抗模仿学习 1.4逆强化学习常用方法 参考文献 1.模仿学习 定义&#xff1a;当我们想训练机器人时&#xff0c;通过复制人类的动作&#xff0c;对机器人进行训…

ssm新生报到系统源码和论文PPT

ssm新生报到系统源码和论文PPT004 开发环境 开发工具&#xff1a;idea 数据库mysql5.7(mysql5.7最佳) 数据库链接工具&#xff1a;navcat,小海豚等 开发技术&#xff1a;java ssm tomcat8.5 选题依据及意义 每学年九月份随着新生的入校&#xff0c;学校工作中的重点都会集…

Endnote中导入和显示中文文献国标格式具体实现步骤

Endnote中导入和显示中文文献国标格式具体实现步骤 目录 Endnote中导入和显示中文文献国标格式具体实现步骤一、下载中文文献引用标准格式二、将下载的两种格式复制到Endnote安装文件下的Styles子文件夹中三、对导入的样式进行标记&#xff0c;以便在word中方便显示和使用四、在…

领航优配:美联储货币政策风向或已生变 私行纵论下半年黄金配置价值

美联储钱银方针风向或已生变&#xff0c;黄金的拥趸开端跃跃欲试。 费城联储主席帕特里克哈克周二标明&#xff0c;美国有一条通往经济软着陆的路径&#xff0c;失业率或许有所上升&#xff0c;但起伏不会太大&#xff1b;不希望美联储过度收紧钱银方针&#xff0c;估计明年某时…

springBoot整合RabbitMq实现手动确认消息

如何保证消息的可靠性投递&#xff1f; 1.保证生产者向broke可靠性投递&#xff0c;开启ack投递成功确认&#xff0c;如果失败的话进行消息补偿 /*** author yueF_L* date 2023-08-10 01:32* ConfirmCallback&#xff1a;消息只要被 RabbitMQ broker 接收到就会触发confirm方…

OpenAI-Translator 实战总结

最近在极客时间学习《AI 大模型应用开发实战营》&#xff0c;自己一边跟着学一边开发了一个进阶版本的 OpenAI-Translator&#xff0c;在这里简单记录下开发过程和心得体会&#xff0c;供有兴趣的同学参考 功能概览 通过openai的chat API&#xff0c;实现一个pdf翻译器实现一个…

牛客小白月赛75C题题解

文章目录 方豆子问题建模问题分析代码 方豆子 问题建模 给定一个整数n&#xff0c;要求输出n级好豆豆&#xff0c;n级好豆豆由3个n-1级好豆豆和1个n-1级坏豆豆组成&#xff0c;已经给出了1级好豆豆和1级坏豆豆。 问题分析 由于最终的豆豆是由其上一级的豆豆产生的&#xff0…

将应用设置成系统App/获取Android设备SN号

1&#xff0c;和系统签名一致&#xff1b;&#xff08;签名设置签名文件&#xff09; 2&#xff0c;配置Manifest 至此你的App就是一个系统App了&#xff0c;可以执行一些系统App才能有的操作&#xff0c;如获取机器SN号&#xff1a; public String getSerialNumber() {Strin…

如何系统的学习单片机?

一、学习单片机需要的一些基础知识 &#xff08;1&#xff09;要具有一些模电、数电的知识&#xff08;不一定要精通&#xff0c;但基本至少要知道&#xff09; &#xff08;2&#xff09;具备C语言基础&#xff0c;有基础就可以入门了。数据结构、设计模式、汇编这些&#x…

IAR目标代码4字节对齐

向工程添加文件 eof.c : // 文件头 #if defined(__CC_ARM) // MDK // uint32_t g_update_flag[2] __attribute__((zero_init, at(0x1000FFF0)));const unsigned long gc_eof __attribute__((used)) 0xFFFFFFFFul; #elif defined(__ICCARM__) // IAR__root const unsigned…

【ur3机械臂配置夹爪Robotiq2F-85】

【ur3机械臂配置夹爪Robotiq2F-85】 1. 前言2. 按照官网要求清点安装设备3. 在示教器上配置夹爪3.1 另一头连接好夹爪和缆线3.2 下载官网驱动 5. 总结 1. 前言 欢迎大家阅读2345VOR的博客【ur3机械臂配置夹爪Robotiq2F-85】&#x1f973;&#x1f973;&#x1f973;2345VOR鹏鹏…

【100天精通python】Day31:使用python操作数据库_数据库编程接口,连接对象和游标对象,数据库连接配置

专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/qq_35831906/category_12375510.html 数据库编程接口是用于连接、操作和管理数据库的一组函数、类和方法。不同类型的数据库可能有不同的编程接口。以下是一些常见的数据库编程接口&#xff1a; 一、数据库编程接口 …

Android AOSP源码编译——AOSP下载(一)

一、电脑配置 Ubuntu16.04 16G&#xff0c;硬盘的大小最好大于300G (我这边是找了个win电脑装了双系统 没有使用虚拟机的方式) 二、基础环境配置 1、安装git sudo apt install git配置git email和name git config --global user.email "youexample.com" git conf…

大环境下,企业如何找到大数据传输解决方案

随着网络技术的进步和智能设备的普及&#xff0c;大数据成为了当下社会的热点话题。但是&#xff0c;大数据的传输和处理仍然存在着很多的困难和挑战。在大数据传输中&#xff0c;如何解决数据量巨大、网络带宽不足、传输时间过长和数据安全等问题&#xff0c;是当前亟待破解的…

zmibra ssl证书替换

一、阿里云上申请证书 选择其他证书 二、证书上传及制作 首先当然要去阿里云申请的ssl证书下载其他类型证书,解压缩后有两个文件上传到相应目录, 文件名类似18131-mail.xxx.comkey和181111-mail.xxx.com.pem 创建目录 /opt/zimbra/ssl/aliyunssl/ 上传这两个文件 以上是…

JVM 查看配置 jinfo 及使用 jstat,查看堆栈jstack及GC

1. Jinfo 查看正在运行的Java应用程序的扩展参数: 包含 JVM 参数与 java 系统参数 命令&#xff1a; jinfo pid 2 jstat 查看堆内存使用情况及 GC 回收频率等&#xff1a; jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数] 2.1 jstat -gc pid 最常用&#xff0c;可…

多区域平台lazada,虾皮电商商品详情API接口返回值说明

Lazada和虾皮&#xff08;Shopee&#xff09;都是知名的电商平台&#xff0c;主要在东南亚地区运营。以下是关于它们的一些信息&#xff1a; Lazada&#xff08;来赞达&#xff09;&#xff1a; Lazada成立于2012年&#xff0c;起初是一个全球性的电子商务平台&#xff0c;后来…

如何使用Mac终端给树莓派pico构建C/C++程序进行开发,以及遇到各种问题该怎么处理,不使用任何IDE或编辑器(例如VS Code)

写本文的原因是官方的教程已经过时了&#xff0c;如果你现在按照官方教程来在 Mac 上进行配置&#xff0c;那么会遇到一堆问题&#xff0c;比如我几乎把能踩的“雷”都踩了。所以这里记录了完整过程&#xff0c;以及各种错误的原因和处理方法&#xff0c;不然以后换 Mac 了或者…