161 lines
3.7 KiB
C
161 lines
3.7 KiB
C
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include <linux/uinput.h>
|
|
#include <sys/stat.h>
|
|
|
|
int read_file(char* filename);
|
|
|
|
void emit(int fd, int type, int code, int val) {
|
|
struct input_event ie;
|
|
ie.type = type;
|
|
ie.code = code;
|
|
ie.value = val;
|
|
ie.time.tv_sec = 0;
|
|
ie.time.tv_usec = 0;
|
|
|
|
write(fd, &ie, sizeof(ie));
|
|
}
|
|
|
|
int handle_line(char* line) {
|
|
static time_t timer_seconds = 0;
|
|
static long timer_nanos = 0;
|
|
|
|
time_t seconds;
|
|
long nanos;
|
|
char type;
|
|
char details[32];
|
|
struct timespec to_sleep;
|
|
struct timespec remaining;
|
|
|
|
int matched = sscanf(line, "%ld %ld,%c,%s\n", &seconds, &nanos, &type, details);
|
|
if(matched == 0) {
|
|
printf("Line '%s' appears incorrect. Exiting", line);
|
|
return 1;
|
|
} else if(matched < 4) {
|
|
printf("Only matched %d", matched);
|
|
return 1;
|
|
}
|
|
|
|
to_sleep.tv_sec = seconds - timer_seconds;
|
|
to_sleep.tv_nsec = nanos - timer_nanos;
|
|
if(to_sleep.tv_nsec < 0) {
|
|
--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);
|
|
int result = nanosleep(&to_sleep, &remaining);
|
|
while(nanosleep(&to_sleep, &remaining) == -1) {
|
|
to_sleep.tv_sec = remaining.tv_sec;
|
|
to_sleep.tv_nsec = remaining.tv_nsec;
|
|
}
|
|
timer_seconds = seconds;
|
|
timer_nanos = nanos;
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if(argc < 2) {
|
|
printf("Please provide a capture file.");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if(read_file(argv[1])) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int read_file(char* filename) {
|
|
FILE* fp;
|
|
char* line = NULL;
|
|
size_t len = 0;
|
|
ssize_t read;
|
|
|
|
fp = fopen(filename, "r");
|
|
if (fp == NULL) {
|
|
printf("Failed to open file %s: %d\n", filename, errno);
|
|
return 1;
|
|
}
|
|
|
|
while((read = getline(&line, &len, fp)) != -1) {
|
|
if(handle_line(line)) {
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
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_KEYBIT, BTN_LEFT);
|
|
|
|
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");
|
|
|
|
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;
|
|
}
|