diff --git a/Makefile b/Makefile index c34b32e..80ae2f4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CFLAGS=-g -std=c11 -pedantic # -Wall -Werror LDFLAGS=-lpthread CC=gcc -OBJECTS=main.o gamepad_output.o imu_output.o +OBJECTS=main.o gamepad_output.o imu_output.o input_dev.o output_dev.o TARGET=rogue_enemy all: $(TARGET) diff --git a/imu_output.c b/imu_output.c index fc46725..06d0ae8 100644 --- a/imu_output.c +++ b/imu_output.c @@ -6,6 +6,11 @@ void *imu_thread_func(void *ptr) { output_dev_t *out_dev = (output_dev_t*)ptr; + /*timeval now = {0}; + gettimeofday(&now, NULL); + secAtInit = now.tv_sec; + usecAtInit = now.tv_usec;*/ + for (;;) { pthread_mutex_lock(&out_dev->ctrl_mutex); diff --git a/input_dev.c b/input_dev.c new file mode 100644 index 0000000..582f42e --- /dev/null +++ b/input_dev.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "input_dev.h" + +int open_and_hide_input() { + int fd = -1; + char buf[256]; + + fd = open("/dev/input/event3", O_RDONLY); + if (fd == -1) { + perror("open_port: Unable to open /dev/ttyAMA0 - "); + return(-1); + } + + // Turn off blocking for reads, use (fd, F_SETFL, FNDELAY) if you want that + //fcntl(fd, F_SETFL, 0); + + while(1){ + int n = read(fd, (void*)buf, 255); + if (n < 0) { + perror("Read failed - "); + return -1; + } else if (n == 0) { + printf("No data on port\n"); + } else { + buf[n] = '\0'; + printf("%i bytes read : %s", n, buf); + } + sleep(1); + printf("i'm still doing something"); + } + close(fd); + return fd; +} \ No newline at end of file diff --git a/input_dev.h b/input_dev.h index 2cbf659..a3d8148 100644 --- a/input_dev.h +++ b/input_dev.h @@ -1,12 +1,12 @@ #pragma once -#include -#include +#include "rogue_enemy.h" #define INPUT_DEV_CTRL_FLAG_EXIT 0x00000001U -#define INPUT_DEV_CTRL_FLAG_DATA 0x00000002U typedef struct input_dev { pthread_mutex_t ctrl_mutex; uint32_t crtl_flags; -} input_dev_t; \ No newline at end of file +} input_dev_t; + +int open_and_hide_input(); \ No newline at end of file diff --git a/main.c b/main.c index b76ed2c..31681bb 100644 --- a/main.c +++ b/main.c @@ -1,11 +1,4 @@ -#include #include -#include -#include -#include -#include -#include -#include #include "imu_output.h" #include "gamepad_output.h" @@ -22,27 +15,42 @@ output_dev_t gamepadd_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) { if (signo == SIGINT) { - 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); - + request_termination(); printf("received SIGINT\n"); } } int main(int argc, char ** argv) { - + imu_dev.fd = create_imu("/dev/uinput", "Virtual IMU - ROGueENEMY"); + if (imu_dev.fd < 0) { + fprintf(stderr, "Unable to create IMU virtual device\n"); + return EXIT_FAILURE; + } + + gamepadd_dev.fd = create_gamepad("/dev/uinput", "Virtual Controller - ROGueENEMY"); + if (gamepadd_dev.fd < 0) { + close(imu_dev.fd); + fprintf(stderr, "Unable to create gamepad virtual device\n"); + return EXIT_FAILURE; + } + __sighandler_t sigint_hndl = signal(SIGINT, sig_handler); if (sigint_hndl == SIG_ERR) { - fprintf(stderr, "Error registering SIGINT handler"); - return -1; + fprintf(stderr, "Error registering SIGINT handler\n"); + return EXIT_FAILURE; } int ret = 0; @@ -51,15 +59,17 @@ int main(int argc, char ** argv) { int imu_thread_creation = pthread_create(&imu_thread, NULL, imu_thread_func, (void*)(&imu_dev)); if (imu_thread_creation != 0) { - fprintf(stderr, "Error creating IMU output thread: %d", imu_thread_creation); + fprintf(stderr, "Error creating IMU output thread: %d\n", imu_thread_creation); ret = -1; + request_termination(); goto imu_thread_err; } int gamepad_thread_creation = pthread_create(&gamepad_thread, NULL, gamepad_thread_func, (void*)(&gamepadd_dev)); if (gamepad_thread_creation != 0) { - fprintf(stderr, "Error creating gamepad output thread: %d", gamepad_thread_creation); + fprintf(stderr, "Error creating gamepad output thread: %d\n", gamepad_thread_creation); ret = -1; + request_termination(); goto gamepad_thread_err; } @@ -69,34 +79,5 @@ gamepad_thread_err: pthread_join(imu_thread, NULL); imu_thread_err: - return ret; - - int fd; - char buf[256]; - - fd = open("/dev/input/event3", O_RDONLY); - if (fd == -1) { - perror("open_port: Unable to open /dev/ttyAMA0 - "); - return(-1); - } - - // Turn off blocking for reads, use (fd, F_SETFL, FNDELAY) if you want that - //fcntl(fd, F_SETFL, 0); - - while(1){ - int n = read(fd, (void*)buf, 255); - if (n < 0) { - perror("Read failed - "); - return -1; - } else if (n == 0) { - printf("No data on port\n"); - } else { - buf[n] = '\0'; - printf("%i bytes read : %s", n, buf); - } - sleep(1); - printf("i'm still doing something"); - } - close(fd); - return 0; + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } \ No newline at end of file diff --git a/output_dev.c b/output_dev.c new file mode 100644 index 0000000..c4d2867 --- /dev/null +++ b/output_dev.c @@ -0,0 +1,139 @@ +#include "output_dev.h" + +int create_imu(const char* uinput_path, const char* name) { + int fd = open(uinput_path, O_WRONLY | O_NONBLOCK); + if(fd < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + struct uinput_setup dev = {0}; + if (strlen(name) < UINPUT_MAX_NAME_SIZE) { + strcpy(dev.name, name); + } else { + strncpy(dev.name, name, UINPUT_MAX_NAME_SIZE-1); + } + + dev.id.bustype = BUS_VIRTUAL; + dev.id.vendor = OUTPUT_DEV_VENDOR_ID; + dev.id.product = OUTPUT_DEV_PRODUCT_ID; + + ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_ACCELEROMETER); + ioctl(fd, UI_SET_EVBIT, EV_ABS); + //ioctl(fd, UI_SET_EVBIT, EV_KEY); + ioctl(fd, UI_SET_EVBIT, EV_MSC); + ioctl(fd, UI_SET_MSCBIT, MSC_TIMESTAMP); + + ioctl(fd, UI_SET_ABSBIT, ABS_X); + ioctl(fd, UI_SET_ABSBIT, ABS_Y); + ioctl(fd, UI_SET_ABSBIT, ABS_Z); + ioctl(fd, UI_SET_ABSBIT, ABS_RX); + ioctl(fd, UI_SET_ABSBIT, ABS_RY); + ioctl(fd, UI_SET_ABSBIT, ABS_RZ); + + //ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER); + //ioctl(fd, UI_SET_KEYBIT, BTN_THUMB); + + struct uinput_abs_setup devAbsX = {0}; + devAbsX.code = ABS_X; + devAbsX.absinfo.minimum = -ACCEL_RANGE; + devAbsX.absinfo.maximum = ACCEL_RANGE; + devAbsX.absinfo.resolution = 255; // 255 units = 1g + devAbsX.absinfo.fuzz = 5; + devAbsX.absinfo.flat = 0; + if(ioctl(fd, UI_ABS_SETUP, &devAbsX) < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + struct uinput_abs_setup devAbsY = {0}; + devAbsY.code = ABS_Y; + devAbsY.absinfo.minimum = -ACCEL_RANGE; + devAbsY.absinfo.maximum = ACCEL_RANGE; + devAbsY.absinfo.resolution = 255; // 255 units = 1g + devAbsY.absinfo.fuzz = 5; + devAbsY.absinfo.flat = 0; + if(ioctl(fd, UI_ABS_SETUP, &devAbsY) < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + struct uinput_abs_setup devAbsZ = {0}; + devAbsZ.code = ABS_Z; + devAbsZ.absinfo.minimum = -ACCEL_RANGE; + devAbsZ.absinfo.maximum = ACCEL_RANGE; + devAbsZ.absinfo.resolution = 255; // 255 units = 1g + devAbsZ.absinfo.fuzz = 5; + devAbsZ.absinfo.flat = 0; + if(ioctl(fd, UI_ABS_SETUP, &devAbsZ) < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + struct uinput_abs_setup devAbsRX = {0}; + devAbsRX.code = ABS_RX; + devAbsRX.absinfo.minimum = -GYRO_RANGE; + devAbsRX.absinfo.maximum = GYRO_RANGE; + devAbsRX.absinfo.resolution = 1; // 1 unit = 1 degree/s + devAbsRX.absinfo.fuzz = 0; + devAbsRX.absinfo.flat = GYRO_DEADZONE; + if(ioctl(fd, UI_ABS_SETUP, &devAbsRX) < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + struct uinput_abs_setup devAbsRY = {0}; + devAbsRY.code = ABS_RY; + devAbsRY.absinfo.minimum = -GYRO_RANGE; + devAbsRY.absinfo.maximum = GYRO_RANGE; + devAbsRY.absinfo.resolution = 1; // 1 unit = 1 degree/s + devAbsRY.absinfo.fuzz = 0; + devAbsRY.absinfo.flat = GYRO_DEADZONE; + if(ioctl(fd, UI_ABS_SETUP, &devAbsRY) < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + struct uinput_abs_setup devAbsRZ = {0}; + devAbsRZ.code = ABS_RZ; + devAbsRZ.absinfo.minimum = -GYRO_RANGE; + devAbsRZ.absinfo.maximum = GYRO_RANGE; + devAbsRZ.absinfo.resolution = 1; // 1 unit = 1 degree/s + devAbsRZ.absinfo.fuzz = 0; + devAbsRZ.absinfo.flat = GYRO_DEADZONE; + if(ioctl(fd, UI_ABS_SETUP, &devAbsRZ) < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + if(ioctl(fd, UI_DEV_SETUP, &dev) < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + if(ioctl(fd, UI_DEV_CREATE) < 0) { + fd = -1; + close(fd); + goto create_imu_err; + } + + int64_t secAtInit = 0; + int64_t usecAtInit = 0; + +create_imu_err: + return fd; +} + +int create_gamepad(const char* uinput_path, const char* name) { + +create_gamepad_err: + return -1; +} \ No newline at end of file diff --git a/output_dev.h b/output_dev.h index 80d8a3a..78e1305 100644 --- a/output_dev.h +++ b/output_dev.h @@ -1,14 +1,28 @@ #pragma once -#include -#include +#include "rogue_enemy.h" + +#define OUTPUT_DEV_VENDOR_ID 0x4532 +#define OUTPUT_DEV_PRODUCT_ID 0x0924 #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 + +#define GYRO_DEADZONE 1 // degrees/s to count as zero movement + typedef struct output_dev { int fd; pthread_mutex_t ctrl_mutex; uint32_t crtl_flags; -} output_dev_t; \ No newline at end of file + + uint32_t max_events; + uint32_t events_count; + struct input_event events_list; +} output_dev_t; + +int create_imu(const char* uinput_path, const char* name); +int create_gamepad(const char* uinput_path, const char* name); \ No newline at end of file diff --git a/rogue_enemy.h b/rogue_enemy.h new file mode 100644 index 0000000..25dcd0b --- /dev/null +++ b/rogue_enemy.h @@ -0,0 +1,15 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include \ No newline at end of file