diff --git a/input_dev.c b/input_dev.c index 214d0bd..c5a536f 100644 --- a/input_dev.c +++ b/input_dev.c @@ -146,6 +146,7 @@ struct input_ctx { struct libevdev* dev; dev_iio_t *iio_dev; queue_t* queue; + queue_t* rumble_queue; uint32_t flags; message_t messages[MAX_MESSAGES_IN_FLIGHT]; ev_input_filter_t input_filter_fn; @@ -560,28 +561,25 @@ static void input_udev( if (effect_upload_res == 0) { const int timeout_ms = 500; - struct timespec timeout; - if (clock_gettime(CLOCK_MONOTONIC, &timeout) == 0) { - timeout.tv_sec += timeout_ms / 1000; - timeout.tv_nsec += (timeout_ms % 1000) * 1000000; + void* rmsg = NULL; - const int rumble_sem_wait_result = sem_timedwait(&in_dev->logic->rumble.sem_full, &timeout); - - if (rumble_sem_wait_result == 0) { - // here read properties - struct input_event rumble_upload = { - .type = EV_FF, - .code = effect.id, - .value = in_dev->logic->rumble.value, - }; + const int rumble_msg_recv_res = queue_pop_timeout(ctx->rumble_queue, &rmsg, timeout_ms); + if (rumble_msg_recv_res == 0) { + rumble_message_t *const rumble_msg = (rumble_message_t*)rmsg; - printf("Rumble upload: %d\n", rumble_upload.value); + // here read properties + struct input_event rumble_upload = { + .type = EV_FF, + .code = effect.id, + .value = rumble_msg->value, + }; - sem_post(&in_dev->logic->rumble.sem_empty); - } - + free(rumble_msg); + + printf("Rumble upload: %d\n", rumble_upload.value); } + } } @@ -604,6 +602,7 @@ void *input_dev_thread_func(void *ptr) { struct input_ctx ctx = { .dev = NULL, .queue = &in_dev->logic->input_queue, + .rumble_queue = &in_dev->logic->rumble_events_queue, .input_filter_fn = in_dev->ev_input_filter_fn, .flags = 0x00000000U }; diff --git a/logic.c b/logic.c index fc9c684..601b4a9 100644 --- a/logic.c +++ b/logic.c @@ -1,5 +1,6 @@ #include "logic.h" #include "platform.h" +#include "queue.h" #include "virt_ds4.h" #include @@ -64,10 +65,7 @@ int logic_create(logic_t *const logic) { fprintf(stderr, "Unable to initialize Asus RC71L MCU: %d\n", init_platform_res); } - logic->rumble.value = 0; - sem_init(&logic->rumble.sem_empty, 0, 1); - sem_init(&logic->rumble.sem_full, 0, 0); - + queue_init(&logic->rumble_events_queue, 1); return 0; } diff --git a/logic.h b/logic.h index a1d8d79..f7ceb5d 100644 --- a/logic.h +++ b/logic.h @@ -55,11 +55,9 @@ typedef enum gamepad_output { GAMEPAD_OUTPUT_DS4, } gamepad_output_t; -typedef struct rumble { - sem_t sem_full, sem_empty; - +typedef struct rumble_message { int32_t value; -} rumble_t; +} rumble_message_t; typedef struct logic { @@ -80,7 +78,7 @@ typedef struct logic { gamepad_output_t restore_to; - rumble_t rumble; + queue_t rumble_events_queue; } logic_t; diff --git a/output_dev.c b/output_dev.c index 27757c8..8fa3f6f 100644 --- a/output_dev.c +++ b/output_dev.c @@ -830,31 +830,33 @@ void *output_dev_rumble_thread_func(void* ptr) { // here transmit the rumble request to the input-device-handling components pthread_mutex_lock(&out_dev->logic->gamepad_mutex); - + uint64_t tmp_ev_count = out_dev->logic->gamepad.rumble_events_count; + uint8_t right_motor = out_dev->logic->gamepad.motors_intensity[0]; + uint8_t left_motor = out_dev->logic->gamepad.motors_intensity[1]; + pthread_mutex_unlock(&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; + if (tmp_ev_count != rumble_events_count) { + rumble_message_t *const rumble_msg = malloc(sizeof(rumble_message_t)); + if(rumble_msg != NULL) { + rumble_msg->value = right_motor * 220; - const int result = sem_timedwait(&out_dev->logic->rumble.sem_empty, &timeout); + const int rumble_emit_res = queue_push_timeout(&out_dev->logic->rumble_events_queue, (void*)rumble_msg, timeout_ms); - 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); + if (rumble_emit_res == 0) { + printf("Rumble request propagated\n"); // update the rumble events counter: this rumble event was handled - rumble_events_count = out_dev->logic->gamepad.rumble_events_count; + rumble_events_count = tmp_ev_count; + } else { + fprintf(stderr, "Error propating the rumble event: %d\n", rumble_emit_res); } + } else { + fprintf(stderr, "Error allocating resources to request a rumble\n"); } } - pthread_mutex_unlock(&out_dev->logic->gamepad_mutex); + if (logic_termination_requested(out_dev->logic)) { break;