前面的文章简单的讲述了字符设备驱动程序的编写,用字符设备驱动的方式实现了按键驱动,但是,出了我们的自己编写的针对我们的这个驱动程序的应用程序之外,其他应用程序都无法接收我们这个驱动的键值输入,为了让所有应用程序都可以接收我们的按键驱动解析的键值,Linux内核定义了“输入子系统”的概念,也就是说,只要我们按照这个模型进行驱动开发,并为其提供必须的接口函数,那么,Linux内核就可以正常来获取我们的键盘值了。
输入子系统的原理分析强烈推荐观看韦东山老师的视频讲座,讲的非常清楚,我这里是按照输入子系统的方式实现的按键驱动,下面是源码,放在这里做个备份:
#include #include #include #include #include #include static struct input_dev *buttons_dev; static struct timer_list timer; struct button_desc* button_desc = NULL; struct button_desc{ char* name; unsigned int pin; unsigned int irq; unsigned int val; }; static struct button_desc buttons_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, }, }; static void timer_function(unsigned long data){ 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); } static irqreturn_t irq_handler(int irq, void *devid){ button_desc = (struct button_desc*)devid; mod_timer(&timer, jiffies + HZ/100); return IRQ_RETVAL(IRQ_HANDLED); } static int buttons_init(void){ int i; buttons_dev = input_allocate_device(); if(buttons_dev == NULL){ printk(KERN_ERR "Error: allocate input device failed!n"); 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("1n"); if(input_register_device(buttons_dev)){ goto error_1; } printk("2n"); init_timer(&timer); timer.function = timer_function; add_timer(&timer); printk("3n"); 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])){ goto error_2; } } printk("4n"); return 0; 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; } static void buttons_exit(void){ int i; 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"); 很显然,基于输入子系统的按键驱动比起直接编写的字符驱动设备要简单的多,不过按键消抖还是要加的,上面的代码加上了按键消抖。
上一篇:S5PV210 nand 4bit ecc笔记与AM335x的ECC
下一篇:I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之触摸屏驱动移植
推荐阅读最新更新时间:2024-11-09 20:36
设计资源 培训 开发板 精华推荐
- CN0158
- AD8337-EVALZ-SS,单电源同相评估套件,为 AD8337 VGA 的测试和评估提供平台
- CRD-5FF0912P,用于 7L D2PAK 的 SiC MOSFET 高频评估板
- OP297FSZ精密电流泵运算放大器的典型应用
- OP213ESZ精密称重传感器秤放大器的典型应用
- LT1086CT-5 高效双电源的典型应用
- DC495B,具有 LTC4006EGN-6、8.4V/2A 锂离子电池充电器的演示板,DCIN = 15-20V @ 2A,BAT OUT = 8.4V @ 2A
- ADP2139CB-1.8EVALZ,ADP2138 评估板,800 mA,输出电压 1.8 V,3 MHz 降压稳压器
- 使用 ON Semiconductor 的 LM2575-12 的参考设计
- 电磁炮套件NO.2