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!
");
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 ----------
");
 22             break;
 23         case EV_KEY:
 24             printf("key code%d is %s!
", 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
", event.value);
 31             } else if ((event.code == ABS_Y) ||
 32                  (event.code == ABS_MT_POSITION_Y)) {
 33                 printf("y = %d
", event.value);
 34             } else if ((event.code == ABS_PRESSURE) || 
 35                 (event.code == ABS_MT_PRESSURE)) {
 36                 printf("pressure value: %d
", event.value);
 37             }
 38             break;
 39         case EV_REL:
 40             if (event.code == REL_X) {
 41                 printf("x = %d
", event.value);
 42             } else if (event.code == REL_Y) {
 43                 printf("y = %d
", 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...
");
 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!
");
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 ----------
");
 23             } else if (event.code == SYN_MT_REPORT) {
 24                 printf("----------- syn mt report ------------
");
 25             }
 26             break;
 27         case EV_KEY:
 28             printf("key code%d is %s!
", 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
", event.value);
 35             } else if ((event.code == ABS_Y) ||
 36                  (event.code == ABS_MT_POSITION_Y)) {
 37                 printf("y = %d
", event.value);
 38             } else if ((event.code == ABS_PRESSURE) || 
 39                 (event.code == ABS_MT_PRESSURE)) {
 40                 printf("pressure value: %d
", event.value);
 41             }
 42             break;
 43         case EV_REL:
 44             if (event.code == REL_X) {
 45                 printf("x = %d
", event.value);
 46             } else if (event.code == REL_Y) {
 47                 printf("y = %d
", 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...
");
 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!
");
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 ----------
");
 23             } else if (event.code == SYN_MT_REPORT) {
 24                 printf("----------- syn mt report ------------
");
 25             }
 26             break;
 27         case EV_KEY:
 28             printf("key code%d is %s!
", 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
", event.value);
 35             } else if ((event.code == ABS_Y) ||
 36                  (event.code == ABS_MT_POSITION_Y)) {
 37                 printf("y = %d
", event.value);
 38             } else if ((event.code == ABS_PRESSURE) || 
 39                 (event.code == ABS_MT_PRESSURE)) {
 40                 printf("pressure value: %d
", event.value);
 41             }
 42             break;
 43         case EV_REL:
 44             if (event.code == REL_X) {
 45                 printf("x = %d
", event.value);
 46             } else if (event.code == REL_Y) {
 47                 printf("y = %d
", 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...
");
 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 }
复制代码

                                                                                 

 

原文地址:https://www.cnblogs.com/sky-heaven/p/10681998.html