参考:读取/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;
}