threading rework to support rumble
This commit is contained in:
parent
0ca1c08158
commit
9f2e1e9de5
7 changed files with 91 additions and 60 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#include "input_dev.h"
|
||||
#include "logic.h"
|
||||
#include "message.h"
|
||||
#include "queue.h"
|
||||
#include "dev_iio.h"
|
||||
|
|
@ -326,9 +327,7 @@ static void input_iio(
|
|||
int open_sysfs_idx = -1;
|
||||
|
||||
for (;;) {
|
||||
const uint32_t flags = in_dev->crtl_flags;
|
||||
if (flags & INPUT_DEV_CTRL_FLAG_EXIT) {
|
||||
in_dev->crtl_flags &= ~INPUT_DEV_CTRL_FLAG_EXIT;
|
||||
if (logic_termination_requested(in_dev->logic)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -435,9 +434,7 @@ static void input_udev(
|
|||
int open_sysfs_idx = -1;
|
||||
|
||||
for (;;) {
|
||||
const uint32_t flags = in_dev->crtl_flags;
|
||||
if (flags & INPUT_DEV_CTRL_FLAG_EXIT) {
|
||||
in_dev->crtl_flags &= ~INPUT_DEV_CTRL_FLAG_EXIT;
|
||||
if (logic_termination_requested(in_dev->logic)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
#undef INCLUDE_INPUT_DEBUG
|
||||
#undef IGNORE_INPUT_SCAN
|
||||
|
||||
#define INPUT_DEV_CTRL_FLAG_EXIT 0x00000001U
|
||||
|
||||
typedef uint32_t (*ev_input_filter_t)(struct input_event*, size_t*, uint32_t*, uint32_t*);
|
||||
|
||||
typedef enum input_dev_type {
|
||||
|
|
@ -30,8 +28,6 @@ typedef struct input_dev {
|
|||
const uinput_filters_t* ev_filters;
|
||||
const iio_filters_t* iio_filters;
|
||||
|
||||
volatile uint32_t crtl_flags;
|
||||
|
||||
ev_input_filter_t ev_input_filter_fn;
|
||||
|
||||
logic_t *logic;
|
||||
|
|
|
|||
8
logic.c
8
logic.c
|
|
@ -131,3 +131,11 @@ logic_begin_status_update_err:
|
|||
void logic_end_status_update(logic_t *const logic) {
|
||||
pthread_mutex_unlock(&logic->gamepad_mutex);
|
||||
}
|
||||
|
||||
void logic_request_termination(logic_t *const logic) {
|
||||
logic->flags |= LOGIC_FLAGS_TERMINATION_REQUESTED;
|
||||
}
|
||||
|
||||
int logic_termination_requested(logic_t *const logic) {
|
||||
return (logic->flags & LOGIC_FLAGS_TERMINATION_REQUESTED) != 0;
|
||||
}
|
||||
11
logic.h
11
logic.h
|
|
@ -46,8 +46,9 @@ typedef struct gamepad_status {
|
|||
|
||||
} gamepad_status_t;
|
||||
|
||||
#define LOGIC_FLAGS_VIRT_DS4_ENABLE 0x00000001U
|
||||
#define LOGIC_FLAGS_PLATFORM_ENABLE 0x00000002U
|
||||
#define LOGIC_FLAGS_VIRT_DS4_ENABLE 0x00000001U
|
||||
#define LOGIC_FLAGS_PLATFORM_ENABLE 0x00000002U
|
||||
#define LOGIC_FLAGS_TERMINATION_REQUESTED 0x80000000U
|
||||
|
||||
typedef enum gamepad_output {
|
||||
GAMEPAD_OUTPUT_EVDEV = 0,
|
||||
|
|
@ -71,7 +72,7 @@ typedef struct logic {
|
|||
|
||||
pthread_t virt_ds4_thread;
|
||||
|
||||
uint32_t flags;
|
||||
volatile uint32_t flags;
|
||||
|
||||
// the mutex is not needed if only one thread is writing this and others are checking with equality
|
||||
//pthread_mutex_t gamepad_output_mutex;
|
||||
|
|
@ -92,3 +93,7 @@ int logic_copy_gamepad_status(logic_t *const logic, gamepad_status_t *const out)
|
|||
int logic_begin_status_update(logic_t *const logic);
|
||||
|
||||
void logic_end_status_update(logic_t *const logic);
|
||||
|
||||
void logic_request_termination(logic_t *const logic);
|
||||
|
||||
int logic_termination_requested(logic_t *const logic);
|
||||
29
main.c
29
main.c
|
|
@ -10,7 +10,6 @@ logic_t global_logic;
|
|||
static output_dev_t out_gamepadd_dev = {
|
||||
.gamepad_fd = -1,
|
||||
.imu_fd = -1,
|
||||
.crtl_flags = 0x00000000U,
|
||||
.logic = &global_logic,
|
||||
};
|
||||
|
||||
|
|
@ -20,7 +19,6 @@ static iio_filters_t in_iio_filters = {
|
|||
|
||||
static input_dev_t in_iio_dev = {
|
||||
.dev_type = input_dev_type_iio,
|
||||
.crtl_flags = 0x00000000U,
|
||||
.iio_filters = &in_iio_filters,
|
||||
.logic = &global_logic,
|
||||
//.input_filter_fn = input_filter_imu_identity,
|
||||
|
|
@ -32,7 +30,6 @@ static uinput_filters_t in_asus_kb_1_filters = {
|
|||
|
||||
static input_dev_t in_asus_kb_1_dev = {
|
||||
.dev_type = input_dev_type_uinput,
|
||||
.crtl_flags = 0x00000000U,
|
||||
.ev_filters = &in_asus_kb_1_filters,
|
||||
.logic = &global_logic,
|
||||
.ev_input_filter_fn = input_filter_asus_kb,
|
||||
|
|
@ -44,7 +41,6 @@ static uinput_filters_t in_asus_kb_2_filters = {
|
|||
|
||||
static input_dev_t in_asus_kb_2_dev = {
|
||||
.dev_type = input_dev_type_uinput,
|
||||
.crtl_flags = 0x00000000U,
|
||||
.ev_filters = &in_asus_kb_2_filters,
|
||||
.logic = &global_logic,
|
||||
.ev_input_filter_fn = input_filter_asus_kb,
|
||||
|
|
@ -56,7 +52,6 @@ static uinput_filters_t in_asus_kb_3_filters = {
|
|||
|
||||
static input_dev_t in_asus_kb_3_dev = {
|
||||
.dev_type = input_dev_type_uinput,
|
||||
.crtl_flags = 0x00000000U,
|
||||
.ev_filters = &in_asus_kb_3_filters,
|
||||
.logic = &global_logic,
|
||||
.ev_input_filter_fn = input_filter_asus_kb,
|
||||
|
|
@ -68,25 +63,15 @@ static uinput_filters_t in_xbox_filters = {
|
|||
|
||||
static input_dev_t in_xbox_dev = {
|
||||
.dev_type = input_dev_type_uinput,
|
||||
.crtl_flags = 0x00000000U,
|
||||
.ev_filters = &in_xbox_filters,
|
||||
.logic = &global_logic,
|
||||
.ev_input_filter_fn = input_filter_identity,
|
||||
};
|
||||
|
||||
void request_termination(void) {
|
||||
out_gamepadd_dev.crtl_flags |= OUTPUT_DEV_CTRL_FLAG_EXIT;
|
||||
|
||||
in_xbox_dev.crtl_flags |= INPUT_DEV_CTRL_FLAG_EXIT;
|
||||
in_asus_kb_3_dev.crtl_flags |= INPUT_DEV_CTRL_FLAG_EXIT;
|
||||
in_asus_kb_2_dev.crtl_flags |= INPUT_DEV_CTRL_FLAG_EXIT;
|
||||
in_asus_kb_1_dev.crtl_flags |= INPUT_DEV_CTRL_FLAG_EXIT;
|
||||
}
|
||||
|
||||
void sig_handler(int signo)
|
||||
{
|
||||
if (signo == SIGINT) {
|
||||
request_termination();
|
||||
logic_request_termination(&global_logic);
|
||||
printf("received SIGINT\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -140,7 +125,7 @@ int main(int argc, char ** argv) {
|
|||
if (gamepad_thread_creation != 0) {
|
||||
fprintf(stderr, "Error creating gamepad output thread: %d\n", gamepad_thread_creation);
|
||||
ret = -1;
|
||||
request_termination();
|
||||
logic_request_termination(&global_logic);
|
||||
goto gamepad_thread_err;
|
||||
}
|
||||
|
||||
|
|
@ -148,7 +133,7 @@ int main(int argc, char ** argv) {
|
|||
if (xbox_thread_creation != 0) {
|
||||
fprintf(stderr, "Error creating xbox input thread: %d\n", xbox_thread_creation);
|
||||
ret = -1;
|
||||
request_termination();
|
||||
logic_request_termination(&global_logic);
|
||||
goto xbox_drv_thread_err;
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +141,7 @@ int main(int argc, char ** argv) {
|
|||
if (asus_kb_1_thread_creation != 0) {
|
||||
fprintf(stderr, "Error creating asus keyboard (1) input thread: %d\n", asus_kb_1_thread_creation);
|
||||
ret = -1;
|
||||
request_termination();
|
||||
logic_request_termination(&global_logic);
|
||||
goto asus_kb_1_thread_err;
|
||||
}
|
||||
|
||||
|
|
@ -164,7 +149,7 @@ int main(int argc, char ** argv) {
|
|||
if (asus_kb_2_thread_creation != 0) {
|
||||
fprintf(stderr, "Error creating asus keyboard (2) input thread: %d\n", asus_kb_2_thread_creation);
|
||||
ret = -1;
|
||||
request_termination();
|
||||
logic_request_termination(&global_logic);
|
||||
goto asus_kb_2_thread_err;
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +157,7 @@ int main(int argc, char ** argv) {
|
|||
if (asus_kb_3_thread_creation != 0) {
|
||||
fprintf(stderr, "Error creating asus keyboard (3) input thread: %d\n", asus_kb_3_thread_creation);
|
||||
ret = -1;
|
||||
request_termination();
|
||||
logic_request_termination(&global_logic);
|
||||
goto asus_kb_3_thread_err;
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +165,7 @@ int main(int argc, char ** argv) {
|
|||
if (iio_thread_creation != 0) {
|
||||
fprintf(stderr, "Error creating iio input thread: %d\n", asus_kb_3_thread_creation);
|
||||
ret = -1;
|
||||
request_termination();
|
||||
logic_request_termination(&global_logic);
|
||||
goto iio_thread_err;
|
||||
}
|
||||
|
||||
|
|
|
|||
85
output_dev.c
85
output_dev.c
|
|
@ -806,7 +806,7 @@ static void handle_msg(output_dev_t *const out_dev, message_t *const msg) {
|
|||
}
|
||||
}
|
||||
|
||||
void *output_dev_thread_func(void *ptr) {
|
||||
void *output_dev_rumble_thread_func(void* ptr) {
|
||||
output_dev_t *const out_dev = (output_dev_t*)ptr;
|
||||
|
||||
struct timeval now = {0};
|
||||
|
|
@ -820,6 +820,67 @@ void *output_dev_thread_func(void *ptr) {
|
|||
pthread_mutex_lock(&out_dev->logic->gamepad_mutex);
|
||||
uint64_t rumble_events_count = out_dev->logic->gamepad.rumble_events_count;
|
||||
pthread_mutex_unlock(&out_dev->logic->gamepad_mutex);
|
||||
|
||||
// maximum number of ms that the gamepad can remain in a blocked status
|
||||
const int timeout_ms = 10;
|
||||
|
||||
for (;;) {
|
||||
// sleep for about 4ms: this is an aggressive polling for rumble.
|
||||
usleep(4000);
|
||||
|
||||
// here transmit the rumble request to the input-device-handling components
|
||||
pthread_mutex_lock(&out_dev->logic->gamepad_mutex);
|
||||
|
||||
// check if the gamepad has notified the presence of a rumble event
|
||||
if (out_dev->logic->gamepad.rumble_events_count != rumble_events_count) {
|
||||
|
||||
struct timespec timeout;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &timeout) == 0) {
|
||||
timeout.tv_sec += timeout_ms / 1000;
|
||||
timeout.tv_nsec += (timeout_ms % 1000) * 1000000;
|
||||
|
||||
int result = sem_timedwait(&out_dev->logic->rumble.sem_empty, &timeout);
|
||||
|
||||
if (result == 0) {
|
||||
// translate the rumble to evdev
|
||||
out_dev->logic->rumble.value = out_dev->logic->gamepad.motors_intensity[0] * 255;
|
||||
|
||||
// wake up the input thread that will propagate the rumble to raw devices.
|
||||
sem_post(&out_dev->logic->rumble.sem_full);
|
||||
|
||||
// update the rumble events counter: this rumble event was handled
|
||||
rumble_events_count = out_dev->logic->gamepad.rumble_events_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&out_dev->logic->gamepad_mutex);
|
||||
|
||||
if (logic_termination_requested(out_dev->logic)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *output_dev_thread_func(void *ptr) {
|
||||
output_dev_t *const out_dev = (output_dev_t*)ptr;
|
||||
|
||||
struct timeval now = {0};
|
||||
|
||||
#if defined(INCLUDE_TIMESTAMP)
|
||||
gettimeofday(&now, NULL);
|
||||
__time_t secAtInit = now.tv_sec;
|
||||
__time_t usecAtInit = now.tv_usec;
|
||||
#endif
|
||||
|
||||
pthread_t rumble_thread;
|
||||
const int rumble_thread_creation = pthread_create(&rumble_thread, NULL, output_dev_rumble_thread_func, ptr);
|
||||
if (rumble_thread_creation != 0) {
|
||||
fprintf(stderr, "Error creating the rumble thread: %d -- rumble will not work.\n", rumble_thread_creation);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
void *raw_ev;
|
||||
const int pop_res = queue_pop_timeout(&out_dev->logic->input_queue, &raw_ev, 1000);
|
||||
|
|
@ -835,29 +896,13 @@ void *output_dev_thread_func(void *ptr) {
|
|||
fprintf(stderr, "Cannot read from input queue: %d\n", pop_res);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
// here transmit the rumble request to the input-device-handling components
|
||||
pthread_mutex_lock(&out_dev->logic->gamepad_mutex);
|
||||
|
||||
// check if the gamepad has notified the presence of a rumble event
|
||||
if (out_dev->logic->gamepad.rumble_events_count != rumble_events_count) {
|
||||
sem_wait(&out_dev->logic->rumble.sem_empty);
|
||||
|
||||
// translate the rumble to evdev
|
||||
out_dev->logic->rumble.value = out_dev->logic->gamepad.motors_intensity[0];
|
||||
|
||||
sem_post(&out_dev->logic->rumble.sem_full);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&out_dev->logic->gamepad_mutex);
|
||||
|
||||
const uint32_t flags = out_dev->crtl_flags;
|
||||
if (flags & OUTPUT_DEV_CTRL_FLAG_EXIT) {
|
||||
out_dev->crtl_flags &= ~OUTPUT_DEV_CTRL_FLAG_EXIT;
|
||||
if (logic_termination_requested(out_dev->logic)) {
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
pthread_join(rumble_thread, NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@
|
|||
|
||||
#define PHYS_STR "00:11:22:33:44:55"
|
||||
|
||||
#define OUTPUT_DEV_CTRL_FLAG_EXIT 0x00000001U
|
||||
#define OUTPUT_DEV_CTRL_FLAG_DATA 0x00000002U
|
||||
|
||||
#define ACCEL_RANGE 512
|
||||
#define GYRO_RANGE 2000 // max range is +/- 35 radian/s
|
||||
|
||||
|
|
@ -59,8 +56,6 @@ typedef struct output_dev {
|
|||
int imu_fd;
|
||||
int mouse_fd;
|
||||
|
||||
volatile uint32_t crtl_flags;
|
||||
|
||||
logic_t *logic;
|
||||
} output_dev_t;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue