linux 输入子系统(2)----简单实例分析系统结构(input_dev层)
实例代码如下:
- #include <linux/input.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <asm/irq.h>
- #include <asm/io.h>
- #define BUTTON_IRQ 123
- static struct input_dev *button_dev ;/*输入设备结构体*/
- static irqreturn_t button_interrupt(int irq, void *dummy) /*中断处理函数*/
- {
- input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & );/*向输入子系统报告产生按键事件*/ ===========》》》》》【3】
- input_sync(button_dev);/*通知接受者,一个报告发送完毕*/
- return IRQ_HANDLED;
- }
- static int __init button_init(void)
- {
- int error;
- if (request_irq(BUTTON_IRQ, button_interrupt, , "button", NULL)) { /*申请中断*/
- printk(KERN_ERR "button.c: Can't allocate irq %d\n", BUTTON_IRQ);
- return -EBUSY;
- }
- button_dev=input_allocate_device();/*分配一个设备结构体*/ ===========》》》》》》【1】
- if(!button_dev)
- {
- printk(KERN_ERR"button.c:Not enough memory\n");
- error= -ENOMEM;
- goto err_free_irq;
- }
- button_dev.evbit[] = BIT_MASK(EV_KEY);/*设置按键信息*/ 设置输入设备所支持的事件类型
- button_dev.keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
- error=input_register_device(button_dev);/*注册一个输入设备*/ ===========》》》》》》【2】
- if(error)
- {
- printk(KERN_ERR"failed to register device\n");
- goto err_free_dev;
- }
- return ;
- err_free_dev:
- input_free_device(button_dev);
- err_free_irq:
- free_irq(BUTTON_IRQ,button_interrupt);
- return error;
- }
- static void __exit button_exit(void)
- {
- input_unregister_device(button_dev);/*注销按键设备*/
- free_irq(BUTTON_IRQ, button_interrupt);/*释放按键占用的中断*/
- }
- module_init(button_init);
- module_exit(button_exit);
- 【1】input_allocate_device()函数分配一个input_dev结构体,输入设备用input_dev结构体描述。
- struct input_dev *input_allocate_device(void)
- {
- struct input_dev *dev;
- dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);/*分配一个input_dev结构体,并初始化为0*/
- if (dev) {
- dev->dev.type = &input_dev_type;/*初始化设备类型*/
- dev->dev.class = &input_class;/*设置为输入设备类*/
- device_initialize(&dev->dev);/*初始化device结构*/
- mutex_init(&dev->mutex);/*初始化互斥锁*/
- spin_lock_init(&dev->event_lock);/*初始化事件自旋锁*/
- INIT_LIST_HEAD(&dev->h_list);/*初始化链表*/
- INIT_LIST_HEAD(&dev->node);/*初始化链表*/
- __module_get(THIS_MODULE);
- }
- return dev;
- }
【2】input_register_device()将input_dev结构体注册到输入子系统核心中。
- int input_register_device(struct input_dev *dev)
- {
- static atomic_t input_no = ATOMIC_INIT();
- struct input_handler *handler;
- const char *path;
- int error;
- /* Every input device generates EV_SYN/SYN_REPORT events. */
- __set_bit(EV_SYN, dev->evbit);/*设置input_dev所支持的事件类型,由input_dev的evbit成员来表示*/
- /* KEY_RESERVED is not supposed to be transmitted to userspace. */
- __clear_bit(KEY_RESERVED, dev->keybit);
- /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
- input_cleanse_bitmasks(dev);
- /*
- * If delay and period are pre-set by the driver, then autorepeating
- * is handled by the driver itself and we don't do it in input.c.
- */
- init_timer(&dev->timer);/*初始化一个timer定时器,为处理重复击键*/
- if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
- dev->timer.data = (long) dev;
- dev->timer.function = input_repeat_key;
- dev->rep[REP_DELAY] = ;/*这两个值没有定义则设为默认,为自动处理重复按键定义*/
- dev->rep[REP_PERIOD] = ;
- }
- /*检查函数是否定义,未定义则使用默认*/
- if (!dev->getkeycode)
- dev->getkeycode = input_default_getkeycode;/*得到键值*/
- if (!dev->setkeycode)
- dev->setkeycode = input_default_setkeycode;/*设置键值*/
- dev_set_name(&dev->dev, "input%ld",
- (unsigned long) atomic_inc_return(&input_no) - );/*设置input_dev中的device 的名字,以input0/1/2出现在sysfs文件系统中*/
- error = device_add(&dev->dev);
- if (error)
- return error;
- path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
- printk(KERN_INFO "input: %s as %s\n",
- dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
- kfree(path);
- error = mutex_lock_interruptible(&input_mutex);
- if (error) {
- device_del(&dev->dev);
- return error;
- }
- list_add_tail(&dev->node, &input_dev_list);/*加入链表*/
- list_for_each_entry(handler, &input_handler_list, node)
- input_attach_handler(dev, handler);/*调用input_attach_handler来匹配input_dev和handler*/===========》》》》》》【2.1】
- input_wakeup_procfs_readers();
- mutex_unlock(&input_mutex);
- return ;
- }
- 其中input_dev所支持的事件类型在include/linux/input.h中定义,如下:
![]()
【2.1】input_attach_handler()匹配input_dev和handler。
- 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);/*handler 与dev之间的匹配*/
- if (!id)
- return -ENODEV;
- error = handler->connect(handler, dev, id);/*匹配成功,则调用connect将handler与dev连接起来*/
- if (error && error != -ENODEV)
- printk(KERN_ERR
- "input: failed to attach handler %s to device %s, "
- "error: %d\n",
- handler->name, kobject_name(&dev->dev.kobj), error);
- return error;
- }
总结【2】:注册input device 就是为input device 设置默认值,并将其挂接到input_dev_list中,并且与挂载在input_handler_list中的handler相匹配,如果匹配成功,则调用connect。
【3】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);
- }
- input_event()报告指定type、value的输入事件:
- void input_event(struct input_dev *dev,
- unsigned int type, unsigned int code, int value)
- {
- unsigned long flags;
- if (is_event_supported(type, dev->evbit, EV_MAX)) {
- spin_lock_irqsave(&dev->event_lock, flags);
- add_input_randomness(type, code, value);
- input_handle_event(dev, type, code, value);//向输入子系统传送事件信息,,不继续深入分析了-------------------------!!
- spin_unlock_irqrestore(&dev->event_lock, flags);
- }
- }
linux 输入子系统(2)----简单实例分析系统结构(input_dev层)的更多相关文章
- linux 输入子系统(3)----事件处理(input_handler层)
输入子系统主要设计input_dev.input_handler.input_handle.如下: [1]每个struct input_dev代表一个输入设备 struct input_dev { c ...
- linux输入子系统简述【转】
本文转载自:http://blog.csdn.net/xubin341719/article/details/7678035 1,linux输入子系统简述 其实驱动这部分大多还是转载别人的,linux ...
- 7.Linux 输入子系统分析
为什么要引入输入子系统? 在前面我们写了一些简单的字符设备的驱动程序,我们是怎么样打开一个设备并操作的呢? 一般都是在执行应用程序时,open一个特定的设备文件,如:/dev/buttons .... ...
- Linux输入子系统框架分析(1)
在Linux下的输入设备键盘.触摸屏.鼠标等都能够用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层.事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备 ...
- Linux输入子系统详解
input输入子系统框架 linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler).输入子系统核心层(Input ...
- linux输入子系统
linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件处理层(EventHandler).输入子系统核心层(InputCore)和输入子系统设备驱 ...
- Linux输入子系统(Input Subsystem)
Linux输入子系统(Input Subsystem) http://blog.csdn.net/lbmygf/article/details/7360084 input子系统分析 http://b ...
- linux输入子系统概念介绍
在此文章之前,我们讲解的都是简单的字符驱动,涉及的内容有字符驱动的框架.自动创建设备节点.linux中断.poll机制.异步通知.同步互斥.非阻塞.定时器去抖动. 上一节文章链接:http://blo ...
- linux输入子系统(input subsystem)之evdev.c事件处理过程
1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input ...
随机推荐
- Android进阶笔记13:RoboBinding(实现了数据绑定 Presentation Model(MVVM) 模式的Android开源框架)
1.RoboBinding RoboBinding是一个实现了数据绑定 Presentation Model(MVVM) 模式的Android开源框架.从简单的角度看,他移除了如addXXListen ...
- mysql root给其它用户授权问题
今天登录mysql,给其它用户授权遇到问题 mysql> grant all privileges on testdb.* to 'dbuser'@'10.4.14.14' identified ...
- Linux kill -9 和 kill -15 的区别
“我的天呀!”,网页编辑没有自动保存草稿的功能.害的我昨天写的东西都没有了.算了,不计较这些了.反正也没写多少. 嘻嘻. 大家对kill -9 肯定非常熟悉,在工作中也经常用到.特别是你去重启tomc ...
- 使用openoffice将word文件转换为pdf格式遇到问题:The type com.sun.star.lang.XEventListener cannot be resolved. It is indirectly referenced from required
The type com.sun.star.lang.XEventListener cannot be resolved. It is indirectly referenced from requi ...
- LeetCode 122
Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price of a ...
- [改善Java代码]Java的泛型是类型擦除的
泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...
- 如何通过wifi在android手机上安装调试应用
如何通过wifi在android手机上安装调试应用 1. 首先还是要打开手机的usb调试选项,并通过usb线连接手机.2. 然后执行“adb tcpip 5555”,把adb从usb模式切换到tcpi ...
- px和em之间的转换
很多网页设计者在写css时都是在通用选择器中就设置了字体的大小,中文情况下一般为12px.然而IE浏览器却无法调整那些使用px作为单位的字体大小.其实使用em作为单位是可以避免这一情况的. 一.em和 ...
- Memcached学习(三)
通过Java客户端实现与Memcached的交互,Java客户端的实现了使用了开源的Memcached-Java-Client,开源地址在GitHub上. 如下是通过该开源库实现的Memcached交 ...
- 初识 AutoLayout
一.使用"公式": 1.frame: 原点以及自身的位置来确定自身的位置 2.autoLayout: 根据参照视图的位置 来定义自己的位置 3.autoLayout: 相对布局 ...