Compare commits
2 commits
6072f88002
...
cc16d4983e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc16d4983e | ||
|
|
0b7f888a2f |
8 changed files with 555 additions and 154 deletions
|
|
@ -35,6 +35,7 @@ add_executable(${STRAY_EXECUTABLE_NAME}
|
||||||
settings.c
|
settings.c
|
||||||
virt_ds4.c
|
virt_ds4.c
|
||||||
virt_ds5.c
|
virt_ds5.c
|
||||||
|
virt_mouse.c
|
||||||
devices_status.c
|
devices_status.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -44,6 +45,7 @@ add_executable(${ALLINONE_EXECUTABLE_NAME}
|
||||||
settings.c
|
settings.c
|
||||||
virt_ds4.c
|
virt_ds4.c
|
||||||
virt_ds5.c
|
virt_ds5.c
|
||||||
|
virt_mouse.c
|
||||||
devices_status.c
|
devices_status.c
|
||||||
dev_evdev.c
|
dev_evdev.c
|
||||||
dev_iio.c
|
dev_iio.c
|
||||||
|
|
|
||||||
366
dev_out.c
366
dev_out.c
|
|
@ -5,6 +5,7 @@
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "virt_ds4.h"
|
#include "virt_ds4.h"
|
||||||
#include "virt_ds5.h"
|
#include "virt_ds5.h"
|
||||||
|
#include "virt_mouse.h"
|
||||||
|
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
|
|
||||||
|
|
@ -20,6 +21,24 @@ static void handle_incoming_message_gamepad_action(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_incoming_message_mouse_event(
|
||||||
|
const dev_out_settings_t *const in_settings,
|
||||||
|
const in_message_mouse_event_t *const msg_payload,
|
||||||
|
mouse_status_t *const inout_mouse
|
||||||
|
) {
|
||||||
|
if (msg_payload->type == MOUSE_ELEMENT_X) {
|
||||||
|
inout_mouse->x += msg_payload->value;
|
||||||
|
} else if (msg_payload->type == MOUSE_ELEMENT_Y) {
|
||||||
|
inout_mouse->y += msg_payload->value;
|
||||||
|
} else if (msg_payload->type == MOUSE_BTN_LEFT) {
|
||||||
|
inout_mouse->btn_left = msg_payload->value;
|
||||||
|
} else if (msg_payload->type == MOUSE_BTN_MIDDLE) {
|
||||||
|
inout_mouse->btn_middle = msg_payload->value;
|
||||||
|
} else if (msg_payload->type == MOUSE_BTN_RIGHT) {
|
||||||
|
inout_mouse->btn_right = msg_payload->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_incoming_message_gamepad_set(
|
static void handle_incoming_message_gamepad_set(
|
||||||
const dev_out_settings_t *const in_settings,
|
const dev_out_settings_t *const in_settings,
|
||||||
const in_message_gamepad_set_element_t *const msg_payload,
|
const in_message_gamepad_set_element_t *const msg_payload,
|
||||||
|
|
@ -196,6 +215,12 @@ static void handle_incoming_message(
|
||||||
&msg->data.action,
|
&msg->data.action,
|
||||||
&dev_stats->gamepad
|
&dev_stats->gamepad
|
||||||
);
|
);
|
||||||
|
} else if (msg->type == MOUSE_EVENT) {
|
||||||
|
handle_incoming_message_mouse_event(
|
||||||
|
in_settings,
|
||||||
|
&msg->data.mouse_event,
|
||||||
|
&dev_stats->mouse
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,14 +254,26 @@ void *dev_out_thread_func(void *ptr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int current_gamepad_fd = -1;
|
||||||
|
int current_keyboard_fd = -1;
|
||||||
|
int current_mouse_fd = -1;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
virt_dualshock_t ds4;
|
virt_dualshock_t ds4;
|
||||||
virt_dualsense_t ds5;
|
virt_dualsense_t ds5;
|
||||||
} controller_data;
|
} controller_data;
|
||||||
|
|
||||||
int current_gamepad_fd = -1;
|
virt_mouse_t mouse_data;
|
||||||
//int current_keyboard_fd = -1;
|
const int mouse_init_res = virt_mouse_init(&mouse_data);
|
||||||
//int current_mouse_fd = -1;
|
if (mouse_init_res < 0) {
|
||||||
|
fprintf(stderr, "Unable to initialize virtual mouse -- will continue regardless\n");
|
||||||
|
} else {
|
||||||
|
current_mouse_fd = virt_mouse_get_fd(&mouse_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int64_t kbd_report_timing_us = 1125;
|
||||||
|
const int64_t mouse_report_timing_us = 950;
|
||||||
|
const int64_t gamepad_report_timing_us = 1250;
|
||||||
|
|
||||||
if (current_gamepad == GAMEPAD_DUALSENSE) {
|
if (current_gamepad == GAMEPAD_DUALSENSE) {
|
||||||
const int ds5_init_res = virt_dualsense_init(&controller_data.ds5);
|
const int ds5_init_res = virt_dualsense_init(&controller_data.ds5);
|
||||||
|
|
@ -260,8 +297,8 @@ void *dev_out_thread_func(void *ptr) {
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
struct timeval gamepad_last_hid_report_sent = now;
|
struct timeval gamepad_last_hid_report_sent = now;
|
||||||
//struct timeval mouse_last_hid_report_sent = now;
|
struct timeval mouse_last_hid_report_sent = now;
|
||||||
//struct timeval keyboard_last_hid_report_sent = now;
|
struct timeval keyboard_last_hid_report_sent = now;
|
||||||
|
|
||||||
uint8_t tmp_buf[256];
|
uint8_t tmp_buf[256];
|
||||||
|
|
||||||
|
|
@ -272,9 +309,12 @@ void *dev_out_thread_func(void *ptr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int64_t gamepad_time_diff_usecs = get_timediff_usec(&gamepad_last_hid_report_sent, &now);
|
||||||
|
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);
|
gettimeofday(&now, NULL);
|
||||||
int64_t gamepad_time_diff_usecs = get_timediff_usec(&gamepad_last_hid_report_sent, &now);
|
if (gamepad_time_diff_usecs >= gamepad_report_timing_us) {
|
||||||
if (gamepad_time_diff_usecs >= 1250) {
|
|
||||||
gamepad_last_hid_report_sent = now;
|
gamepad_last_hid_report_sent = now;
|
||||||
|
|
||||||
if (current_gamepad == GAMEPAD_DUALSENSE) {
|
if (current_gamepad == GAMEPAD_DUALSENSE) {
|
||||||
|
|
@ -284,170 +324,200 @@ void *dev_out_thread_func(void *ptr) {
|
||||||
virt_dualshock_compose(&controller_data.ds4, &dev_out_data->dev_stats.gamepad, tmp_buf);
|
virt_dualshock_compose(&controller_data.ds4, &dev_out_data->dev_stats.gamepad, tmp_buf);
|
||||||
virt_dualshock_send(&controller_data.ds4, tmp_buf);
|
virt_dualshock_send(&controller_data.ds4, tmp_buf);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
FD_ZERO(&read_fds);
|
|
||||||
|
|
||||||
|
// this does reset the for, ensuring every other device has nothing to say
|
||||||
|
continue;
|
||||||
|
} else if (mouse_time_diff_usecs >= mouse_report_timing_us) {
|
||||||
|
mouse_last_hid_report_sent = now;
|
||||||
|
|
||||||
|
virt_mouse_send(&mouse_data, &dev_out_data->dev_stats.mouse, &now);
|
||||||
|
|
||||||
|
// this does reset the for, ensuring every other device has nothing to say
|
||||||
|
continue;
|
||||||
|
} else if (kbd_time_diff_usecs >= kbd_report_timing_us) {
|
||||||
|
keyboard_last_hid_report_sent = now;
|
||||||
|
|
||||||
|
// this does reset the for, ensuring every other device has nothing to say
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// once here no output device needs to send out its report
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
|
||||||
|
if (dev_out_data->communication.type == ipc_unix_pipe) {
|
||||||
|
FD_SET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds);
|
||||||
|
} else if (dev_out_data->communication.type == ipc_server_sockets) {
|
||||||
|
if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) {
|
||||||
|
for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
|
||||||
|
const int fd = dev_out_data->communication.endpoint.ssocket.clients[i];
|
||||||
|
if (fd > 0) {
|
||||||
|
FD_SET(fd, &read_fds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_mouse_fd > 0) {
|
||||||
|
FD_SET(current_mouse_fd, &read_fds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: FD_SET(current_keyboard_fd, &read_fds);
|
||||||
|
|
||||||
|
if (current_gamepad_fd > 0) {
|
||||||
|
FD_SET(current_gamepad_fd, &read_fds);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int64_t timeout_gamepad_time_diff_usecs = gamepad_report_timing_us - gamepad_time_diff_usecs;
|
||||||
|
const int64_t timeout_mouse_time_diff_usecs = mouse_time_diff_usecs - mouse_report_timing_us;
|
||||||
|
const int64_t timeout_kbd_time_diff_usecs = kbd_report_timing_us - kbd_time_diff_usecs;
|
||||||
|
|
||||||
|
int64_t next_timing_out_device_diff_usecs = timeout_kbd_time_diff_usecs < timeout_mouse_time_diff_usecs ? timeout_kbd_time_diff_usecs : timeout_mouse_time_diff_usecs;
|
||||||
|
next_timing_out_device_diff_usecs = next_timing_out_device_diff_usecs < timeout_gamepad_time_diff_usecs ? next_timing_out_device_diff_usecs : timeout_gamepad_time_diff_usecs;
|
||||||
|
|
||||||
|
// calculate the shortest timeout between one of the multiple device will needs to send out its hid report
|
||||||
|
struct timeval timeout = {
|
||||||
|
.tv_sec = (__time_t)next_timing_out_device_diff_usecs / (__time_t)1000000,
|
||||||
|
.tv_usec = (__suseconds_t)next_timing_out_device_diff_usecs % (__suseconds_t)1000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
int ready_fds = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout);
|
||||||
|
gamepad_status_qam_quirk_ext_time(&dev_out_data->dev_stats.gamepad, &now);
|
||||||
|
|
||||||
|
if (ready_fds == -1) {
|
||||||
|
const int err = errno;
|
||||||
|
fprintf(stderr, "Error reading events for output devices: %d\n", err);
|
||||||
|
continue;
|
||||||
|
} else if (ready_fds == 0) {
|
||||||
|
// timeout: do nothing but continue. next iteration will take care
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((current_gamepad_fd > 0) && (FD_ISSET(current_gamepad_fd, &read_fds))) {
|
||||||
|
const uint64_t prev_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count;
|
||||||
|
const uint64_t prev_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count;
|
||||||
|
|
||||||
|
out_message_t out_msgs[4];
|
||||||
|
size_t out_msgs_count = 0;
|
||||||
|
if (current_gamepad == GAMEPAD_DUALSENSE) {
|
||||||
|
virt_dualsense_event(&controller_data.ds5, &dev_out_data->dev_stats.gamepad);
|
||||||
|
} else if (current_gamepad == GAMEPAD_DUALSHOCK) {
|
||||||
|
virt_dualshock_event(&controller_data.ds4, &dev_out_data->dev_stats.gamepad);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint64_t current_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count;
|
||||||
|
const uint64_t current_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count;
|
||||||
|
|
||||||
|
if (current_leds_events_count != prev_leds_events_count) {
|
||||||
|
const out_message_t msg = {
|
||||||
|
.type = OUT_MSG_TYPE_LEDS,
|
||||||
|
.data = {
|
||||||
|
.leds = {
|
||||||
|
.r = dev_out_data->dev_stats.gamepad.leds_colors[0],
|
||||||
|
.g = dev_out_data->dev_stats.gamepad.leds_colors[1],
|
||||||
|
.b = dev_out_data->dev_stats.gamepad.leds_colors[2],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
out_msgs[out_msgs_count++] = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_motors_events_count != prev_motors_events_count) {
|
||||||
|
const out_message_t msg = {
|
||||||
|
.type = OUT_MSG_TYPE_RUMBLE,
|
||||||
|
.data = {
|
||||||
|
.rumble = {
|
||||||
|
.motors_left = dev_out_data->dev_stats.gamepad.motors_intensity[0],
|
||||||
|
.motors_right = dev_out_data->dev_stats.gamepad.motors_intensity[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
out_msgs[out_msgs_count++] = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send out game-generated events to sockets
|
||||||
if (dev_out_data->communication.type == ipc_unix_pipe) {
|
if (dev_out_data->communication.type == ipc_unix_pipe) {
|
||||||
FD_SET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds);
|
for (int msg_idx = 0; msg_idx < out_msgs_count; ++msg_idx) {
|
||||||
|
const int write_res = write(dev_out_data->communication.endpoint.pipe.out_message_pipe_fd, (void*)&out_msgs[msg_idx], sizeof(out_message_t));
|
||||||
|
if (write_res != sizeof(out_message_t)) {
|
||||||
|
fprintf(stderr, "Error in writing out_message to out_message_pipe: %d\n", write_res);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (dev_out_data->communication.type == ipc_server_sockets) {
|
} else if (dev_out_data->communication.type == ipc_server_sockets) {
|
||||||
if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) {
|
if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) {
|
||||||
for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
|
for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
|
||||||
const int fd = dev_out_data->communication.endpoint.ssocket.clients[i];
|
if (dev_out_data->communication.endpoint.ssocket.clients[i] > 0) {
|
||||||
if (fd > 0) {
|
for (int msg_idx = 0; msg_idx < out_msgs_count; ++msg_idx) {
|
||||||
FD_SET(fd, &read_fds);
|
const int write_res = write(dev_out_data->communication.endpoint.ssocket.clients[i], (void*)&out_msgs[msg_idx], sizeof(out_message_t));
|
||||||
}
|
if (write_res != sizeof(out_message_t)) {
|
||||||
}
|
fprintf(stderr, "Error in writing out_message to socket number %d: %d\n", i, write_res);
|
||||||
|
close(dev_out_data->communication.endpoint.ssocket.clients[i]);
|
||||||
pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex);
|
dev_out_data->communication.endpoint.ssocket.clients[i] = -1;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: FD_SET(current_mouse_fd, &read_fds);
|
|
||||||
// TODO: FD_SET(current_keyboard_fd, &read_fds);
|
|
||||||
FD_SET(current_gamepad_fd, &read_fds);
|
|
||||||
|
|
||||||
// calculate the shortest timeout between one of the multiple device will needs to send out its hid report
|
|
||||||
struct timeval timeout = {
|
|
||||||
.tv_sec = (__time_t)gamepad_time_diff_usecs / (__time_t)1000000,
|
|
||||||
.tv_usec = (__suseconds_t)gamepad_time_diff_usecs % (__suseconds_t)1000000,
|
|
||||||
};
|
|
||||||
|
|
||||||
int ready_fds = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout);
|
|
||||||
gamepad_status_qam_quirk_ext_time(&dev_out_data->dev_stats.gamepad, &now);
|
|
||||||
|
|
||||||
if (ready_fds == -1) {
|
|
||||||
const int err = errno;
|
|
||||||
fprintf(stderr, "Error reading events for output devices: %d\n", err);
|
|
||||||
continue;
|
|
||||||
} else if (ready_fds == 0) {
|
|
||||||
// timeout: do nothing but continue. next iteration will take care
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (FD_ISSET(current_gamepad_fd, &read_fds)) {
|
|
||||||
const uint64_t prev_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count;
|
|
||||||
const uint64_t prev_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count;
|
|
||||||
|
|
||||||
out_message_t out_msgs[4];
|
|
||||||
size_t out_msgs_count = 0;
|
|
||||||
if (current_gamepad == GAMEPAD_DUALSENSE) {
|
|
||||||
virt_dualsense_event(&controller_data.ds5, &dev_out_data->dev_stats.gamepad);
|
|
||||||
} else if (current_gamepad == GAMEPAD_DUALSHOCK) {
|
|
||||||
virt_dualshock_event(&controller_data.ds4, &dev_out_data->dev_stats.gamepad);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint64_t current_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count;
|
|
||||||
const uint64_t current_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count;
|
|
||||||
|
|
||||||
if (current_leds_events_count != prev_leds_events_count) {
|
|
||||||
const out_message_t msg = {
|
|
||||||
.type = OUT_MSG_TYPE_LEDS,
|
|
||||||
.data = {
|
|
||||||
.leds = {
|
|
||||||
.r = dev_out_data->dev_stats.gamepad.leds_colors[0],
|
|
||||||
.g = dev_out_data->dev_stats.gamepad.leds_colors[1],
|
|
||||||
.b = dev_out_data->dev_stats.gamepad.leds_colors[2],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
out_msgs[out_msgs_count++] = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_motors_events_count != prev_motors_events_count) {
|
|
||||||
const out_message_t msg = {
|
|
||||||
.type = OUT_MSG_TYPE_RUMBLE,
|
|
||||||
.data = {
|
|
||||||
.rumble = {
|
|
||||||
.motors_left = dev_out_data->dev_stats.gamepad.motors_intensity[0],
|
|
||||||
.motors_right = dev_out_data->dev_stats.gamepad.motors_intensity[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
out_msgs[out_msgs_count++] = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send out game-generated events to sockets
|
|
||||||
if (dev_out_data->communication.type == ipc_unix_pipe) {
|
|
||||||
for (int msg_idx = 0; msg_idx < out_msgs_count; ++msg_idx) {
|
|
||||||
const int write_res = write(dev_out_data->communication.endpoint.pipe.out_message_pipe_fd, (void*)&out_msgs[msg_idx], sizeof(out_message_t));
|
|
||||||
if (write_res != sizeof(out_message_t)) {
|
|
||||||
fprintf(stderr, "Error in writing out_message to out_message_pipe: %d\n", write_res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (dev_out_data->communication.type == ipc_server_sockets) {
|
|
||||||
if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) {
|
|
||||||
for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
|
|
||||||
if (dev_out_data->communication.endpoint.ssocket.clients[i] > 0) {
|
|
||||||
for (int msg_idx = 0; msg_idx < out_msgs_count; ++msg_idx) {
|
|
||||||
const int write_res = write(dev_out_data->communication.endpoint.ssocket.clients[i], (void*)&out_msgs[msg_idx], sizeof(out_message_t));
|
|
||||||
if (write_res != sizeof(out_message_t)) {
|
|
||||||
fprintf(stderr, "Error in writing out_message to socket number %d: %d\n", i, write_res);
|
|
||||||
close(dev_out_data->communication.endpoint.ssocket.clients[i]);
|
|
||||||
dev_out_data->communication.endpoint.ssocket.clients[i] = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read and handle incoming data: this data is packed into in_message_t
|
|
||||||
if (dev_out_data->communication.type == ipc_unix_pipe) {
|
|
||||||
if (FD_ISSET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds)) {
|
|
||||||
in_message_t incoming_message;
|
|
||||||
const size_t in_message_pipe_read_res = read(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, (void*)&incoming_message, sizeof(in_message_t));
|
|
||||||
if (in_message_pipe_read_res == sizeof(in_message_t)) {
|
|
||||||
handle_incoming_message(
|
|
||||||
&dev_out_data->settings,
|
|
||||||
&incoming_message,
|
|
||||||
&dev_out_data->dev_stats
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Error reading from in_message_pipe_fd: got %zu bytes, expected %zu bytes\n", in_message_pipe_read_res, sizeof(in_message_t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (dev_out_data->communication.type == ipc_server_sockets) {
|
|
||||||
if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) {
|
|
||||||
for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
|
|
||||||
const int fd = dev_out_data->communication.endpoint.ssocket.clients[i];
|
|
||||||
if ((fd > 0) && (FD_ISSET(fd, &read_fds))) {
|
|
||||||
in_message_t incoming_message;
|
|
||||||
const size_t in_message_pipe_read_res = read(fd, (void*)&incoming_message, sizeof(in_message_t));
|
|
||||||
if (in_message_pipe_read_res == sizeof(in_message_t)) {
|
|
||||||
handle_incoming_message(
|
|
||||||
&dev_out_data->settings,
|
|
||||||
&incoming_message,
|
|
||||||
&dev_out_data->dev_stats
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Error reading from socket number %d: got %zu bytes, expected %zu bytes\n", i, in_message_pipe_read_res, sizeof(in_message_t));
|
|
||||||
close(dev_out_data->communication.endpoint.ssocket.clients[i]);
|
|
||||||
dev_out_data->communication.endpoint.ssocket.clients[i] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex);
|
pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read and handle incoming data: this data is packed into in_message_t
|
||||||
|
if (dev_out_data->communication.type == ipc_unix_pipe) {
|
||||||
|
if (FD_ISSET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds)) {
|
||||||
|
in_message_t incoming_message;
|
||||||
|
const size_t in_message_pipe_read_res = read(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, (void*)&incoming_message, sizeof(in_message_t));
|
||||||
|
if (in_message_pipe_read_res == sizeof(in_message_t)) {
|
||||||
|
handle_incoming_message(
|
||||||
|
&dev_out_data->settings,
|
||||||
|
&incoming_message,
|
||||||
|
&dev_out_data->dev_stats
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Error reading from in_message_pipe_fd: got %zu bytes, expected %zu bytes\n", in_message_pipe_read_res, sizeof(in_message_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (dev_out_data->communication.type == ipc_server_sockets) {
|
||||||
|
if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) {
|
||||||
|
for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
|
||||||
|
const int fd = dev_out_data->communication.endpoint.ssocket.clients[i];
|
||||||
|
if ((fd > 0) && (FD_ISSET(fd, &read_fds))) {
|
||||||
|
in_message_t incoming_message;
|
||||||
|
const size_t in_message_pipe_read_res = read(fd, (void*)&incoming_message, sizeof(in_message_t));
|
||||||
|
if (in_message_pipe_read_res == sizeof(in_message_t)) {
|
||||||
|
handle_incoming_message(
|
||||||
|
&dev_out_data->settings,
|
||||||
|
&incoming_message,
|
||||||
|
&dev_out_data->dev_stats
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Error reading from socket number %d: got %zu bytes, expected %zu bytes\n", i, in_message_pipe_read_res, sizeof(in_message_t));
|
||||||
|
close(dev_out_data->communication.endpoint.ssocket.clients[i]);
|
||||||
|
dev_out_data->communication.endpoint.ssocket.clients[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the output device
|
// close the gamepad output device
|
||||||
if (current_gamepad == GAMEPAD_DUALSENSE) {
|
if (current_gamepad == GAMEPAD_DUALSENSE) {
|
||||||
virt_dualsense_close(&controller_data.ds5);
|
virt_dualsense_close(&controller_data.ds5);
|
||||||
} else if (current_gamepad == GAMEPAD_DUALSHOCK) {
|
} else if (current_gamepad == GAMEPAD_DUALSHOCK) {
|
||||||
virt_dualshock_close(&controller_data.ds4);
|
virt_dualshock_close(&controller_data.ds4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close the mouse device
|
||||||
|
virt_mouse_close(&mouse_data);
|
||||||
|
|
||||||
// end communication
|
// end communication
|
||||||
if (dev_out_data->communication.type == ipc_server_sockets) {
|
if (dev_out_data->communication.type == ipc_server_sockets) {
|
||||||
// close every client socket
|
// close every client socket
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,16 @@ void kbd_status_init(keyboard_status_t *const stats) {
|
||||||
stats->connected = true;
|
stats->connected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mouse_status_init(mouse_status_t *const stats) {
|
||||||
|
stats->connected = true;
|
||||||
|
|
||||||
|
stats->x = 0;
|
||||||
|
stats->y = 0;
|
||||||
|
stats->btn_left = 0;
|
||||||
|
stats->btn_middle = 0;
|
||||||
|
stats->btn_right = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void gamepad_status_init(gamepad_status_t *const stats) {
|
void gamepad_status_init(gamepad_status_t *const stats) {
|
||||||
stats->connected = true;
|
stats->connected = true;
|
||||||
stats->joystick_positions[0][0] = 0;
|
stats->joystick_positions[0][0] = 0;
|
||||||
|
|
@ -45,7 +55,7 @@ void gamepad_status_init(gamepad_status_t *const stats) {
|
||||||
void devices_status_init(devices_status_t *const stats) {
|
void devices_status_init(devices_status_t *const stats) {
|
||||||
gamepad_status_init(&stats->gamepad);
|
gamepad_status_init(&stats->gamepad);
|
||||||
kbd_status_init(&stats->kbd);
|
kbd_status_init(&stats->kbd);
|
||||||
// TODO: mouse init
|
mouse_status_init(&stats->mouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gamepad_status_qam_quirk(gamepad_status_t *const gamepad_stats) {
|
void gamepad_status_qam_quirk(gamepad_status_t *const gamepad_stats) {
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,19 @@ typedef struct keyboard_status {
|
||||||
bool connected;
|
bool connected;
|
||||||
} keyboard_status_t;
|
} keyboard_status_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct mouse_status {
|
||||||
|
bool connected;
|
||||||
|
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
|
||||||
|
uint8_t btn_left;
|
||||||
|
uint8_t btn_middle;
|
||||||
|
uint8_t btn_right;
|
||||||
|
|
||||||
|
} mouse_status_t;
|
||||||
|
|
||||||
typedef struct devices_status {
|
typedef struct devices_status {
|
||||||
// this mutex MUST be grabbed when reading and/or writing below properties
|
// this mutex MUST be grabbed when reading and/or writing below properties
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
@ -77,8 +90,12 @@ typedef struct devices_status {
|
||||||
|
|
||||||
keyboard_status_t kbd;
|
keyboard_status_t kbd;
|
||||||
|
|
||||||
|
mouse_status_t mouse;
|
||||||
|
|
||||||
} devices_status_t;
|
} devices_status_t;
|
||||||
|
|
||||||
|
void mouse_status_init(mouse_status_t *const stats);
|
||||||
|
|
||||||
void kbd_status_init(keyboard_status_t *const stats);
|
void kbd_status_init(keyboard_status_t *const stats);
|
||||||
|
|
||||||
void gamepad_status_init(gamepad_status_t *const stats);
|
void gamepad_status_init(gamepad_status_t *const stats);
|
||||||
|
|
|
||||||
16
message.h
16
message.h
|
|
@ -64,6 +64,19 @@ typedef struct in_message_gamepad_set_element {
|
||||||
} status;
|
} status;
|
||||||
} in_message_gamepad_set_element_t;
|
} in_message_gamepad_set_element_t;
|
||||||
|
|
||||||
|
typedef enum mouse_element {
|
||||||
|
MOUSE_ELEMENT_X,
|
||||||
|
MOUSE_ELEMENT_Y,
|
||||||
|
MOUSE_BTN_LEFT,
|
||||||
|
MOUSE_BTN_MIDDLE,
|
||||||
|
MOUSE_BTN_RIGHT,
|
||||||
|
} mouse_element_t;
|
||||||
|
|
||||||
|
typedef struct in_message_mouse_event {
|
||||||
|
mouse_element_t type;
|
||||||
|
int32_t value;
|
||||||
|
} in_message_mouse_event_t;
|
||||||
|
|
||||||
typedef enum in_message_gamepad_action {
|
typedef enum in_message_gamepad_action {
|
||||||
GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER,
|
GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER,
|
||||||
GAMEPAD_ACTION_OPEN_STEAM_QAM,
|
GAMEPAD_ACTION_OPEN_STEAM_QAM,
|
||||||
|
|
@ -72,6 +85,7 @@ typedef enum in_message_gamepad_action {
|
||||||
typedef enum in_in_message_type {
|
typedef enum in_in_message_type {
|
||||||
GAMEPAD_SET_ELEMENT,
|
GAMEPAD_SET_ELEMENT,
|
||||||
GAMEPAD_ACTION,
|
GAMEPAD_ACTION,
|
||||||
|
MOUSE_EVENT,
|
||||||
} in_message_type_t;
|
} in_message_type_t;
|
||||||
|
|
||||||
typedef struct in_message {
|
typedef struct in_message {
|
||||||
|
|
@ -83,6 +97,8 @@ typedef struct in_message {
|
||||||
in_message_gamepad_action_t action;
|
in_message_gamepad_action_t action;
|
||||||
|
|
||||||
in_message_gamepad_set_element_t gamepad_set;
|
in_message_gamepad_set_element_t gamepad_set;
|
||||||
|
|
||||||
|
in_message_mouse_event_t mouse_event;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
} in_message_t;
|
} in_message_t;
|
||||||
|
|
|
||||||
126
rog_ally.c
126
rog_ally.c
|
|
@ -1,7 +1,10 @@
|
||||||
#include "rog_ally.h"
|
#include "rog_ally.h"
|
||||||
#include "input_dev.h"
|
#include "input_dev.h"
|
||||||
#include "dev_hidraw.h"
|
#include "dev_hidraw.h"
|
||||||
|
#include "message.h"
|
||||||
#include "xbox360.h"
|
#include "xbox360.h"
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef enum rc71l_platform_mode {
|
typedef enum rc71l_platform_mode {
|
||||||
rc71l_platform_mode_hidraw,
|
rc71l_platform_mode_hidraw,
|
||||||
|
|
@ -81,7 +84,11 @@ static char* find_kernel_sysfs_device_path(struct udev *udev) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int asus_kbd_ev_map(
|
static int get_next_mode(int current_mode) {
|
||||||
|
return 1 + ((current_mode + 1) % 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int asus_kbd_ev_map(
|
||||||
const dev_in_settings_t *const conf,
|
const dev_in_settings_t *const conf,
|
||||||
const evdev_collected_t *const e,
|
const evdev_collected_t *const e,
|
||||||
in_message_t *const messages,
|
in_message_t *const messages,
|
||||||
|
|
@ -99,10 +106,10 @@ int asus_kbd_ev_map(
|
||||||
.type = GAMEPAD_SET_ELEMENT,
|
.type = GAMEPAD_SET_ELEMENT,
|
||||||
.data = {
|
.data = {
|
||||||
.gamepad_set = {
|
.gamepad_set = {
|
||||||
.element = GAMEPAD_BTN_L5,
|
.element = GAMEPAD_BTN_L5,
|
||||||
.status = {
|
.status = {
|
||||||
.btn = e->ev[1].value,
|
.btn = e->ev[1].value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -165,7 +172,116 @@ int asus_kbd_ev_map(
|
||||||
|
|
||||||
printf("Asus MCU kernel interface found at %s -- switching mode\n", kernel_sysfs);
|
printf("Asus MCU kernel interface found at %s -- switching mode\n", kernel_sysfs);
|
||||||
|
|
||||||
|
const size_t tmp_path_max_len = strlen(kernel_sysfs) + 256;
|
||||||
|
char *tmp_path = malloc(tmp_path_max_len);
|
||||||
|
|
||||||
|
if (tmp_path != NULL) {
|
||||||
|
memset(tmp_path, 0, tmp_path_max_len);
|
||||||
|
snprintf(tmp_path, tmp_path_max_len - 1, "%s/gamepad_mode", kernel_sysfs);
|
||||||
|
|
||||||
|
int gamepad_mode_fd = open(tmp_path, O_RDONLY | O_NONBLOCK);
|
||||||
|
if (gamepad_mode_fd > 0) {
|
||||||
|
char current_mode_str[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
int current_mode_read_res = read(gamepad_mode_fd, (void*)current_mode_str, sizeof(current_mode_str));
|
||||||
|
if (current_mode_read_res > 0) {
|
||||||
|
int current_mode;
|
||||||
|
sscanf("%d", current_mode_str, ¤t_mode);
|
||||||
|
|
||||||
|
const int new_mode = get_next_mode(current_mode);
|
||||||
|
printf("Current mode is set to %d -- switching to %d", current_mode, new_mode);
|
||||||
|
|
||||||
|
// end the current mode read
|
||||||
|
close(gamepad_mode_fd);
|
||||||
|
|
||||||
|
char new_mode_str[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
snprintf(new_mode_str, sizeof(new_mode_str) - 1, "%d", new_mode);
|
||||||
|
gamepad_mode_fd = open(tmp_path, O_RDONLY);
|
||||||
|
if (gamepad_mode_fd > 0) {
|
||||||
|
if (write(gamepad_mode_fd, new_mode_str, strlen(new_mode_str)) > 0) {
|
||||||
|
printf("Controller mode switched successfully to %d\n", new_mode);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unable to switch controller mode: %d -- expect bugs\n", errno);
|
||||||
|
}
|
||||||
|
close(gamepad_mode_fd);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unable to open gamepad mode file to switch mode: %d\n", errno);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
close(gamepad_mode_fd);
|
||||||
|
fprintf(stderr, "Unable to read gamepad_mode file to get current mode: %d", errno);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unable to open gamepad_mode file in read-only mode to get current mode: %d", errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tmp_path);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unable to allocate enough memory\n");
|
||||||
|
}
|
||||||
|
|
||||||
free(kernel_sysfs);
|
free(kernel_sysfs);
|
||||||
|
} else if (e->ev[i].code == BTN_LEFT) {
|
||||||
|
const in_message_t current_message = {
|
||||||
|
.type = MOUSE_EVENT,
|
||||||
|
.data = {
|
||||||
|
.mouse_event = {
|
||||||
|
.type = MOUSE_BTN_LEFT,
|
||||||
|
.value = e->ev[i].value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
messages[written_msg++] = current_message;
|
||||||
|
} else if (e->ev[i].code == BTN_MIDDLE) {
|
||||||
|
const in_message_t current_message = {
|
||||||
|
.type = MOUSE_EVENT,
|
||||||
|
.data = {
|
||||||
|
.mouse_event = {
|
||||||
|
.type = MOUSE_BTN_MIDDLE,
|
||||||
|
.value = e->ev[i].value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
messages[written_msg++] = current_message;
|
||||||
|
} else if (e->ev[i].code == BTN_RIGHT) {
|
||||||
|
const in_message_t current_message = {
|
||||||
|
.type = MOUSE_EVENT,
|
||||||
|
.data = {
|
||||||
|
.mouse_event = {
|
||||||
|
.type = MOUSE_BTN_RIGHT,
|
||||||
|
.value = e->ev[i].value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
messages[written_msg++] = current_message;
|
||||||
|
}
|
||||||
|
} else if (e->ev[i].type == EV_REL) {
|
||||||
|
if (e->ev[i].code == REL_X) {
|
||||||
|
const in_message_t current_message = {
|
||||||
|
.type = MOUSE_EVENT,
|
||||||
|
.data = {
|
||||||
|
.mouse_event = {
|
||||||
|
.type = MOUSE_ELEMENT_X,
|
||||||
|
.value = e->ev[i].value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
messages[written_msg++] = current_message;
|
||||||
|
} else if (e->ev[i].code == REL_Y) {
|
||||||
|
const in_message_t current_message = {
|
||||||
|
.type = MOUSE_EVENT,
|
||||||
|
.data = {
|
||||||
|
.mouse_event = {
|
||||||
|
.type = MOUSE_ELEMENT_Y,
|
||||||
|
.value = e->ev[i].value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
messages[written_msg++] = current_message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
141
virt_mouse.c
Normal file
141
virt_mouse.c
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
#include "virt_mouse.h"
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
int virt_mouse_init(virt_mouse_t *const mouse) {
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
|
mouse->status_recv = 0;
|
||||||
|
|
||||||
|
int fd = open("/dev/uinput", O_RDWR);
|
||||||
|
if(fd < 0) {
|
||||||
|
ret = errno;
|
||||||
|
goto virt_mouse_init_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ioctl(fd, UI_SET_EVBIT, EV_REL);
|
||||||
|
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
||||||
|
ioctl(fd, UI_SET_EVBIT, EV_MSC);
|
||||||
|
ioctl(fd, UI_SET_EVBIT, EV_SYN);
|
||||||
|
ioctl(fd, UI_SET_MSCBIT, MSC_TIMESTAMP);
|
||||||
|
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
|
||||||
|
ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE);
|
||||||
|
ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT);
|
||||||
|
ioctl(fd, UI_SET_RELBIT, REL_X);
|
||||||
|
ioctl(fd, UI_SET_RELBIT, REL_Y);
|
||||||
|
ioctl(fd, UI_SET_RELBIT, REL_WHEEL);
|
||||||
|
ioctl(fd, UI_SET_RELBIT, REL_WHEEL_HI_RES);
|
||||||
|
|
||||||
|
struct uinput_setup dev = {0};
|
||||||
|
strncpy(dev.name, VIRT_MOUSE_DEV_NAME, UINPUT_MAX_NAME_SIZE-1);
|
||||||
|
dev.id.bustype = BUS_VIRTUAL;
|
||||||
|
dev.id.vendor = VIRT_MOUSE_DEV_VENDOR_ID;
|
||||||
|
dev.id.product = VIRT_MOUSE_DEV_PRODUCT_ID;
|
||||||
|
dev.id.version = VIRT_MOUSE_DEV_VERSION;
|
||||||
|
|
||||||
|
if(ioctl(fd, UI_DEV_SETUP, &dev) < 0) {
|
||||||
|
ret = errno > 0 ? errno : -1 * errno;
|
||||||
|
ret = ret == 0 ? -EIO : ret;
|
||||||
|
goto virt_mouse_init_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ioctl(fd, UI_DEV_CREATE) < 0) {
|
||||||
|
ret = errno > 0 ? errno : -1 * errno;
|
||||||
|
ret = ret == 0 ? -EIO : ret;
|
||||||
|
goto virt_mouse_init_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialization ok
|
||||||
|
mouse->prev_btn_left = 0;
|
||||||
|
mouse->prev_btn_right = 0;
|
||||||
|
mouse->prev_btn_middle = 0;
|
||||||
|
mouse->fd = fd;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
virt_mouse_init_err:
|
||||||
|
if (ret != 0) {
|
||||||
|
mouse->fd = -1;
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int virt_mouse_get_fd(virt_mouse_t *const mouse) {
|
||||||
|
return mouse->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int virt_mouse_send(virt_mouse_t *const mouse, mouse_status_t *const status, struct timeval *const now) {
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
struct input_event tmp_ev;
|
||||||
|
if (now == NULL) {
|
||||||
|
gettimeofday(&tmp_ev.time, NULL);
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
status->x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
status->y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_ev.type = EV_KEY;
|
||||||
|
|
||||||
|
if (status->btn_left != mouse->prev_btn_left) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virt_mouse_send_err:
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void virt_mouse_close(virt_mouse_t *const mouse) {
|
||||||
|
close(mouse->fd);
|
||||||
|
}
|
||||||
29
virt_mouse.h
Normal file
29
virt_mouse.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "message.h"
|
||||||
|
#include "devices_status.h"
|
||||||
|
|
||||||
|
#define VIRT_MOUSE_DEV_NAME "ROGueENEMY - mouse"
|
||||||
|
|
||||||
|
#define VIRT_MOUSE_DEV_VENDOR_ID 0x108c
|
||||||
|
#define VIRT_MOUSE_DEV_PRODUCT_ID 0x0323
|
||||||
|
#define VIRT_MOUSE_DEV_VERSION 0x0111
|
||||||
|
|
||||||
|
typedef struct virt_mouse {
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
uint8_t prev_btn_left;
|
||||||
|
uint8_t prev_btn_right;
|
||||||
|
uint8_t prev_btn_middle;
|
||||||
|
|
||||||
|
uint64_t status_recv;
|
||||||
|
|
||||||
|
} virt_mouse_t;
|
||||||
|
|
||||||
|
int virt_mouse_init(virt_mouse_t *const mouse);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void virt_mouse_close(virt_mouse_t *const mouse);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue