diff --git a/playback.c b/playback.c index 1f47a60..a95ac96 100644 --- a/playback.c +++ b/playback.c @@ -10,7 +10,13 @@ #include #include -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) {}