我正在尝试使用绝对坐标移动光标.这是代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <linux/input.h> #include <linux/uinput.h> #include <signal.h> #define die(str,args...) do { \ perror(str); \ exit(EXIT_FAILURE); \ } while(0) int fd; static void signal_handler(int signo) { printf("\nCaught SIGINT\n"); if(ioctl(fd,UI_DEV_DESTROY) < 0) die("error: cannot destroy uinput device\n"); else printf("Destroyed uinput_user_dev\n\n"); close(fd); exit(EXIT_SUCCESS); } int main(void) { struct uinput_user_dev uidev; struct input_event ev; int x,y; int i; if(signal(SIGINT,signal_handler)==SIG_ERR) { printf("error registering signal handler\n"); exit(EXIT_FAILURE); } fd = open("/dev/uinput",O_WRONLY | O_NONBLOCK); if(fd < 0) die("error: open"); if(ioctl(fd,UI_SET_EVBIT,EV_KEY) < 0) die("error: ioctl"); // if(ioctl(fd,UI_SET_KEYBIT,BTN_MOUSE) < 0) // die("error: ioctl"); if(ioctl(fd,BTN_LEFT) < 0) die("error: ioctl"); if(ioctl(fd,BTN_RIGHT) < 0) die("error: ioctl"); if(ioctl(fd,EV_REL) < 0) die("error: ioctl"); if(ioctl(fd,UI_SET_RELBIT,REL_X) < 0) die("error: ioctl"); if(ioctl(fd,REL_Y) < 0) die("error: ioctl"); if(ioctl(fd,EV_ABS) < 0) die("error: ioctl"); if(ioctl(fd,UI_SET_ABSBIT,ABS_X) < 0) die("error: ioctl"); if(ioctl(fd,ABS_Y) < 0) die("error: ioctl"); memset(&uidev,sizeof(uidev)); snprintf(uidev.name,UINPUT_MAX_NAME_SIZE,"uinput-sample"); uidev.id.bustype = BUS_USB; uidev.id.vendor = 0x1; uidev.id.product = 0x1; uidev.id.version = 1; uidev.absmin[ABS_X]=0; uidev.absmax[ABS_X]=1023; uidev.absfuzz[ABS_X]=0; uidev.absflat[ABS_X ]=0; uidev.absmin[ABS_Y]=0; uidev.absmax[ABS_Y]=767; uidev.absfuzz[ABS_Y]=0; uidev.absflat[ABS_Y ]=0; if(write(fd,&uidev,sizeof(uidev)) < 0) die("error: write0"); if(ioctl(fd,UI_DEV_CREATE) < 0) die("error: ioctl"); sleep(2); while(1) { printf("\nEnter the absoulte x(0-1023) and y(0-767) co-ordinates:"); scanf("%d %d",&x,&y); memset(&ev,sizeof(struct input_event)); gettimeofday(&ev.time,NULL); ev.type = EV_ABS; ev.code = ABS_X; ev.value = x; if(write(fd,&ev,sizeof(struct input_event)) < 0) die("error: write1"); memset(&ev,sizeof(struct input_event)); ev.type = EV_SYN; if(write(fd,sizeof(struct input_event)) < 0) die("error: write4"); memset(&ev,sizeof(struct input_event)); ev.type = EV_ABS; ev.code = ABS_Y; ev.value = y; if(write(fd,sizeof(struct input_event)) < 0) die("error: write2"); memset(&ev,sizeof(struct input_event)) < 0) die("error: write3"); usleep(15000); printf("\nWritten x:%d y:%d to uinput.Press CTRL-C to quit:",x,y); } if(ioctl(fd,UI_DEV_DESTROY) < 0) die("error: cannot destroy uinput device\n"); close(fd); return 0; }
该程序似乎通过uinput将我输入的绝对坐标发送到内核的输入核心.
在启用evbug之后,我在dmesg上验证了这一点.但我的鼠标指针不会在屏幕上移动.我想知道我搞砸了什么.
也许EV_ABS与光标无关?我想知道因为使用EV_REL移动光标可以正常工作,如this tutorial所述.
样品运行:
ravi@linux-lxaf:~/workspace/driver> sudo ./a.out Enter the absoulte x(0-1023) and y(0-767) co-ordinates:100 200 Written x:100 y:200 to uinput.Press CTRL-C to quit: Enter the absoulte x(0-1023) and y(0-767) co-ordinates:10 765 Written x:10 y:765 to uinput.Press CTRL-C to quit: Enter the absoulte x(0-1023) and y(0-767) co-ordinates:^C Caught SIGINT Destroyed uinput_user_dev
Dmesg输出:
ravi@linux-lxaf:~/workspace/driver> dmesg |grep input16 [ 4750.660420] input: uinput-sample as /devices/virtual/input/input16 [ 4750.660594] evbug.c: Connected device: input16 (uinput-sample at unknown) [ 4761.389036] evbug.c: Event. Dev: input16,Type: 3,Code: 0,Value: 100 [ 4761.389047] evbug.c: Event. Dev: input16,Type: 0,Value: 0 [ 4761.389053] evbug.c: Event. Dev: input16,Code: 1,Value: 200 [ 4761.389058] evbug.c: Event. Dev: input16,Value: 0 [ 4776.893126] evbug.c: Event. Dev: input16,Value: 10 [ 4776.893138] evbug.c: Event. Dev: input16,Value: 0 [ 4776.893144] evbug.c: Event. Dev: input16,Value: 765 [ 4776.893148] evbug.c: Event. Dev: input16,Value: 0 [ 4778.729711] evbug.c: Event. Dev: input16,Value: 1 [ 4778.745506] evbug.c: Disconnected device: input16
解决方法
我刚刚发现输入内核将EV_ABS值作为绝对值传播到设备节点,如从/ dev / input / eventX中看到的那样(现在看起来很明显!).一直以来,控制光标的应用程序(X11? )当我给它绝对值时,期待相对鼠标移动,这可能会让它感到困惑!