diff --git a/CMakeLists.txt b/CMakeLists.txt index 0da6ee7..6fdc6b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,33 +9,46 @@ project( VERSION 1.0 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) find_package(Threads REQUIRED) -# Adding something we can run - Output name matches target name -add_executable(${EXECUTABLE_NAME} +add_executable(${ROGUE_EXECUTABLE_NAME} dev_evdev.c dev_iio.c dev_hidraw.c dev_in.c - dev_out.c main.c settings.c - virt_ds4.c - virt_ds5.c - devices_status.c rog_ally.c legion_go.c xbox360.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) \ No newline at end of file +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) \ No newline at end of file diff --git a/dev_in.c b/dev_in.c index d781181..e1f5a69 100644 --- a/dev_in.c +++ b/dev_in.c @@ -1,6 +1,7 @@ #include "dev_in.h" #include "dev_hidraw.h" #include "input_dev.h" +#include "ipc.h" #include "message.h" #include "dev_evdev.h" #include "dev_iio.h" @@ -55,7 +56,7 @@ typedef struct dev_in { } 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; /* @@ -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) { 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 (;;) { 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) { if (devices[i].type == DEV_IN_TYPE_EV) { // 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 - 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; - 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_msg.type == OUT_MSG_TYPE_RUMBLE) { handle_rumble(devices, max_devices, &out_msg.data.rumble); @@ -432,6 +462,12 @@ void* dev_in_thread_func(void *ptr) { } } 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)); + + // 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; } + 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) { evdev_collected_t coll = { .ev_count = 0 }; - const int fill_res = fill_message_from_evdev(&devices[i].dev.evdev, &coll); - if (fill_res != 0) { - fprintf(stderr, "Unable to fill input_event(s) for device %zd: %d -- Will reconnect the device\n", i, fill_res); + controller_msg_count = fill_message_from_evdev(&devices[i].dev.evdev, &coll); + if (controller_msg_count != 0) { + 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); devices[i].type = DEV_IN_TYPE_NONE; - } else { - 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); + continue; } + + 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) { - const int fill_res = send_message_from_iio(&devices[i].dev.iio); - if (fill_res != 0) { - fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, fill_res); + controller_msg_count = map_message_from_iio(&devices[i].dev.iio, &controller_msg[0], controller_msg_avail); + if (controller_msg_count != 0) { + 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); devices[i].type = DEV_IN_TYPE_NONE; + continue; } } 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); - if (fill_res != 0) { - fprintf(stderr, "Error in performing operations for device %zd: %d -- Will reconnect to the device\n", i, fill_res); + 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 (controller_msg_count != 0) { + 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); 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; + } } } } diff --git a/dev_in.h b/dev_in.h index adc4d58..18bc8e2 100644 --- a/dev_in.h +++ b/dev_in.h @@ -1,8 +1,11 @@ #pragma once +#include "ipc.h" #include "message.h" #include "input_dev.h" +#define MAX_IN_MESSAGES 8 + typedef struct dev_in_data { size_t max_messages_in_flight; @@ -12,11 +15,7 @@ typedef struct dev_in_data { // declarations of devices to monitor input_dev_composite_t *input_dev_decl; - // 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_t communication; } dev_in_data_t; diff --git a/dev_out.c b/dev_out.c index 96be64e..829c946 100644 --- a/dev_out.c +++ b/dev_out.c @@ -1,8 +1,10 @@ #include "dev_out.h" #include "devices_status.h" +#include "message.h" #include "virt_ds4.h" #include "virt_ds5.h" +#include static void handle_incoming_message_gamepad_action( const in_message_gamepad_action_t *const msg_payload, @@ -219,7 +221,22 @@ void *dev_out_thread_func(void *ptr) { } } else { 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_keyboard_fd, &read_fds); FD_SET(current_gamepad_fd, &read_fds); @@ -242,23 +259,93 @@ void *dev_out_thread_func(void *ptr) { continue; } + 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) { - 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) { - 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)) { - in_message_t incoming_message; - size_t in_message_pipe_read_res = read(dev_out->in_message_pipe_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)); + // read and handle incoming data: this data is packed into in_message_t + if (dev_out->communication.type == ipc_unix_pipe) { + if (FD_ISSET(dev_out->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->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(&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); } } + + } } diff --git a/dev_out.h b/dev_out.h index 1db237e..9da81c3 100644 --- a/dev_out.h +++ b/dev_out.h @@ -1,5 +1,6 @@ #pragma once +#include "ipc.h" #include "message.h" #include "devices_status.h" @@ -11,11 +12,7 @@ typedef enum dev_out_gamepad_device { typedef struct dev_out_data { - // 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_t communication; dev_out_gamepad_device_t gamepad; diff --git a/devices_status.c b/devices_status.c index e39a875..bd67963 100644 --- a/devices_status.c +++ b/devices_status.c @@ -35,6 +35,10 @@ void gamepad_status_init(gamepad_status_t *const stats) { stats->accel[0] = 0; stats->accel[1] = 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; } diff --git a/devices_status.h b/devices_status.h index 9a9c7db..8d39b26 100644 --- a/devices_status.h +++ b/devices_status.h @@ -58,6 +58,9 @@ typedef struct gamepad_status { uint64_t rumble_events_count; 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; } gamepad_status_t; diff --git a/input_dev.h b/input_dev.h index 3485c4d..edbbde0 100644 --- a/input_dev.h +++ b/input_dev.h @@ -17,8 +17,8 @@ typedef struct evdev_collected { * A function with this signature grapbs input_event data and sends to the pipe messages * constructed from that data. */ -typedef void (*ev_map)(const evdev_collected_t *const e, int in_messages_pipe_fd, void* user_data); -typedef int (*hidraw_map)(int hidraw_fd, 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, in_message_t *const messages, size_t messages_len, void* user_data); typedef enum input_dev_type { input_dev_type_uinput, @@ -92,9 +92,3 @@ typedef struct input_dev_composite { platform_deinit deinit_fn; } 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); diff --git a/ipc.h b/ipc.h new file mode 100644 index 0000000..c298a80 --- /dev/null +++ b/ipc.h @@ -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" \ No newline at end of file diff --git a/legion_go.c b/legion_go.c index 990d4dc..4f942df 100644 --- a/legion_go.c +++ b/legion_go.c @@ -40,9 +40,11 @@ static struct llg_hidraw_data { uint8_t last_packet[64]; } 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; + int msg_count = 0; + int read_res = read(hidraw_fd, llg_data->last_packet, sizeof(llg_data->last_packet)); if (read_res != 64) { 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 - - const ssize_t in_message_pipe_write_res = write(in_messages_pipe_fd, (void*)¤t_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; - } + messages[msg_count++] = current_message; */ // successful return - return 0; + return msg_count; } static input_dev_t in_hidraw_dev = { diff --git a/main.c b/main.c index f01e3ce..d4eee0f 100644 --- a/main.c +++ b/main.c @@ -27,9 +27,6 @@ void sig_handler(int signo) 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; int main(int argc, char ** argv) { @@ -38,13 +35,6 @@ int main(int argc, char ** argv) { init_config(&settings); 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; 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); - 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 - dev_in_thread_data.timeout_ms = 400; - dev_in_thread_data.in_message_pipe_fd = in_message_pipes[1]; - dev_in_thread_data.out_message_pipe_fd = out_message_pipes[0]; - dev_in_thread_data.input_dev_decl = in_devs; + dev_in_data_t dev_in_thread_data = { + .timeout_ms = 1200, + .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; - 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) { fprintf(stderr, "Error creating dev_in thread: %d\n", dev_in_thread_creation); ret = -1; @@ -95,15 +76,6 @@ int main(int argc, char ** argv) { 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 __sighandler_t sigint_hndl = signal(SIGINT, sig_handler); @@ -118,9 +90,5 @@ main_err: 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; } diff --git a/rog_ally.c b/rog_ally.c index 18b45c8..0d261a7 100644 --- a/rog_ally.c +++ b/rog_ally.c @@ -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 (e->ev_count == 2) && (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*)¤t_message, sizeof(in_message_t)); - 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); - } + messages[written_msg++] = current_message; } else if ( // this is what happens at release of the right-screen button of the ROG Ally (e->ev_count == 2) && (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*)¤t_message, sizeof(in_message_t)); - 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); - } + messages[written_msg++] = current_message; } else if ( (e->ev_count == 2) && (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*)¤t_message, sizeof(in_message_t)); - 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); - } + messages[written_msg++] = current_message; } else if ( (e->ev_count == 2) && (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*)¤t_message, sizeof(in_message_t)); - 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); - } + messages[written_msg++] = current_message; } + + return written_msg; } static hidraw_filters_t n_key_hidraw_filters = { diff --git a/rogue_enemy.h b/rogue_enemy.h index e293267..abd4e83 100644 --- a/rogue_enemy.h +++ b/rogue_enemy.h @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include diff --git a/stray_ally.c b/stray_ally.c new file mode 100644 index 0000000..dbb0c0c --- /dev/null +++ b/stray_ally.c @@ -0,0 +1,132 @@ +#include +#include +#include + +#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; +} diff --git a/virt_ds4.c b/virt_ds4.c index d8cd663..b615aaa 100644 --- a/virt_ds4.c +++ b/virt_ds4.c @@ -402,7 +402,7 @@ int virt_dualshock_get_fd(virt_dualshock_t *const in_gamepad) { 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; 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]; if ((valid_flag0 & DS4_OUTPUT_VALID_FLAG0_LED)) { - const out_message_t msg = { - .type = OUT_MSG_TYPE_LEDS, - .data = { - .leds = { - .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; - } + out_device_status->leds_colors[0] = lightbar_red; + out_device_status->leds_colors[1] = lightbar_green; + out_device_status->leds_colors[2] = lightbar_blue; + out_device_status->leds_events_count++; } else if (valid_flag0 & DS4_OUTPUT_VALID_FLAG0_LED_BLINK) { - const out_message_t msg = { - .type = OUT_MSG_TYPE_LEDS, - .data = { - .leds = { - .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; - } + out_device_status->leds_colors[0] = lightbar_red; + out_device_status->leds_colors[1] = lightbar_green; + out_device_status->leds_colors[2] = lightbar_blue; + out_device_status->leds_events_count++; } if ((valid_flag0 & DS4_OUTPUT_VALID_FLAG0_MOTOR)) { out_device_status->motors_intensity[0] = motor_left; out_device_status->motors_intensity[1] = motor_right; - ++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; - } + out_device_status->rumble_events_count++; if (gamepad->debug) { printf( diff --git a/virt_ds4.h b/virt_ds4.h index b3eee9d..986e011 100644 --- a/virt_ds4.h +++ b/virt_ds4.h @@ -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_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); diff --git a/virt_ds5.c b/virt_ds5.c index 1c56168..3117d1d 100644 --- a/virt_ds5.c +++ b/virt_ds5.c @@ -142,7 +142,7 @@ int virt_dualsense_get_fd(virt_dualsense_t *const in_gamepad) { 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; 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->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) { printf( "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) { - const out_message_t msg = { - .type = OUT_MSG_TYPE_LEDS, - .data = { - .leds = { - .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; - } + out_device_status->leds_colors[0] = lightbar_red; + out_device_status->leds_colors[1] = lightbar_green; + out_device_status->leds_colors[2] = lightbar_blue; + out_device_status->leds_events_count++; } break; diff --git a/virt_ds5.h b/virt_ds5.h index 7108b8f..61a4c5d 100644 --- a/virt_ds5.h +++ b/virt_ds5.h @@ -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_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); diff --git a/xbox360.c b/xbox360.c index 4a60c9e..e140717 100644 --- a/xbox360.c +++ b/xbox360.c @@ -1,8 +1,9 @@ #include "xbox360.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; + int written_msg = 0; for (uint32_t i = 0; i < coll->ev_count; ++i) { 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; } - // send the button event over the pipe - if (write(in_messages_pipe_fd, (void*)¤t_message, sizeof(in_message_t)) != sizeof(in_message_t)) { - fprintf(stderr, "Unable to write gamepad data to the in_message pipe\n"); + if (written_msg == (messages_len-1)) { + return -ENOMEM; } + + messages[written_msg++] = current_message; } else if (coll->ev[i].type == EV_ABS) { in_message_t current_message = { .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; } - // send the button event over the pipe - if (write(in_messages_pipe_fd, (void*)¤t_message, sizeof(in_message_t)) != sizeof(in_message_t)) { - fprintf(stderr, "Unable to write gamepad data to the in_message pipe\n"); + if (written_msg == (messages_len-1)) { + return -ENOMEM; } + + messages[written_msg++] = current_message; } } } diff --git a/xbox360.h b/xbox360.h index cf71568..824c30f 100644 --- a/xbox360.h +++ b/xbox360.h @@ -6,4 +6,4 @@ typedef struct xbox360_settings { bool nintendo_layout; } 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);