WIP: input device
This commit is contained in:
parent
75abf3c6e8
commit
d6aee2c63d
9 changed files with 151 additions and 58 deletions
4
Makefile
4
Makefile
|
|
@ -1,7 +1,7 @@
|
||||||
CFLAGS=-g -std=c11 -pedantic -Wall # -Werror
|
CFLAGS=-g -O0 -std=c11 -fPIE -pedantic -Wall # -Werror
|
||||||
LDFLAGS=-lpthread
|
LDFLAGS=-lpthread
|
||||||
CC=gcc
|
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
|
TARGET=rogue_enemy
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
|
||||||
15
input_dev.c
15
input_dev.c
|
|
@ -9,6 +9,21 @@
|
||||||
|
|
||||||
#include "input_dev.h"
|
#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 open_and_hide_input() {
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@
|
||||||
#define INPUT_DEV_CTRL_FLAG_EXIT 0x00000001U
|
#define INPUT_DEV_CTRL_FLAG_EXIT 0x00000001U
|
||||||
|
|
||||||
typedef struct input_dev {
|
typedef struct input_dev {
|
||||||
pthread_mutex_t ctrl_mutex;
|
volatile uint32_t crtl_flags;
|
||||||
uint32_t crtl_flags;
|
|
||||||
} input_dev_t;
|
} input_dev_t;
|
||||||
|
|
||||||
|
void *input_dev_thread_func(void *ptr);
|
||||||
|
|
||||||
int open_and_hide_input();
|
int open_and_hide_input();
|
||||||
56
main.c
56
main.c
|
|
@ -3,30 +3,44 @@
|
||||||
#include "input_dev.h"
|
#include "input_dev.h"
|
||||||
#include "output_dev.h"
|
#include "output_dev.h"
|
||||||
|
|
||||||
|
ev_queue_t imu_ev;
|
||||||
|
ev_queue_t gamepad_ev;
|
||||||
|
|
||||||
output_dev_t imu_dev = {
|
output_dev_t imu_dev = {
|
||||||
.fd = -1,
|
.fd = -1,
|
||||||
.ctrl_mutex = PTHREAD_MUTEX_INITIALIZER,
|
|
||||||
.crtl_flags = 0x00000000U,
|
.crtl_flags = 0x00000000U,
|
||||||
.max_events = 32,
|
.queue = &imu_ev,
|
||||||
.events_list = NULL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
output_dev_t gamepadd_dev = {
|
output_dev_t gamepadd_dev = {
|
||||||
.fd = -1,
|
.fd = -1,
|
||||||
.ctrl_mutex = PTHREAD_MUTEX_INITIALIZER,
|
|
||||||
.crtl_flags = 0x00000000U,
|
.crtl_flags = 0x00000000U,
|
||||||
.max_events = 32,
|
.queue = &gamepad_ev,
|
||||||
.events_list = NULL,
|
};
|
||||||
|
|
||||||
|
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() {
|
void request_termination() {
|
||||||
pthread_mutex_lock(&imu_dev.ctrl_mutex);
|
|
||||||
imu_dev.crtl_flags |= OUTPUT_DEV_CTRL_FLAG_EXIT;
|
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;
|
gamepadd_dev.crtl_flags |= OUTPUT_DEV_CTRL_FLAG_EXIT;
|
||||||
pthread_mutex_unlock(&gamepadd_dev.ctrl_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sig_handler(int signo)
|
void sig_handler(int signo)
|
||||||
|
|
@ -38,23 +52,11 @@ void sig_handler(int signo)
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
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);
|
imu_dev.fd = create_output_dev("/dev/uinput", "Virtual IMU - ROGueENEMY", output_dev_imu);
|
||||||
if (imu_dev.fd < 0) {
|
if (imu_dev.fd < 0) {
|
||||||
free(imu_dev.events_list);
|
// TODO: free(imu_dev.events_list);
|
||||||
free(gamepadd_dev.events_list);
|
// TODO: free(gamepadd_dev.events_list);
|
||||||
fprintf(stderr, "Unable to create IMU virtual device\n");
|
fprintf(stderr, "Unable to create IMU virtual device\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
@ -104,8 +106,8 @@ imu_thread_err:
|
||||||
if (!(imu_dev.fd < 0))
|
if (!(imu_dev.fd < 0))
|
||||||
close(imu_dev.fd);
|
close(imu_dev.fd);
|
||||||
|
|
||||||
free(imu_dev.events_list);
|
// TODO: free(imu_dev.events_list);
|
||||||
free(gamepadd_dev.events_list);
|
// TODO: free(gamepadd_dev.events_list);
|
||||||
|
|
||||||
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
20
output_dev.c
20
output_dev.c
|
|
@ -150,25 +150,11 @@ void *output_dev_thread_func(void *ptr) {
|
||||||
output_dev_t *out_dev = (output_dev_t*)ptr;
|
output_dev_t *out_dev = (output_dev_t*)ptr;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
pthread_mutex_lock(&out_dev->ctrl_mutex);
|
uint32_t flags = out_dev->crtl_flags;
|
||||||
|
if (flags & OUTPUT_DEV_CTRL_FLAG_EXIT) {
|
||||||
if (out_dev->crtl_flags & OUTPUT_DEV_CTRL_FLAG_EXIT) {
|
out_dev->crtl_flags &= ~OUTPUT_DEV_CTRL_FLAG_EXIT;
|
||||||
pthread_mutex_unlock(&out_dev->ctrl_mutex);
|
|
||||||
break;
|
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;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "rogue_enemy.h"
|
#include "rogue_enemy.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
#define OUTPUT_DEV_VENDOR_ID 0x4532
|
#define OUTPUT_DEV_VENDOR_ID 0x4532
|
||||||
#define OUTPUT_DEV_PRODUCT_ID 0x0924
|
#define OUTPUT_DEV_PRODUCT_ID 0x0924
|
||||||
|
|
@ -21,12 +22,9 @@ typedef enum output_dev_type {
|
||||||
typedef struct output_dev {
|
typedef struct output_dev {
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
pthread_mutex_t ctrl_mutex;
|
volatile uint32_t crtl_flags;
|
||||||
uint32_t crtl_flags;
|
|
||||||
|
|
||||||
uint32_t max_events;
|
ev_queue_t *queue;
|
||||||
uint32_t events_count;
|
|
||||||
struct input_event *events_list;
|
|
||||||
} output_dev_t;
|
} output_dev_t;
|
||||||
|
|
||||||
int create_output_dev(const char* uinput_path, const char* name, output_dev_type_t type);
|
int create_output_dev(const char* uinput_path, const char* name, output_dev_type_t type);
|
||||||
|
|
|
||||||
67
queue.c
Normal file
67
queue.c
Normal 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
21
queue.h
Normal 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);
|
||||||
|
|
@ -1,14 +1,17 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.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/uinput.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue