Linux input子系统学习总结(二)----Input事件驱动

时间:2022-08-31 20:22:40

Input 事件驱动:  (主要文件 :drivers/input/evdev.c  、  drivers/input/input.h)基于kernel 4.0 

一、 关键函数调用顺序:

1、input_register_handler(&evdev_handler); ///注册 evdev_handler 这个input事件驱evdev.c   

 

2、input_attach_handler(dev, handler);////input 设备和 input 事件进行匹配   input.h

 

3、handler->connect(handler, dev, id);///调用evdev_handler 的 connect 函数(.connect = evdev_connect

 

4、evdev_connect(struct input_handler *handler, struct input_dev *dev,

const struct input_device_id *id)

 

5、cdev_init(&evdev->cdev, &evdev_fops);//// 初始化一个 cdev

 

6、device_add(&evdev->dev);///把初始化好的 evdev 添加到内核

              Linux input子系统学习总结(二)----Input事件驱动

  在系统启动时系统会注册input事件驱动 evdev_handler,通过遍历系统中已经存在input设备,并与之进行匹配,匹配成功即条用connect函数

创建evdev设备,即input设备节点,初始化完成之后,上层应用程序通过evdev_fops对输入设备节点进行open/write/read/ioctrl等一系列操作,

从而完成input输入子系统的整个功能实现;

 

二、关键代码段

 static struct input_handler evdev_handler = {
.event = evdev_event,
.events = evdev_events,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.legacy_minors = true,
.minor = EVDEV_MINOR_BASE,///次设备号从64开始
.name = "evdev",
.id_table = evdev_ids,
}; static int __init evdev_init(void)
{
return input_register_handler(&evdev_handler); ///注册 evdev_handler 这个input事件驱动
}
 int input_register_handler(struct input_handler *handler)///把input 事件驱动注册到内核
{
struct input_dev *dev;
int error; error = mutex_lock_interruptible(&input_mutex);
if (error)
return error; INIT_LIST_HEAD(&handler->h_list);///初始化链表头,把链表的前和后都指向它自己 list_add_tail(&handler->node, &input_handler_list);///把 handler的 node 加到 input_handler_list这个双向链表,之后就可以通过这个链表访问所有的input_handler list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);////inout 设备和 input 事件进行匹配 input_wakeup_procfs_readers(); mutex_unlock(&input_mutex);
return ;
}
 static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error; id = input_match_device(handler, dev);///input_dev 和 input_handler 通过id_table进行匹配
if (!id)
return -ENODEV; error = handler->connect(handler, dev, id);///如果返回id不为空就执行handler 的 connect ---> 调用 evdev.c 的 connect 函数
if (error && error != -ENODEV)
pr_err("failed to attach handler %s to device %s, error: %d\n",
handler->name, kobject_name(&dev->dev.kobj), error); return error;
}
 /*
* Create new evdev device. Note that input core serializes calls
* to connect and disconnect.
*/
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
int minor;
int dev_no;
int error; minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);//动态分配一个新的设备号minor
if (minor < ) {
error = minor;
pr_err("failed to reserve new minor: %d\n", error);
return error;
} evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);///初始化evdev ,为evdev分配空间
if (!evdev) {
error = -ENOMEM;
goto err_free_minor;
} INIT_LIST_HEAD(&evdev->client_list);///初始化队列
spin_lock_init(&evdev->client_lock);
mutex_init(&evdev->mutex);
init_waitqueue_head(&evdev->wait);///初始化等待队列
evdev->exist = true; dev_no = minor;
/* Normalize device number if it falls into legacy range */
if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)
dev_no -= EVDEV_MINOR_BASE;
dev_set_name(&evdev->dev, "event%d", dev_no);///给设备设置名字(event0、event1、...) evdev->handle.dev = input_get_device(dev);
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;
evdev->handle.private = evdev; evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);////根据主设备号(主设备号都是13)和次设备号生成一个设备号(次设备号从64开始)
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
evdev->dev.release = evdev_free;
device_initialize(&evdev->dev);///对设备进行初始化 error = input_register_handle(&evdev->handle);///注册 handle,handle 用来关联 input_dev 和 input_handler
if (error)
goto err_free_evdev; cdev_init(&evdev->cdev, &evdev_fops);//// 初始化一个 cdev
evdev->cdev.kobj.parent = &evdev->dev.kobj;
error = cdev_add(&evdev->cdev, evdev->dev.devt, );
if (error)
goto err_unregister_handle; error = device_add(&evdev->dev);///把初始化好的 evdev 添加到内核
if (error)
goto err_cleanup_evdev; return ; err_cleanup_evdev:
evdev_cleanup(evdev);
err_unregister_handle:
input_unregister_handle(&evdev->handle);
err_free_evdev:
put_device(&evdev->dev);
err_free_minor:
input_free_minor(minor);
return error;
}

如下图 ,在linux 系统上 /dev/input这个路径下可以看到已经注册好的input设备节点,input设备的主设备号都是13,其中

按键设备的次设备号从64~95,鼠标设备的次设备号从32~63。

Linux input子系统学习总结(二)----Input事件驱动

Linux input子系统学习总结(二)----Input事件驱动的更多相关文章

  1. input子系统学习笔记六 按键驱动实例分析下【转】

    转自:http://blog.chinaunix.net/uid-20776117-id-3212095.html 本文接着input子系统学习笔记五 按键驱动实例分析上接续分析这个按键驱动实例! i ...

  2. input子系统分析之二&colon;数据结构

    内核版本:3.9.5 1. input_dev,用来标识输入设备 struct input_dev { const char *name; const char *phys; const char * ...

  3. Linux时间子系统之(二):软件架构

    专题文档汇总目录 Notes:从框架上讲解了时间子系统,从底向上包括CPU Local TImer.Global Counter.Clock Souce/Clock Events模块管理.Tick D ...

  4. Linux Input子系统浅析(二)-- 模拟tp上报键值【转】

    转自:https://blog.csdn.net/xiaopangzi313/article/details/52383226 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...

  5. linux输入子系统(6)-input子系统介绍及结构图

    注:本系列转自: http://www.ourunix.org/post/290.html input子系统介绍         输入设备(如按键,键盘,触摸屏,鼠标,蜂鸣器等)是典型的字符设备,其一 ...

  6. linux 输入子系统(4)---- input子系统的初始化

    Input子系统的初始化函数为input_init(),如下: static int __init input_init(void) { int err; input_init_abs_bypass( ...

  7. Linux input子系统学习总结(三)----Input设备驱动

    Input 设备驱动 ---操作硬件获取硬件寄存器中设备输入的数据,并把数据交给核心层: 一 .设备驱动的注册步骤: 1.分配一个struct  input_dev :          struct ...

  8. Linux input子系统学习总结(一)---- 三个重要的结构体

    一 . 总体架构 图 上层是图形界面和应用程序,通过监听设备节点,获取用户相应的输入事件,根据输入事件来做出相应的反应:eventX (X从0开始)表示 按键事件,mice 表示鼠标事件 Input ...

  9. Linux System Programming 学习笔记&lpar;二&rpar; 文件I&sol;O

    1.每个Linux进程都有一个最大打开文件数,默认情况下,最大值是1024 文件描述符不仅可以引用普通文件,也可以引用套接字socket,目录,管道(everything is a file) 默认情 ...

随机推荐

  1. Two Sum Leetcode Java

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  2. 开发者所需要知道的 iOS 10 SDK 新特性

    转自:https://onevcat.com/2016/06/ios-10-sdk/ 写的很好啊.哈哈哈 总览 距离 iPhone 横空出世已经过去了 9 个年头,iOS 的版本号也跨入了两位数.在我 ...

  3. poj 1985 Cow Marathon 树的直径

    题目链接:http://poj.org/problem?id=1985 After hearing about the epidemic of obesity in the USA, Farmer J ...

  4. 10 个实用的 jQuery 表单操作代码片段

    jQuery 绝对是一个伟大的开源JavaScript类库,是帮助我们快速和高效开发前端应用的利器.可能大家在日常的开发过程中常常会处理表单相关的 JavaScript,在今天这篇代码片段分享文章中, ...

  5. PL&sol;SQL Developer 在windows7 64位系统下连Oaracle11g64位系统的解决经验

    PL/SQL Developer 在windows7 64位系统下连Oaracle11g64位系统的解决经验 一.问题现象及解决方法 现象: 1.PL/SQL 无法登录64位数据库 2.在PL/SQL ...

  6. lock锁速记

    1.Lock关键字主要实现锁互斥,确保一个线程A在请求此操作时不会被其线程B请求中断(假设A先请求并在没有未完成的操作情况下申请了此互斥锁).lock的参数必须是基于引用类型的对象,不要是基本类型像b ...

  7. pip离线安装python包

    1 首先在一台能上网的机器上得到python包 1) 新建一个空目录,如 /home/ubuntu/zcy/ss,用来存储下载下来的所需安装包 2)下载安装包:pip install --downlo ...

  8. java 的Calendar类的可视化日历示例

    import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; imp ...

  9. Sqli-labs介绍、下载、安装

    SQLI和sqli-labs介绍 SQLI,sql injection,我们称之为sql注入.何为sql,英文:Structured Query Language,叫做结构化查询语言.常见的结构化数据 ...

  10. 1&period;1&lpar;学习笔记)JSP(Java Server Pages)基础(脚本元素、指令元素)

    一.JSP简介 JSP全称为Java Server Pages,是一种动态网页开发技术,可以在HTML界面中嵌入java代码, 实现动态的提供数据.访问JSP时服务器会将JSP翻译成Servlet,访 ...