您的位置:首页 > 运维架构 > Linux

linux 输入子系统(2)----简单实例分析系统结构(input_dev层)

2013-10-13 14:17 786 查看
实例代码如下:

#include<linux/input.h>
#include<linux/module.h>
#include<linux/init.h>

#include<asm/irq.h>
#include<asm/io.h>

#defineBUTTON_IRQ123
staticstructinput_dev*button_dev;/*输入设备结构体*/
staticirqreturn_tbutton_interrupt(intirq,void*dummy)/*中断处理函数*/
{
input_report_key(button_dev,BTN_0,inb(BUTTON_PORT)&1);/*向输入子系统报告产生按键事件*/===========》》》》》【3】
input_sync(button_dev);/*通知接受者,一个报告发送完毕*/
returnIRQ_HANDLED;
}

staticint__initbutton_init(void)
{
interror;
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=input_allocate_device();/*分配一个设备结构体*/===========》》》》》》【1】
if(!button_dev)
{
printk(KERN_ERR"button.c:Notenoughmemory\n");
error=-ENOMEM;
gotoerr_free_irq;
}
button_dev.evbit[0]=BIT_MASK(EV_KEY);/*设置按键信息*/设置输入设备所支持的事件类型
button_dev.keybit[BIT_WORD(BTN_0)]=BIT_MASK(BTN_0);

error=input_register_device(button_dev);/*注册一个输入设备*/===========》》》》》》【2】
if(error)
{
printk(KERN_ERR"failedtoregisterdevice\n");
gotoerr_free_dev;
}
return0;

err_free_dev:
input_free_device(button_dev);
err_free_irq:
free_irq(BUTTON_IRQ,button_interrupt);
returnerror;
}

staticvoid__exitbutton_exit(void)
{
input_unregister_device(button_dev);/*注销按键设备*/
free_irq(BUTTON_IRQ,button_interrupt);/*释放按键占用的中断*/
}

module_init(button_init);
module_exit(button_exit);


【1】input_allocate_device()函数分配一个input_dev结构体,输入设备用input_dev结构体描述。


structinput_dev*input_allocate_device(void)
{
structinput_dev*dev;

dev=kzalloc(sizeof(structinput_dev),GFP_KERNEL);/*分配一个input_dev结构体,并初始化为0*/
if(dev){
dev->dev.type=&input_dev_type;/*初始化设备类型*/
dev->dev.class=&input_class;/*设置为输入设备类*/
device_initialize(&dev->dev);/*初始化device结构*/
mutex_init(&dev->mutex);/*初始化互斥锁*/
spin_lock_init(&dev->event_lock);/*初始化事件自旋锁*/
INIT_LIST_HEAD(&dev->h_list);/*初始化链表*/
INIT_LIST_HEAD(&dev->node);/*初始化链表*/

__module_get(THIS_MODULE);
}

returndev;
}


【2】input_register_device()将input_dev结构体注册到输入子系统核心中。

intinput_register_device(structinput_dev*dev)
{
staticatomic_tinput_no=ATOMIC_INIT(0);
structinput_handler*handler;
constchar*path;
interror;

/*EveryinputdevicegeneratesEV_SYN/SYN_REPORTevents.*/
__set_bit(EV_SYN,dev->evbit);/*设置input_dev所支持的事件类型,由input_dev的evbit成员来表示*/

/*KEY_RESERVEDisnotsupposedtobetransmittedtouserspace.*/
__clear_bit(KEY_RESERVED,dev->keybit);

/*Makesurethatbitmasksnotmentionedindev->evbitareclean.*/
input_cleanse_bitmasks(dev);

/*
*Ifdelayandperiodarepre-setbythedriver,thenautorepeating
*ishandledbythedriveritselfandwedon'tdoitininput.c.
*/
init_timer(&dev->timer);/*初始化一个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;
}

/*检查函数是否定义,未定义则使用默认*/
if(!dev->getkeycode)
dev->getkeycode=input_default_getkeycode;/*得到键值*/

if(!dev->setkeycode)
dev->setkeycode=input_default_setkeycode;/*设置键值*/

dev_set_name(&dev->dev,"input%ld",
(unsignedlong)atomic_inc_return(&input_no)-1);/*设置input_dev中的device的名字,以input0/1/2出现在sysfs文件系统中*/

error=device_add(&dev->dev);
if(error)
returnerror;

path=kobject_get_path(&dev->dev.kobj,GFP_KERNEL);
printk(KERN_INFO"input:%sas%s\n",
dev->name?dev->name:"Unspecifieddevice",path?path:"N/A");
kfree(path);

error=mutex_lock_interruptible(&input_mutex);
if(error){
device_del(&dev->dev);
returnerror;
}

list_add_tail(&dev->node,&input_dev_list);/*加入链表*/

list_for_each_entry(handler,&input_handler_list,node)
input_attach_handler(dev,handler);/*调用input_attach_handler来匹配input_dev和handler*/===========》》》》》》【2.1】

input_wakeup_procfs_readers();

mutex_unlock(&input_mutex);

return0;
}


  其中input_dev所支持的事件类型在include/linux/input.h中定义,如下:


 
 【2.1】input_attach_handler()匹配input_dev和handler。


staticintinput_attach_handler(structinput_dev*dev,structinput_handler*handler)
{
conststructinput_device_id*id;
interror;

id=input_match_device(handler,dev);/*handler与dev之间的匹配*/
if(!id)
return-ENODEV;

error=handler->connect(handler,dev,id);/*匹配成功,则调用connect将handler与dev连接起来*/
if(error&&error!=-ENODEV)
printk(KERN_ERR
"input:failedtoattachhandler%stodevice%s,"
"error:%d\n",
handler->name,kobject_name(&dev->dev.kobj),error);

returnerror;
}


总结【2】:注册inputdevice就是为inputdevice设置默认值,并将其挂接到input_dev_list中,并且与挂载在input_handler_list中的handler相匹配,如果匹配成功,则调用connect。

【3】input_report_key()向输入子系统报告发生的事件:

staticinlinevoidinput_report_key(structinput_dev*dev,unsignedintcode,intvalue)
{
input_event(dev,EV_KEY,code,!!value);
}


input_event()报告指定type、value的输入事件:


voidinput_event(structinput_dev*dev,
unsignedinttype,unsignedintcode,intvalue)
{
unsignedlongflags;

if(is_event_supported(type,dev->evbit,EV_MAX)){

spin_lock_irqsave(&dev->event_lock,flags);
add_input_randomness(type,code,value);
input_handle_event(dev,type,code,value);//向输入子系统传送事件信息,,不继续深入分析了-------------------------!!
spin_unlock_irqrestore(&dev->event_lock,flags);
}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: