From 458ef9f07d187ad45932285bc1d2d90c9d9f041a Mon Sep 17 00:00:00 2001 From: Denis Date: Sat, 23 Dec 2023 23:59:33 +0100 Subject: [PATCH] works with both kernel and sdl2 while using bt --- dev_out.c | 21 ++--- virt_ds5.c | 13 ++- virt_kbd.c | 251 +++++++++++++++------------------------------------ virt_mouse.c | 78 ++++++++-------- 4 files changed, 133 insertions(+), 230 deletions(-) diff --git a/dev_out.c b/dev_out.c index a205f0a..2707747 100644 --- a/dev_out.c +++ b/dev_out.c @@ -374,13 +374,8 @@ static void handle_incoming_message( } } -int64_t get_timediff_usec(const struct timeval *const past, const struct timeval *const now) { - struct timeval tdiff; - timersub(now, past, &tdiff); - - //const int64_t sgn = ((now->tv_sec > past->tv_sec) || ((now->tv_sec == past->tv_sec) && (now->tv_usec > past->tv_usec))) ? -1 : +1; - - return (int64_t)(tdiff.tv_sec) * (int64_t)1000000 + (int64_t)(tdiff.tv_usec); +int64_t get_timediff_usec(const struct timespec *const start, const struct timespec *const end) { + return (end->tv_sec - start->tv_sec) * 1000000000LL + (end->tv_nsec - start->tv_nsec); } void *dev_out_thread_func(void *ptr) { @@ -453,12 +448,12 @@ void *dev_out_thread_func(void *ptr) { } } - struct timeval now = {0}; - gettimeofday(&now, NULL); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); - struct timeval gamepad_last_hid_report_sent = now; - struct timeval mouse_last_hid_report_sent = now; - struct timeval keyboard_last_hid_report_sent = now; + struct timespec gamepad_last_hid_report_sent = now; + struct timespec mouse_last_hid_report_sent = now; + struct timespec keyboard_last_hid_report_sent = now; uint8_t tmp_buf[256]; @@ -473,7 +468,7 @@ void *dev_out_thread_func(void *ptr) { const int64_t mouse_time_diff_usecs = get_timediff_usec(&mouse_last_hid_report_sent, &now); const int64_t kbd_time_diff_usecs = get_timediff_usec(&keyboard_last_hid_report_sent, &now); - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC, &now); if ((current_gamepad_fd > 0) && (gamepad_time_diff_usecs >= gamepad_report_timing_us)) { gamepad_last_hid_report_sent = now; diff --git a/virt_ds5.c b/virt_ds5.c index 6b90fe2..65f3969 100644 --- a/virt_ds5.c +++ b/virt_ds5.c @@ -1037,7 +1037,7 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons // first byte is report-id which is 0x01 if ( (!gamepad->bluetooth) && (ev.u.output.data[0] != DS_OUTPUT_REPORT_USB) && - (gamepad->bluetooth) && (ev.u.output.data[0] != DS_OUTPUT_REPORT_BT) + (gamepad->bluetooth) && ((ev.u.output.data[0] != DS_OUTPUT_REPORT_BT) && (ev.u.output.data[0] < 0x10)) ) { fprintf( stderr, @@ -1050,7 +1050,16 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons // When using bluetooth, the first byte after the reportID is uint8_t seq_tag, // while the next one is uint8_t tag, following bytes are the same. - const uint8_t *const common_report = (gamepad->bluetooth) ? &ev.u.output.data[3] : &ev.u.output.data[1]; + size_t offset = 1; + if ((gamepad->bluetooth) && (ev.u.output.data[0] > 0x10)) { + offset = 2; + } else if ((gamepad->bluetooth) && (ev.u.output.data[0] == 0x02)) { + offset = 3; + } else if ((gamepad->bluetooth) && (ev.u.output.data[0] == 0x01)) { + offset = 1; + } + + const uint8_t *const common_report = &ev.u.output.data[offset]; const uint8_t valid_flag0 = common_report[0]; const uint8_t valid_flag1 = common_report[1]; diff --git a/virt_kbd.c b/virt_kbd.c index b535124..7a7ca3a 100644 --- a/virt_kbd.c +++ b/virt_kbd.c @@ -99,376 +99,252 @@ int virt_kbd_get_fd(virt_kbd_t *const kbd) { int virt_kbd_send(virt_kbd_t *const kbd, keyboard_status_t *const status, struct timeval *const now) { int res = 0; - struct timeval syn_time; - gettimeofday(&syn_time, NULL); + size_t events_count = 0; + struct input_event events[12]; struct input_event tmp_ev; - gettimeofday(&tmp_ev.time, NULL); - if (now != NULL) { - tmp_ev.time = *now; - } tmp_ev.type = EV_KEY; if (status->q != kbd->prev_q) { tmp_ev.code = KEY_Q; tmp_ev.value = kbd->prev_q = status->q; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->w != kbd->prev_w) { tmp_ev.code = KEY_W; tmp_ev.value = kbd->prev_w = status->w; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->e != kbd->prev_e) { tmp_ev.code = KEY_E; tmp_ev.value = kbd->prev_e = status->e; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->r != kbd->prev_r) { tmp_ev.code = KEY_R; tmp_ev.value = kbd->prev_r = status->r; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->t != kbd->prev_t) { tmp_ev.code = KEY_T; tmp_ev.value = kbd->prev_t = status->t; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->y != kbd->prev_y) { tmp_ev.code = KEY_Y; tmp_ev.value = kbd->prev_y = status->y; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->u != kbd->prev_u) { tmp_ev.code = KEY_U; tmp_ev.value = kbd->prev_u = status->u; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->i != kbd->prev_i) { tmp_ev.code = KEY_I; tmp_ev.value = kbd->prev_i = status->i; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->o != kbd->prev_o) { tmp_ev.code = KEY_O; tmp_ev.value = kbd->prev_o = status->o; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->p != kbd->prev_p) { tmp_ev.code = KEY_P; tmp_ev.value = kbd->prev_p = status->p; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->a != kbd->prev_a) { tmp_ev.code = KEY_A; tmp_ev.value = kbd->prev_a = status->a; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->s != kbd->prev_s) { tmp_ev.code = KEY_S; tmp_ev.value = kbd->prev_s = status->s; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->d != kbd->prev_d) { tmp_ev.code = KEY_D; tmp_ev.value = kbd->prev_d = status->d; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->f != kbd->prev_f) { tmp_ev.code = KEY_F; tmp_ev.value = kbd->prev_f = status->f; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->g != kbd->prev_g) { tmp_ev.code = KEY_G; tmp_ev.value = kbd->prev_g = status->g; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->h != kbd->prev_h) { tmp_ev.code = KEY_H; tmp_ev.value = kbd->prev_h = status->h; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->j != kbd->prev_j) { tmp_ev.code = KEY_J; tmp_ev.value = kbd->prev_j = status->j; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->k != kbd->prev_k) { tmp_ev.code = KEY_K; tmp_ev.value = kbd->prev_k = status->k; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->l != kbd->prev_l) { tmp_ev.code = KEY_L; tmp_ev.value = kbd->prev_l = status->l; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->z != kbd->prev_z) { tmp_ev.code = KEY_Z; tmp_ev.value = kbd->prev_z = status->z; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->x != kbd->prev_x) { tmp_ev.code = KEY_X; tmp_ev.value = kbd->prev_x = status->x; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->c != kbd->prev_c) { tmp_ev.code = KEY_C; tmp_ev.value = kbd->prev_c = status->c; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->v != kbd->prev_v) { tmp_ev.code = KEY_V; tmp_ev.value = kbd->prev_v = status->v; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->b != kbd->prev_b) { tmp_ev.code = KEY_B; tmp_ev.value = kbd->prev_b = status->b; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->n != kbd->prev_n) { tmp_ev.code = KEY_N; tmp_ev.value = kbd->prev_n = status->n; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->m != kbd->prev_m) { tmp_ev.code = KEY_M; tmp_ev.value = kbd->prev_m = status->m; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_0 != kbd->prev_num_0) { tmp_ev.code = KEY_0; tmp_ev.value = kbd->prev_num_0 = status->num_0; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_1 != kbd->prev_num_1) { tmp_ev.code = KEY_1; tmp_ev.value = kbd->prev_num_1 = status->num_1; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_2 != kbd->prev_num_2) { tmp_ev.code = KEY_2; tmp_ev.value = kbd->prev_num_2 = status->num_2; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_3 != kbd->prev_num_3) { tmp_ev.code = KEY_3; tmp_ev.value = kbd->prev_num_3 = status->num_3; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_4 != kbd->prev_num_4) { tmp_ev.code = KEY_4; tmp_ev.value = kbd->prev_num_4 = status->num_4; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_5 != kbd->prev_num_5) { tmp_ev.code = KEY_5; tmp_ev.value = kbd->prev_num_5 = status->num_5; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_6 != kbd->prev_num_6) { tmp_ev.code = KEY_6; tmp_ev.value = kbd->prev_num_6 = status->num_6; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_7 != kbd->prev_num_7) { tmp_ev.code = KEY_7; tmp_ev.value = kbd->prev_num_7 = status->num_7; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_8 != kbd->prev_num_8) { tmp_ev.code = KEY_8; tmp_ev.value = kbd->prev_num_8 = status->num_8; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->num_9 != kbd->prev_num_9) { tmp_ev.code = KEY_9; tmp_ev.value = kbd->prev_num_9 = status->num_9; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->lctrl != kbd->prev_lctrl) { tmp_ev.code = KEY_LEFTCTRL; tmp_ev.value = kbd->prev_lctrl = status->lctrl; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->up != kbd->prev_up) { tmp_ev.code = KEY_UP; tmp_ev.value = kbd->prev_up = status->up; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->down != kbd->prev_down) { tmp_ev.code = KEY_DOWN; tmp_ev.value = kbd->prev_down = status->down; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->left != kbd->prev_left) { tmp_ev.code = KEY_LEFT; tmp_ev.value = kbd->prev_left = status->left; - if (write(kbd->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_kbd_send_err; - } + events[events_count++] = tmp_ev; } if (status->right != kbd->prev_right) { @@ -493,18 +369,39 @@ int virt_kbd_send(virt_kbd_t *const kbd, keyboard_status_t *const status, struct } #endif - syn_time.tv_usec += 1; - const struct input_event syn_ev = { - .code = SYN_REPORT, - .type = EV_SYN, - .value = 0, - .time = syn_time, - }; - const ssize_t sync_written = write(kbd->fd, (void*)&syn_ev, sizeof(syn_ev)); - if (sync_written != sizeof(syn_ev)) { - fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", sync_written, sizeof(syn_ev)); - } + if (events_count > 0) { + struct timeval t; + if (now != NULL) { + t = *now; + } else { + gettimeofday(&t, NULL); + } + + struct input_event syn_ev = { + .code = SYN_REPORT, + .type = EV_SYN, + .value = 0, + .time = t, + }; + syn_ev.time.tv_usec += 1; + events[events_count++] = syn_ev; + + for (size_t i = 0; i < events_count; ++i) { + if (i != (events_count - 1)) { + events[i].time = t; + } + + const ssize_t sync_written = write(kbd->fd, (void*)&events[i], sizeof(struct input_event)); + if (sync_written != sizeof(syn_ev)) { + fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", sync_written, sizeof(syn_ev)); + res = errno; + res = res < 0 ? res : -1*res; + res = res == 0 ? -EIO : res; + goto virt_kbd_send_err; + } + } + } virt_kbd_send_err: return res; } diff --git a/virt_mouse.c b/virt_mouse.c index 24374f8..ff02eaf 100644 --- a/virt_mouse.c +++ b/virt_mouse.c @@ -66,33 +66,22 @@ int virt_mouse_get_fd(virt_mouse_t *const mouse) { int virt_mouse_send(virt_mouse_t *const mouse, mouse_status_t *const status, struct timeval *const now) { int res = 0; - struct timeval syn_time; - gettimeofday(&syn_time, NULL); + size_t events_count = 0; + struct input_event events[12]; struct input_event tmp_ev; - gettimeofday(&tmp_ev.time, NULL); - if (now != NULL) { - tmp_ev.time = *now; - } - tmp_ev.type = EV_REL; if (status->x != 0) { tmp_ev.code = REL_X; tmp_ev.value = status->x; - if (write(mouse->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_mouse_send_err; - } + events[events_count++] = tmp_ev; } if (status->y != 0) { tmp_ev.code = REL_Y; tmp_ev.value = status->y; - if (write(mouse->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_mouse_send_err; - } + events[events_count++] = tmp_ev; } tmp_ev.type = EV_KEY; @@ -101,30 +90,21 @@ int virt_mouse_send(virt_mouse_t *const mouse, mouse_status_t *const status, str mouse->prev_btn_left = status->btn_left; tmp_ev.code = BTN_LEFT; tmp_ev.value = status->btn_left; - if (write(mouse->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_mouse_send_err; - } + events[events_count++] = tmp_ev; } if (status->btn_middle != mouse->prev_btn_middle) { mouse->prev_btn_middle = status->btn_middle; tmp_ev.code = BTN_MIDDLE; tmp_ev.value = status->btn_middle; - if (write(mouse->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_mouse_send_err; - } + events[events_count++] = tmp_ev; } if (status->btn_right != mouse->prev_btn_right) { mouse->prev_btn_right = status->btn_right; tmp_ev.code = BTN_RIGHT; tmp_ev.value = status->btn_right; - if (write(mouse->fd, &tmp_ev, sizeof(tmp_ev)) != sizeof(struct input_event)) { - res = errno < 0 ? errno : -1 * errno; - goto virt_mouse_send_err; - } + events[events_count++] = tmp_ev; } #if 0 @@ -140,17 +120,39 @@ int virt_mouse_send(virt_mouse_t *const mouse, mouse_status_t *const status, str } #endif - syn_time.tv_usec += 1; - const struct input_event syn_ev = { - .code = SYN_REPORT, - .type = EV_SYN, - .value = 0, - .time = syn_time, - }; - const ssize_t sync_written = write(mouse->fd, (void*)&syn_ev, sizeof(syn_ev)); - if (sync_written != sizeof(syn_ev)) { - fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", sync_written, sizeof(syn_ev)); - } + if (events_count > 0) { + struct timeval t; + if (now != NULL) { + t = *now; + } else { + gettimeofday(&t, NULL); + } + + struct input_event syn_ev = { + .code = SYN_REPORT, + .type = EV_SYN, + .value = 0, + .time = t, + }; + syn_ev.time.tv_usec += 1; + + events[events_count++] = syn_ev; + + for (size_t i = 0; i < events_count; ++i) { + if (i != (events_count - 1)) { + events[i].time = t; + } + + const ssize_t sync_written = write(mouse->fd, (void*)&events[i], sizeof(struct input_event)); + if (sync_written != sizeof(syn_ev)) { + fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", sync_written, sizeof(syn_ev)); + res = errno; + res = res < 0 ? res : -1*res; + res = res == 0 ? -EIO : res; + goto virt_mouse_send_err; + } + } + } virt_mouse_send_err: return res;