转自: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 }

 

10. linux输入子系统/input 设备【转】的更多相关文章

  1. Linux输入子系统(Input Subsystem)

    Linux输入子系统(Input Subsystem) http://blog.csdn.net/lbmygf/article/details/7360084 input子系统分析  http://b ...

  2. Linux 输入子系统 input

    一.输入子系统 针对输入设备设计:触摸屏.键盘.按键.传感器.鼠标...... 二.每种设备都属于字符设备驱动,程序的写法步骤也相同 1.实现入口函数 xxx_init() 和卸载函数 xxx_exi ...

  3. Linux输入子系统(转)

    Linux输入子系统(Input Subsystem) 1.1.input子系统概述 输入设备(如按键,键盘,触摸屏,鼠标等)是典型的字符设备,其一般的工作机制是低层在按键,触摸等动作发生时产生一个中 ...

  4. linux输入子系统(input subsystem)之evdev.c事件处理过程

    1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input ...

  5. Linux 输入子系统

    Technorati 标签: Kernel 输入子系统 Input      在Linux中,输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理,是底层在按键.触摸时,触发一个 ...

  6. 7.Linux 输入子系统分析

    为什么要引入输入子系统? 在前面我们写了一些简单的字符设备的驱动程序,我们是怎么样打开一个设备并操作的呢? 一般都是在执行应用程序时,open一个特定的设备文件,如:/dev/buttons .... ...

  7. Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值

    Android底层开发之Linux输入子系统要不要推断系统休眠状态上报键值 题外话:一个问题研究到最后,那边记录文档的前半部分基本上都是没用的,甚至是错误的. 重点在最后,前边不过一些假想猜測. ht ...

  8. Linux输入子系统 转载

    NQian 记录成长~ 首页 新随笔 联系 订阅 管理 随笔 - 305  文章 - 0  评论 - 254 12.Linux之输入子系统分析(详解)   在此节之前,我们学的都是简单的字符驱动,涉及 ...

  9. Linux输入子系统框架分析(1)

    在Linux下的输入设备键盘.触摸屏.鼠标等都能够用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层.事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备 ...

随机推荐

  1. tensorboard 可视化网络运行过程

    在 tf.summary 里设置好要查看保存的参数后运行会生成 events.out.tfevents.{time}.{machine-name} 的文件,这个就是用 tensorboard 来查看的 ...

  2. P5239 回忆京都(洛谷3月月赛T2)

    题目描述 射命丸文在取材中发现了一个好玩的东西,叫做组合数. 组合数的定义如下:从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合.所有组合的数量,就是组合数 ...

  3. 第一个Jsp页面,基于普元EOS

    跨界了.搞一下Jsp,实现MES系统看板一处.

  4. C# Note35: 异步操作

    .NET Framework 为异步操作提供了两种设计模式:使用 IAsyncResult 对象的异步操作与使用事件的异步操作. IAsyncResult 异步设计模式 通过名为 BeginOpera ...

  5. hdu-5786(补图最短路)

    题意:给你n个点,m条无向边,问你这n个点构成的完全图,不用那m条边,由一个s出现的单源最短路 解题思路:首先,暴力建图不行,点太多,那么我们就按照它的规则来,把m条边建好,但是建的这个图表示不走的方 ...

  6. koa-router 后台路由管理框架

    koa-router是koa框架配套的路由管理模块,对后台的接口分离出来. 首先引入koa和koa-router, 然后分批设置路由: 代码中的institution.modifyInsStatus是 ...

  7. Javascript初识之数据类型

    一.JavaScript概述 1.ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组 ...

  8. Routing 为 Magento 2 一个重要的部分,本文介绍基本应用

    Routing 为 Magento 2 一个重要的部分,本文介绍基本应用 Magento 2请求的流程 在Magento 2中,请求URL将如下所示: http://example.com/index ...

  9. sopUI上手教程

    1.新建项目 File-->New SOAP Project-->Project Name:填入项目名  Initial WSDL:填入项目的 web Services 2.添加WSDL ...

  10. Mock6 moco框架中如何加入header

    新建一个 startupWithHeader.json,这次在request里面添加了headers属性 [ { "description": "这是一个带header的 ...