参考:读取/dev/input/mice可以得到所有鼠标的信息,只要有鼠标读它就行,因为所有的鼠标的消息都会发给它一份,而且mice是全局唯一且固定的,所以即使没有插入鼠标设备,mice也是存在
测试1:拔掉所有鼠标,用键盘输入ls /dev/input发现mice还在,而mouse(i)没了
测试2:插上两个鼠标
hexdump /dev/input/mouse0后移动这个设备对应的鼠标,桌面光标移动,并且终端打印数据,而移动mouse1对应的鼠标,桌面光标在动,但是没有打印数据,反过来一样
测试3:hexdump /dev/input/mice后移动一个鼠标,打印数据,移动另一个鼠标也打印数据
通过c编程得到mice设备的数据:c读/dev/input/mice
但是通过读取/dev/input/mice的数据只有左右中键和x,y变化量,没有滚轮变化量,因为鼠标在系统中被配置成了没有滚轮的PS/2鼠标,只有配置为IMPS/2鼠标,读取mice才能够得到滚轮的变化,。
但是最好还是通过输入子系统输入事件来读取数据。
通过cat /proc/bus/input/devices查看鼠标设备对应的事件,对于普通光学鼠标来讲,只有一个事件,如果是有附加功能的鼠标如游戏鼠标的话就有多个事件,所以实现通过hexdump /dev/input/event(i)测试哪个是鼠标的事件。
然后通过c代码测试
#include <stdio.h> #include <stdlib.h> #include <linux/input.h> #include <fcntl.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> //cat /proc/bus/input/devices找到鼠标的对应的事件 #define MOUSE "/dev/input/event4" int main(int argc,char **argv) { int fd, retval; struct input_event event; fd_set readfds; int ret; struct timeval tv; struct timeval time; // 打开鼠标设备, fd = open(MOUSE, O_RDONLY ); // 判断是否打开成功 if(fd<0) { perror("open ""MOUSE"); exit(1); } while(1) { // 设置最长等待时间 tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO( &readfds ); FD_SET( fd, &readfds ); retval = select( fd+1, &readfds, NULL, NULL, &tv ); if(retval==0) { printf( "Time out!\n" ); } if(FD_ISSET(fd,&readfds)) { // 读取鼠标设备中的数据 ret=read(fd,&event,sizeof(struct input_event)); // 打印出从鼠标设备中读取到的数据 time=event.time; printf("timeS=%d,timeUS=%d,type=0x%02x,code=0x%02x,value=%d \n",time.tv_sec,time.tv_usec,event.type,event.code,event.value); } } close(fd); return 0; }
比如按下鼠标左键后松开产生的事件如下,timeS+timeUS是系统从1970过来的总时间,事件类型和事件码看linux/input.h即可,这里也可以找到事件类型和事件码的含义,1~3是按下事件,下面第一个事件是EV_MSC杂项事件,事件码为4表示MSC_SCAN,第二个事件是EV_KEY事件,事件码为0x110表示BTN_LEFT,值为1表示按下,第三个事件是同步事件,主要作为事件的分隔用的,4~5是松开事件
timeS=1523006075,timeUS=428047,type=0x04,code=0x04,value=589825 timeS=1523006075,timeUS=428047,type=0x01,code=0x110,value=1 timeS=1523006075,timeUS=428047,type=0x00,code=0x00,value=0 timeS=1523006075,timeUS=572049,type=0x04,code=0x04,value=589825 timeS=1523006075,timeUS=572049,type=0x01,code=0x110,value=0 timeS=1523006075,timeUS=572049,type=0x00,code=0x00,value=0
鼠标移动的话产生同步事件,EV_REL事件,code=0表示REL_X,为1表示REL_Y,分别表示x和y轴的变化量,其值记录在value中,鼠标向右,x变化量大于0,鼠标向左小于0,鼠标像下y变化量大于0,向上小于0,移动越快,变化量绝对值越大
timeS=1523006369,timeUS=940137,type=0x00,code=0x00,value=0 timeS=1523006369,timeUS=948197,type=0x02,code=0x00,value=3 timeS=1523006369,timeUS=948197,type=0x00,code=0x00,value=0 timeS=1523006369,timeUS=956196,type=0x02,code=0x00,value=2 timeS=1523006369,timeUS=956196,type=0x02,code=0x01,value=2 timeS=1523006369,timeUS=956196,type=0x00,code=0x00,value=0 timeS=1523006369,timeUS=996198,type=0x02,code=0x00,value=1
键盘和触摸和摇杆等其他的设备都是差不多的,用上面的测试代码就可以得到事件的描述。
下面贴个控制键盘led灯的测试
#include <stdio.h> #include <stdlib.h> #include <linux/input.h> #include <fcntl.h> #include <sys/time.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> /** ref:https://askubuntu.com/questions/321512/how-to-set-or-clear-usb-keyboard-leds **/ #define DEV "/dev/input/event3" int main(int argc,char **argv) { int fd, retval; struct input_event event; fd = open(DEV, O_RDWR);//需要写权限,不写报错bad file descriptor if(fd<0) { perror("open "DEV); exit(1); } event.type = EV_LED; event.value = 0; while(1){ event.value = event.value?0:1; //0点亮,1熄灭 event.code = LED_CAPSL;//caps灯 if (write(fd,&event,sizeof (struct input_event)) < 0){ perror("write "DEV); } event.code = LED_NUML;//num灯 if (write(fd,&event,sizeof (struct input_event)) < 0){ perror("write "DEV); } event.code = LED_SCROLLL;//scroll灯 if (write(fd,&event,sizeof (struct input_event)) < 0){ perror("write "DEV); } sleep(1); } close(fd); return 0; }