Linux设备模型之input子系统详解Word下载.docx

上传人:b****6 文档编号:21113212 上传时间:2023-01-27 格式:DOCX 页数:32 大小:71.30KB
下载 相关 举报
Linux设备模型之input子系统详解Word下载.docx_第1页
第1页 / 共32页
Linux设备模型之input子系统详解Word下载.docx_第2页
第2页 / 共32页
Linux设备模型之input子系统详解Word下载.docx_第3页
第3页 / 共32页
Linux设备模型之input子系统详解Word下载.docx_第4页
第4页 / 共32页
Linux设备模型之input子系统详解Word下载.docx_第5页
第5页 / 共32页
点击查看更多>>
下载资源
资源描述

Linux设备模型之input子系统详解Word下载.docx

《Linux设备模型之input子系统详解Word下载.docx》由会员分享,可在线阅读,更多相关《Linux设备模型之input子系统详解Word下载.docx(32页珍藏版)》请在冰豆网上搜索。

Linux设备模型之input子系统详解Word下载.docx

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

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1