Compare commits

...

4 commits

Author SHA1 Message Date
Denis
ea5f026e04
timer timeout to evdev 2023-12-17 17:37:58 +01:00
Denis
6eb6847444
using nanoseconds as such 2023-12-17 16:43:45 +01:00
Denis
71603dc4d6
WIP: timer implementation 2023-12-17 15:48:17 +01:00
Denis
466f1a4db6
improving devices support 2023-12-17 03:50:36 +01:00
8 changed files with 305 additions and 13 deletions

View file

@ -17,6 +17,7 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
add_executable(${ROGUE_EXECUTABLE_NAME}
dev_timer.c
dev_evdev.c
dev_iio.c
dev_hidraw.c
@ -49,6 +50,7 @@ add_executable(${ALLINONE_EXECUTABLE_NAME}
virt_mouse.c
virt_kbd.c
devices_status.c
dev_timer.c
dev_evdev.c
dev_iio.c
dev_hidraw.c

136
dev_in.c
View file

@ -5,6 +5,7 @@
#include "message.h"
#include "dev_evdev.h"
#include "dev_iio.h"
#include "dev_timer.h"
#include <libconfig.h>
@ -13,6 +14,7 @@ typedef enum dev_in_type {
DEV_IN_TYPE_HIDRAW,
DEV_IN_TYPE_IIO,
DEV_IN_TYPE_EV,
DEV_IN_TYPE_TIMER,
} dev_in_type_t;
typedef struct dev_in_iio {
@ -44,12 +46,29 @@ typedef struct dev_in_ev {
struct ff_effect ff_effect;
ev_callbacks_t callbacks;
void* user_data;
} dev_in_ev_t;
typedef struct dev_in_timer {
dev_timer_t* timer;
const char* name;
timer_callbacks_t callbacks;
void* user_data;
} dev_in_timer_t;
typedef union dev_in_aggr {
dev_in_ev_t evdev;
dev_in_iio_t iio;
dev_in_hidraw_t hidraw;
dev_in_timer_t timer;
} dev_in_aggr_t;
typedef struct dev_in {
@ -155,6 +174,23 @@ fill_message_from_evdev_err_completed:
return res;
}
static int timer_open_device(
const dev_in_settings_t *const in_settings,
const timer_filters_t *const in_filters,
dev_in_timer_t *const out_dev
) {
int res = dev_timer_open(in_filters, &out_dev->timer);
if (res != 0) {
fprintf(stderr, "Unable to open the timer device: %d\n", res);
goto timer_open_device_err;
}
printf("Opened timer device: %s\n", in_filters->name);
timer_open_device_err:
return res;
}
static int hidraw_open_device(
const dev_in_settings_t *const in_settings,
const hidraw_filters_t *const in_filters,
@ -270,6 +306,10 @@ static void hidraw_close_device(dev_in_hidraw_t *const out_hidraw) {
dev_hidraw_close(out_hidraw->hidrawdev);
}
static void timer_close_device(dev_in_timer_t *const out_hidraw) {
dev_timer_close(out_hidraw->timer);
}
static void handle_rumble_device(const dev_in_settings_t *const conf, dev_in_ev_t *const in_dev, const out_message_rumble_t *const in_rumble_msg) {
if (!in_dev->has_rumble_support) {
return;
@ -346,6 +386,25 @@ static void handle_leds(const dev_in_settings_t *const conf, dev_in_t *const in_
}
}
static void handle_timeout(
const dev_in_settings_t *const conf,
dev_in_t *const in_devs,
size_t in_devs_count,
const char* name,
uint64_t expirations
) {
for (size_t i = 0; i < in_devs_count; ++i) {
if (in_devs[i].type == DEV_IN_TYPE_EV) {
in_devs[i].dev.hidraw.callbacks.timeout_callback(
conf,
name,
expirations,
in_devs[i].dev.evdev.user_data
);
}
}
}
static int open_socket(struct sockaddr_un *serveraddr) {
int res = -ENODEV;
@ -440,8 +499,11 @@ void* dev_in_thread_func(void *ptr) {
&dev_in_data->input_dev_decl->dev[i]->filters.ev,
&devices[i].dev.evdev
);
if (open_res == 0) {
devices[i].type = DEV_IN_TYPE_EV;
devices[i].dev.evdev.user_data = dev_in_data->input_dev_decl->dev[i]->user_data;
devices[i].dev.evdev.callbacks = dev_in_data->input_dev_decl->dev[i]->map.ev_callbacks;
// device is now connected, query it in select
FD_SET(libevdev_get_fd(devices[i].dev.evdev.evdev), &read_fds);
@ -457,6 +519,9 @@ void* dev_in_thread_func(void *ptr) {
if (open_res == 0) {
devices[i].type = DEV_IN_TYPE_IIO;
// device is now connected, query it in select
FD_SET(dev_iio_get_buffer_fd(devices[i].dev.iio.iiodev), &read_fds);
}
} else if (d_type == input_dev_type_hidraw) {
fprintf(stderr, "Device (hidraw) %zu not found -- Attempt reconnection for device %x:%x\n", i, dev_in_data->input_dev_decl->dev[i]->filters.hidraw.pid, dev_in_data->input_dev_decl->dev[i]->filters.hidraw.vid);
@ -471,6 +536,27 @@ void* dev_in_thread_func(void *ptr) {
devices[i].dev.hidraw.callbacks = dev_in_data->input_dev_decl->dev[i]->map.hidraw_callbacks;
devices[i].dev.hidraw.user_data = dev_in_data->input_dev_decl->dev[i]->user_data;
devices[i].type = DEV_IN_TYPE_HIDRAW;
// device is now connected, query it in select
FD_SET(dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev), &read_fds);
}
} else if (d_type == input_dev_type_timer) {
fprintf(stderr, "Device (timer) %zu not found -- Attempt to create it with name %s\n", i, dev_in_data->input_dev_decl->dev[i]->filters.timer.name);
const int open_res = timer_open_device(
&dev_in_data->settings,
&dev_in_data->input_dev_decl->dev[i]->filters.timer,
&devices[i].dev.timer
);
if (open_res == 0) {
devices[i].dev.timer.callbacks = dev_in_data->input_dev_decl->dev[i]->map.timer_callbacks;
devices[i].dev.timer.user_data = dev_in_data->input_dev_decl->dev[i]->user_data;
devices[i].dev.timer.name = dev_in_data->input_dev_decl->dev[i]->filters.timer.name;
devices[i].type = DEV_IN_TYPE_TIMER;
// device is now connected, query it in select
FD_SET(dev_timer_get_fd(devices[i].dev.timer.timer), &read_fds);
}
}
}
@ -534,6 +620,8 @@ void* dev_in_thread_func(void *ptr) {
fd = dev_iio_get_buffer_fd(devices[i].dev.iio.iiodev);
} else if (devices[i].type == DEV_IN_TYPE_HIDRAW) {
fd = dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev);
} else if (devices[i].type == DEV_IN_TYPE_TIMER) {
fd = dev_timer_get_fd(devices[i].dev.timer.timer);
} else {
continue;
}
@ -560,12 +648,12 @@ void* dev_in_thread_func(void *ptr) {
continue;
}
controller_msg_count = dev_in_data->input_dev_decl->dev[i]->map.ev_input_map_fn(
controller_msg_count = devices[i].dev.evdev.callbacks.input_map_fn(
&dev_in_data->settings,
&coll,
&controller_msg[0],
controller_msg_avail,
dev_in_data->input_dev_decl->dev[i]->user_data
devices[i].dev.evdev.user_data
);
} else if (devices[i].type == DEV_IN_TYPE_IIO) {
controller_msg_count = map_message_from_iio(
@ -573,6 +661,7 @@ void* dev_in_thread_func(void *ptr) {
&controller_msg[0],
controller_msg_avail
);
if (controller_msg_count < 0) {
fprintf(stderr, "Error in reading iio buffer for device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count);
iio_close_device(&devices[i].dev.iio);
@ -580,19 +669,53 @@ void* dev_in_thread_func(void *ptr) {
continue;
}
} else if (devices[i].type == DEV_IN_TYPE_HIDRAW) {
controller_msg_count = dev_in_data->input_dev_decl->dev[i]->map.hidraw_callbacks.map_callback(
controller_msg_count = devices[i].dev.hidraw.callbacks.map_callback(
&dev_in_data->settings,
dev_hidraw_get_fd(devices[i].dev.hidraw.hidrawdev),
fd,
&controller_msg[0],
controller_msg_avail,
dev_in_data->input_dev_decl->dev[i]->user_data
devices[i].dev.hidraw.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;
}
} else if (devices[i].type == DEV_IN_TYPE_TIMER) {
uint64_t expirations;
ssize_t num_read = read(fd, &expirations, sizeof(uint64_t));
if (num_read != sizeof(uint64_t)) {
fprintf(stderr, "Error in reading expirations from timer device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count);
timer_close_device(&devices[i].dev.timer);
devices[i].type = DEV_IN_TYPE_NONE;
continue;
}
controller_msg_count = devices[i].dev.timer.callbacks.map_fn(
&dev_in_data->settings,
fd,
expirations,
&controller_msg[0],
controller_msg_avail,
devices[i].dev.timer.user_data
);
if (controller_msg_count < 0) {
fprintf(stderr, "Error in timer device %zd: %d -- Will reconnect to the device\n", i, controller_msg_count);
timer_close_device(&devices[i].dev.timer);
devices[i].type = DEV_IN_TYPE_NONE;
continue;
}
handle_timeout(
&dev_in_data->settings,
devices,
max_devices,
devices[i].dev.timer.name,
expirations
);
}
// send messages (if any)
@ -652,6 +775,9 @@ void* dev_in_thread_func(void *ptr) {
} else if (devices[i].type == DEV_IN_TYPE_HIDRAW) {
hidraw_close_device(&devices[i].dev.hidraw);
devices[i].type = DEV_IN_TYPE_NONE;
} else if (devices[i].type == DEV_IN_TYPE_TIMER) {
timer_close_device(&devices[i].dev.timer);
devices[i].type = DEV_IN_TYPE_NONE;
}
}

60
dev_timer.c Normal file
View file

@ -0,0 +1,60 @@
#include "dev_timer.h"
int dev_timer_open(
const timer_filters_t *const in_filters,
dev_timer_t **const out_dev
) {
int res = -ENODEV;
*out_dev = malloc(sizeof(dev_timer_t));
if (*out_dev == NULL) {
res = -ENOMEM;
goto dev_timer_open_err;
}
memset(*out_dev, 0, sizeof(dev_timer_t));
const int fd = timerfd_create(CLOCK_MONOTONIC, 0);
if (fd < 0) {
res = errno < 0 ? errno : -1 * errno;
if (res == 0) {
res = fd;
}
goto dev_timer_open_err;
}
(*out_dev)->fd = fd;
(*out_dev)->timer_spec.it_value.tv_sec = in_filters->ticktime_ms / (__time_t)1000;
(*out_dev)->timer_spec.it_value.tv_nsec = (in_filters->ticktime_ms % (__syscall_slong_t)1000) * (__syscall_slong_t)1000000;
(*out_dev)->timer_spec.it_interval.tv_sec = in_filters->ticktime_ms / (__time_t)1000;
(*out_dev)->timer_spec.it_interval.tv_nsec = (in_filters->ticktime_ms % (__syscall_slong_t)1000) * (__syscall_slong_t)1000000;
if (timerfd_settime((*out_dev)->fd, 0, &(*out_dev)->timer_spec, NULL) < 0) {
res = errno < 0 ? errno : -1 * errno;
if (res == 0) {
res = -EIO;
}
goto dev_timer_open_err;
}
res = 0;
dev_timer_open_err:
if (res != 0) {
if (fd > 0) {
close(fd);
}
free(*out_dev);
}
return res;
}
void dev_timer_close(dev_timer_t *const inout_dev) {
close(inout_dev->fd);
}
int dev_timer_get_fd(const dev_timer_t *const in_dev) {
return in_dev->fd;
}

18
dev_timer.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include "input_dev.h"
typedef struct dev_timer {
struct itimerspec timer_spec;
int fd;
} dev_timer_t;
int dev_timer_open(
const timer_filters_t *const in_filters,
dev_timer_t **const out_dev
);
void dev_timer_close(dev_timer_t *const inout_dev);
int dev_timer_get_fd(const dev_timer_t *const in_dev);

View file

@ -18,12 +18,25 @@ typedef struct evdev_collected {
* A function with this signature grapbs input_event data and sends to the pipe messages
* constructed from that data.
*/
typedef int (*ev_map)(const dev_in_settings_t *const conf, const evdev_collected_t *const e, in_message_t *const messages, size_t messages_len, void* user_data);
typedef int (*ev_map)(
const dev_in_settings_t *const conf,
const evdev_collected_t *const e,
in_message_t *const messages,
size_t messages_len,
void* user_data
);
typedef void (*ev_timer)(
const dev_in_settings_t *const conf,
const char* const timer_name,
uint64_t expired,
void* user_data
);
typedef enum input_dev_type {
input_dev_type_uinput,
input_dev_type_iio,
input_dev_type_hidraw,
input_dev_type_timer,
} input_dev_type_t;
typedef struct hidraw_filters {
@ -48,6 +61,7 @@ typedef struct hidraw_callbacks {
hidraw_set_leds leds_callback;
hidraw_rumble rumble_callback;
hidraw_map map_callback;
ev_timer timeout_callback;
} hidraw_callbacks_t;
typedef struct iio_settings {
@ -55,6 +69,22 @@ typedef struct iio_settings {
int8_t post_matrix[3][3];
} iio_settings_t;
typedef int (*timer_map)(const dev_in_settings_t *const conf, int timer_fd, uint64_t expirations, in_message_t *const messages, size_t messages_len, void* user_data);
typedef struct timer_callbacks {
timer_map map_fn;
} timer_callbacks_t;
typedef struct ev_callbacks {
ev_map input_map_fn;
ev_timer timeout_callback;
} ev_callbacks_t;
typedef struct timer_filters {
char name[128];
uint64_t ticktime_ms;
} timer_filters_t;
typedef struct input_dev {
input_dev_type_t dev_type;
@ -62,14 +92,16 @@ typedef struct input_dev {
uinput_filters_t ev;
iio_filters_t iio;
hidraw_filters_t hidraw;
timer_filters_t timer;
} filters;
void* user_data;
union input_dev_map {
iio_settings_t iio_settings;
ev_map ev_input_map_fn;
ev_callbacks_t ev_callbacks;
hidraw_callbacks_t hidraw_callbacks;
timer_callbacks_t timer_callbacks;
} map;
} input_dev_t;

View file

@ -11,7 +11,9 @@ static input_dev_t in_xbox_dev = {
}
},
.map = {
.ev_input_map_fn = xbox360_ev_map,
.ev_callbacks = {
.input_map_fn = xbox360_ev_map,
},
}
};

View file

@ -844,6 +844,15 @@ static input_dev_t in_iio_dev = {
//.input_filter_fn = input_filter_imu_identity,
};
static void rc71l_timer_asus_kbd(
const dev_in_settings_t *const conf,
const char* const timer_name,
uint64_t expired,
void* user_data
) {
}
static input_dev_t in_asus_kb_1_dev = {
.dev_type = input_dev_type_uinput,
.filters = {
@ -853,7 +862,10 @@ static input_dev_t in_asus_kb_1_dev = {
},
.user_data = (void*)&asus_userdata,
.map = {
.ev_input_map_fn = asus_kbd_ev_map,
.ev_callbacks = {
.input_map_fn = asus_kbd_ev_map,
.timeout_callback = rc71l_timer_asus_kbd,
},
}
};
@ -866,7 +878,10 @@ static input_dev_t in_asus_kb_2_dev = {
},
.user_data = (void*)&asus_userdata,
.map = {
.ev_input_map_fn = asus_kbd_ev_map,
.ev_callbacks = {
.input_map_fn = asus_kbd_ev_map,
.timeout_callback = rc71l_timer_asus_kbd,
},
}
};
@ -879,10 +894,22 @@ static input_dev_t in_asus_kb_3_dev = {
},
.user_data = &asus_userdata,
.map = {
.ev_input_map_fn = asus_kbd_ev_map,
.ev_callbacks = {
.input_map_fn = asus_kbd_ev_map,
.timeout_callback = rc71l_timer_asus_kbd,
},
}
};
static void rc71l_timer_xbox360(
const dev_in_settings_t *const conf,
const char* const timer_name,
uint64_t expired,
void* user_data
) {
}
static input_dev_t in_xbox_dev = {
.dev_type = input_dev_type_uinput,
.filters = {
@ -891,7 +918,10 @@ static input_dev_t in_xbox_dev = {
}
},
.map = {
.ev_input_map_fn = xbox360_ev_map,
.ev_callbacks = {
.input_map_fn = xbox360_ev_map,
.timeout_callback = rc71l_timer_xbox360,
},
}
};
@ -989,6 +1019,26 @@ static int rc71l_platform_leds(const dev_in_settings_t *const conf, uint8_t r, u
return 0;
}
int rc71l_timer_map(const dev_in_settings_t *const conf, int timer_fd, uint64_t expirations, in_message_t *const messages, size_t messages_len, void* user_data) {
return 0;
}
input_dev_t timer_dev = {
.dev_type = input_dev_type_timer,
.filters = {
.timer = {
.name = "RC71L_timer",
.ticktime_ms = 150,
}
},
.user_data = NULL,
.map = {
.timer_callbacks = {
.map_fn = rc71l_timer_map,
}
}
};
input_dev_composite_t rc71l_composite = {
.dev = {
&in_xbox_dev,
@ -997,8 +1047,9 @@ input_dev_composite_t rc71l_composite = {
&in_asus_kb_2_dev,
&in_asus_kb_3_dev,
&nkey_dev,
&timer_dev,
},
.dev_count = 6,
.dev_count = 7,
.init_fn = rc71l_platform_init,
.deinit_fn = rc71l_platform_deinit,
.leds_fn = rc71l_platform_leds,

View file

@ -28,6 +28,7 @@
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/signalfd.h>
#include <sys/timerfd.h>
#include <sys/un.h>
#include <linux/hidraw.h>