前面的文章简略的叙述了字符设备驱动程序的编写,用字符设备驱动的方法完成了按键驱动,可是,出了咱们的自己编写的针对咱们的这个驱动程序的应用程序之外,其他应用程序都无法接纳咱们这个驱动的键值输入,为了让一切应用程序都可以接纳咱们的按键驱动解析的键值,Linux内核界说了“输入子系统”的概念,也就是说,只需咱们依照这个模型进行驱动开发,并为其供给有必要的接口函数,那么,Linux内核就可以正常来获取咱们的键盘值了。
输入子系统的原理剖析强烈推荐观看韦东山教师的视频讲座,讲的十分清楚,我这儿是依照输入子系统的方法完成的按键驱动,下面是源码,放在这儿做个备份:
- #include
- #include
- #include
- #include
- #include
interrupt.h> - #include
- staticstructinput_dev*buttons_dev;
- staticstructtimer_listtimer;
- structbutton_desc*button_desc=NULL;
- structbutton_desc{
- char*name;
- unsignedintpin;
- unsignedintirq;
- unsignedintval;
- };
- staticstructbutton_descbuttons_desc[8]={
- [0]={
- .name=”S1″,
- .pin=S5PV210_GPH0(0),
- .irq=IRQ_EINT(0),
- .val=KEY_L,
- },
- [1]={
- .name=”S2″,
- .pin=S5PV210_GPH0(1),
- .irq=IRQ_EINT(1),
- .val=KEY_S,
- },
- [2]={
- .name=”S3″,
- .pin=S5PV210_GPH0(2),
- .irq=IRQ_EINT(2),
- .val=KEY_C,
- },
- [3]={
- .name=”S4″,
- .pin=S5PV210_GPH0(3),
- .irq=IRQ_EINT(3),
- .val=KEY_ENTER,
- },
- [4]={
- .name=”S5″,
- .pin=S5PV210_GPH0(4),
- .irq=IRQ_EINT(4),
- .val=KEY_LEFTCTRL,
- },
- [5]={
- .name=”S6″,
- .pin=S5PV210_GPH0(5),
- .irq=IRQ_EINT(5),
- .val=KEY_MINUS,
- },
- [6]={
- .name=”S7″,
- .pin=S5PV210_GPH2(6),
- .irq=IRQ_EINT(22),
- .val=KEY_CAPSLOCK,
- },
- [7]={
- .name=”S8″,
- .pin=S5PV210_GPH2(7),
- .irq=IRQ_EINT(23),
- .val=KEY_SPACE,
- },
- };
- staticvoidtimer_function(unsignedlongdata){
- if(button_desc==NULL)
- return;
- if(gpio_get_value(button_desc->pin)){
- input_event(buttons_dev,EV_KEY,button_desc->val,0);
- }
- else{
- input_event(buttons_dev,EV_KEY,button_desc->val,1);
- }
- input_sync(buttons_dev);
- }
- staticirqreturn_tirq_handler(intirq,void*devid){
- button_desc=(structbutton_desc*)devid;
- mod_timer(&timer,jiffies+HZ/100);
- returnIRQ_RETVAL(IRQ_HANDLED);
- }
- staticintbuttons_init(void){
- inti;
- buttons_dev=input_allocate_device();
- if(buttons_dev==NULL){
- printk(KERN_ERR”Error:allocateinputdevicefailed!”);
- return-ENOMEM;
- }
- __set_bit(EV_KEY,buttons_dev->evbit);
- __set_bit(EV_REP,buttons_dev->evbit);
- __set_bit(KEY_L,buttons_dev->keybit);
- __set_bit(KEY_S,buttons_dev->keybit);
- __set_bit(KEY_C,buttons_dev->keybit);
- __set_bit(KEY_SPACE,buttons_dev->keybit);
- __set_bit(KEY_MINUS,buttons_dev->keybit);
- __set_bit(KEY_ENTER,buttons_dev->keybit);
- __set_bit(KEY_LEFTCTRL,buttons_dev->keybit);
- __set_bit(KEY_CAPSLOCK,buttons_dev->keybit);
- printk(“1”);
- if(input_register_device(buttons_dev)){
- gotoerror_1;
- }
- printk(“2”);
- init_timer(&timer);
- timer.function=timer_function;
- add_timer(&timer);
- printk(“3”);
- for(i=0;i!=8;++i){
- if(request_irq(buttons_desc[i].irq,irq_handler,
- IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,buttons_desc[i].name,&buttons_desc[i])){
- gotoerror_2;
- }
- }
- printk(“4”);
- return0;
- error_2:
- for(–i;i>=0;–i){
- free_irq(buttons_desc[i].irq,&buttons_desc[i]);
- }
- input_unregister_device(buttons_dev);
- error_1:
- input_free_device(buttons_dev);
- return-EBUSY;
- }
- staticvoidbuttons_exit(void){
- inti;
- for(i=0;i!=8;++i){
- free_irq(buttons_desc[i].irq,&buttons_desc[i]);
- }
- input_unregister_device(buttons_dev);
- input_free_device(buttons_dev);
- }
- module_init(buttons_init);
- module_exit(buttons_exit);
- MODULE_LICENSE(“GPL”);
很显然,根据输入子系统的按键驱动比起直接编写的字符驱动设备要简略的多,不过按键消抖仍是要加的,上面的代码加上了按键消抖。如果在开发过程中遇到了什么问题,仍是欢迎留言评论。