WIP: input device

This commit is contained in:
Denis Benato 2023-11-02 16:12:02 +01:00
parent 75abf3c6e8
commit d6aee2c63d
9 changed files with 151 additions and 58 deletions

View file

@ -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)

View file

@ -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;
}
}

View file

@ -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();

60
main.c
View file

@ -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;
}
}

View file

@ -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;

View file

@ -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);

67
queue.c Normal file
View file

@ -0,0 +1,67 @@
#include "queue.h"
#include <stdlib.h>
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;
}

21
queue.h Normal file
View file

@ -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);

View file

@ -1,14 +1,17 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdatomic.h>
#include <inttypes.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <linux/uinput.h>
#include <linux/input.h>