linux 输入子系统(2)----简单实例分析系统结构(input_dev层)
2013-10-13 14:17
786 查看
实例代码如下:
【2】input_register_device()将input_dev结构体注册到输入子系统核心中。
总结【2】:注册inputdevice就是为inputdevice设置默认值,并将其挂接到input_dev_list中,并且与挂载在input_handler_list中的handler相匹配,如果匹配成功,则调用connect。
【3】input_report_key()向输入子系统报告发生的事件:
#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); } }
相关文章推荐
- linux驱动—input输入子系统—The simplest example(一个最简单的实例)分析(2)
- linux input输入子系统分析《二》:s3c2440的ADC简单驱动实例分析
- linux input输入子系统分析《二》:s3c2440的ADC简单驱动实例分析
- linux input输入子系统分析《二》:s3c2440的ADC简单驱动实例分析
- linux驱动—input输入子系统—The simplest example(一个最简单的实例)分析(1)
- input输入子系统分析《二》:s3c2440的ADC简单驱动实例分析
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- linux input输入子系统分析《三》:S3C2440的触摸屏驱动实例
- Linux 输入(input)子系统架构分析
- 和菜鸟一起学linux之input系统简单实例
- 和菜鸟一起学linux之input系统简单实例
- linux input输入子系统分析《一》:初识input输入子系统
- linux3.10.x的input输入子系统流程分析<一>
- linux input输入子系统分析《一》:初识input输入子系统
- linux input输入子系统应用分析