Create IMU virtual device
This commit is contained in:
parent
2d40a35a48
commit
ecea75cf5f
8 changed files with 253 additions and 58 deletions
2
Makefile
2
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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
41
input_dev.c
Normal file
41
input_dev.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#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;
|
||||
|
||||
int open_and_hide_input();
|
||||
69
main.c
69
main.c
|
|
@ -1,11 +1,4 @@
|
|||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "imu_output.h"
|
||||
#include "gamepad_output.h"
|
||||
|
|
@ -22,9 +15,7 @@ output_dev_t gamepadd_dev = {
|
|||
.crtl_flags = 0x00000000U,
|
||||
};
|
||||
|
||||
void sig_handler(int signo)
|
||||
{
|
||||
if (signo == SIGINT) {
|
||||
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);
|
||||
|
|
@ -32,17 +23,34 @@ void sig_handler(int signo)
|
|||
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) {
|
||||
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;
|
||||
}
|
||||
139
output_dev.c
Normal file
139
output_dev.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
18
output_dev.h
18
output_dev.h
|
|
@ -1,14 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#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;
|
||||
|
||||
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);
|
||||
15
rogue_enemy.h
Normal file
15
rogue_enemy.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <linux/uinput.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <pthread.h>
|
||||
Loading…
Add table
Add a link
Reference in a new issue