split up application in two different sub-applications

This commit is contained in:
Denis 2023-12-12 23:46:08 +01:00
parent 7e91e73327
commit 00fb3a02e3
No known key found for this signature in database
GPG key ID: DD9B63F805CF5C03
20 changed files with 441 additions and 210 deletions

View file

@ -9,33 +9,46 @@ project(
VERSION 1.0 VERSION 1.0
LANGUAGES C) LANGUAGES C)
set(EXECUTABLE_NAME "rogue-enemy") set(ROGUE_EXECUTABLE_NAME "rogue-enemy")
set(STRAY_EXECUTABLE_NAME "stray-ally")
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
# Adding something we can run - Output name matches target name add_executable(${ROGUE_EXECUTABLE_NAME}
add_executable(${EXECUTABLE_NAME}
dev_evdev.c dev_evdev.c
dev_iio.c dev_iio.c
dev_hidraw.c dev_hidraw.c
dev_in.c dev_in.c
dev_out.c
main.c main.c
settings.c settings.c
virt_ds4.c
virt_ds5.c
devices_status.c
rog_ally.c rog_ally.c
legion_go.c legion_go.c
xbox360.c xbox360.c
rogue_enemy.c rogue_enemy.c
) )
set_property(TARGET ${EXECUTABLE_NAME} PROPERTY C_STANDARD 17) add_executable(${STRAY_EXECUTABLE_NAME}
dev_out.c
stray_ally.c
settings.c
virt_ds4.c
virt_ds5.c
devices_status.c
)
target_link_libraries(${EXECUTABLE_NAME} PRIVATE Threads::Threads -levdev -ludev -lconfig -lm) set_property(TARGET ${ROGUE_EXECUTABLE_NAME} PROPERTY C_STANDARD 17)
set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINKER_LANGUAGE C) target_link_libraries(${ROGUE_EXECUTABLE_NAME} PRIVATE Threads::Threads -levdev -ludev -lconfig -lm)
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin) set_target_properties(${ROGUE_EXECUTABLE_NAME} PROPERTIES LINKER_LANGUAGE C)
install(TARGETS ${ROGUE_EXECUTABLE_NAME} DESTINATION bin)
set_property(TARGET ${STRAY_EXECUTABLE_NAME} PROPERTY C_STANDARD 17)
target_link_libraries(${STRAY_EXECUTABLE_NAME} PRIVATE Threads::Threads -levdev -ludev -lconfig -lm)
set_target_properties(${STRAY_EXECUTABLE_NAME} PROPERTIES LINKER_LANGUAGE C)
install(TARGETS ${STRAY_EXECUTABLE_NAME} DESTINATION bin)

View file

@ -1,6 +1,7 @@
#include "dev_in.h" #include "dev_in.h"
#include "dev_hidraw.h" #include "dev_hidraw.h"
#include "input_dev.h" #include "input_dev.h"
#include "ipc.h"
#include "message.h" #include "message.h"
#include "dev_evdev.h" #include "dev_evdev.h"
#include "dev_iio.h" #include "dev_iio.h"
@ -55,7 +56,7 @@ typedef struct dev_in {
} dev_in_t; } dev_in_t;
static int send_message_from_iio(dev_in_iio_t *const in_iio) { static int map_message_from_iio(dev_in_iio_t *const in_iio, in_message_t *const messages, size_t messages_len) {
int res = -EIO; int res = -EIO;
/* /*
@ -333,6 +334,15 @@ static void handle_rumble(dev_in_t *const in_devs, size_t in_devs_count, const o
} }
} }
static int open_socket(void) {
int res = -ENODEV;
open_socket_err:
return res;
}
void* dev_in_thread_func(void *ptr) { void* dev_in_thread_func(void *ptr) {
dev_in_data_t *const dev_in_data = (dev_in_data_t*)ptr; dev_in_data_t *const dev_in_data = (dev_in_data_t*)ptr;
@ -364,7 +374,20 @@ void* dev_in_thread_func(void *ptr) {
for (;;) { for (;;) {
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_SET(dev_in_data->out_message_pipe_fd, &read_fds);
if (dev_in_data->communication.type == ipc_unix_pipe) {
FD_SET(dev_in_data->communication.endpoint.pipe.out_message_pipe_fd, &read_fds);
} else if (dev_in_data->communication.type == ipc_client_socket) {
dev_in_data->communication.endpoint.socket = open_socket();
// do not do a thing! that will consume messages and they won't be available anymore!
if (dev_in_data->communication.endpoint.socket < 0) {
fprintf(stderr, "Unable to connect to server: %d -- will retry connection\n", dev_in_data->communication.endpoint.socket);
usleep(500000);
continue;
}
}
for (size_t i = 0; i < max_devices; ++i) { for (size_t i = 0; i < max_devices; ++i) {
if (devices[i].type == DEV_IN_TYPE_EV) { if (devices[i].type == DEV_IN_TYPE_EV) {
// device is present, query it in select // device is present, query it in select
@ -415,9 +438,16 @@ void* dev_in_thread_func(void *ptr) {
} }
// check for messages incoming like set leds or activate rumble // check for messages incoming like set leds or activate rumble
if (FD_ISSET(dev_in_data->out_message_pipe_fd, &read_fds)) { int out_message_fd = -1;
if (dev_in_data->communication.type == ipc_unix_pipe) {
out_message_fd = dev_in_data->communication.endpoint.pipe.out_message_pipe_fd;
} else if (dev_in_data->communication.type == ipc_client_socket) {
}
if (FD_ISSET(out_message_fd, &read_fds)) {
out_message_t out_msg; out_message_t out_msg;
const ssize_t out_message_pipe_read_res = read(dev_in_data->out_message_pipe_fd, (void*)&out_msg, sizeof(out_message_t)); const ssize_t out_message_pipe_read_res = read(out_message_fd, (void*)&out_msg, sizeof(out_message_t));
if (out_message_pipe_read_res == sizeof(out_message_t)) { if (out_message_pipe_read_res == sizeof(out_message_t)) {
if (out_msg.type == OUT_MSG_TYPE_RUMBLE) { if (out_msg.type == OUT_MSG_TYPE_RUMBLE) {
handle_rumble(devices, max_devices, &out_msg.data.rumble); handle_rumble(devices, max_devices, &out_msg.data.rumble);
@ -432,6 +462,12 @@ void* dev_in_thread_func(void *ptr) {
} }
} else { } else {
fprintf(stderr, "Error reading from out_message_pipe_fd: got %zu bytes, expected %zu butes\n", out_message_pipe_read_res, sizeof(out_message_t)); fprintf(stderr, "Error reading from out_message_pipe_fd: got %zu bytes, expected %zu butes\n", out_message_pipe_read_res, sizeof(out_message_t));
// in case of an error reschedule to socket for reconnection
if (dev_in_data->communication.type == ipc_client_socket) {
close(out_message_fd);
dev_in_data->communication.endpoint.socket = -1;
}
} }
} }
@ -452,32 +488,61 @@ void* dev_in_thread_func(void *ptr) {
continue; continue;
} }
in_message_t controller_msg[MAX_IN_MESSAGES];
size_t controller_msg_avail = sizeof(controller_msg) / sizeof(in_message_t);
int controller_msg_count = -EIO;
// the following part fills controller_msg and writes in controller_msg_count an error or the number of messages to be sent to the output device
if (devices[i].type == DEV_IN_TYPE_EV) { if (devices[i].type == DEV_IN_TYPE_EV) {
evdev_collected_t coll = { evdev_collected_t coll = {
.ev_count = 0 .ev_count = 0
}; };
const int fill_res = fill_message_from_evdev(&devices[i].dev.evdev, &coll); controller_msg_count = fill_message_from_evdev(&devices[i].dev.evdev, &coll);
if (fill_res != 0) { if (controller_msg_count != 0) {
fprintf(stderr, "Unable to fill input_event(s) for device %zd: %d -- Will reconnect the device\n", i, fill_res); fprintf(stderr, "Unable to fill input_event(s) for device %zd: %d -- Will reconnect the device\n", i, controller_msg_count);
evdev_close_device(&devices[i].dev.evdev); evdev_close_device(&devices[i].dev.evdev);
devices[i].type = DEV_IN_TYPE_NONE; devices[i].type = DEV_IN_TYPE_NONE;
} else { continue;
dev_in_data->input_dev_decl->dev[i]->map.ev_input_map_fn(&coll, dev_in_data->in_message_pipe_fd, dev_in_data->input_dev_decl->dev[i]->user_data);
} }
dev_in_data->input_dev_decl->dev[i]->map.ev_input_map_fn(&coll, &controller_msg[0], controller_msg_avail, dev_in_data->input_dev_decl->dev[i]->user_data);
} else if (devices[i].type == DEV_IN_TYPE_IIO) { } else if (devices[i].type == DEV_IN_TYPE_IIO) {
const int fill_res = send_message_from_iio(&devices[i].dev.iio); controller_msg_count = map_message_from_iio(&devices[i].dev.iio, &controller_msg[0], controller_msg_avail);
if (fill_res != 0) { if (controller_msg_count != 0) {
fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, fill_res); fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count);
iio_close_device(&devices[i].dev.iio); iio_close_device(&devices[i].dev.iio);
devices[i].type = DEV_IN_TYPE_NONE; devices[i].type = DEV_IN_TYPE_NONE;
continue;
} }
} else if (devices[i].type == DEV_IN_TYPE_HIDRAW) { } else if (devices[i].type == DEV_IN_TYPE_HIDRAW) {
const int fill_res = dev_in_data->input_dev_decl->dev[i]->map.hidraw_input_map_fn(dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev), dev_in_data->in_message_pipe_fd, dev_in_data->input_dev_decl->dev[i]->user_data); controller_msg_count = dev_in_data->input_dev_decl->dev[i]->map.hidraw_input_map_fn(dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev), &controller_msg[0], controller_msg_avail, dev_in_data->input_dev_decl->dev[i]->user_data);
if (fill_res != 0) { if (controller_msg_count != 0) {
fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, fill_res); fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count);
hidraw_close_device(&devices[i].dev.hidraw); hidraw_close_device(&devices[i].dev.hidraw);
devices[i].type = DEV_IN_TYPE_NONE; devices[i].type = DEV_IN_TYPE_NONE;
continue;
}
}
// send messages (if any)
if (controller_msg_count > 0) {
int in_message_fd = -1;
if (dev_in_data->communication.type == ipc_client_socket) {
in_message_fd = dev_in_data->communication.endpoint.socket;
} else if (dev_in_data->communication.type == ipc_unix_pipe) {
in_message_fd = dev_in_data->communication.endpoint.pipe.in_message_pipe_fd;
}
const int write_res = write(in_message_fd, (void*)&controller_msg[0], controller_msg_count);
if (write_res < 0) {
fprintf(stderr, "Error in writing input event messages: %d\n", write_res);
// in case of an error reschedule to socket for reconnection
if (dev_in_data->communication.type == ipc_client_socket) {
close(in_message_fd);
dev_in_data->communication.endpoint.socket = -1;
}
} }
} }
} }

View file

@ -1,8 +1,11 @@
#pragma once #pragma once
#include "ipc.h"
#include "message.h" #include "message.h"
#include "input_dev.h" #include "input_dev.h"
#define MAX_IN_MESSAGES 8
typedef struct dev_in_data { typedef struct dev_in_data {
size_t max_messages_in_flight; size_t max_messages_in_flight;
@ -12,11 +15,7 @@ typedef struct dev_in_data {
// declarations of devices to monitor // declarations of devices to monitor
input_dev_composite_t *input_dev_decl; input_dev_composite_t *input_dev_decl;
// this pipe is reserved for reporting in_message_t ipc_t communication;
int in_message_pipe_fd;
// this messages is reserved for receiving out_message_t
int out_message_pipe_fd;
} dev_in_data_t; } dev_in_data_t;

107
dev_out.c
View file

@ -1,8 +1,10 @@
#include "dev_out.h" #include "dev_out.h"
#include "devices_status.h" #include "devices_status.h"
#include "message.h"
#include "virt_ds4.h" #include "virt_ds4.h"
#include "virt_ds5.h" #include "virt_ds5.h"
#include <pthread.h>
static void handle_incoming_message_gamepad_action( static void handle_incoming_message_gamepad_action(
const in_message_gamepad_action_t *const msg_payload, const in_message_gamepad_action_t *const msg_payload,
@ -219,7 +221,22 @@ void *dev_out_thread_func(void *ptr) {
} }
} else { } else {
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
FD_SET(dev_out->in_message_pipe_fd, &read_fds);
if (dev_out->communication.type == ipc_unix_pipe) {
FD_SET(dev_out->communication.endpoint.pipe.in_message_pipe_fd, &read_fds);
} else if (dev_out->communication.type == ipc_server_sockets) {
if (pthread_mutex_lock(&dev_out->communication.endpoint.ssocket.mutex) == 0) {
for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
const int fd = dev_out->communication.endpoint.ssocket.clients[i];
if (fd > 0) {
FD_SET(fd, &read_fds);
}
}
pthread_mutex_unlock(&dev_out->communication.endpoint.ssocket.mutex);
}
}
// TODO: FD_SET(current_mouse_fd, &read_fds); // TODO: FD_SET(current_mouse_fd, &read_fds);
// TODO: FD_SET(current_keyboard_fd, &read_fds); // TODO: FD_SET(current_keyboard_fd, &read_fds);
FD_SET(current_gamepad_fd, &read_fds); FD_SET(current_gamepad_fd, &read_fds);
@ -242,23 +259,93 @@ void *dev_out_thread_func(void *ptr) {
continue; continue;
} }
if (FD_ISSET(current_gamepad_fd, &read_fds)) { if (FD_ISSET(current_gamepad_fd, &read_fds)) {
const uint64_t prev_leds_events_count = dev_out->dev_stats.gamepad.leds_events_count;
const uint64_t prev_motors_events_count = dev_out->dev_stats.gamepad.rumble_events_count;
out_message_t out_msgs[4];
size_t out_msgs_count = 0;
if (current_gamepad == GAMEPAD_DUALSENSE) { if (current_gamepad == GAMEPAD_DUALSENSE) {
virt_dualsense_event(&controller_data.ds5, &dev_out->dev_stats.gamepad, dev_out->out_message_pipe_fd); virt_dualsense_event(&controller_data.ds5, &dev_out->dev_stats.gamepad);
} else if (current_gamepad == GAMEPAD_DUALSHOCK) { } else if (current_gamepad == GAMEPAD_DUALSHOCK) {
virt_dualshock_event(&controller_data.ds4, &dev_out->dev_stats.gamepad, dev_out->out_message_pipe_fd); virt_dualshock_event(&controller_data.ds4, &dev_out->dev_stats.gamepad);
}
const uint64_t current_leds_events_count = dev_out->dev_stats.gamepad.leds_events_count;
const uint64_t current_motors_events_count = dev_out->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->dev_stats.gamepad.leds_colors[0],
.g = dev_out->dev_stats.gamepad.leds_colors[1],
.b = dev_out->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->dev_stats.gamepad.motors_intensity[0],
.motors_right = dev_out->dev_stats.gamepad.motors_intensity[1],
}
}
};
out_msgs[out_msgs_count++] = msg;
}
// send out game-generated events to sockets
int fd = -1;
if (dev_out->communication.type == ipc_unix_pipe) {
fd = dev_out->communication.endpoint.pipe.out_message_pipe_fd;
} else if (dev_out->communication.type == ipc_server_sockets) {
} }
} }
if (FD_ISSET(dev_out->in_message_pipe_fd, &read_fds)) { // read and handle incoming data: this data is packed into in_message_t
in_message_t incoming_message; if (dev_out->communication.type == ipc_unix_pipe) {
size_t in_message_pipe_read_res = read(dev_out->in_message_pipe_fd, (void*)&incoming_message, sizeof(in_message_t)); if (FD_ISSET(dev_out->communication.endpoint.pipe.in_message_pipe_fd, &read_fds)) {
if (in_message_pipe_read_res == sizeof(in_message_t)) { in_message_t incoming_message;
handle_incoming_message(&incoming_message, &dev_out->dev_stats); const size_t in_message_pipe_read_res = read(dev_out->communication.endpoint.pipe.in_message_pipe_fd, (void*)&incoming_message, sizeof(in_message_t));
} else { if (in_message_pipe_read_res == sizeof(in_message_t)) {
fprintf(stderr, "Error reading from in_message_pipe_fd: got %zu bytes, expected %zu butes\n", in_message_pipe_read_res, sizeof(in_message_t)); handle_incoming_message(&incoming_message, &dev_out->dev_stats);
} else {
fprintf(stderr, "Error reading from in_message_pipe_fd: got %zu bytes, expected %zu butes\n", in_message_pipe_read_res, sizeof(in_message_t));
}
}
} else if (dev_out->communication.type == ipc_server_sockets) {
if (pthread_mutex_lock(&dev_out->communication.endpoint.ssocket.mutex) == 0) {
for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
const int fd = dev_out->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(&incoming_message, &dev_out->dev_stats);
} else {
fprintf(stderr, "Error reading from in_message_pipe_fd: got %zu bytes, expected %zu butes\n", in_message_pipe_read_res, sizeof(in_message_t));
dev_out->communication.endpoint.ssocket.clients[i] = -1;
close(fd);
}
}
}
pthread_mutex_unlock(&dev_out->communication.endpoint.ssocket.mutex);
} }
} }
} }
} }

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "ipc.h"
#include "message.h" #include "message.h"
#include "devices_status.h" #include "devices_status.h"
@ -11,11 +12,7 @@ typedef enum dev_out_gamepad_device {
typedef struct dev_out_data { typedef struct dev_out_data {
// this pipe is reserved for reporting in_message_t ipc_t communication;
int in_message_pipe_fd;
// this messages is reserved for receiving out_message_t
int out_message_pipe_fd;
dev_out_gamepad_device_t gamepad; dev_out_gamepad_device_t gamepad;

View file

@ -35,6 +35,10 @@ void gamepad_status_init(gamepad_status_t *const stats) {
stats->accel[0] = 0; stats->accel[0] = 0;
stats->accel[1] = 0; stats->accel[1] = 0;
stats->accel[2] = 0; stats->accel[2] = 0;
stats->leds_events_count = 0;
stats->leds_colors[0] = 0;
stats->leds_colors[1] = 0;
stats->leds_colors[2] = 0;
stats->flags = 0; stats->flags = 0;
} }

View file

@ -58,6 +58,9 @@ typedef struct gamepad_status {
uint64_t rumble_events_count; uint64_t rumble_events_count;
uint8_t motors_intensity[2]; // 0 = left, 1 = right uint8_t motors_intensity[2]; // 0 = left, 1 = right
uint64_t leds_events_count;
uint8_t leds_colors[3]; // r | g | b
volatile uint32_t flags; volatile uint32_t flags;
} gamepad_status_t; } gamepad_status_t;

View file

@ -17,8 +17,8 @@ typedef struct evdev_collected {
* A function with this signature grapbs input_event data and sends to the pipe messages * A function with this signature grapbs input_event data and sends to the pipe messages
* constructed from that data. * constructed from that data.
*/ */
typedef void (*ev_map)(const evdev_collected_t *const e, int in_messages_pipe_fd, void* user_data); typedef int (*ev_map)(const evdev_collected_t *const e, in_message_t *const messages, size_t messages_len, void* user_data);
typedef int (*hidraw_map)(int hidraw_fd, int in_messages_pipe_fd, void* user_data); typedef int (*hidraw_map)(int hidraw_fd, in_message_t *const messages, size_t messages_len, void* user_data);
typedef enum input_dev_type { typedef enum input_dev_type {
input_dev_type_uinput, input_dev_type_uinput,
@ -92,9 +92,3 @@ typedef struct input_dev_composite {
platform_deinit deinit_fn; platform_deinit deinit_fn;
} input_dev_composite_t; } input_dev_composite_t;
uint32_t input_filter_imu_identity(struct input_event* events, size_t* size, uint32_t* count, uint32_t* flags);
uint32_t input_filter_identity(struct input_event* events, size_t* size, uint32_t* count, uint32_t* flags);
uint32_t input_filter_asus_kb(struct input_event*, size_t*, uint32_t*, uint32_t* flags);

38
ipc.h Normal file
View file

@ -0,0 +1,38 @@
#pragma once
#include "rogue_enemy.h"
#define MAX_CONNECTED_CLIENTS 8
typedef struct ipc_strategy_socket {
pthread_mutex_t mutex;
int clients[MAX_CONNECTED_CLIENTS];
} ipc_strategy_socket_t;
typedef struct ipc_strategy_pipe {
// this pipe is reserved for reporting in_message_t
int in_message_pipe_fd;
// this messages is reserved for receiving out_message_t
int out_message_pipe_fd;
} ipc_strategy_pipe_t;
typedef enum ipc_strategy {
ipc_unix_pipe,
ipc_server_sockets,
ipc_client_socket,
} ipc_strategy_t;
typedef struct ipc {
ipc_strategy_t type;
union {
ipc_strategy_pipe_t pipe;
ipc_strategy_socket_t ssocket;
int socket;
} endpoint;
} ipc_t;
#define SERVER_PATH "/tmp/server.sock"

View file

@ -40,9 +40,11 @@ static struct llg_hidraw_data {
uint8_t last_packet[64]; uint8_t last_packet[64];
} llg_hidraw_user_data; } llg_hidraw_user_data;
static int llg_hidraw_map(int hidraw_fd, int in_messages_pipe_fd, void* user_data) { static int llg_hidraw_map(int hidraw_fd, in_message_t *const messages, size_t messages_len, void* user_data) {
struct llg_hidraw_data *const llg_data = (struct llg_hidraw_data*)user_data; struct llg_hidraw_data *const llg_data = (struct llg_hidraw_data*)user_data;
int msg_count = 0;
int read_res = read(hidraw_fd, llg_data->last_packet, sizeof(llg_data->last_packet)); int read_res = read(hidraw_fd, llg_data->last_packet, sizeof(llg_data->last_packet));
if (read_res != 64) { if (read_res != 64) {
fprintf(stderr, "Error reading from hidraw device\n"); fprintf(stderr, "Error reading from hidraw device\n");
@ -64,16 +66,11 @@ static int llg_hidraw_map(int hidraw_fd, int in_messages_pipe_fd, void* user_dat
}; };
// this does send messages to the output device // this does send messages to the output device
messages[msg_count++] = current_message;
const ssize_t in_message_pipe_write_res = write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t));
if (in_message_pipe_write_res != sizeof(in_message_t)) {
fprintf(stderr, "Unable to write data for L4 to the in_message pipe: %zu\n", in_message_pipe_write_res);
return -EINVAL;
}
*/ */
// successful return // successful return
return 0; return msg_count;
} }
static input_dev_t in_hidraw_dev = { static input_dev_t in_hidraw_dev = {

54
main.c
View file

@ -27,9 +27,6 @@ void sig_handler(int signo)
static const char* configuration_file = "/etc/ROGueENEMY/config.cfg"; static const char* configuration_file = "/etc/ROGueENEMY/config.cfg";
dev_in_data_t dev_in_thread_data;
dev_out_data_t dev_out_thread_data;
controller_settings_t settings; controller_settings_t settings;
int main(int argc, char ** argv) { int main(int argc, char ** argv) {
@ -38,13 +35,6 @@ int main(int argc, char ** argv) {
init_config(&settings); init_config(&settings);
fill_config(&settings, configuration_file); fill_config(&settings, configuration_file);
/*
const int logic_creation_res = logic_create(&global_logic);
if (logic_creation_res < 0) {
fprintf(stderr, "Unable to create logic: %d", logic_creation_res);
return EXIT_FAILURE;
}
*/
input_dev_composite_t* in_devs = NULL; input_dev_composite_t* in_devs = NULL;
int dmi_name_fd = open("/sys/class/dmi/id/board_name", O_RDONLY | O_NONBLOCK); int dmi_name_fd = open("/sys/class/dmi/id/board_name", O_RDONLY | O_NONBLOCK);
@ -65,29 +55,20 @@ int main(int argc, char ** argv) {
} }
close(dmi_name_fd); close(dmi_name_fd);
int dev_in_thread_creation = -1;
int dev_out_thread_creation = -1;
int out_message_pipes[2];
pipe(out_message_pipes);
int in_message_pipes[2];
pipe(in_message_pipes);
// populate the input device thread data // populate the input device thread data
dev_in_thread_data.timeout_ms = 400; dev_in_data_t dev_in_thread_data = {
dev_in_thread_data.in_message_pipe_fd = in_message_pipes[1]; .timeout_ms = 1200,
dev_in_thread_data.out_message_pipe_fd = out_message_pipes[0]; .input_dev_decl = in_devs,
dev_in_thread_data.input_dev_decl = in_devs; .communication = {
.type = ipc_client_socket,
.endpoint = {
.socket = -1,
}
}
};
// populate the output device thread data
//dev_out_thread_data.timeout_ms = 400;
dev_out_thread_data.in_message_pipe_fd = in_message_pipes[0];
dev_out_thread_data.out_message_pipe_fd = out_message_pipes[1];
dev_out_thread_data.gamepad = GAMEPAD_DUALSENSE;
pthread_t dev_in_thread; pthread_t dev_in_thread;
dev_in_thread_creation = pthread_create(&dev_in_thread, NULL, dev_in_thread_func, (void*)(&dev_in_thread_data)); const int dev_in_thread_creation = pthread_create(&dev_in_thread, NULL, dev_in_thread_func, (void*)(&dev_in_thread_data));
if (dev_in_thread_creation != 0) { if (dev_in_thread_creation != 0) {
fprintf(stderr, "Error creating dev_in thread: %d\n", dev_in_thread_creation); fprintf(stderr, "Error creating dev_in thread: %d\n", dev_in_thread_creation);
ret = -1; ret = -1;
@ -95,15 +76,6 @@ int main(int argc, char ** argv) {
goto main_err; goto main_err;
} }
pthread_t dev_out_thread;
dev_out_thread_creation = pthread_create(&dev_out_thread, NULL, dev_out_thread_func, (void*)(&dev_out_thread_data));
if (dev_out_thread_creation != 0) {
fprintf(stderr, "Error creating dev_out thread: %d\n", dev_out_thread_creation);
ret = -1;
//logic_request_termination(&global_logic);
goto main_err;
}
/* /*
// TODO: once the application is able to exit de-comment this // TODO: once the application is able to exit de-comment this
__sighandler_t sigint_hndl = signal(SIGINT, sig_handler); __sighandler_t sigint_hndl = signal(SIGINT, sig_handler);
@ -118,9 +90,5 @@ main_err:
pthread_join(dev_in_thread, NULL); pthread_join(dev_in_thread, NULL);
} }
if (dev_out_thread_creation == 0) {
pthread_join(dev_out_thread, NULL);
}
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
} }

View file

@ -432,7 +432,9 @@ static const uint8_t rc71l_mode_switch_commands[][23][64] = {
} }
}; };
void asus_kbd_ev_map(const evdev_collected_t *const e, int in_messages_pipe_fd, void* user_data) { int asus_kbd_ev_map(const evdev_collected_t *const e, in_message_t *const messages, size_t messages_len, void* user_data) {
int written_msg = 0;
if ( // this is what happens at release of the left-screen button of the ROG Ally if ( // this is what happens at release of the left-screen button of the ROG Ally
(e->ev_count == 2) && (e->ev_count == 2) &&
(e->ev[0].type == EV_MSC) && (e->ev[0].type == EV_MSC) &&
@ -449,10 +451,7 @@ void asus_kbd_ev_map(const evdev_collected_t *const e, int in_messages_pipe_fd,
} }
}; };
const ssize_t in_message_pipe_write_res = write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t)); messages[written_msg++] = current_message;
if (in_message_pipe_write_res != sizeof(in_message_t)) {
fprintf(stderr, "Unable to write data for MENU to the in_message pipe: %zu\n", in_message_pipe_write_res);
}
} else if ( // this is what happens at release of the right-screen button of the ROG Ally } else if ( // this is what happens at release of the right-screen button of the ROG Ally
(e->ev_count == 2) && (e->ev_count == 2) &&
(e->ev[0].type == EV_MSC) && (e->ev[0].type == EV_MSC) &&
@ -469,10 +468,7 @@ void asus_kbd_ev_map(const evdev_collected_t *const e, int in_messages_pipe_fd,
} }
}; };
const ssize_t in_message_pipe_write_res = write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t)); messages[written_msg++] = current_message;
if (in_message_pipe_write_res != sizeof(in_message_t)) {
fprintf(stderr, "Unable to write data for QAM to the in_message pipe: %zu\n", in_message_pipe_write_res);
}
} else if ( } else if (
(e->ev_count == 2) && (e->ev_count == 2) &&
(e->ev[0].type == EV_MSC) && (e->ev[0].type == EV_MSC) &&
@ -493,10 +489,7 @@ void asus_kbd_ev_map(const evdev_collected_t *const e, int in_messages_pipe_fd,
} }
}; };
const ssize_t in_message_pipe_write_res = write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t)); messages[written_msg++] = current_message;
if (in_message_pipe_write_res != sizeof(in_message_t)) {
fprintf(stderr, "Unable to write data for L5 to the in_message pipe: %zu\n", in_message_pipe_write_res);
}
} else if ( } else if (
(e->ev_count == 2) && (e->ev_count == 2) &&
(e->ev[0].type == EV_MSC) && (e->ev[0].type == EV_MSC) &&
@ -517,11 +510,10 @@ void asus_kbd_ev_map(const evdev_collected_t *const e, int in_messages_pipe_fd,
} }
}; };
const ssize_t in_message_pipe_write_res = write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t)); messages[written_msg++] = current_message;
if (in_message_pipe_write_res != sizeof(in_message_t)) {
fprintf(stderr, "Unable to write data for R5 to the in_message pipe: %zu\n", in_message_pipe_write_res);
}
} }
return written_msg;
} }
static hidraw_filters_t n_key_hidraw_filters = { static hidraw_filters_t n_key_hidraw_filters = {

View file

@ -23,6 +23,8 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <linux/hidraw.h> #include <linux/hidraw.h>
#include <linux/input-event-codes.h> #include <linux/input-event-codes.h>

132
stray_ally.c Normal file
View file

@ -0,0 +1,132 @@
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include "input_dev.h"
#include "dev_in.h"
#include "dev_out.h"
#include "settings.h"
#include "rog_ally.h"
#include "legion_go.h"
/*
logic_t global_logic;
static output_dev_t out_gamepadd_dev = {
.logic = &global_logic,
};
void sig_handler(int signo)
{
if (signo == SIGINT) {
logic_request_termination(&global_logic);
printf("Received SIGINT\n");
}
}
*/
static const char* configuration_file = "/etc/ROGueENEMY/config.cfg";
controller_settings_t settings;
int main(int argc, char ** argv) {
int ret = 0;
init_config(&settings);
fill_config(&settings, configuration_file);
// populate the output device thread data
dev_out_data_t dev_out_thread_data = {
.communication = {
.type = ipc_server_sockets,
.endpoint = {
.ssocket = {
.mutex = PTHREAD_MUTEX_INITIALIZER,
.clients = { -1, -1, -1, -1, -1, -1, -1, -1 },
}
}
},
.gamepad = GAMEPAD_DUALSENSE,
};
pthread_t dev_out_thread;
const int dev_out_thread_creation = pthread_create(&dev_out_thread, NULL, dev_out_thread_func, (void*)(&dev_out_thread_data));
if (dev_out_thread_creation != 0) {
fprintf(stderr, "Error creating dev_out thread: %d\n", dev_out_thread_creation);
ret = -1;
//logic_request_termination(&global_logic);
goto main_err;
}
int sd=-1;
int rc, length;
struct sockaddr_un serveraddr;
do {
sd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sd < 0)
{
fprintf(stderr, "socket() failed");
break;
}
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sun_family = AF_UNIX;
strcpy(serveraddr.sun_path, SERVER_PATH);
int rc = bind(sd, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr));
if (rc < 0)
{
perror("bind() failed");
break;
}
while (true) {
const int client_fd = accept(sd, NULL, NULL);
if (client_fd < 0) {
fprintf(stderr, "Error in getting a client connected: %d\n", client_fd);
continue;
}
// here the client_fd is good
if (pthread_mutex_lock(&dev_out_thread_data.communication.endpoint.ssocket.mutex) == 0) {
int i;
for (i = 0; i < MAX_CONNECTED_CLIENTS; ++i) {
if (dev_out_thread_data.communication.endpoint.ssocket.clients[i] == -1) {
dev_out_thread_data.communication.endpoint.ssocket.clients[i] = client_fd;
break;
}
}
if (i == MAX_CONNECTED_CLIENTS) {
fprintf(stderr, "Could not find a free spot fot the incoming client -- client will be rejected\n");
close(client_fd);
}
pthread_mutex_unlock(&dev_out_thread_data.communication.endpoint.ssocket.mutex);
}
}
} while (false);
if (sd != -1) {
close(sd);
}
unlink(SERVER_PATH);
/*
// TODO: once the application is able to exit de-comment this
__sighandler_t sigint_hndl = signal(SIGINT, sig_handler);
if (sigint_hndl == SIG_ERR) {
fprintf(stderr, "Error registering SIGINT handler\n");
return EXIT_FAILURE;
}
*/
main_err:
if (dev_out_thread_creation == 0) {
pthread_join(dev_out_thread, NULL);
}
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

View file

@ -402,7 +402,7 @@ int virt_dualshock_get_fd(virt_dualshock_t *const in_gamepad) {
return in_gamepad->fd; return in_gamepad->fd;
} }
int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *const out_device_status, int out_message_pipe_fd) { int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *const out_device_status) {
struct uhid_event ev; struct uhid_event ev;
ssize_t ret; ssize_t ret;
@ -505,58 +505,21 @@ int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *cons
const uint8_t lightbar_blink_off = ev.u.output.data[10]; const uint8_t lightbar_blink_off = ev.u.output.data[10];
if ((valid_flag0 & DS4_OUTPUT_VALID_FLAG0_LED)) { if ((valid_flag0 & DS4_OUTPUT_VALID_FLAG0_LED)) {
const out_message_t msg = { out_device_status->leds_colors[0] = lightbar_red;
.type = OUT_MSG_TYPE_LEDS, out_device_status->leds_colors[1] = lightbar_green;
.data = { out_device_status->leds_colors[2] = lightbar_blue;
.leds = { out_device_status->leds_events_count++;
.r = lightbar_red,
.g = lightbar_green,
.b = lightbar_blue,
}
}
};
const int write_res = write(out_message_pipe_fd, (void*)&msg, sizeof(msg));
if (write_res != 0) {
return write_res;
}
} else if (valid_flag0 & DS4_OUTPUT_VALID_FLAG0_LED_BLINK) { } else if (valid_flag0 & DS4_OUTPUT_VALID_FLAG0_LED_BLINK) {
const out_message_t msg = { out_device_status->leds_colors[0] = lightbar_red;
.type = OUT_MSG_TYPE_LEDS, out_device_status->leds_colors[1] = lightbar_green;
.data = { out_device_status->leds_colors[2] = lightbar_blue;
.leds = { out_device_status->leds_events_count++;
.r = lightbar_red,
.g = lightbar_green,
.b = lightbar_blue,
}
}
};
const int write_res = write(out_message_pipe_fd, (void*)&msg, sizeof(msg));
if (write_res != 0) {
return write_res;
}
} }
if ((valid_flag0 & DS4_OUTPUT_VALID_FLAG0_MOTOR)) { if ((valid_flag0 & DS4_OUTPUT_VALID_FLAG0_MOTOR)) {
out_device_status->motors_intensity[0] = motor_left; out_device_status->motors_intensity[0] = motor_left;
out_device_status->motors_intensity[1] = motor_right; out_device_status->motors_intensity[1] = motor_right;
++out_device_status->rumble_events_count; out_device_status->rumble_events_count++;
const out_message_t msg = {
.type = OUT_MSG_TYPE_RUMBLE,
.data = {
.rumble = {
.motors_left = motor_left,
.motors_right = motor_right,
}
}
};
const int write_res = write(out_message_pipe_fd, (void*)&msg, sizeof(msg));
if (write_res != 0) {
return write_res;
}
if (gamepad->debug) { if (gamepad->debug) {
printf( printf(

View file

@ -25,7 +25,7 @@ int virt_dualshock_init(virt_dualshock_t *const gamepad);
int virt_dualshock_get_fd(virt_dualshock_t *const gamepad); int virt_dualshock_get_fd(virt_dualshock_t *const gamepad);
int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *const out_device_status, int out_message_pipe_fd); int virt_dualshock_event(virt_dualshock_t *const gamepad, gamepad_status_t *const out_device_status);
void virt_dualshock_compose(virt_dualshock_t *const gamepad, gamepad_status_t *const in_device_status, uint8_t *const out_buf); void virt_dualshock_compose(virt_dualshock_t *const gamepad, gamepad_status_t *const in_device_status, uint8_t *const out_buf);

View file

@ -142,7 +142,7 @@ int virt_dualsense_get_fd(virt_dualsense_t *const in_gamepad) {
return in_gamepad->fd; return in_gamepad->fd;
} }
int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *const out_device_status, int out_message_pipe_fd) int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *const out_device_status)
{ {
struct uhid_event ev; struct uhid_event ev;
ssize_t ret; ssize_t ret;
@ -235,21 +235,6 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons
out_device_status->motors_intensity[1] = motor_right; out_device_status->motors_intensity[1] = motor_right;
++out_device_status->rumble_events_count; ++out_device_status->rumble_events_count;
const out_message_t msg = {
.type = OUT_MSG_TYPE_RUMBLE,
.data = {
.rumble = {
.motors_left = motor_left,
.motors_right = motor_right,
}
}
};
const int write_res = write(out_message_pipe_fd, (void*)&msg, sizeof(msg));
if (write_res != 0) {
return write_res;
}
if (gamepad->debug) { if (gamepad->debug) {
printf( printf(
"Updated rumble -- motor_left: %d, motor_right: %d, valid_flag0; %d, valid_flag1: %d\n", "Updated rumble -- motor_left: %d, motor_right: %d, valid_flag0; %d, valid_flag1: %d\n",
@ -263,21 +248,10 @@ int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *cons
} }
if (valid_flag1 & DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE) { if (valid_flag1 & DS_OUTPUT_VALID_FLAG1_LIGHTBAR_CONTROL_ENABLE) {
const out_message_t msg = { out_device_status->leds_colors[0] = lightbar_red;
.type = OUT_MSG_TYPE_LEDS, out_device_status->leds_colors[1] = lightbar_green;
.data = { out_device_status->leds_colors[2] = lightbar_blue;
.leds = { out_device_status->leds_events_count++;
.r = lightbar_red,
.g = lightbar_green,
.b = lightbar_blue,
}
}
};
const int write_res = write(out_message_pipe_fd, (void*)&msg, sizeof(msg));
if (write_res != 0) {
return write_res;
}
} }
break; break;

View file

@ -27,7 +27,7 @@ int virt_dualsense_init(virt_dualsense_t *const gamepad);
int virt_dualsense_get_fd(virt_dualsense_t *const gamepad); int virt_dualsense_get_fd(virt_dualsense_t *const gamepad);
int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *const out_device_status, int out_message_pipe_fd); int virt_dualsense_event(virt_dualsense_t *const gamepad, gamepad_status_t *const out_device_status);
void virt_dualsense_compose(virt_dualsense_t *const gamepad, gamepad_status_t *const in_device_status, uint8_t *const out_buf); void virt_dualsense_compose(virt_dualsense_t *const gamepad, gamepad_status_t *const in_device_status, uint8_t *const out_buf);

View file

@ -1,8 +1,9 @@
#include "xbox360.h" #include "xbox360.h"
#include "message.h" #include "message.h"
void xbox360_ev_map(const evdev_collected_t *const coll, int in_messages_pipe_fd, void* user_data) { int xbox360_ev_map(const evdev_collected_t *const coll, in_message_t *const messages, size_t messages_len, void* user_data) {
const xbox360_settings_t *const settings = (xbox360_settings_t*)user_data; const xbox360_settings_t *const settings = (xbox360_settings_t*)user_data;
int written_msg = 0;
for (uint32_t i = 0; i < coll->ev_count; ++i) { for (uint32_t i = 0; i < coll->ev_count; ++i) {
if (coll->ev[i].type == EV_KEY) { if (coll->ev[i].type == EV_KEY) {
@ -45,10 +46,11 @@ void xbox360_ev_map(const evdev_collected_t *const coll, int in_messages_pipe_fd
current_message.data.action = GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER; current_message.data.action = GAMEPAD_ACTION_PRESS_AND_RELEASE_CENTER;
} }
// send the button event over the pipe if (written_msg == (messages_len-1)) {
if (write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t)) != sizeof(in_message_t)) { return -ENOMEM;
fprintf(stderr, "Unable to write gamepad data to the in_message pipe\n");
} }
messages[written_msg++] = current_message;
} else if (coll->ev[i].type == EV_ABS) { } else if (coll->ev[i].type == EV_ABS) {
in_message_t current_message = { in_message_t current_message = {
.type = GAMEPAD_SET_ELEMENT, .type = GAMEPAD_SET_ELEMENT,
@ -80,10 +82,11 @@ void xbox360_ev_map(const evdev_collected_t *const coll, int in_messages_pipe_fd
current_message.data.gamepad_set.status.btn = coll->ev[i].value; current_message.data.gamepad_set.status.btn = coll->ev[i].value;
} }
// send the button event over the pipe if (written_msg == (messages_len-1)) {
if (write(in_messages_pipe_fd, (void*)&current_message, sizeof(in_message_t)) != sizeof(in_message_t)) { return -ENOMEM;
fprintf(stderr, "Unable to write gamepad data to the in_message pipe\n");
} }
messages[written_msg++] = current_message;
} }
} }
} }

View file

@ -6,4 +6,4 @@ typedef struct xbox360_settings {
bool nintendo_layout; bool nintendo_layout;
} xbox360_settings_t; } xbox360_settings_t;
void xbox360_ev_map(const evdev_collected_t *const e, int in_messages_pipe_fd, void* user_data); int xbox360_ev_map(const evdev_collected_t *const coll, in_message_t *const messages, size_t messages_len, void* user_data);