10. linux输入子系统/input 设备【转】
转自:https://www.cnblogs.com/crmn/articles/6696819.html
按键事件信息之上报
绝对事件信息之上报
相对事件信息之上报
功能键驱动编写
多点触控事件的上报
只产生数据的一类设备,站在内核角度叫输入设备,内核对输入设备实现的一套函数接口==》内核输入子系统
产生的数据:发生的事件
对产生数据的特点进行分类:
绝对事件:绝对坐标等
相对事件:相对坐标等
按键事件
同步事件
这些事件须上报到应用层
input子系统简介:
输入设备(如按键,键盘,触摸屏,鼠标等)是典型的字符设备,其一般的工作机制是底层在按键,触摸等动作发生时产生一个中断(或驱动通过timer定时查询),然后cpu通过SPI,I2C或者外部存储器总线读取键值,坐标等数据,放一个缓冲区,字符设备驱动管理该缓冲区,而驱动的read()接口让用户可以读取键值,坐标等数据。
在Linux中,输入子系统是由输入子系统设备驱动层、输入子系统核心层(Input Core)和输入子系统事件处理层(Event Handler)组成。其中设备驱动层提供对硬件各寄存器的读写访问和将底层硬件对用户输入访问的响应转换为标准的输入事件,再通过核心层提交给事件处理层;而核心层对下提供了设备驱动层的编程接口,对上又提供了事件处理层的编程接口;而事件处理层就为我们用户空间的应用程序提供了统一访问设备的接口和驱动层提交来的事件处理。所以这使得我们输入设备的驱动部分不在用关心对设备文件的操作,而是要关心对各硬件寄存器的操作和提交的输入事件。
1.4. 输入子系统设备驱动层实现原理
在Linux中,Input设备用input_dev结构体描述,定义在input.h中。设备的驱动只需按照如下步骤就可实现了。
1).在驱动模块加载函数中设置Input设备支持input子系统的哪些事件;
2).将Input设备注册到input子系统中;
3).在Input设备发生输入操作时(如:键盘被按下/抬起、触摸屏被触摸/抬起/移动、鼠标被移动/单击/抬起时等),提交所发生的事件及对应的键值/坐标等状态。
1.6.与软件设计有关的API函数
1.6.1.分配一个输入设备
Struct input_dev *input_allocate_device*(void);
1.6.2.注册一个输入设备
Int input_register_device(struct input_dev *dev);
1.6.3.驱动实现-事件支持
Set_bit告诉inout子系统它支持哪些事件
Set_bit(EV_KEY,button_dev.evbit)
Struct input_dev中有两个成员,一个是evbit;一个是keybit.分别用来表示设备所支持的事件类型和按键类型。
1.6.3.1事件类型
Linux中输入设备的事件类型有(这里只列出了常用的一些,更多请看linux/input.h中):EV_SYN 0x00 同步事件
EV_KEY 0x01 按键事件
EV_REL 0x02 相对坐标
EV_ABS 0x03 绝对坐标
EV_MSC 0x04 其它
EV_LED 0x11 LED
EV_SND 0x12 声音
EV_REP 0x14 Repeat
EV_FF 0x15 力反馈
1.6.4.驱动实现-报告事件
Void input_event(struct input_dev *dev,unsigned int type,unsigned int code,int value);//报告指定type,code的输入事件
Void input_report_key(struct input_dev *dev,unsigned int code,int value);//报告键值
Void input_report_rel(struct input_dev *dev,unsigned int code,int value);//报告相对坐标
Void input_report_abs(struct input_dev *dev,unsigned int code,int value);//报告绝对坐标
Void input_sync(struct input_dev *dev);//报告同步事件
在触摸屏驱动设计中,一次坐标及按下状态的整个报告过程如下:
Input_report_abs(input_dev,ABS_X,x);//X坐标
Input_report_abs(input_dev,ABS_Y,y);//Y坐标
Input_report_abs(input_dev,ABS_PRESSURE,pres);//压力
input_sync(struct input_dev *dev);//同步
1.6.5释放与注销设备
Void input_free_device(struct input_dev *dev);
Void input_unregister_device(struct input_dev *);
======================================================
[root@localhost linux-3.5]# vim -t input_event
/*解压并使用现成的根文件系统*/
=============================================================
funkeys目录
1 obj-m := demo.o 2 3 KERNEL := /linux-3.5 4 5 all: 6 make -C $(KERNEL) M=`pwd` 7 clean: 8 make -C $(KERNEL) M=`pwd` clean 9
demo.c
1 /* 2 * 按键状态上报 3 * 4 * */ 5 /* head file */ 6 #include <linux/init.h> 7 #include <linux/module.h> 8 #include <plat/irqs.h> 9 #include <linux/interrupt.h> 10 11 #include <linux/input.h> 12 13 struct mill_key{ 14 int code;//定义按键编码 15 int irqnum; 16 char *name; 17 u32 cnt; 18 }millkeys[] = { 19 {KEY_UP, IRQ_EINT(26), "key1", 0}, 20 {KEY_DOWN, IRQ_EINT(27), "key2", 0}, 21 {KEY_LEFT, IRQ_EINT(28), "key3", 0}, 22 {KEY_RIGHT, IRQ_EINT(29), "key4", 0}, 23 }; 24 25 /*1st*/ 26 static struct input_dev *funckeys;//1.定义一个输入设备的地址 27 28 static struct tasklet_struct task; 29 30 static void mill_unregister_irqkey(void) 31 { 32 int i; 33 34 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 35 free_irq(millkeys[i].irqnum, &millkeys[i]); 36 } 37 38 } 39 40 /*irq bootm half*/ 41 static void do_bh_handler (unsigned long data) 42 { 43 struct mill_key *ptr = (void *)data; 44 ptr->cnt++; 45 46 input_report_key(funckeys, ptr->code, ptr->cnt%2);//按键事件的封装并上报该按键事件 47 input_sync(funckeys);//每一时刻读完数据上报一个同步事件,全部上报完了再上报一个同步事件,从时间上区分 48 } 49 50 /*irq top half*/ 51 static irqreturn_t do_handler(int irqnum, void *dev) 52 { 53 task.data = (unsigned long)dev; 54 55 tasklet_schedule(&task); 56 57 return IRQ_HANDLED; 58 } 59 60 static int mill_register_irqkey(void) 61 { 62 int i; 63 int ret; 64 65 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 66 ret = request_irq( 67 millkeys[i].irqnum, do_handler, 68 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 69 millkeys[i].name, &millkeys[i]); 70 if (ret < 0) { 71 goto error0; 72 } 73 } 74 75 return 0; 76 error0: 77 while (i--) { 78 free_irq(millkeys[i].irqnum, &millkeys[i]); 79 } 80 81 return ret; 82 } 83 84 /* driver module entry */ 85 static int __init demo_init(void) 86 { 87 int code, ret; 88 int i; 89 90 /*2nd*/ 91 funckeys = input_allocate_device();//2.为该输入设备分配地址空间 92 if (!funckeys) {//申请失败则返回错误负值 93 return -ENOMEM; 94 } 95 96 /*3rd*/ 97 //#define EV_KEY 0x01 //按键 98 funckeys->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); 99 //3.从大的事件分类中获取按键这个事件分类并取按键的编码/ 100 // 1/32 == 0 1<<(1%32) == 1位置1 101 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 102 code = millkeys[i].code; 103 funckeys->keybit[BIT_WORD(code)] |= BIT_MASK(code);//3.依次获取4个按键的编码 104 // 103/32 == 3 1<<(103%32) == 7位置1 105 } 106 /* 107 #define KEY_UP 103 108 #define KEY_LEFT 105 109 #define KEY_RIGHT 106 110 #define KEY_DOWN 108 111 */ 112 113 /*4th: 向内核注册输入字符设备驱动*/ 114 ret = input_register_device(funckeys);//4.向内核注册该输入字符设备驱动 115 if (ret < 0) { 116 goto error0; 117 } 118 119 tasklet_init(&task, do_bh_handler, 0); 120 121 ret = mill_register_irqkey(); 122 if (ret < 0) { 123 goto error1; 124 } 125 126 printk("funckeys device is ok!\n"); 127 128 return 0; 129 error1: 130 input_unregister_device(funckeys); 131 return ret; 132 error0: 133 input_free_device(funckeys); 134 return ret; 135 } 136 137 module_init(demo_init); 138 139 140 /* driver module exit */ 141 static void __exit demo_exit(void) 142 { 143 tasklet_kill(&task); 144 145 mill_unregister_irqkey(); 146 147 input_unregister_device(funckeys); 148 } 149 module_exit(demo_exit); 150 151 /* driver module description */ 152 MODULE_LICENSE("GPL"); 153 154 MODULE_AUTHOR("crmn"); 155 MODULE_VERSION("crmn1.0"); 156 MODULE_DESCRIPTION("example for driver module arch");
app
1 #include <fcntl.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <sys/stat.h> 6 #include <linux/input.h> 7 #include <sys/epoll.h> 8 #include <assert.h> 9 10 #define CNT 3 11 12 void get_event(int fd) 13 { 14 int ret; 15 struct input_event event;//对输入设备封装一个结构体 16 17 ret = read(fd, &event, sizeof(event));// 18 19 switch (event.type) {///事件类型的分类 20 case EV_SYN: 21 printf("------------ syn ----------\n"); 22 break; 23 case EV_KEY: 24 printf("key code%d is %s!\n", event.code,//例如某个事件(按键类型)类型里众多按键里相应按键的编码 25 event.value?"down":"up");//该事件里某个按键发生的值:按下/按上 26 break; 27 case EV_ABS: 28 if ((event.code == ABS_X) || 29 (event.code == ABS_MT_POSITION_X)) { 30 printf("x = %d\n", event.value); 31 } else if ((event.code == ABS_Y) || 32 (event.code == ABS_MT_POSITION_Y)) { 33 printf("y = %d\n", event.value); 34 } else if ((event.code == ABS_PRESSURE) || 35 (event.code == ABS_MT_PRESSURE)) { 36 printf("pressure value: %d\n", event.value); 37 } 38 break; 39 case EV_REL: 40 if (event.code == REL_X) { 41 printf("x = %d\n", event.value); 42 } else if (event.code == REL_Y) { 43 printf("y = %d\n", event.value); 44 } 45 break; 46 default: 47 break; 48 } 49 } 50 51 void add_to_epfd(int epfd, int fd) 52 { 53 int ret; 54 55 struct epoll_event event = {//定义一个感兴趣的事件结构体对象 56 .events = EPOLLIN, //a.感兴趣的事件/对应的文件描述符可读 57 .data = { //b.保存触发事件的文件描述符相关的数据 58 .fd = fd, 59 }, 60 }; 61 62 ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);//2.epoll的事件注册函数 63 //1返回值/注册新的fd到epfd/需要监听的fd/告诉内核需要监听什么事 64 65 assert(ret == 0); 66 } 67 68 int main(int argc, char **argv) 69 { 70 int epfd, fd; 71 int ret; 72 int i; 73 struct epoll_event events[CNT];//参数events是分配好的epoll_event结构体数组,epoll将会把发生的事件赋值到events数组中 74 75 #define LEN 64 76 char buf[LEN]; 77 78 epfd = epoll_create(CNT);//1.创建一个epoll的句柄,指向内核一段空间,对应struct file结构体 79 assert(epfd > 0); 80 81 for (i = 0; i < CNT; i++) { 82 snprintf(buf, LEN, "/dev/input/event%d", i); 83 fd = open(buf, O_RDONLY); 84 add_to_epfd(epfd, fd); 85 } 86 87 while (1) { 88 ret = epoll_wait(epfd, events, CNT, -1);//3.收集在epoll监控的事件中已经发送的事件/返回值是满足条件的前几个文件描述符 89 //1返回值/感兴趣事件/感兴趣事件大小为4/不确定或者永久等待,一直阻塞等待,睡着。。。 90 if (ret < 0) { 91 perror("epoll_wait"); 92 exit(1); 93 }else if (ret == 0) {//-1:立马返回/有超时时间(2000ms):显示超时 94 printf("hehe, timeout...\n"); 95 continue; 96 } 97 98 for (i = 0; i < ret; i++) { 99 if (events[i].events&EPOLLIN) {//获取满足条件的文件描述符对应的元素的结构体 100 get_event(events[i].data.fd); 101 } 102 } 103 } 104 105 return 0; 106 }
提示:x/y为绝对坐标,分别大约显示-22到22、front/back、left/right
============================================================
sim_ts目录
demo.c
1 /*按键模拟单点触控触摸屏的方式来实现上报 2 * */ 3 /* head file */ 4 #include <linux/init.h> 5 #include <linux/module.h> 6 #include <plat/irqs.h> 7 #include <linux/interrupt.h> 8 9 #include <linux/input.h> 10 11 struct mill_key{ 12 int irqnum; 13 char *name; 14 u32 cnt; 15 }millkeys[] = { 16 {IRQ_EINT(26), "key1", 0}, 17 {IRQ_EINT(27), "key2", 0}, 18 {IRQ_EINT(28), "key3", 0}, 19 {IRQ_EINT(29), "key4", 0}, 20 }; 21 22 static u32 pos[2] = { 20,20 }; 23 24 /*1st*/ 25 static struct input_dev *funckeys; 26 27 static struct tasklet_struct task; 28 29 static void mill_unregister_irqkey(void) 30 { 31 int i; 32 33 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 34 free_irq(millkeys[i].irqnum, &millkeys[i]); 35 } 36 37 } 38 39 /*irq bootm half*/ 40 static void do_bh_handler (unsigned long data) 41 { 42 struct mill_key *ptr = (void *)data; 43 ptr->cnt++; 44 45 if (ptr->cnt%2) { 46 input_report_abs(funckeys, ABS_PRESSURE, 1); 47 input_report_abs(funckeys, ABS_X, pos[0]); 48 input_report_abs(funckeys, ABS_Y, pos[1]); 49 pos[0]++; pos[0] %= 800; 50 pos[1]++; pos[1] %= 480; 51 } else { 52 input_report_abs(funckeys, ABS_PRESSURE, 0); 53 } 54 input_sync(funckeys); 55 } 56 57 /*irq top half*/ 58 static irqreturn_t do_handler(int irqnum, void *dev) 59 { 60 task.data = (unsigned long)dev; 61 62 tasklet_schedule(&task); 63 64 return IRQ_HANDLED; 65 } 66 67 static int mill_register_irqkey(void) 68 { 69 int i; 70 int ret; 71 72 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 73 ret = request_irq( 74 millkeys[i].irqnum, do_handler, 75 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 76 millkeys[i].name, &millkeys[i]); 77 if (ret < 0) { 78 goto error0; 79 } 80 } 81 82 return 0; 83 error0: 84 while (i--) { 85 free_irq(millkeys[i].irqnum, &millkeys[i]); 86 } 87 88 return ret; 89 } 90 91 /* driver module entry */ 92 static int __init demo_init(void) 93 { 94 int ret; 95 96 /*2nd*/ 97 funckeys = input_allocate_device(); 98 if (!funckeys) { 99 return -ENOMEM; 100 } 101 102 /*3rd*/ 103 funckeys->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); 104 105 funckeys->absbit[BIT_WORD(ABS_X)] |= BIT_MASK(ABS_X); 106 funckeys->absbit[BIT_WORD(ABS_Y)] |= BIT_MASK(ABS_Y); 107 funckeys->absbit[BIT_WORD(ABS_PRESSURE)] |= BIT_MASK(ABS_PRESSURE); 108 109 input_set_abs_params(funckeys, ABS_X, 0, 799, 0, 0); 110 input_set_abs_params(funckeys, ABS_Y, 0, 479, 0, 0); 111 input_set_abs_params(funckeys, ABS_PRESSURE, 0, 1, 0, 0); 112 113 /*4th: 向内核注册输入字符设备驱动*/ 114 ret = input_register_device(funckeys); 115 if (ret < 0) { 116 goto error0; 117 } 118 119 tasklet_init(&task, do_bh_handler, 0); 120 121 ret = mill_register_irqkey(); 122 if (ret < 0) { 123 goto error1; 124 } 125 126 printk("funckeys device is ok!\n"); 127 128 return 0; 129 error1: 130 input_unregister_device(funckeys); 131 return ret; 132 error0: 133 input_free_device(funckeys); 134 return ret; 135 } 136 137 module_init(demo_init); 138 139 140 /* driver module exit */ 141 static void __exit demo_exit(void) 142 { 143 tasklet_kill(&task); 144 145 mill_unregister_irqkey(); 146 147 input_unregister_device(funckeys); 148 } 149 module_exit(demo_exit); 150 151 /* driver module description */ 152 MODULE_LICENSE("GPL"); 153 154 MODULE_AUTHOR("crmn"); 155 MODULE_VERSION("crmn1.0"); 156 MODULE_DESCRIPTION("example for driver module arch");
app
1 #include <fcntl.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <sys/stat.h> 6 #include <linux/input.h> 7 #include <sys/epoll.h> 8 #include <assert.h> 9 10 #define CNT 3 11 12 void get_event(int fd) 13 { 14 int ret; 15 struct input_event event; 16 17 ret = read(fd, &event, sizeof(event)); 18 19 switch (event.type) { 20 case EV_SYN: 21 if (event.code == SYN_REPORT) { 22 printf("------------ syn report ----------\n"); 23 } else if (event.code == SYN_MT_REPORT) { 24 printf("----------- syn mt report ------------\n"); 25 } 26 break; 27 case EV_KEY: 28 printf("key code%d is %s!\n", event.code, 29 event.value?"down":"up"); 30 break; 31 case EV_ABS: 32 if ((event.code == ABS_X) || 33 (event.code == ABS_MT_POSITION_X)) { 34 printf("x = %d\n", event.value); 35 } else if ((event.code == ABS_Y) || 36 (event.code == ABS_MT_POSITION_Y)) { 37 printf("y = %d\n", event.value); 38 } else if ((event.code == ABS_PRESSURE) || 39 (event.code == ABS_MT_PRESSURE)) { 40 printf("pressure value: %d\n", event.value); 41 } 42 break; 43 case EV_REL: 44 if (event.code == REL_X) { 45 printf("x = %d\n", event.value); 46 } else if (event.code == REL_Y) { 47 printf("y = %d\n", event.value); 48 } 49 break; 50 default: 51 break; 52 } 53 } 54 55 void add_to_epfd(int epfd, int fd) 56 { 57 int ret; 58 59 struct epoll_event event = { 60 .events = EPOLLIN, 61 .data = { 62 .fd = fd, 63 }, 64 }; 65 66 ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); 67 68 assert(ret == 0); 69 } 70 71 int main(int argc, char **argv) 72 { 73 int epfd, fd; 74 int ret; 75 int i; 76 struct epoll_event events[CNT]; 77 78 #define LEN 64 79 char buf[LEN]; 80 81 epfd = epoll_create(CNT); 82 assert(epfd > 0); 83 84 for (i = 0; i < CNT; i++) { 85 snprintf(buf, LEN, "/dev/input/event%d", i); 86 fd = open(buf, O_RDONLY); 87 add_to_epfd(epfd, fd); 88 } 89 90 while (1) { 91 ret = epoll_wait(epfd, events, CNT, -1); 92 if (ret < 0) { 93 perror("epoll_wait"); 94 exit(1); 95 }else if (ret == 0) { 96 printf("hehe, timeout...\n"); 97 continue; 98 } 99 100 for (i = 0; i < ret; i++) { 101 if (events[i].events&EPOLLIN) { 102 get_event(events[i].data.fd); 103 } 104 } 105 } 106 107 return 0; 108 }
===============================================================
sim_mts目录
demo.c
1 /* 2 * 按键模拟触摸屏的方式来实现顺序上报 3 * */ 4 /* head file */ 5 #include <linux/init.h> 6 #include <linux/module.h> 7 #include <plat/irqs.h> 8 #include <linux/interrupt.h> 9 10 #include <linux/input.h> 11 12 struct mill_key{ 13 int irqnum; 14 char *name; 15 u32 cnt; 16 }millkeys[] = { 17 {IRQ_EINT(26), "key1", 0}, 18 {IRQ_EINT(27), "key2", 0}, 19 {IRQ_EINT(28), "key3", 0}, 20 {IRQ_EINT(29), "key4", 0}, 21 }; 22 23 static u32 mts_pos[4][2] = { 24 {0,0}, 25 {20,20}, 26 {30,30}, 27 {249, 400} 28 }; 29 30 /*1st*/ 31 static struct input_dev *funckeys; 32 33 static struct tasklet_struct task; 34 35 static void mill_unregister_irqkey(void) 36 { 37 int i; 38 39 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 40 free_irq(millkeys[i].irqnum, &millkeys[i]); 41 } 42 43 } 44 45 /*irq bootm half*/ 46 static void do_bh_handler (unsigned long data) 47 { 48 int i = 0; 49 50 struct mill_key *ptr = (void *)data; 51 ptr->cnt++; 52 53 if (ptr->cnt%2) { 54 input_report_abs(funckeys, ABS_MT_PRESSURE, 1); 55 for (i = 0; i < 4; i++) { 56 input_report_abs(funckeys, ABS_MT_POSITION_X, mts_pos[i][0]); 57 input_report_abs(funckeys, ABS_MT_POSITION_Y, mts_pos[i][1]); 58 input_mt_sync(funckeys); 59 } 60 } else { 61 input_report_abs(funckeys, ABS_MT_PRESSURE, 0); 62 } 63 input_sync(funckeys); 64 } 65 66 /*irq top half*/ 67 static irqreturn_t do_handler(int irqnum, void *dev) 68 { 69 task.data = (unsigned long)dev; 70 71 tasklet_schedule(&task); 72 73 return IRQ_HANDLED; 74 } 75 76 static int mill_register_irqkey(void) 77 { 78 int i; 79 int ret; 80 81 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 82 ret = request_irq( 83 millkeys[i].irqnum, do_handler, 84 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 85 millkeys[i].name, &millkeys[i]); 86 if (ret < 0) { 87 goto error0; 88 } 89 } 90 91 return 0; 92 error0: 93 while (i--) { 94 free_irq(millkeys[i].irqnum, &millkeys[i]); 95 } 96 97 return ret; 98 } 99 100 /* driver module entry */ 101 static int __init demo_init(void) 102 { 103 int ret; 104 105 /*2nd*/ 106 funckeys = input_allocate_device(); 107 if (!funckeys) { 108 return -ENOMEM; 109 } 110 111 /*3rd*/ 112 funckeys->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); 113 114 funckeys->absbit[BIT_WORD(ABS_MT_POSITION_X)] |= BIT_MASK(ABS_MT_POSITION_X);//一个编码对应一个位,防止覆盖 115 funckeys->absbit[BIT_WORD(ABS_MT_POSITION_Y)] |= BIT_MASK(ABS_MT_POSITION_Y); 116 funckeys->absbit[BIT_WORD(ABS_MT_PRESSURE)] |= BIT_MASK(ABS_MT_PRESSURE); 117 118 119 /*4th: 向内核注册输入字符设备驱动*/ 120 ret = input_register_device(funckeys); 121 if (ret < 0) { 122 goto error0; 123 } 124 125 tasklet_init(&task, do_bh_handler, 0); 126 127 ret = mill_register_irqkey(); 128 if (ret < 0) { 129 goto error1; 130 } 131 132 printk("funckeys device is ok!\n"); 133 134 return 0; 135 error1: 136 input_unregister_device(funckeys); 137 return ret; 138 error0: 139 input_free_device(funckeys); 140 return ret; 141 } 142 143 module_init(demo_init); 144 145 146 /* driver module exit */ 147 static void __exit demo_exit(void) 148 { 149 tasklet_kill(&task); 150 151 mill_unregister_irqkey(); 152 153 input_unregister_device(funckeys); 154 } 155 module_exit(demo_exit); 156 157 /* driver module description */ 158 MODULE_LICENSE("GPL"); 159 160 MODULE_AUTHOR("crmn"); 161 MODULE_VERSION("crmn1.0"); 162 MODULE_DESCRIPTION("example for driver module arch");
app
1 #include <fcntl.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <sys/stat.h> 6 #include <linux/input.h> 7 #include <sys/epoll.h> 8 #include <assert.h> 9 10 #define CNT 3 11 12 void get_event(int fd) 13 { 14 int ret; 15 struct input_event event; 16 17 ret = read(fd, &event, sizeof(event)); 18 19 switch (event.type) { 20 case EV_SYN: 21 if (event.code == SYN_REPORT) { 22 printf("------------ syn report ----------\n"); 23 } else if (event.code == SYN_MT_REPORT) { 24 printf("----------- syn mt report ------------\n"); 25 } 26 break; 27 case EV_KEY: 28 printf("key code%d is %s!\n", event.code, 29 event.value?"down":"up"); 30 break; 31 case EV_ABS: 32 if ((event.code == ABS_X) || 33 (event.code == ABS_MT_POSITION_X)) { 34 printf("x = %d\n", event.value); 35 } else if ((event.code == ABS_Y) || 36 (event.code == ABS_MT_POSITION_Y)) { 37 printf("y = %d\n", event.value); 38 } else if ((event.code == ABS_PRESSURE) || 39 (event.code == ABS_MT_PRESSURE)) { 40 printf("pressure value: %d\n", event.value); 41 } 42 break; 43 case EV_REL: 44 if (event.code == REL_X) { 45 printf("x = %d\n", event.value); 46 } else if (event.code == REL_Y) { 47 printf("y = %d\n", event.value); 48 } 49 break; 50 default: 51 break; 52 } 53 } 54 55 void add_to_epfd(int epfd, int fd) 56 { 57 int ret; 58 59 struct epoll_event event = { 60 .events = EPOLLIN, 61 .data = { 62 .fd = fd, 63 }, 64 }; 65 66 ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); 67 68 assert(ret == 0); 69 } 70 71 int main(int argc, char **argv) 72 { 73 int epfd, fd; 74 int ret; 75 int i; 76 struct epoll_event events[CNT]; 77 78 #define LEN 64 79 char buf[LEN]; 80 81 epfd = epoll_create(CNT); 82 assert(epfd > 0); 83 84 for (i = 0; i < CNT; i++) { 85 snprintf(buf, LEN, "/dev/input/event%d", i); 86 fd = open(buf, O_RDONLY); 87 add_to_epfd(epfd, fd); 88 } 89 90 while (1) { 91 ret = epoll_wait(epfd, events, CNT, -1); 92 if (ret < 0) { 93 perror("epoll_wait"); 94 exit(1); 95 }else if (ret == 0) { 96 printf("hehe, timeout...\n"); 97 continue; 98 } 99 100 for (i = 0; i < ret; i++) { 101 if (events[i].events&EPOLLIN) { 102 get_event(events[i].data.fd); 103 } 104 } 105 } 106 107 return 0; 108 }