没有合适的资源?快使用搜索试试~ 我知道了~
Linux设备模型之input子系统详解.docx
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 87 浏览量
2023-04-11
22:05:52
上传
评论
收藏 183KB DOCX 举报
温馨提示
试读
24页
Linux设备模型之input子系统详解.docx
资源推荐
资源详情
资源评论
Linux设备模型之input子系统详解(2011-10-17 08:56)标签:模型 设备 Linux input
分类:设备驱动
本文系本站原创,欢迎转载!
转载请注明出处: iex i ao. cub I og. 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子系统的例子,并附带相应的说明。以此
为例分析如下:
ttinclude <linux/input. h>ttinclude <linux/module. h>
ttinclude <linux/init.h>ttinclude <asm/irq. h>
ttinclude <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〃, buttonirq);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 input_handle_event (struct input_dev *dev,u
nsigned int type, unsigned int code, int value) {int disposition =
INPUT_IGNORE_EVENT;
switch (type) {case EV_SYN:
switch (code) {case SYN_CONFIG:
disposition 二
INPUT_PASS_TO_ALL;break;
case SYN_REPORT:
if (!dev->sync)
{dev->sync = 1;
disposition = INPUT_PASS_TO_HANDLERS;)
break;) break;
case EV_KEY:
〃判断按键值是否被支持
if (is_event_supported(code, dev-
>keybit, KEYJ1AX) &&!!test_bit (code,
dev->key) != value) {
if (value != 2)
{_changebit(code, dev->key);
if (value)input_start_autorepeat(dev, code);
disposition
=INPUT_PASS_TO_HA
NDLERS;
} break;case EVSW:
if (is_event_supported(code, dev-
>swbit, SWJ1AX) &&
!!test_bit (code, dev->sw) !=
value) {
_changebit(c ode,
dev->sw);
disposition =
INPUT_PASS_TO_HANDLERS;
) break;case EV_ABS:
if (is_event_supported(code, dev-
>absbit, ABS_MAX)) {
value =
input_defuzz_abs_event(value,dev->abs[code], dev->absfuzz[code]);
if (dev-
>abs[code] != value) {dev->abs[code]= value;
disposition = INPUT_PASS_TO_HANDLERS;)
)break;
case EV_REL:
if (is_event_supported(code, dev-
>relbit, RELMAX) && value)
disposition =
INPUT_PASS_TO_HANDLERS;break;
case EV_MSC:
if (is_event_supported(code,dev-
>mscbit, MSCMAX))
disposition =
INPUT_PASS_TO_ALL;break;
case EVLED:
if (is_event_supported(code, dev-
>ledbit, LEDJ1AX) &&
!!test_bit(code, dev->led) !=
value) {
—change_bit(c
ode, dev->led);
disposition =
INPUT_PASS_TO_ALL;}
break;case EV_SND:
if (is_event_supported(code, dev-
>sndbit, SNDJIAX)) {if
(!!test_bit(code, dev-〉snd) != !lvalue)—change_bit(code, dev->snd);
disposition 二
INPUT_PASS_TO_ALL;)
break;case EV REP:
if (code〈二 REPJIAX && value)= 0&&
dev->rep[code] != value) {
dev->rep[code]
=value;
disposition =
INPUT_PASS_TO_ALL;break;
case EV_FF:
if (value >= 0) disposition =
INPUT_PASS_TO_ALL;break;
case EV_PWR:
disposition = INPUT_PASS_TO_ALL;
break;)
if (type != EV_SYN) dev->sync = 0;
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
dev->event (dev, type, code,
value);if (disposition & INPUT_PASS_T0 HANDLERS)
input_pass_event (dev, type, code,
value);)
在这里,我们忽略掉具体事件的处理.到最后,如果该事件需要input device来完 成
的,就会将disposition设置成INPUT_PASS_T0 DEVICE.如果需要handler来 完成的,就
将dispostion设为INPUT_PASS_TO_DEVICE.如果需要两者都参与,将 disposition 设置
为 INPUT_PASS_TO_ALL.
需要输入设备参与的,回调设备的event函数.如果需要handler参与的.调用
input_pass_event ().代码如下:
static void input jass_event (struct input_dev *dev,unsig
ned int type, unsigned int code, int value) (struct input_handle "handle;
rcu_read_lock();handle = rcudereference(dev->grab);
if (handle)
handle->handler->event(handle, type,
code, value);else
list_for_each_entry_rcu(handle,&dev->h_list, dnode) (handle->open)
handle-〉handler—>event(handle,
type,
code, value);rcu_read_unlock();
) " "如果input device被强制指定了 handler,那么调用该handler的event函数.
结合handle注册的分析.我们知道.会将handle挂到input device的h list 链表上.
如果没有为input device强制指定handler.就会遍历input device->h_list 上的
handle成员.如果该handle被翻开,那么调用与输入设备对应的handler的 eventO函
数.注意,只有在handle被翻开的情况下才会接收到事件.
另外,输入设备的handler强制设置一般是用带EVIOCGRAB标志的ioctl来完成 的.如下
是发图的方示总结evnet的处理过程:
Inpu t_d e、事件处理图
「没自强却蟒逆的况.rfV力仃n【的&上的I磋 个hafhlk1.他〜工存6双input Jc中兀足 yihandlcrfi
f
, I^ •妇R E 所-与 mpul de、仃 ffEfi,.hindlcr 的GentF. M
我们已经分析了 input device, handler和handle的注册过程以及事件的上报
和 处理.下面以evdev为实例做分析.来贯穿理解一下整个过程.
七:evdev概述
Evdev 对应的设备节点一般位于/dev/input/eventO ~ /dev/input/event4.理 论上
可以对应32个设备节点.分别代表被handler匹配的32个input device.
可以用cat /dev/input/eventO.然后移动鼠标或者键盘按键就会有数据输出(两 者之
间只能选一.因为一个设备文件只能关能一个输入设备).还可以往这个文件 里写数
据,使其产生特定的事件.这个过程我们之后再详细分析.
为了分析这一过程,必须从input子系统的初始化说起.
八:input子系统的初始化Input子系统的初始化函数为input_init ().代码如下:
static int _init input_init (void){ — "
int err;err = class_register(&input_class);
if (err) {
printk (KERN_ERR 〃input: unable to
register input_dev class\n〃);
return err;err = input_proc_init();
if (err)
goto faill;
err = register_chrdev(INPUTMAJOR, “input”, &input_fops);if
(err) {
printk (KERN_ERR "input: unable to
register char major %d〃, INPUT MAJOR);
goto fail2;}
return 0;
fail2:input_proc_exit();
faill:class_unregister(&input_class);return err;
)在这个初始化函数里,先注册了一个名为" input”的类.所有input device都属 于
这个类.在sysfs中表现就是.所有input device所代表的目录都位于
剩余23页未读,继续阅读
资源评论
智慧安全方案
- 粉丝: 3607
- 资源: 59万+
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功