Make mouse playback work.
This only includes left mouse button clicks, not right mouse button clicks or scrollwheels.
This commit is contained in:
parent
61843f23c3
commit
829432d443
160
playback.c
160
playback.c
|
@ -10,7 +10,13 @@
|
|||
#include <linux/uinput.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int read_file(char* filename);
|
||||
int handle_keyboard(char* details, int keyboard_fd);
|
||||
int handle_line(char* line, int keyboard_fd, int mouse_fd);
|
||||
int handle_mouse(char* details, int mouse_fd);
|
||||
int read_file(char* filename, int keyboard_fd, int mouse_fd);
|
||||
int setup_mouse();
|
||||
void teardown_keyboard(int fd);
|
||||
void teardown_mouse(int fd);
|
||||
|
||||
void emit(int fd, int type, int code, int val) {
|
||||
struct input_event ie;
|
||||
|
@ -23,7 +29,19 @@ void emit(int fd, int type, int code, int val) {
|
|||
write(fd, &ie, sizeof(ie));
|
||||
}
|
||||
|
||||
int handle_line(char* line) {
|
||||
int handle_keyboard(char* details, int keyboard_fd) {
|
||||
int code, event_type, value;
|
||||
int matched = sscanf(details, "%d,%d,%d", &event_type, &code, &value);
|
||||
if(matched != 3) {
|
||||
printf("Didn't match enough values for a keyboard event.\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Event type: %d, Code: %d, Value: %d\n",
|
||||
event_type, code, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_line(char* line, int keyboard_fd, int mouse_fd) {
|
||||
static time_t timer_seconds = 0;
|
||||
static long timer_nanos = 0;
|
||||
|
||||
|
@ -49,7 +67,6 @@ int handle_line(char* line) {
|
|||
--to_sleep.tv_nsec;
|
||||
to_sleep.tv_nsec += 1000000000L;
|
||||
}
|
||||
printf("%s", line);
|
||||
// printf("Timer %ld %ld\n", timer_seconds, timer_nanos);
|
||||
// printf("Read %ld %ld\n", seconds, nanos);
|
||||
// printf("Sleep %ld %ld\n", to_sleep.tv_sec, to_sleep.tv_nsec);
|
||||
|
@ -60,6 +77,47 @@ int handle_line(char* line) {
|
|||
}
|
||||
timer_seconds = seconds;
|
||||
timer_nanos = nanos;
|
||||
|
||||
if(type == 'k') {
|
||||
return handle_keyboard(details, keyboard_fd);
|
||||
} else if(type == 'm') {
|
||||
return handle_mouse(details, mouse_fd);
|
||||
} else {
|
||||
printf("Unexpected type %c/n", type);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int handle_mouse(char* details, int mouse_fd) {
|
||||
static int current_left = 0;
|
||||
static int current_middle = 0;
|
||||
static int current_right = 0;
|
||||
|
||||
int left, middle, right, x, y;
|
||||
int matched = sscanf(details, "l%d,m%d,r%d,x%d,y%d",
|
||||
&left, &middle, &right, &x, &y);
|
||||
if(matched != 5) {
|
||||
printf("Failed to match enough data for a mouse event.\n");
|
||||
return 1;
|
||||
}
|
||||
printf("L: %d M: %d, R: %d, X: %d, Y: %d\n",
|
||||
left, middle, right, x, y);
|
||||
|
||||
/* Move the mouse diagonally, 5 units per axis */
|
||||
if(x != 0) {
|
||||
emit(mouse_fd, EV_REL, REL_X, x);
|
||||
}
|
||||
if(y != 0) {
|
||||
emit(mouse_fd, EV_REL, REL_Y, y);
|
||||
}
|
||||
|
||||
if(left != current_left) {
|
||||
emit(mouse_fd, EV_KEY, BTN_MOUSE, left);
|
||||
current_left = left;
|
||||
}
|
||||
emit(mouse_fd, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -69,13 +127,18 @@ int main(int argc, char* argv[]) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(read_file(argv[1])) {
|
||||
exit(EXIT_FAILURE);
|
||||
int result = 0;
|
||||
int mouse_fd = setup_mouse();
|
||||
int keyboard_fd = 0;
|
||||
if(read_file(argv[1], keyboard_fd, mouse_fd)) {
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
teardown_keyboard(keyboard_fd);
|
||||
teardown_mouse(mouse_fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
int read_file(char* filename) {
|
||||
int read_file(char* filename, int keyboard_fd, int mouse_fd) {
|
||||
FILE* fp;
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
@ -88,7 +151,7 @@ int read_file(char* filename) {
|
|||
}
|
||||
|
||||
while((read = getline(&line, &len, fp)) != -1) {
|
||||
if(handle_line(line)) {
|
||||
if(handle_line(line, keyboard_fd, mouse_fd)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -96,65 +159,42 @@ int read_file(char* filename) {
|
|||
|
||||
int setup_mouse() {
|
||||
struct uinput_setup usetup;
|
||||
// int i = 50;
|
||||
int i = 0;
|
||||
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
|
||||
|
||||
/* enable mouse button left and relative events */
|
||||
printf("EV_KEY 0x%08x\n", EV_KEY);
|
||||
printf("UI_SET_EVBIT 0x%08lx\n", UI_SET_EVBIT);
|
||||
printf("UI_SET_KEYBIT 0x%08lx\n", UI_SET_KEYBIT);
|
||||
printf("BTN_LEFT 0x%08x\n", BTN_LEFT);
|
||||
printf("EV_REL 0x%08x\n", EV_REL);
|
||||
|
||||
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
||||
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
||||
|
||||
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
|
||||
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
|
||||
|
||||
ioctl(fd, UI_SET_EVBIT, EV_REL);
|
||||
ioctl(fd, UI_SET_RELBIT, REL_X);
|
||||
ioctl(fd, UI_SET_RELBIT, REL_Y);
|
||||
ioctl(fd, UI_SET_EVBIT, EV_REL);
|
||||
ioctl(fd, UI_SET_RELBIT, REL_X);
|
||||
ioctl(fd, UI_SET_RELBIT, REL_Y);
|
||||
|
||||
memset(&usetup, 0, sizeof(usetup));
|
||||
usetup.id.bustype = BUS_USB;
|
||||
usetup.id.vendor = 0x1234; /* sample vendor */
|
||||
usetup.id.product = 0x5678; /* sample product */
|
||||
strcpy(usetup.name, "Example device");
|
||||
memset(&usetup, 0, sizeof(usetup));
|
||||
usetup.id.bustype = BUS_USB;
|
||||
usetup.id.vendor = 0x1234; /* sample vendor */
|
||||
usetup.id.product = 0x5678; /* sample product */
|
||||
strcpy(usetup.name, "Playback mouses");
|
||||
|
||||
ioctl(fd, UI_DEV_SETUP, &usetup);
|
||||
ioctl(fd, UI_DEV_CREATE);
|
||||
ioctl(fd, UI_DEV_SETUP, &usetup);
|
||||
ioctl(fd, UI_DEV_CREATE);
|
||||
|
||||
/*
|
||||
* On UI_DEV_CREATE the kernel will create the device node for this
|
||||
* device. We are inserting a pause here so that userspace has time
|
||||
* to detect, initialize the new device, and can start listening to
|
||||
* the event, otherwise it will not notice the event we are about
|
||||
* to send. This pause is only needed in our example code!
|
||||
*/
|
||||
sleep(1);
|
||||
|
||||
/* Move the mouse diagonally, 5 units per axis */
|
||||
while (i--) {
|
||||
emit(fd, EV_REL, REL_X, 5);
|
||||
emit(fd, EV_REL, REL_Y, 5);
|
||||
emit(fd, EV_SYN, SYN_REPORT, 0);
|
||||
usleep(15000);
|
||||
}
|
||||
|
||||
// Click left mouse button.
|
||||
|
||||
emit(fd, EV_KEY, BTN_MOUSE, 1);
|
||||
emit(fd, EV_SYN, SYN_REPORT, 0);
|
||||
emit(fd, EV_KEY, BTN_MOUSE, 0);
|
||||
emit(fd, EV_SYN, SYN_REPORT, 0);
|
||||
/*
|
||||
* Give userspace some time to read the events before we destroy the
|
||||
* device with UI_DEV_DESTOY.
|
||||
*/
|
||||
sleep(1);
|
||||
|
||||
ioctl(fd, UI_DEV_DESTROY);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
/*
|
||||
* On UI_DEV_CREATE the kernel will create the device node for this
|
||||
* device. We are inserting a pause here so that userspace has time
|
||||
* to detect, initialize the new device, and can start listening to
|
||||
* the event, otherwise it will not notice the event we are about
|
||||
* to send. This pause is only needed in our example code!
|
||||
*/
|
||||
// sleep(1);
|
||||
printf("Setup mouse to fd %d", fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
void teardown_mouse(int fd) {
|
||||
ioctl(fd, UI_DEV_DESTROY);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void teardown_keyboard(int fd) {}
|
||||
|
|
Loading…
Reference in New Issue