Linux设备模型之input子系统详解Word下载.docx
- 文档编号:21113212
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:32
- 大小:71.30KB
Linux设备模型之input子系统详解Word下载.docx
《Linux设备模型之input子系统详解Word下载.docx》由会员分享,可在线阅读,更多相关《Linux设备模型之input子系统详解Word下载.docx(32页珍藏版)》请在冰豆网上搜索。
asm/io.h>
staticvoidbutton_interrupt(intirq,void*dummy,structpt_regs*fp)
{
input_report_key(&
button_dev,BTN_1,inb(BUTTON_PORT)&
1);
input_sync(&
button_dev);
}
staticint__initbutton_init(void)
if(request_irq(BUTTON_IRQ,button_interrupt,0,"
button"
NULL)){
printk(KERN_ERR"
button.c:
Can'
tallocateirq%d\n"
button_irq);
return-EBUSY;
}
button_dev.evbit[0]=BIT(EV_KEY);
button_dev.keybit[LONG(BTN_0)]=BIT(BTN_0);
input_register_device(&
staticvoid__exitbutton_exit(void)
input_unregister_device(&
free_irq(BUTTON_IRQ,button_interrupt);
module_init(button_init);
module_exit(button_exit);
这个示例module代码还是比较简单,在初始化函数里注册了一个中断处理例程。
然后注册了一个inputdevice.在中断处理程序里,将接收到的按键上报给input子系统。
文档的作者在之后的分析里又对这个module作了优化。
主要是在注册中断处理的时序上。
在修改过后的代码里,为inputdevice定义了open函数,在open的时候再去注册中断处理例程。
具体的信息请自行参考这篇文档。
在资料缺乏的情况下,kernel自带的文档就是剖析kernel相关知识的最好资料.
文档的作者还分析了几个api函数。
列举如下:
1):
set_bit(EV_KEY,button_dev.evbit);
set_bit(BTN_0,button_dev.keybit);
分别用来设置设备所产生的事件以及上报的按键值。
Structiput_dev中有两个成员,一个是evbit.一个是keybit.分别用表示设备所支持的动作和按键类型。
2):
用来注册一个inputdevice.
3):
input_report_key()
用于给上层上报一个按键动作
4):
input_sync()
用来告诉上层,本次的事件已经完成了.
5):
NBITS(x)-returnsthelengthofabitfieldarrayinlongsforxbits
LONG(x)
-returnstheindexinthearrayinlongsforbitx
BIT(x)
-returnstheindexinalongforbitx
这几个宏在input子系统中经常用到。
上面的英文解释已经很清楚了。
三:
input设备注册分析.
Input设备注册的接口为:
input_register_device()。
代码如下:
intinput_register_device(structinput_dev*dev)
staticatomic_tinput_no=ATOMIC_INIT(0);
structinput_handler*handler;
constchar*path;
interror;
__set_bit(EV_SYN,dev->
evbit);
/*
*Ifdelayandperiodarepre-setbythedriver,thenautorepeating
*ishandledbythedriveritselfandwedon'
tdoitininput.c.
*/
init_timer(&
dev->
timer);
if(!
rep[REP_DELAY]&
&
!
rep[REP_PERIOD]){
dev->
timer.data=(long)dev;
timer.function=input_repeat_key;
rep[REP_DELAY]=250;
rep[REP_PERIOD]=33;
在前面的分析中曾分析过。
Input_device的evbit表示该设备所支持的事件。
在这里将其EV_SYN置位,即所有设备都支持这个事件.如果dev->
rep[REP_DELAY]和dev->
rep[REP_PERIOD]没有设值,则将其赋默认值。
这主要是处理重复按键的.
getkeycode)
getkeycode=input_default_getkeycode;
setkeycode)
setkeycode=input_default_setkeycode;
snprintf(dev->
dev.bus_id,sizeof(dev->
dev.bus_id),
"
input%ld"
(unsignedlong)atomic_inc_return(&
input_no)-1);
error=device_add(&
dev);
if(error)
returnerror;
path=kobject_get_path(&
dev.kobj,GFP_KERNEL);
printk(KERN_INFO"
input:
%sas%s\n"
name?
name:
"
Unspecifieddevice"
path?
path:
N/A"
);
kfree(path);
error=mutex_lock_interruptible(&
input_mutex);
if(error){
device_del(&
如果inputdevice没有定义getkeycode和setkeycode.则将其赋默认值。
还记得在键盘驱动中的分析吗?
这两个操作函数就可以用来取键的扫描码和设置键的扫描码。
然后调用device_add()将input_dev中封装的device注册到sysfs
list_add_tail(&
node,&
input_dev_list);
list_for_each_entry(handler,&
input_handler_list,node)
input_attach_handler(dev,handler);
input_wakeup_procfs_readers();
mutex_unlock(&
return0;
这里就是重点了。
将inputdevice
挂到input_dev_list链表上.然后,对每一个挂在input_handler_list的handler调用input_attach_handler().在这里的情况有好比设备模型中的device和driver的匹配。
所有的inputdevice都挂在input_dev_list链上。
所有的handle都挂在input_handler_list上。
看一下这个匹配的详细过程。
匹配是在input_attach_handler()中完成的。
staticintinput_attach_handler(structinput_dev*dev,structinput_handler*handler)
conststructinput_device_id*id;
if(handler->
blacklist&
input_match_device(handler->
blacklist,dev))
return-ENODEV;
id=input_match_device(handler->
id_table,dev);
id)
error=handler->
connect(handler,dev,id);
if(error&
error!
=-ENODEV)
printk(KERN_ERR
failedtoattachhandler%stodevice%s,"
error:
%d\n"
handler->
name,kobject_name(&
dev.kobj),error);
如果handle的blacklist被赋值。
要先匹配blacklist中的数据跟dev->
id的数据是否匹配。
匹配成功过后再来匹配handle->
id和dev->
id中的数据。
如果匹配成功,则调用handler->
connect().
来看一下具体的数据匹配过程,这是在input_match_device()中完成的。
staticconststructinput_device_id*input_match_device(conststructinput_device_id*id,
structinput_dev*dev)
inti;
for(;
id->
flags||id->
driver_info;
id++){
if(id->
flags&
INPUT_DEVICE_ID_MATCH_BUS)
bustype!
=dev->
id.bustype)
continue;
INPUT_DEVICE_ID_MATCH_VENDOR)
vendor!
id.vendor)
INPUT_DEVICE_ID_MATCH_PRODUCT)
product!
id.product)
INPUT_DEVICE_ID_MATCH_VERSION)
version!
id.version)
MATCH_BIT(evbit,
EV_MAX);
MATCH_BIT(,,KEY_MAX);
MATCH_BIT(relbit,REL_MAX);
MATCH_BIT(absbit,ABS_MAX);
MATCH_BIT(mscbit,MSC_MAX);
MATCH_BIT(ledbit,LED_MAX);
MATCH_BIT(sndbit,SND_MAX);
MATCH_BIT(ffbit,
FF_MAX);
MATCH_BIT(swbit,
SW_MAX);
returnid;
returnNULL;
MATCH_BIT宏的定义如下:
#defineMATCH_BIT(bit,max)\
for(i=0;
i<
BITS_TO_LONGS(max);
i++)\
if((id->
bit[i]&
bit[i])!
=id->
bit[i])\
break;
\
if(i!
=BITS_TO_LONGS(max))\
由此看到。
在id->
flags中定义了要匹配的项。
定义INPUT_DEVICE_ID_MATCH_BUS。
则是要比较inputdevice和inputhandler的总线类型。
INPUT_DEVICE_ID_MATCH_VENDOR,INPUT_DEVICE_ID_MATCH_PRODUCT,INPUT_DEVICE_ID_MATCH_VERSION分别要求设备厂商。
设备号和设备版本.
如果id->
flags定义的类型匹配成功。
或者是id->
flags没有定义,就会进入到MATCH_BIT的匹配项了.从MATCH_BIT宏的定义可以看出。
只有当iputdevice和inputhandler的id成员在evbit,keybit,…swbit项相同才会匹配成功。
而且匹配的顺序是从evbit,keybit到swbit.只要有一项不同,就会循环到id中的下一项进行比较.
简而言之,注册inputdevice的过程就是为inputdevice设置默认值,并将其挂以input_dev_list.与挂载在input_handler_list中的handler相匹配。
如果匹配成功,就会调用handler的connect函数.
四:
handler注册分析
Handler注册的接口如下所示:
intinput_register_handler(structinput_handler*handler)
structinput_dev*dev;
intretval;
retval=mutex_lock_interruptible(&
if(retval)
returnretval;
INIT_LIST_HEAD(&
handler->
h_list);
fops!
=NULL){
if(input_table[handler->
minor>
>
5]){
retval=-EBUSY;
gotoout;
input_table[handler->
5]=handler;
input_handler_list);
list_for_each_entry(dev,&
input_dev_list,node)
out:
minor表示对应input设备节点的次设备号.以handler->
minor右移五位做为索引值插入到input_table[]中..之后再来分析input_talbe[]的作用.
然后将handler挂到input_handler_list中.然后将其与挂在input_dev_list中的inputdevice匹配.这个过程和inputdevice的注册有相似的地方.都是注册到各自的链表,.然后与另外一条链表的对象相匹配.
五:
handle的注册
intinput_register_handle(structinput_handle*handle)
structinput_handler*handler=handle->
handler;
structinput_dev*dev=handle->
dev;
*Wetakedev->
mutexheretopreventracewith
*input_release_device().
mutex);
list_add_tail_rcu(&
handle->
d_node,&
synchronize_rcu();
*Sincewearesupposedtobecalledfrom->
connect()
*whichismutuallyexclusivewith->
disconnect()
*wecan'
tberacingwithinput_unregister_handle()
*andsoseparatelockis
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 设备 模型 input 子系统 详解