Add support for playing back keyboard messages.
Also fix a timing bug where I was waiting 1 second too long any time the nansec clock rolled over.
This commit is contained in:
parent
829432d443
commit
a3579fd339
100
playback.c
100
playback.c
|
@ -10,13 +10,12 @@
|
||||||
#include <linux/uinput.h>
|
#include <linux/uinput.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
int handle_keyboard(char* details, int keyboard_fd);
|
int handle_udevice(char* details, int udevice_fd);
|
||||||
int handle_line(char* line, int keyboard_fd, int mouse_fd);
|
int handle_line(char* line, int udevice_fd);
|
||||||
int handle_mouse(char* details, int mouse_fd);
|
int handle_mouse(char* details, int udevice_fd);
|
||||||
int read_file(char* filename, int keyboard_fd, int mouse_fd);
|
int read_file(char* filename, int udevice_fd);
|
||||||
int setup_mouse();
|
int setup_udevice();
|
||||||
void teardown_keyboard(int fd);
|
void teardown_udevice(int fd);
|
||||||
void teardown_mouse(int fd);
|
|
||||||
|
|
||||||
void emit(int fd, int type, int code, int val) {
|
void emit(int fd, int type, int code, int val) {
|
||||||
struct input_event ie;
|
struct input_event ie;
|
||||||
|
@ -29,21 +28,30 @@ void emit(int fd, int type, int code, int val) {
|
||||||
write(fd, &ie, sizeof(ie));
|
write(fd, &ie, sizeof(ie));
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_keyboard(char* details, int keyboard_fd) {
|
int handle_keyboard(char* details, int udevice_fd) {
|
||||||
int code, event_type, value;
|
int code, event_type, value;
|
||||||
int matched = sscanf(details, "%d,%d,%d", &event_type, &code, &value);
|
int matched = sscanf(details, "%d,%d,%d", &event_type, &code, &value);
|
||||||
if(matched != 3) {
|
if(matched != 3) {
|
||||||
printf("Didn't match enough values for a keyboard event.\n");
|
printf("Didn't match enough values for a keyboard event.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("Event type: %d, Code: %d, Value: %d\n",
|
// printf("Event type: %d, Code: %d, Value: %d\n",
|
||||||
event_type, code, value);
|
// event_type, code, value);
|
||||||
|
if(event_type != 1) {
|
||||||
|
printf("Not sure what to do with event type %d", event_type);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
emit(udevice_fd, EV_KEY, code, value);
|
||||||
|
emit(udevice_fd, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_line(char* line, int keyboard_fd, int mouse_fd) {
|
int handle_line(char* line, int udevice_fd) {
|
||||||
static time_t timer_seconds = 0;
|
static time_t timer_seconds = 0;
|
||||||
static long timer_nanos = 0;
|
static long timer_nanos = 0;
|
||||||
|
static time_t total_seconds = 0;
|
||||||
|
static long total_nanos = 0;
|
||||||
|
|
||||||
time_t seconds;
|
time_t seconds;
|
||||||
long nanos;
|
long nanos;
|
||||||
|
@ -61,34 +69,47 @@ int handle_line(char* line, int keyboard_fd, int mouse_fd) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remaining.tv_sec = 0;
|
||||||
|
remaining.tv_nsec = 0;
|
||||||
to_sleep.tv_sec = seconds - timer_seconds;
|
to_sleep.tv_sec = seconds - timer_seconds;
|
||||||
to_sleep.tv_nsec = nanos - timer_nanos;
|
to_sleep.tv_nsec = nanos - timer_nanos;
|
||||||
if(to_sleep.tv_nsec < 0) {
|
if(to_sleep.tv_nsec < 0) {
|
||||||
--to_sleep.tv_nsec;
|
--to_sleep.tv_sec;
|
||||||
to_sleep.tv_nsec += 1000000000L;
|
to_sleep.tv_nsec += 1000000000L;
|
||||||
}
|
}
|
||||||
// printf("Timer %ld %ld\n", timer_seconds, timer_nanos);
|
// printf("Timer %ld %ld\n", timer_seconds, timer_nanos);
|
||||||
// printf("Read %ld %ld\n", seconds, nanos);
|
// printf("Read %ld %ld\n", seconds, nanos);
|
||||||
// printf("Sleep %ld %ld\n", to_sleep.tv_sec, to_sleep.tv_nsec);
|
// 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) {
|
while(nanosleep(&to_sleep, &remaining) == -1) {
|
||||||
|
printf("Sleep harder\n");
|
||||||
to_sleep.tv_sec = remaining.tv_sec;
|
to_sleep.tv_sec = remaining.tv_sec;
|
||||||
to_sleep.tv_nsec = remaining.tv_nsec;
|
to_sleep.tv_nsec = remaining.tv_nsec;
|
||||||
}
|
}
|
||||||
|
if(remaining.tv_sec != 0 || remaining.tv_nsec != 0) {
|
||||||
|
printf("oops, remaining.\n");
|
||||||
|
}
|
||||||
|
total_seconds += to_sleep.tv_sec;
|
||||||
|
total_nanos += to_sleep.tv_nsec;
|
||||||
|
if(total_nanos > 1000000000L) {
|
||||||
|
total_nanos -= 1000000000L;
|
||||||
|
total_seconds += 1;
|
||||||
|
}
|
||||||
timer_seconds = seconds;
|
timer_seconds = seconds;
|
||||||
timer_nanos = nanos;
|
timer_nanos = nanos;
|
||||||
|
|
||||||
|
printf("%ld %ld\tslept %ld %ld\n",
|
||||||
|
total_seconds, total_nanos, to_sleep.tv_sec, to_sleep.tv_nsec);
|
||||||
if(type == 'k') {
|
if(type == 'k') {
|
||||||
return handle_keyboard(details, keyboard_fd);
|
return handle_keyboard(details, udevice_fd);
|
||||||
} else if(type == 'm') {
|
} else if(type == 'm') {
|
||||||
return handle_mouse(details, mouse_fd);
|
return handle_mouse(details, udevice_fd);
|
||||||
} else {
|
} else {
|
||||||
printf("Unexpected type %c/n", type);
|
printf("Unexpected type %c/n", type);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_mouse(char* details, int mouse_fd) {
|
int handle_mouse(char* details, int udevice_fd) {
|
||||||
static int current_left = 0;
|
static int current_left = 0;
|
||||||
static int current_middle = 0;
|
static int current_middle = 0;
|
||||||
static int current_right = 0;
|
static int current_right = 0;
|
||||||
|
@ -100,22 +121,30 @@ int handle_mouse(char* details, int mouse_fd) {
|
||||||
printf("Failed to match enough data for a mouse event.\n");
|
printf("Failed to match enough data for a mouse event.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
printf("L: %d M: %d, R: %d, X: %d, Y: %d\n",
|
// printf("L: %d M: %d, R: %d, X: %d, Y: %d\n",
|
||||||
left, middle, right, x, y);
|
// left, middle, right, x, y);
|
||||||
|
|
||||||
/* Move the mouse diagonally, 5 units per axis */
|
/* Move the mouse diagonally, 5 units per axis */
|
||||||
if(x != 0) {
|
if(x != 0) {
|
||||||
emit(mouse_fd, EV_REL, REL_X, x);
|
emit(udevice_fd, EV_REL, REL_X, x);
|
||||||
}
|
}
|
||||||
if(y != 0) {
|
if(y != 0) {
|
||||||
emit(mouse_fd, EV_REL, REL_Y, y);
|
emit(udevice_fd, EV_REL, REL_Y, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(left != current_left) {
|
if(left != current_left) {
|
||||||
emit(mouse_fd, EV_KEY, BTN_MOUSE, left);
|
emit(udevice_fd, EV_KEY, BTN_LEFT, left);
|
||||||
current_left = left;
|
current_left = left;
|
||||||
}
|
}
|
||||||
emit(mouse_fd, EV_SYN, SYN_REPORT, 0);
|
if(middle != current_middle) {
|
||||||
|
emit(udevice_fd, EV_KEY, BTN_MIDDLE, middle);
|
||||||
|
current_middle = middle;
|
||||||
|
}
|
||||||
|
if(right != current_right) {
|
||||||
|
emit(udevice_fd, EV_KEY, BTN_RIGHT, right);
|
||||||
|
current_right = right;
|
||||||
|
}
|
||||||
|
emit(udevice_fd, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -128,17 +157,15 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int mouse_fd = setup_mouse();
|
int udevice_fd = setup_udevice();
|
||||||
int keyboard_fd = 0;
|
if(read_file(argv[1], udevice_fd)) {
|
||||||
if(read_file(argv[1], keyboard_fd, mouse_fd)) {
|
|
||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
teardown_keyboard(keyboard_fd);
|
teardown_udevice(udevice_fd);
|
||||||
teardown_mouse(mouse_fd);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_file(char* filename, int keyboard_fd, int mouse_fd) {
|
int read_file(char* filename, int udevice_fd) {
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
char* line = NULL;
|
char* line = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
@ -151,13 +178,13 @@ int read_file(char* filename, int keyboard_fd, int mouse_fd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while((read = getline(&line, &len, fp)) != -1) {
|
while((read = getline(&line, &len, fp)) != -1) {
|
||||||
if(handle_line(line, keyboard_fd, mouse_fd)) {
|
if(handle_line(line, udevice_fd)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int setup_mouse() {
|
int setup_udevice() {
|
||||||
struct uinput_setup usetup;
|
struct uinput_setup usetup;
|
||||||
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
|
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
|
||||||
|
|
||||||
|
@ -165,6 +192,14 @@ int setup_mouse() {
|
||||||
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
||||||
|
|
||||||
|
// Add keyboard keys. We could do this individually but we're super
|
||||||
|
// lazy and it appears a loop should work fine based on the linux/input-event-codes.h header
|
||||||
|
for(int i = KEY_ESC; i <= KEY_MICMUTE; i++) {
|
||||||
|
ioctl(fd, UI_SET_KEYBIT, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add mouse buttons
|
||||||
|
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
|
||||||
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_EVBIT, EV_REL);
|
||||||
|
@ -188,13 +223,10 @@ int setup_mouse() {
|
||||||
* to send. This pause is only needed in our example code!
|
* to send. This pause is only needed in our example code!
|
||||||
*/
|
*/
|
||||||
// sleep(1);
|
// sleep(1);
|
||||||
printf("Setup mouse to fd %d", fd);
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void teardown_mouse(int fd) {
|
void teardown_udevice(int fd) {
|
||||||
ioctl(fd, UI_DEV_DESTROY);
|
ioctl(fd, UI_DEV_DESTROY);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void teardown_keyboard(int fd) {}
|
|
||||||
|
|
Loading…
Reference in New Issue