没有合适的资源?快使用搜索试试~ 我知道了~
Linux设备模型之input子系统详解.doc
0 下载量 166 浏览量
2022-12-01
06:22:49
上传
评论
收藏 228KB DOC 举报
温馨提示
试读
27页
Linux设备模型之input子系统详解.doc
资源推荐
资源详情
资源评论
Linux 设备模型之 input 子系统详解 (2011-10-17 08:56)
标签: 模型 设备 Linux input 分类: 设备驱动
------------------------------------------
本文系本站原创,欢迎转载!
转载请注明出处:http://ericxiao.cublog.cn/
------------------------------------------
一:前言
在键盘驱动代码分析的笔记中,接触到了 input 子系统.键盘驱动,键盘驱动将
检测到的所有按键都上报给了 input 子系统。Input 子系统是所有 I/O 设备驱动
的中间层,为上层提供了一个统一的界面。例如,在终端系统中,我们不需要去
管有多少个键盘,多少个鼠标。它只要从 input 子系统中去取对应的事件(按键,
鼠标移位等)就可以了。今天就对 input 子系统做一个详尽的分析.
下面的代码是基于 linux kernel 2.6.25.分析的代码主要位于
kernel2.6.25/drivers/input 下面.
二:使用 input 子系统的例子
在内核自带的文档 Documentation/input/input-programming.txt 中。有一个使
用 input 子系统的例子,并附带相应的说明。以此为例分析如下:
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/io.h>
static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) &
1);
input_sync(&button_dev);
}
static int __init button_init(void)
{
if (request_irq(BUTTON_IRQ, button_interrupt, 0,
"button", NULL)) {
printk(KERN_ERR "button.c: Can't
allocate irq %d", button_irq);
return -EBUSY;
}
button_dev.evbit[0] = BIT(EV_KEY);
button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0);
input_register_device(&button_dev);
}
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);
这个示例 module 代码还是比较简单,在初始化函数里注册了一个中断处理例程。
然后注册了一个 input device.在中断处理程序里,将接收到的按键上报给
input 子系统。
文档的作者在之后的分析里又对这个 module 作了优化。主要是在注册中断处理
的时序上。在修改过后的代码里,为 input device 定义了 open 函数,在 open
的时候再去注册中断处理例程。具体的信息请自行参考这篇文档。在资料缺乏的
情况下,kernel 自带的文档就是剖析 kernel 相关知识的最好资料.
文档的作者还分析了几个 api 函数。列举如下:
1):set_bit(EV_KEY, button_dev.evbit);
set_bit(BTN_0, button_dev.keybit);
分别用来设置设备所产生的事件以及上报的按键值。Struct iput_dev 中有两个
成员,一个是 evbit.一个是 keybit.分别用表示设备所支持的动作和按键类型。
2): input_register_device(&button_dev);
用来注册一个 input device.
3): input_report_key()
用于给上层上报一个按键动作
4): input_sync()
用来告诉上层,本次的事件已经完成了.
5): NBITS(x) - returns the length of a bitfield array in longs for x bits
LONG(x) - returns the index in the array in longs for bit x
BIT(x) - returns the index in a long for bit x
这几个宏在 input 子系统中经常用到。上面的英文解释已经很清楚了。
三:input 设备注册分析.
Input 设备注册的接口为:input_register_device()。代码如下:
int input_register_device(struct input_dev *dev)
{
static atomic_t input_no = ATOMIC_INIT(0);
struct input_handler *handler;
const char *path;
int error;
__set_bit(EV_SYN, dev->evbit);
/*
* 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);
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.data = (long) dev;
dev->timer.function =
input_repeat_key;
dev->rep[REP_DELAY] = 250;
dev->rep[REP_PERIOD] = 33;
}
在前面的分析中曾分析过。Input_device 的 evbit 表示该设备所支持的事件。
在这里将其 EV_SYN 置位,即所有设备都支持这个事件.如果
dev->rep[REP_DELAY]和 dev->rep[REP_PERIOD]没有设值,则将其赋默认值。这
主要是处理重复按键的.
if (!dev->getkeycode)
dev->getkeycode =
input_default_getkeycode;
if (!dev->setkeycode)
dev->setkeycode =
input_default_setkeycode;
snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"input%ld", (unsigned long)
atomic_inc_return(&input_no) - 1);
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;
}
如果 input device 没有定义 getkeycode 和 setkeycode.则将其赋默认值。还记
得在键盘驱动中的分析吗?这两个操作函数就可以用来取键的扫描码和设置键的
扫描码。然后调用 device_add()将 input_dev 中封装的 device 注册到 sysfs
list_add_tail(&dev->node, &input_dev_list);
list_for_each_entry(handler, &input_handler_list,
node)
input_attach_handler(dev,
handler);
input_wakeup_procfs_readers();
mutex_unlock(&input_mutex);
return 0;
}
这里就是重点了。将 input device 挂到 input_dev_list 链表上.然后,对每一
个挂在 input_handler_list 的 handler 调用 input_attach_handler().在这里
的情况有好比设备模型中的 device 和 driver 的匹配。所有的 input device 都
挂在 input_dev_list 链上。所有的 handle 都挂在 input_handler_list 上。
看一下这个匹配的详细过程。匹配是在 input_attach_handler()中完成的。代
码如下:
static int input_attach_handler(struct input_dev *dev, struct
input_handler *handler)
{
const struct input_device_id *id;
int error;
if (handler->blacklist &&
input_match_device(handler->blacklist, dev))
return -ENODEV;
id = input_match_device(handler->id_table, dev);
if (!id)
return -ENODEV;
error = handler->connect(handler, dev, id);
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;
}
如果 handle 的 blacklist 被赋值。要先匹配 blacklist 中的数据跟 dev->id 的
数据是否匹配。匹配成功过后再来匹配 handle->id 和 dev->id 中的数据。如果
匹配成功,则调用 handler->connect().
来看一下具体的数据匹配过程,这是在 input_match_device()中完成的。代码
如下:
static const struct input_device_id *input_match_device(const struct
input_device_id *id,
struct
input_dev *dev)
{
int i;
for (; id->flags || id->driver_info; id++) {
if (id->flags &
INPUT_DEVICE_ID_MATCH_BUS)
if
(id->bustype != dev->id.bustype)
continue;
if (id->flags &
INPUT_DEVICE_ID_MATCH_VENDOR)
if
(id->vendor != dev->id.vendor)
continue;
if (id->flags &
INPUT_DEVICE_ID_MATCH_PRODUCT)
if
(id->product != dev->id.product)
continue;
剩余26页未读,继续阅读
资源评论
xinkai1688
- 粉丝: 320
- 资源: 8万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- SSCMS登录模块需要的JS文件
- JSP网络购物中心毕业设计(源代码+论文).rar
- 白盒测试报告.docx
- 基于LM5117芯片评估开发板硬件参考设计(原理图+PCB)+中英文数据手册资料.zip
- 照片批量重命名软件(文件批量修改图片文件名)
- app.apk
- 人工智能(AI)是计算机科学的一个分支,旨在开发和应用能够模拟、延伸和扩展人类智能的理论、方法和技术,包括机器人、语言识别、图像
- 嵌入式与物联网开发是当今信息技术领域的两大重要分支,它们相互交织,共同推动着智能化时代的进步 嵌入式开发主要关注在嵌入式操作
- 网络安全,这一看似高深莫测的领域,实则与我们每个人的生活息息相关
- 毕业设计基于深度学习的视觉问答系统源码+文档说明+答辩PPT.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功