转自: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. C# 使用微软自带的Speech进行语音输出

    1.在VS中使用微软自带的Speech进行语音播报,首先需要添加引用: 2.具体实现逻辑代码如下:

  2. [P1169] 棋盘制作 &悬线法学习笔记

    学习笔记 悬线法 最大子矩阵问题: 在一个给定的矩形中有一些障碍点,找出内部不包含障碍点的,边与整个矩形平行或重合的最大子矩形. 极大子矩型:无法再向外拓展的有效子矩形 最大子矩型:最大的一个有效子矩 ...

  3. [亲测]七步学会ASP.NET Core 2.0怎么发布/部署到Ubuntu Linux服务器并配置Nginx反向代理实现域名访问

    前言 ASP.NET Core 2.0 怎么发布到Ubuntu服务器?又如何在服务器上配置使用ASP.NET Core网站绑定到指定的域名,让外网用户可以访问呢? 步骤 第1步:准备工作 一台Liun ...

  4. 更多的贴片SOT-23三极管,请点击以下表格购买。

    更多的贴片SOT-23三极管,请点击以下表格购买. 型号 标识 电流 V数 极性 封装 购买链接 S9012 2T1 0.3A 20V PNP SOT-23 点击购买 S9013 J3 0.3A 25 ...

  5. CodeVs 1615 数据备份

    题目:数据备份 链接:Here 题意:有n个点在一条线上,每次连线可以连接两个点(每个点只能被连一次),要求找出m个连线,他们的和最小(连线权值就是两点距离),输出最小的和.给出n.m和每个点的坐标. ...

  6. Spring-framework

    1.spring注解驱动开发 官方文档 @Configuration 告诉spring这是一个配置类,配置类=配置文件 @Bean 给容器中注入一个bean,类型为返回值类型,id默认用方法名作为id ...

  7. Python——hashilib 模块(哈希模块)

    hashilib 模块 摘要算法 import hashlib # 提供摘要算法的模块 md5 = hashlib.md5() md5.update(b'alex3714') print(md5.he ...

  8. position:sticky

    使用sticky定位可以简洁的实现固定功能 例如,左右布局页面,左侧菜单,右侧内容,内容区域滚动时,不希望菜单区域滚动,而是固定不动 以往要实现这个功能,需要使用fixed定位菜单,菜单脱离文档流,布 ...

  9. Python判断自定义的参数格式是否正确

    import argparse def args_validation(valid_list, valid_value): assert valid_value in valid_list, 'inv ...

  10. Entity Framework入门教程(7)--- EF中的查询方法

    这里主要介绍两种查询方法 Linq to entity(L2E)和Sql 1.L2E查询 L2E查询时可以使用linq query语法,或者lambda表达式,默认返回的类型是IQueryable,( ...