From d6aee2c63d4a798ae97e93d048df5752cc72a292 Mon Sep 17 00:00:00 2001 From: Denis Benato Date: Thu, 2 Nov 2023 16:12:02 +0100 Subject: [PATCH] WIP: input device --- Makefile | 4 +-- input_dev.c | 17 ++++++++++++- input_dev.h | 5 ++-- main.c | 60 +++++++++++++++++++++++---------------------- output_dev.c | 20 +++------------ output_dev.h | 8 +++--- queue.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ queue.h | 21 ++++++++++++++++ rogue_enemy.h | 7 ++++-- 9 files changed, 151 insertions(+), 58 deletions(-) create mode 100644 queue.c create mode 100644 queue.h diff --git a/Makefile b/Makefile index 05c0c7c..8c9130d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -CFLAGS=-g -std=c11 -pedantic -Wall # -Werror +CFLAGS=-g -O0 -std=c11 -fPIE -pedantic -Wall # -Werror LDFLAGS=-lpthread CC=gcc -OBJECTS=main.o input_dev.o output_dev.o +OBJECTS=main.o input_dev.o output_dev.o queue.o TARGET=rogue_enemy all: $(TARGET) diff --git a/input_dev.c b/input_dev.c index 582f42e..5bdbe02 100644 --- a/input_dev.c +++ b/input_dev.c @@ -9,6 +9,21 @@ #include "input_dev.h" +void *input_dev_thread_func(void *ptr) { + input_dev_t *out_dev = (input_dev_t*)ptr; + + for (;;) { + uint32_t flags = out_dev->crtl_flags; + if (flags & INPUT_DEV_CTRL_FLAG_EXIT) { + out_dev->crtl_flags &= ~INPUT_DEV_CTRL_FLAG_EXIT; + break; + } + } + + return NULL; +} + + int open_and_hide_input() { int fd = -1; char buf[256]; @@ -38,4 +53,4 @@ int open_and_hide_input() { } close(fd); return fd; -} \ No newline at end of file +} diff --git a/input_dev.h b/input_dev.h index a3d8148..b506edf 100644 --- a/input_dev.h +++ b/input_dev.h @@ -5,8 +5,9 @@ #define INPUT_DEV_CTRL_FLAG_EXIT 0x00000001U typedef struct input_dev { - pthread_mutex_t ctrl_mutex; - uint32_t crtl_flags; + volatile uint32_t crtl_flags; } input_dev_t; +void *input_dev_thread_func(void *ptr); + int open_and_hide_input(); \ No newline at end of file diff --git a/main.c b/main.c index c7a59ae..b974d3e 100644 --- a/main.c +++ b/main.c @@ -3,30 +3,44 @@ #include "input_dev.h" #include "output_dev.h" +ev_queue_t imu_ev; +ev_queue_t gamepad_ev; + output_dev_t imu_dev = { .fd = -1, - .ctrl_mutex = PTHREAD_MUTEX_INITIALIZER, .crtl_flags = 0x00000000U, - .max_events = 32, - .events_list = NULL, + .queue = &imu_ev, }; output_dev_t gamepadd_dev = { .fd = -1, - .ctrl_mutex = PTHREAD_MUTEX_INITIALIZER, .crtl_flags = 0x00000000U, - .max_events = 32, - .events_list = NULL, + .queue = &gamepad_ev, +}; + +input_dev_t in_asus_kb_1_dev = { + .crtl_flags = 0x00000000U, +}; + +input_dev_t in_asus_kb_2_dev = { + .crtl_flags = 0x00000000U, +}; + +input_dev_t in_asus_kb_3_dev = { + .crtl_flags = 0x00000000U, +}; + +input_dev_t in_asus_kb_4_dev = { + .crtl_flags = 0x00000000U, +}; + +input_dev_t in_xbox_dev = { + .crtl_flags = 0x00000000U, }; void request_termination() { - pthread_mutex_lock(&imu_dev.ctrl_mutex); imu_dev.crtl_flags |= OUTPUT_DEV_CTRL_FLAG_EXIT; - pthread_mutex_unlock(&imu_dev.ctrl_mutex); - - pthread_mutex_lock(&gamepadd_dev.ctrl_mutex); gamepadd_dev.crtl_flags |= OUTPUT_DEV_CTRL_FLAG_EXIT; - pthread_mutex_unlock(&gamepadd_dev.ctrl_mutex); } void sig_handler(int signo) @@ -38,23 +52,11 @@ void sig_handler(int signo) } int main(int argc, char ** argv) { - imu_dev.events_list = calloc(sizeof(struct input_event), imu_dev.max_events); - if (imu_dev.events_list == NULL) { - fprintf(stderr, "Unable to allocate events list for IMU output\n"); - return EXIT_FAILURE; - } - - imu_dev.events_list = calloc(sizeof(struct input_event), imu_dev.max_events); - if (gamepadd_dev.events_list == NULL) { - free(imu_dev.events_list); - fprintf(stderr, "Unable to allocate events list for gamepad output\n"); - return EXIT_FAILURE; - } - + imu_dev.fd = create_output_dev("/dev/uinput", "Virtual IMU - ROGueENEMY", output_dev_imu); if (imu_dev.fd < 0) { - free(imu_dev.events_list); - free(gamepadd_dev.events_list); + // TODO: free(imu_dev.events_list); + // TODO: free(gamepadd_dev.events_list); fprintf(stderr, "Unable to create IMU virtual device\n"); return EXIT_FAILURE; } @@ -104,8 +106,8 @@ imu_thread_err: if (!(imu_dev.fd < 0)) close(imu_dev.fd); - free(imu_dev.events_list); - free(gamepadd_dev.events_list); + // TODO: free(imu_dev.events_list); + // TODO: free(gamepadd_dev.events_list); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -} \ No newline at end of file +} diff --git a/output_dev.c b/output_dev.c index f459de8..dd5870d 100644 --- a/output_dev.c +++ b/output_dev.c @@ -150,25 +150,11 @@ void *output_dev_thread_func(void *ptr) { output_dev_t *out_dev = (output_dev_t*)ptr; for (;;) { - pthread_mutex_lock(&out_dev->ctrl_mutex); - - if (out_dev->crtl_flags & OUTPUT_DEV_CTRL_FLAG_EXIT) { - pthread_mutex_unlock(&out_dev->ctrl_mutex); + uint32_t flags = out_dev->crtl_flags; + if (flags & OUTPUT_DEV_CTRL_FLAG_EXIT) { + out_dev->crtl_flags &= ~OUTPUT_DEV_CTRL_FLAG_EXIT; break; - } else if (out_dev->crtl_flags & OUTPUT_DEV_CTRL_FLAG_DATA) { - const uint32_t events_count = out_dev->events_count; - for (uint32_t i = 0; i < events_count; ++i) { - // send the event - write(out_dev->fd, (const void*)&out_dev->events_list[i], sizeof(struct input_event)); - - out_dev->events_count -= 1; - } - - // clear out the data present flag - out_dev->crtl_flags &= ~OUTPUT_DEV_CTRL_FLAG_DATA; } - - pthread_mutex_unlock(&out_dev->ctrl_mutex); } return NULL; diff --git a/output_dev.h b/output_dev.h index 01da2f6..e116215 100644 --- a/output_dev.h +++ b/output_dev.h @@ -1,6 +1,7 @@ #pragma once #include "rogue_enemy.h" +#include "queue.h" #define OUTPUT_DEV_VENDOR_ID 0x4532 #define OUTPUT_DEV_PRODUCT_ID 0x0924 @@ -21,12 +22,9 @@ typedef enum output_dev_type { typedef struct output_dev { int fd; - pthread_mutex_t ctrl_mutex; - uint32_t crtl_flags; + volatile uint32_t crtl_flags; - uint32_t max_events; - uint32_t events_count; - struct input_event *events_list; + ev_queue_t *queue; } output_dev_t; int create_output_dev(const char* uinput_path, const char* name, output_dev_type_t type); diff --git a/queue.c b/queue.c new file mode 100644 index 0000000..b1ee40a --- /dev/null +++ b/queue.c @@ -0,0 +1,67 @@ +#include "queue.h" +#include + +int queue_init(ev_queue_t* queue, key_t sem_key, size_t max_elements) { + queue->array_size = max_elements; + queue->array = calloc(sizeof(void*), max_elements); + if (queue->array == NULL) { + perror("calloc"); + return -1; + } + + int semid = semget(sem_key, 1, IPC_CREAT | 0666); + if (semid < 0) + { + free(queue->array); + perror("semget"); + return 1; + } + + if (semctl(semid, 0, SETVAL, 1) < 0) + { + free(queue->array); + perror("semctl"); + return 1; + } + + return 0; +} + +void queue_destroy(ev_queue_t* queue) { + free(queue->array); + queue->array = NULL; +} + +int queue_push(ev_queue_t* queue, void *in_item) { + struct sembuf sem_op; + sem_op.sem_num = 0; + sem_op.sem_op = -1; + sem_op.sem_flg = 0; + semop(queue->sem_id, &sem_op, 1); + + queue->array[queue->in] = in_item; + queue->in = (queue->in + 1) % queue->array_size; + + sem_op.sem_num = 0; + sem_op.sem_op = 1; + semop(queue->sem_id, &sem_op, 1); + + return 0; +} + +int queue_pop(ev_queue_t* queue, void **out_item) { + struct sembuf sem_op; + sem_op.sem_num = 0; + sem_op.sem_op = -1; + sem_op.sem_flg = 0; + semop(queue->sem_id, &sem_op, 1); + + *out_item = queue->array[queue->out]; + queue->out = (queue->out + 1) % queue->array_size; + + sem_op.sem_num = 0; + sem_op.sem_op = 1; + semop(queue->sem_id, &sem_op, 1); + + return 0; +} diff --git a/queue.h b/queue.h new file mode 100644 index 0000000..b5a1ee5 --- /dev/null +++ b/queue.h @@ -0,0 +1,21 @@ +#pragma once + +#include "rogue_enemy.h" + +typedef struct ev_queue { + int sem_id; + + size_t in; + size_t out; + + size_t array_size; + void** array; +} ev_queue_t; + +int queue_init(ev_queue_t* queue, key_t sem_key, size_t max_elements); + +void queue_destroy(ev_queue_t* queue); + +int queue_push(ev_queue_t* queue, void *in_item); + +int queue_pop(ev_queue_t* queue, void **out_item); \ No newline at end of file diff --git a/rogue_enemy.h b/rogue_enemy.h index 50dc525..dfaad8f 100644 --- a/rogue_enemy.h +++ b/rogue_enemy.h @@ -1,14 +1,17 @@ #include #include #include +#include #include #include #include #include -#include #include #include -#include +#include +#include +#include +#include #include #include