input子系统
来源:互联网 发布:龙信数据怎么样 编辑:程序博客网 时间:2024/06/06 00:51
1、简介
1.1 概述
为输入设备(按键、键盘、触摸屏)的驱动规范完成上报输入信息任务的子系统。input是对字符设备驱动的另一种封装。
input子系统在驱动中不是必须的,它的存在只是规范了上报输入信息这一任务,减少驱动与应用开发工程师的沟通成本。
input子系统是输入设备驱动一个标准,一个约定俗成的规范,几乎所有输入设备驱动都是使用input来上报输入信息的
在Linux中,Input子系统由三大部分组成,它们是Input子系统核心层、Input子系统事件处理层和Input子系统设备驱动层。在通常情况下,Input子系统核心层和Input子系统事件处理层都已经实现了,而作为驱动开发者,我们仅仅只需要完成Input子系统设备驱动层。
1.2 编写流程
1、定义一个input_dev结构体
2、申请input_dev内存空间并初始化
3、填充input_dev部分成员
4、向core注册一个input_dev
5、获取键码并上报按键(一般在中断里)
注:input是对字符设备驱动的封装,它在底层实现了file_operations这一套机制而不用我们去填充了,只需按照以上流程即可完成驱动
1.3 主要结构体
//linux/input.hstruct input_dev{ const char *name; //设备名 const char *phys; //设备在系统中路径 const char *uniq; struct input_id id; //用于匹配input hander参数 unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)]; //设备所支持事件类型,主要有EV_SYNC,EV_KEY,EV_REL,EV_ABS等 unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; //按键所对应的位图 unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; //相对坐标对应位图 unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; /绝对坐标对应位图 unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; unsigned long sndbit[BITS_TO_LONGS(SND_CNT)]; unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; unsigned int hint_events_per_packet; unsigned int keycodemax; unsigned int keycodesize; void *keycode; int (*setkeycode)(struct input_dev *dev, const struct input_keymap_entry *ke, unsigned int *old_keycode); int (*getkeycode)(struct input_dev *dev, struct input_keymap_entry *ke); struct ff_device *ff; unsigned int repeat_key; struct timer_list timer; int rep[REP_CNT]; struct input_mt_slot *mt; int mtsize; int slot; int trkid; struct input_absinfo *absinfo; //按键对应的键值 unsigned long key[BITS_TO_LONGS(KEY_CNT)]; //LED对应的指示灯状态 unsigned long led[BITS_TO_LONGS(LED_CNT)]; unsigned long snd[BITS_TO_LONGS(SND_CNT)]; unsigned long sw[BITS_TO_LONGS(SW_CNT)]; int (*open)(struct input_dev *dev); void (*close)(struct input_dev *dev); int (*flush)(struct input_dev *dev, struct file *file); //事件处理函数,主要是接收用户下发的命令,如点亮led; int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); struct input_handle __rcu *grab; spinlock_t event_lock; struct mutex mutex; unsigned int users; bool going_away; bool sync; struct device dev; //设备所支持的input handle; struct list_headh_list; struct list_headnode;};
evbit的值主要有
EV_SYN 同步事件EV_KEY 按键事件EV_REL 相对坐标事件EV_ABS 绝对坐标事件
keybit的值主要有
#define KEY_Q 16#define KEY_W 17#define KEY_E 18#define KEY_R 19#define KEY_T 20
1.3.2 input_dev的赋值
1.3.2.1 直接赋值
evbit[0]= BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY);keybit[BIT_WORD(KEY_D)] |= BIT_MASK(KEY_D);
1.3.2.2 函数赋值
set_bit(nr,addr);参数nr:要置1的那个位;参数addr:数组首地址set_bit( EV_SYN , evbit);set_bit( EV_KEY , evbit);set_bit( KEY_D , keybit);
1.4 主要方法
//申请、初始化input_devstruct input_dev *input_allocate_device(void);//注册input_devint input_register_device(struct input_dev *dev);//注销input_devvoid input_unregister_device(struct input_dev *dev);//上报input_report_key(struct input_dev *dev, unsigned int code, int value);code: 键码(填充结构体时已经注册支持)value:按下1 或 抬起0//同步input_sync(struct input_dev *dev);
2、demo 基于iTop4412
不完整的demo 主要介绍input使用流程
#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/uaccess.h>#include <linux/device.h>#include <asm/io.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>#include <linux/workqueue.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <asm/atomic.h>#include <linux/input.h>#define DEMO_DEBUG#ifdef DEMO_DEBUG#define dem_dbg(fmt, arg...) printk(KERN_WARNING fmt, ##arg)#else#define dem_dbg(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)#endif#define KEY_CODE KEY_LEFTstatic struct input_dev *input_key;static int open_flag = 0;static int dev_id = 123;static int irq;//中断回调static irqreturn_t eint9_interrupt(int irq, void *dev_id) { int gpio_val = 0; printk("%s(%d)\n", __FUNCTION__, __LINE__); /*延时去抖的改进,两次获取电平,如果是抖动直接返回*/ gpio_val = gpio_get_value(EXYNOS4_GPX1(1)); msleep(50); if(gpio_val != gpio_get_value(EXYNOS4_GPX1(1))) return IRQ_HANDLED; if(gpio_val == 0){ //汇报按下事件 input_report_key(input_key, KEY_CODE, 1); }else{ //汇报抬起事件 input_report_key(input_key, KEY_CODE, 0); } //汇报同步事件 input_sync(input_key); return IRQ_HANDLED;}static int key_open(struct input_dev *dev){ dem_dbg("==> %s\n", __FUNCTION__); if(open_flag++ == 0) enable_irq(IRQ_EINT(19)); //打开中断 return 0;}static void key_close(struct input_dev *dev){ dem_dbg("==> %s\n", __FUNCTION__); if(open_flag-- == 0) disable_irq(IRQ_EINT(19)); }static int key_probe(struct platform_device *pdev){ int retval; struct resource *res = NULL; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { dem_dbg("==> no memory resource specified\n"); return PTR_ERR(res); } irq = res->start; //申请中断 retval = request_irq(irq, eint9_interrupt, IRQ_TYPE_EDGE_FALLING /*IRQF_TRIGGER_FALLING*/, "eint9", (void *)&dev_id); if (retval < 0) { printk("Request IRQ %d failed, %d\n", IRQ_EINT(9), retval); goto exit; } disable_irq(irq); //中断关闭 //1 申请input_dev结构体变量空间 input_key = input_allocate_device(); if (!input_key) { dem_dbg("==> allocate input device failed!\n"); retval = -ENOMEM; goto input_alloc_err; } //2 input_dev结构体变量初始化 input_key->name = "key"; //查看cat /proc/bus/input/devices input_key->phys = "inputkey"; input_key->id.bustype = BUS_HOST; input_key->id.vendor = 0x0001; input_key->id.product = 0x0001; input_key->id.version = 0x0100; //指定input设备所支持的事件:按键事件、同步事件、连续长按键事件 input_key->evbit[0] = BIT(EV_KEY) | BIT(EV_SYN) | BIT(EV_REP); //指定input设备支持汇报的键值: KEY_CODE宏指定的KEY_LEFT set_bit(KEY_CODE, input_key->keybit); input_key->open = key_open; input_key->close = key_close; //3 input_dev结构体的注册 retval = input_register_device(input_key); if (retval) { dem_dbg("==> Failed to register input device!\n"); goto input_regs_err; } return 0;input_regs_err: input_free_device(input_key);input_alloc_err: free_irq(irq, (void *)&dev_id);exit: return retval;}static int key_remove(struct platform_device *dev){ dem_dbg("==> in module exit function\n"); free_irq(irq, (void *)&dev_id); //4 input_dev结构体的注销和释放 input_unregister_device(input_key); input_free_device(input_key); return 0;}static struct platform_driver key_driver = { .probe = key_probe, .remove = key_remove, .driver = { .owner = THIS_MODULE, .name = "demo_input", },};static int __init demo_init(void){ dem_dbg("==>demo_init\n"); return platform_driver_register(&key_driver);}static void __exit demo_exit(void){ dem_dbg("==>demo_exit\n"); platform_driver_unregister(&key_driver);}module_init(demo_init);module_exit(demo_exit);MODULE_LICENSE("Dual BSD/GPL");
阅读全文
0 0
- input子系统
- input子系统
- input子系统
- input子系统
- Input 子系统
- Input子系统
- input子系统
- Input子系统
- input子系统
- input子系统
- input子系统
- input 子系统
- input子系统
- input子系统
- input子系统
- input子系统
- input 子系统
- input子系统
- jsp四大作用域
- HDU-5833-Zhu and 772002
- C++函数传递参数的方式有哪几种?
- cannot simultaneously fetch multiple bags 问题的解决办法
- JAVA中的包
- input子系统
- gcc 如何编译so 和 objdump 反汇编
- CentOS7.x 安装、配置JDK、Maven
- spring:tomcat启动服务报错
- intellij idea14 +svn配置 .
- 多线程总结
- Python求解排列中的逆序数个数
- 教务管理系统雏形
- tips:linux命令积累