4412驱动-input 输入子系统

xiaoxiao2021-02-27  229

// cat /proc/bus/input/devices 列出当前系统下注册的所有输入设备 /* 测试方法,将当前终端的标准输入重定向到驱动框架所产生的tty设备上  * exec 0</dev/tty1  */

#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <mach/regs-gpio.h> #include <linux/io.h> #include <linux/interrupt.h> #include <mach/irqs.h> #include <linux/input.h> // cat /proc/bus/input/devices 列出当前系统下注册的所有输入设备 /* 测试方法,将当前终端的标准输入重定向到驱动框架所产生的tty设备上 * exec 0</dev/tty1 */ //#define S3C_ADDR_BASE 0xF6000000 //#define S3C_ADDR(x) (S3C_ADDR_BASE + (x)) //#define S5P_VA_GPIO2 S3C_ADDR(0x02240000) //0x11840000 //GPX3CON 0x11000C60 #define GPX3CON (S5P_VA_GPIO2 + 0x0c60) //0x11840000+0x0c60=0x11840C60 #define GPX3DAT (S5P_VA_GPIO2 + 0x0c64) struct ldm_info { struct input_dev *dev; }; static struct ldm_info ldm; struct key_info { const char *name; size_t code; //键值 bool (*read_stat)(struct key_info*);//声明一个函数指针 unsigned long reg; //本按键所属的状态寄存器的虚拟地址 size_t ctrlbit; //记录各按键在各自所属的寄存器中的对应bit int irqno; //中断号 }; //返回按键的状态:按住时为0,抬起时为1 static bool stat(struct key_info *pkey) { u32 data = readl(pkey->reg);//从内存映射的 I/O 空间读取数据,readl 从 I/O 读取 32 位数据 ( 4 字节 ) return data & pkey->ctrlbit; } static struct key_info key[] = { {"KEY_L", KEY_L, stat, (unsigned long)GPX3DAT, 1 << 2, IRQ_EINT(26)}, {"KEY_S", KEY_S, stat, (unsigned long)GPX3DAT, 1 << 3, IRQ_EINT(27)}, {"KEY_ENTER", KEY_ENTER, stat, (unsigned long)GPX3DAT, 1 << 4, IRQ_EINT(28)}, {"KEY_BACKSPACE", KEY_BACKSPACE, stat, (unsigned long)GPX3DAT, 1 << 5, IRQ_EINT(29)}, }; static irqreturn_t key_handler(int irqno, void *arg) { struct key_info *pkey = (struct key_info *)arg; //读出触发中断的当前按键的状态 if (pkey->read_stat(pkey)) { //抬起 //value=1表示按下,=0表示抬起,硬件状态应根据寄存器反应的电平状态来判断 input_report_key(ldm.dev, pkey->code, 0); } else { //按下 input_report_key(ldm.dev, pkey->code, 1); } //哨兵event input_sync(ldm.dev); return IRQ_HANDLED; } static int __init ldm_init(void) { printk("%s %s\n", __FUNCTION__, __FILE__); int ret = 0; //1 创建输入设备对象 ldm.dev = input_allocate_device(); if (!ldm.dev) { printk("input_allocate_device failed\n"); ret = -ENOMEM; goto err_input_allocate_device; } //2 对象初始化 ldm.dev->name = "ldm_key"; //2.1 定义输入设备的输入类型 //有按键类型的操作 set_bit(EV_KEY, ldm.dev->evbit); //支持连发 set_bit(EV_REP, ldm.dev->evbit); //注册本设备所拥有的所有按键键值 ssize_t i = 0; for (i = 0; i < ARRAY_SIZE(key); ++i) { set_bit(key[i].code, ldm.dev->keybit); } //3 硬件初始化,中断申请,按下抬起都触发中断 for (i = 0; i < ARRAY_SIZE(key); ++i) { ret = request_irq(key[i].irqno, key_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, key[i].name, (void*)(key + i)); if (ret < 0) { printk("request_irq %d faild\n", i); goto err_request_irq; } } //4 注册输入设备 ret = input_register_device(ldm.dev); if (ret < 0) { printk("input_register_device failed\n"); goto err_input_register_device; } return 0; err_input_register_device: err_request_irq: for (i = i - 1; i >= 0; --i) { free_irq(key[i].irqno, (void*)(key + i)); } input_free_device(ldm.dev); err_input_allocate_device: return ret; } static void __exit ldm_exit(void) { printk(KERN_DEBUG "%s %s\n", __FUNCTION__, __FILE__); input_unregister_device(ldm.dev); ssize_t i = ARRAY_SIZE(key);//ARRAY_SIZE求设备结构体中设备的个数 for (i = i - 1; i >= 0; --i) { free_irq(key[i].irqno, (void*)(key + i)); } input_free_device(ldm.dev); } module_init(ldm_init); module_exit(ldm_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("xiangtan da xue chenhaipan");   MODULE_VERSION("2017.5.4"); 

转载请注明原文地址: https://www.6miu.com/read-8590.html

最新回复(0)