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
|
||||
virt_ds4.c
|
||||
virt_ds5.c
|
||||
virt_mouse.c
|
||||
devices_status.c
|
||||
)
|
||||
|
||||
|
|
@ -44,6 +45,7 @@ add_executable(${ALLINONE_EXECUTABLE_NAME}
|
|||
settings.c
|
||||
virt_ds4.c
|
||||
virt_ds5.c
|
||||
virt_mouse.c
|
||||
devices_status.c
|
||||
dev_evdev.c
|
||||
dev_iio.c
|
||||
|
|
|
|||
366
dev_out.c
366
dev_out.c
|
|
@ -5,6 +5,7 @@
|
|||
#include "message.h"
|
||||
#include "virt_ds4.h"
|
||||
#include "virt_ds5.h"
|
||||
#include "virt_mouse.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(
|
||||
const dev_out_settings_t *const in_settings,
|
||||
const in_message_gamepad_set_element_t *const msg_payload,
|
||||
|
|
@ -196,6 +215,12 @@ static void handle_incoming_message(
|
|||
&msg->data.action,
|
||||
&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;
|
||||
}
|
||||
|
||||
int current_gamepad_fd = -1;
|
||||
int current_keyboard_fd = -1;
|
||||
int current_mouse_fd = -1;
|
||||
|
||||
union {
|
||||
virt_dualshock_t ds4;
|
||||
virt_dualsense_t ds5;
|
||||
} controller_data;
|
||||
|
||||
int current_gamepad_fd = -1;
|
||||
//int current_keyboard_fd = -1;
|
||||
//int current_mouse_fd = -1;
|
||||
virt_mouse_t mouse_data;
|
||||
const int mouse_init_res = virt_mouse_init(&mouse_data);
|
||||
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) {
|
||||
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);
|
||||
|
||||
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 timeval mouse_last_hid_report_sent = now;
|
||||
struct timeval keyboard_last_hid_report_sent = now;
|
||||
|
||||
uint8_t tmp_buf[256];
|
||||
|
||||
|
|
@ -272,9 +309,12 @@ void *dev_out_thread_func(void *ptr) {
|
|||
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);
|
||||
int64_t gamepad_time_diff_usecs = get_timediff_usec(&gamepad_last_hid_report_sent, &now);
|
||||
if (gamepad_time_diff_usecs >= 1250) {
|
||||
if (gamepad_time_diff_usecs >= gamepad_report_timing_us) {
|
||||
gamepad_last_hid_report_sent = now;
|
||||
|
||||
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_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) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
virt_dualsense_close(&controller_data.ds5);
|
||||
} else if (current_gamepad == GAMEPAD_DUALSHOCK) {
|
||||
virt_dualshock_close(&controller_data.ds4);
|
||||
}
|
||||
|
||||
// close the mouse device
|
||||
virt_mouse_close(&mouse_data);
|
||||
|
||||
// end communication
|
||||
if (dev_out_data->communication.type == ipc_server_sockets) {
|
||||
// close every client socket
|
||||
|
|
|
|||
|
|
@ -4,6 +4,16 @@ void kbd_status_init(keyboard_status_t *const stats) {
|
|||
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) {
|
||||
stats->connected = true;
|
||||
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) {
|
||||
gamepad_status_init(&stats->gamepad);
|
||||
kbd_status_init(&stats->kbd);
|
||||
// TODO: mouse init
|
||||
mouse_status_init(&stats->mouse);
|
||||
}
|
||||
|
||||
void gamepad_status_qam_quirk(gamepad_status_t *const gamepad_stats) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,19 @@ typedef struct keyboard_status {
|
|||
bool connected;
|
||||
} 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 {
|
||||
// this mutex MUST be grabbed when reading and/or writing below properties
|
||||
pthread_mutex_t mutex;
|
||||
|
|
@ -77,8 +90,12 @@ typedef struct devices_status {
|
|||
|
||||
keyboard_status_t kbd;
|
||||
|
||||
mouse_status_t mouse;
|
||||
|
||||
} devices_status_t;
|
||||
|
||||
void mouse_status_init(mouse_status_t *const stats);
|
||||
|
||||
void kbd_status_init(keyboard_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;
|
||||
} 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 {
|
||||
GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER,
|
||||
GAMEPAD_ACTION_OPEN_STEAM_QAM,
|
||||
|
|
@ -72,6 +85,7 @@ typedef enum in_message_gamepad_action {
|
|||
typedef enum in_in_message_type {
|
||||
GAMEPAD_SET_ELEMENT,
|
||||
GAMEPAD_ACTION,
|
||||
MOUSE_EVENT,
|
||||
} in_message_type_t;
|
||||
|
||||
typedef struct in_message {
|
||||
|
|
@ -83,6 +97,8 @@ typedef struct in_message {
|
|||
in_message_gamepad_action_t action;
|
||||
|
||||
in_message_gamepad_set_element_t gamepad_set;
|
||||
|
||||
in_message_mouse_event_t mouse_event;
|
||||
} data;
|
||||
|
||||
} in_message_t;
|
||||
|
|
|
|||
126
rog_ally.c
126
rog_ally.c
|
|
@ -1,7 +1,10 @@
|
|||
#include "rog_ally.h"
|
||||
#include "input_dev.h"
|
||||
#include "dev_hidraw.h"
|
||||
#include "message.h"
|
||||
#include "xbox360.h"
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef enum rc71l_platform_mode {
|
||||
rc71l_platform_mode_hidraw,
|
||||
|
|
@ -81,7 +84,11 @@ static char* find_kernel_sysfs_device_path(struct udev *udev) {
|
|||
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 evdev_collected_t *const e,
|
||||
in_message_t *const messages,
|
||||
|
|
@ -99,10 +106,10 @@ int asus_kbd_ev_map(
|
|||
.type = GAMEPAD_SET_ELEMENT,
|
||||
.data = {
|
||||
.gamepad_set = {
|
||||
.element = GAMEPAD_BTN_L5,
|
||||
.status = {
|
||||
.btn = e->ev[1].value,
|
||||
}
|
||||
.element = GAMEPAD_BTN_L5,
|
||||
.status = {
|
||||
.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);
|
||||
|
||||
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);
|
||||
} 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