概述
其返回一个指向input_dev类型的指针,该结构体是一个输入设备结构体,包含了输入设备的相关信息(按键码、设备名、支持的事件)。
input_register_device()
这个函数是输入子系统核心(inputcore)提供的函数。它将input_dev结构体注册到输入子系统核心中(input_dev结构体必须由input_allocate_device()函数来分配的)。
如果函数注册失败,必须调用input_free_device()函数来释放分配的空间。
如果函数注册成功,在卸载函数中应该调用input_unregister_device()函数来注销输入设备结构体。
我们看一下函数原型:
intinput_register_device(structinput_dev*dev)
{
//定义一些函数中将用到的局部变量
staticatomic_tinput_no=ATOMIC_INIT(0);
structinput_handler*handler;
constchar*path;
interror;
//设置input_dev所支持的事件类型,由evbit成员来表示。具体类型在后面归纳。
__set_bit(EV_SYN,dev->evbit);
//初始化timer定时器,用来处理重复点击按键。(去抖)
init_timer(&dev->timer);
//如果rep[REP_DELAY]和[REP_PERIOD]没有设值,则赋默认值。为了去抖。
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;
}
//检查下列两个函数是否被定义,没有被定义则赋默认值。
if(!dev->getkeycode)
dev->getkeycode=input_default_getkeycode;//得到指定位置键值
if(!dev->setkeycode)
dev->setkeycode=input_default_setkeycode;//设置指定位置键值
//设置input_dev中device的名字为inputN
//将如input0input1input2出现在sysfs文件系统中
dev_set_name(&dev->dev,"input%ld",(unsignedlong)atomic_inc_return(&input_no)-1);
//将input->dev包含的device结构注册到Linux设备模型中。
//并在文件系统中表现出来
error=device_add(&dev->dev);
if(error)
returnerror;
//打印设备的路径并输出调试信息
path=kobject_get_path(&dev->dev.kobj,GFP_KERNEL);
printk(KERN_INFO"input:%sas%sn",
dev->name?dev->name:
"Unspecifieddevice",path?:"N/A");
kfree(path);
error=mutex_lock_interruptible(&input_mutex);
if(error){
device_del(&dev->dev);
returnerror;
}
//将input_dev加入input_dev_list链表中(这个链表中包含有所有input设备)
list_add_tail(&dev->node,&input_dev_list);
list_for_each_entry(handler,&input_handler_list,node);
//调用input_attatch_handler()函数匹配handler和input_dev。
//这个函数很重要,在后面单独分析。
input_attach_handler(dev,handler);
input_wakeup_procfs_readers();
mutex_unlock(&input_mutex);
return0;
}
给evbit设置的,input_dev所支持的事件类型:
#defineEV_SYN0x00/*表示设备支持所有的事件*/
#defineEV_KEY0x01/*键盘或者按键,表示一个键码*/
#defineEV_REL0x02/*鼠标设备,表示一个相对的光标位置结果*/
#defineEV_ABS0x03/*手写板产生的值,其是一个绝对整数值*/
#defineEV_MSC0x04/*其他类型*/
#defineEV_LED0x11/*LED灯设备*/
#defineEV_SND0x12/*蜂鸣器,输入声音*/
#defineEV_REP0x14/*允许重复按键类型*/
#defineEV_PWR0x16/*电源管理事件*/
input_attatch_handler()
这个函数用来匹配input_dev和handler,匹配成功才进行关联。
函数代码如下
staticintinput_attach_handler(structinput_dev*dev,
structinput_handler*handler)
{
//input_device_id这个结构体表示设备的标识,存储了设备信息。
conststructinput_device_id*id;/*输入设备的指针*/
interror;
//先判断handler的blacklist有无赋值,然后判断是否匹配
//blacklist是一个input_device_id*类型,指向了一个表,表中存放的是该驱动程序应该忽略的设备
if(handler->blacklist&&input_match_device(handler->blacklist,dev))
return-ENODEV;
/***设备和处理函数之间的匹配***/
//匹配handler->id_table指向的列表中的设备和dev->id数据
id=input_match_device(handler->id_table,dev);
if(!id)
return-ENODEV;
//匹配成功则调用handler->connect,连接handler和input_dev
error=handler->connect(handler,dev,id);/*连接设备和处理函数*/
if(error&&error!=-ENODEV)
printk(KERN_ERR
"input:failedtoattachhandler%stodevice%s,"
"error:%dn",
handler->name,kobject_name(&dev->dev.kobj),error);
returnerror;
}
input_device_id结构体的定义:
structinput_device_id{
kernel_ulong_tflags;/*标志信息*/
__u16bustype;/*总线类型*/
__u16vendor;/*制造商ID*/
__u16product;/*产品ID*/
__u16version;/*版本号*/
...
kernel_ulong_tdriver_info;/*驱动额外的信息*/
};
input_match_device()
这个函数用来将input_dev和handler进行匹配。
handler-》id_table中定义了其支持input_dev设备。
staticconststructinput_device_id*input_match_device(conststruct
input_device_id*id,structinput_dev*dev)
{
inti;
//匹配id和dev->id中的信息
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;
if(id->flags&INPUT_DEVICE_ID_MATCH_VERSION)
if(id->version!=dev->id.version)//匹配版本号
continue;
MATCH_BIT(evbit,EV_MAX);
MATCH_BIT(keybit,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;
}
在上面,只有flags中的信息匹配成功,或者flags没有定义才会调用下面。
#defineMATCH_BIT(bit,max)
for(i=0;i< BITS_TO_LONGS(max); i++)
if((id->bit[i]&dev->bit[i])!=id->bit[i])
break;
if(i!=BITS_TO_LONGS(max))
continue;
从宏定义中可以看到,
只有当inputdevice和inputhandler的ID成员在evbit、keybit、…swbit项相同才会匹配成功。而且匹配的顺序是从evbit、keybit到swbit。只要有一项不同,就会循环到ID中的下一项进行比较。
总结
在input的分配和注册中,我们分析了四个函数。
1.input_allocate_device在内存中为输入设备结构体分配空间并进行初始化。
2.input_register_device()-》input_attach_handler()-》input_match_device()
input_register_device
将input_dev结构体注册到输入子系统核心中。主要操作是初始化input_dev并将其device_add进Linux设备驱动模型中(在文件系统中创建inputN等文件);打印其路径;调用input_attach_handler匹配handler和input_dev。
input_attach_handler
匹配handler和input_dev。主要操作是,判断dev在不在devices的黑名单中,不在就调用input_match_device进行匹配,成功就调用handler-》connect连接设备和处理函数。
input_match_device
真正的将input_dev和handler进行匹配。主要操作是匹配id和dev-》id中的信息。包括bustype、vendor、product、version等;再匹配evbit事件类型、keybit按键类型等。
最后
以上就是开放朋友为你收集整理的Linux子程序的调用,Linux input 子系统范例和基本函数解析的全部内容,希望文章能够帮你解决Linux子程序的调用,Linux input 子系统范例和基本函数解析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复