solved warning and cleaned up code
This commit is contained in:
parent
213f24c65f
commit
44326dc69c
15 changed files with 40 additions and 1206 deletions
|
|
@ -25,8 +25,6 @@ add_executable(${EXECUTABLE_NAME}
|
||||||
settings.c
|
settings.c
|
||||||
virt_ds4.c
|
virt_ds4.c
|
||||||
virt_ds5.c
|
virt_ds5.c
|
||||||
virt_mouse_kbd.c
|
|
||||||
virt_evdev.c
|
|
||||||
devices_status.c
|
devices_status.c
|
||||||
rog_ally.c
|
rog_ally.c
|
||||||
legion_go.c
|
legion_go.c
|
||||||
|
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
||||||
CFLAGS= -std=c17 -O3 -march=znver4 -D _DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112L -std=c11 -fPIE -pedantic -Wall -flto=full # -Werror
|
CFLAGS= -std=c17 -O3 -march=znver4 -D _DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112L -std=c11 -fPIE -pedantic -Wall -flto=full # -Werror
|
||||||
LDFLAGS=-lpthread -levdev -ludev -lconfig -lrt -lm -flto=full
|
LDFLAGS=-lpthread -levdev -ludev -lconfig -lrt -lm -flto=full
|
||||||
CC=clang
|
CC=clang
|
||||||
OBJECTS=main.o dev_in.o dev_out.o dev_iio.o dev_evdev.o dev_hidraw.o settings.o virt_ds4.o virt_ds5.o virt_mouse_kbd.o virt_evdev.o devices_status.o xbox360.o rog_ally.o legion_go.o rogue_enemy.o
|
OBJECTS=main.o dev_in.o dev_out.o dev_iio.o dev_evdev.o dev_hidraw.o settings.o virt_ds4.o virt_ds5.o devices_status.o xbox360.o rog_ally.o legion_go.o rogue_enemy.o
|
||||||
TARGET=rogue-enemy
|
TARGET=rogue-enemy
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,6 @@ int dev_hidraw_open(
|
||||||
closedir(d);
|
closedir(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_hidraw_open_err:
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
246
dev_iio.c
246
dev_iio.c
|
|
@ -143,21 +143,12 @@ static int dev_iio_create(int fd, const char* path, dev_iio_t **const out_iio) {
|
||||||
|
|
||||||
// ========================================== in_anglvel_scale ==============================================
|
// ========================================== in_anglvel_scale ==============================================
|
||||||
{
|
{
|
||||||
const char* preferred_scale = LSB_PER_RAD_S_2000_DEG_S_STR;
|
|
||||||
const char *scale_main_file = "/in_anglvel_scale";
|
const char *scale_main_file = "/in_anglvel_scale";
|
||||||
|
|
||||||
char* const anglvel_scale = read_file((*out_iio)->path, scale_main_file);
|
char* const anglvel_scale = read_file((*out_iio)->path, scale_main_file);
|
||||||
if (anglvel_scale != NULL) {
|
if (anglvel_scale != NULL) {
|
||||||
(*out_iio)->flags |= DEV_IIO_HAS_ANGLVEL;
|
(*out_iio)->flags |= DEV_IIO_HAS_ANGLVEL;
|
||||||
(*out_iio)->anglvel_scale_x = (*out_iio)->anglvel_scale_y = (*out_iio)->anglvel_scale_z = strtod(anglvel_scale, NULL);
|
(*out_iio)->anglvel_scale_x = (*out_iio)->anglvel_scale_y = (*out_iio)->anglvel_scale_z = strtod(anglvel_scale, NULL);
|
||||||
free((void*)anglvel_scale);
|
free((void*)anglvel_scale);
|
||||||
|
|
||||||
if (write_file((*out_iio)->path, scale_main_file, preferred_scale, strlen(preferred_scale)) >= 0) {
|
|
||||||
(*out_iio)->anglvel_scale_x = (*out_iio)->anglvel_scale_y = (*out_iio)->anglvel_scale_z = LSB_PER_RAD_S_2000_DEG_S;
|
|
||||||
printf("anglvel scale changed to %f for device %s\n", (*out_iio)->anglvel_scale_x, (*out_iio)->name);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Unable to set preferred in_anglvel_scale for device %s.\n", (*out_iio)->name);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: what about if those are split in in_anglvel_{x,y,z}_scale?
|
// TODO: what about if those are split in in_anglvel_{x,y,z}_scale?
|
||||||
fprintf(stderr, "Unable to read in_anglvel_scale from path %s%s.\n", (*out_iio)->path, scale_main_file);
|
fprintf(stderr, "Unable to read in_anglvel_scale from path %s%s.\n", (*out_iio)->path, scale_main_file);
|
||||||
|
|
@ -171,21 +162,12 @@ static int dev_iio_create(int fd, const char* path, dev_iio_t **const out_iio) {
|
||||||
|
|
||||||
// =========================================== in_accel_scale ===============================================
|
// =========================================== in_accel_scale ===============================================
|
||||||
{
|
{
|
||||||
const char* preferred_scale = LSB_PER_16G_STR;
|
|
||||||
const char *scale_main_file = "/in_accel_scale";
|
const char *scale_main_file = "/in_accel_scale";
|
||||||
|
|
||||||
char* const accel_scale = read_file((*out_iio)->path, scale_main_file);
|
char* const accel_scale = read_file((*out_iio)->path, scale_main_file);
|
||||||
if (accel_scale != NULL) {
|
if (accel_scale != NULL) {
|
||||||
(*out_iio)->flags |= DEV_IIO_HAS_ACCEL;
|
(*out_iio)->flags |= DEV_IIO_HAS_ACCEL;
|
||||||
(*out_iio)->accel_scale_x = (*out_iio)->accel_scale_y = (*out_iio)->accel_scale_z = strtod(accel_scale, NULL);
|
(*out_iio)->accel_scale_x = (*out_iio)->accel_scale_y = (*out_iio)->accel_scale_z = strtod(accel_scale, NULL);
|
||||||
free((void*)accel_scale);
|
free((void*)accel_scale);
|
||||||
|
|
||||||
if (write_file((*out_iio)->path, scale_main_file, preferred_scale, strlen(preferred_scale)) >= 0) {
|
|
||||||
(*out_iio)->accel_scale_x = (*out_iio)->accel_scale_y = (*out_iio)->accel_scale_z = LSB_PER_16G;
|
|
||||||
printf("accel scale changed to %f for device %s\n", (*out_iio)->accel_scale_x, (*out_iio)->name);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Unable to set preferred in_accel_scale for device %s.\n", (*out_iio)->name);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: what about if those are plit in in_accel_{x,y,z}_scale?
|
// TODO: what about if those are plit in in_accel_{x,y,z}_scale?
|
||||||
fprintf(stderr, "Unable to read in_accel_scale file from path %s%s.\n", (*out_iio)->path, scale_main_file);
|
fprintf(stderr, "Unable to read in_accel_scale file from path %s%s.\n", (*out_iio)->path, scale_main_file);
|
||||||
|
|
@ -221,45 +203,27 @@ dev_iio_create_err:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_iio_change_anglvel_sampling_freq(const dev_iio_t *const iio, uint16_t freq_hz, uint16_t freq_hz_frac) {
|
int dev_iio_change_anglvel_sampling_freq(const dev_iio_t *const iio, const char *const freq_str_hz) {
|
||||||
int res = -EINVAL;
|
int res = -EINVAL;
|
||||||
if (!dev_iio_has_anglvel(iio)) {
|
if (!dev_iio_has_anglvel(iio)) {
|
||||||
res = -ENOENT;
|
res = -ENOENT;
|
||||||
goto dev_iio_change_anglvel_sampling_freq_err;
|
goto dev_iio_change_anglvel_sampling_freq_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
char freq_str[16] = {};
|
res = write_file(iio->path, "/in_anglvel_sampling_frequency", freq_str_hz, strlen(freq_str_hz));
|
||||||
snprintf(freq_str, sizeof(freq_str), "%u.%u", (unsigned)freq_hz, (unsigned)freq_hz_frac);
|
|
||||||
|
|
||||||
const char* const preferred_samplig_freq = " 1600.000000";
|
|
||||||
const size_t preferred_samplig_freq_len = strlen(preferred_samplig_freq);
|
|
||||||
|
|
||||||
if (write_file(iio->path, "/in_accel_sampling_frequency", preferred_samplig_freq, preferred_samplig_freq_len) >= 0) {
|
|
||||||
printf("Accel sampling frequency changed to %s\n", preferred_samplig_freq);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Could not change accel sampling frequency\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
res = write_file(iio->path, "/in_anglvel_sampling_frequency", preferred_samplig_freq, preferred_samplig_freq_len);
|
|
||||||
|
|
||||||
dev_iio_change_anglvel_sampling_freq_err:
|
dev_iio_change_anglvel_sampling_freq_err:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_iio_change_accel_sampling_freq(const dev_iio_t *const iio, uint16_t freq_hz, uint16_t freq_hz_frac) {
|
int dev_iio_change_accel_sampling_freq(const dev_iio_t *const iio, const char *const freq_str_hz) {
|
||||||
int res = -EINVAL;
|
int res = -EINVAL;
|
||||||
if (!dev_iio_has_anglvel(iio)) {
|
if (!dev_iio_has_anglvel(iio)) {
|
||||||
res = -ENOENT;
|
res = -ENOENT;
|
||||||
goto dev_iio_change_accel_sampling_freq_err;
|
goto dev_iio_change_accel_sampling_freq_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
char freq_str[16] = {};
|
res = write_file(iio->path, "/in_accel_sampling_frequency", freq_str_hz, strlen(freq_str_hz));
|
||||||
snprintf(freq_str, sizeof(freq_str), "%u.%u", (unsigned)freq_hz, (unsigned)freq_hz_frac);
|
|
||||||
|
|
||||||
const char* const preferred_samplig_freq = " 1600.000000";
|
|
||||||
const size_t preferred_samplig_freq_len = strlen(preferred_samplig_freq);
|
|
||||||
|
|
||||||
res = write_file(iio->path, "/in_accel_sampling_frequency", preferred_samplig_freq, preferred_samplig_freq_len);
|
|
||||||
|
|
||||||
dev_iio_change_accel_sampling_freq_err:
|
dev_iio_change_accel_sampling_freq_err:
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -301,6 +265,16 @@ static bool iio_matches(
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
// Load the kernel module
|
||||||
|
int result = syscall(__NR_finit_module, -1, "iio-trig-hrtimer", 0);
|
||||||
|
if (result == 0) {
|
||||||
|
printf("Kernel module '%s' loaded successfully.\n", "iio-trig-hrtimer");
|
||||||
|
} else {
|
||||||
|
perror("Error loading kernel module");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
modprobe industrialio-sw-trigger
|
modprobe industrialio-sw-trigger
|
||||||
modprobe iio-trig-sysfs
|
modprobe iio-trig-sysfs
|
||||||
modprobe iio-trig-hrtimer
|
modprobe iio-trig-hrtimer
|
||||||
|
|
@ -328,7 +302,7 @@ mount -t configfs none /home/config
|
||||||
mkdir /home/config
|
mkdir /home/config
|
||||||
mkdir /home/config/iio/triggers/hrtimer/rogue
|
mkdir /home/config/iio/triggers/hrtimer/rogue
|
||||||
*/
|
*/
|
||||||
static const char *const iio_hrtrigger_name = "iio-trig-hrtimer";
|
//static const char *const iio_hrtrigger_name = "iio-trig-hrtimer";
|
||||||
|
|
||||||
static const char *const iio_path = "/sys/bus/iio/devices/";
|
static const char *const iio_path = "/sys/bus/iio/devices/";
|
||||||
|
|
||||||
|
|
@ -377,197 +351,9 @@ int dev_iio_open(
|
||||||
closedir(d);
|
closedir(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Load the kernel module
|
|
||||||
int result = syscall(__NR_finit_module, -1, iio_hrtrigger_name, 0);
|
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
printf("Kernel module '%s' loaded successfully.\n", iio_hrtrigger_name);
|
|
||||||
} else {
|
|
||||||
perror("Error loading kernel module");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
dev_iio_open_err:
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void multiplyMatrixVector(const double matrix[3][3], const double vector[3], double result[3]) {
|
|
||||||
result[0] = matrix[0][0] * vector[0] + matrix[1][0] * vector[1] + matrix[2][0] * vector[2];
|
|
||||||
result[1] = matrix[0][1] * vector[0] + matrix[1][1] * vector[1] + matrix[2][1] * vector[2];
|
|
||||||
result[2] = matrix[0][2] * vector[0] + matrix[1][2] * vector[1] + matrix[2][2] * vector[2];
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
int dev_iio_read_imu(const dev_iio_t *const iio, imu_in_message_t *const out) {
|
|
||||||
struct timeval read_time;
|
|
||||||
gettimeofday(&read_time, NULL);
|
|
||||||
|
|
||||||
out->flags = 0x00000000U;
|
|
||||||
|
|
||||||
char tmp[128];
|
|
||||||
|
|
||||||
double gyro_in[3];
|
|
||||||
double accel_in[3];
|
|
||||||
|
|
||||||
double gyro_out[3];
|
|
||||||
double accel_out[3];
|
|
||||||
|
|
||||||
if (iio->accel_x_fd != NULL) {
|
|
||||||
rewind(iio->accel_x_fd);
|
|
||||||
memset((void*)&tmp[0], 0, sizeof(tmp));
|
|
||||||
const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->accel_x_fd);
|
|
||||||
if (tmp_read >= 0) {
|
|
||||||
out->accel_x_raw = strtol(&tmp[0], NULL, 10);
|
|
||||||
accel_in[0] = (double)out->accel_x_raw * iio->accel_scale_x;
|
|
||||||
if ((out->flags & IMU_MESSAGE_FLAGS_ACCEL) == 0) {
|
|
||||||
out->accel_read_time = read_time;
|
|
||||||
out->flags |= IMU_MESSAGE_FLAGS_ACCEL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "While reading accel(x): %d\n", tmp_read);
|
|
||||||
return tmp_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iio->accel_y_fd != NULL) {
|
|
||||||
rewind(iio->accel_y_fd);
|
|
||||||
memset((void*)&tmp[0], 0, sizeof(tmp));
|
|
||||||
const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->accel_y_fd);
|
|
||||||
if (tmp_read >= 0) {
|
|
||||||
out->accel_y_raw = strtol(&tmp[0], NULL, 10);
|
|
||||||
accel_in[1] = (double)out->accel_y_raw * iio->accel_scale_y;
|
|
||||||
if ((out->flags & IMU_MESSAGE_FLAGS_ACCEL) == 0) {
|
|
||||||
out->accel_read_time = read_time;
|
|
||||||
out->flags |= IMU_MESSAGE_FLAGS_ACCEL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "While reading accel(y): %d\n", tmp_read);
|
|
||||||
return tmp_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iio->accel_z_fd != NULL) {
|
|
||||||
rewind(iio->accel_z_fd);
|
|
||||||
memset((void*)&tmp[0], 0, sizeof(tmp));
|
|
||||||
const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->accel_z_fd);
|
|
||||||
if (tmp_read >= 0) {
|
|
||||||
out->accel_z_raw = strtol(&tmp[0], NULL, 10);
|
|
||||||
accel_in[2] = (double)out->accel_z_raw * iio->accel_scale_z;
|
|
||||||
if ((out->flags & IMU_MESSAGE_FLAGS_ACCEL) == 0) {
|
|
||||||
out->accel_read_time = read_time;
|
|
||||||
out->flags |= IMU_MESSAGE_FLAGS_ACCEL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "While reading accel(z): %d\n", tmp_read);
|
|
||||||
return tmp_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iio->anglvel_x_fd != NULL) {
|
|
||||||
rewind(iio->anglvel_x_fd);
|
|
||||||
memset((void*)&tmp[0], 0, sizeof(tmp));
|
|
||||||
const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->anglvel_x_fd);
|
|
||||||
if (tmp_read >= 0) {
|
|
||||||
out->gyro_x_raw = strtol(&tmp[0], NULL, 10);
|
|
||||||
gyro_in[0] = (double)out->gyro_x_raw * iio->anglvel_scale_x;
|
|
||||||
if ((out->flags & IMU_MESSAGE_FLAGS_ANGLVEL) == 0) {
|
|
||||||
out->gyro_read_time = read_time;
|
|
||||||
out->flags |= IMU_MESSAGE_FLAGS_ANGLVEL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "While reading anglvel(x): %d\n", tmp_read);
|
|
||||||
return tmp_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iio->anglvel_y_fd != NULL) {
|
|
||||||
rewind(iio->anglvel_y_fd);
|
|
||||||
memset((void*)&tmp[0], 0, sizeof(tmp));
|
|
||||||
const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->anglvel_y_fd);
|
|
||||||
if (tmp_read >= 0) {
|
|
||||||
out->gyro_y_raw = strtol(&tmp[0], NULL, 10);
|
|
||||||
gyro_in[1] = (double)out->gyro_y_raw *iio->anglvel_scale_y;
|
|
||||||
if ((out->flags & IMU_MESSAGE_FLAGS_ANGLVEL) == 0) {
|
|
||||||
out->gyro_read_time = read_time;
|
|
||||||
out->flags |= IMU_MESSAGE_FLAGS_ANGLVEL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "While reading anglvel(y): %d\n", tmp_read);
|
|
||||||
return tmp_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iio->anglvel_z_fd != NULL) {
|
|
||||||
rewind(iio->anglvel_z_fd);
|
|
||||||
memset((void*)&tmp[0], 0, sizeof(tmp));
|
|
||||||
const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->anglvel_z_fd);
|
|
||||||
if (tmp_read >= 0) {
|
|
||||||
out->gyro_z_raw = strtol(&tmp[0], NULL, 10);
|
|
||||||
gyro_in[2] = (double)out->gyro_z_raw *iio->anglvel_scale_z;
|
|
||||||
if ((out->flags & IMU_MESSAGE_FLAGS_ANGLVEL) == 0) {
|
|
||||||
out->gyro_read_time = read_time;
|
|
||||||
out->flags |= IMU_MESSAGE_FLAGS_ANGLVEL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "While reading anglvel(z): %d\n", tmp_read);
|
|
||||||
return tmp_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iio->temp_fd != NULL) {
|
|
||||||
rewind(iio->temp_fd);
|
|
||||||
memset((void*)&tmp[0], 0, sizeof(tmp));
|
|
||||||
const int tmp_read = fread((void*)&tmp[0], 1, sizeof(tmp), iio->temp_fd);
|
|
||||||
if (tmp_read >= 0) {
|
|
||||||
out->temp_raw = strtol(&tmp[0], NULL, 10);
|
|
||||||
out->temp_in_k = (double)out->temp_raw *iio->temp_scale;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "While reading temp: %d\n", tmp_read);
|
|
||||||
return tmp_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
multiplyMatrixVector(iio->mount_matrix, gyro_in, gyro_out);
|
|
||||||
multiplyMatrixVector(iio->mount_matrix, accel_in, accel_out);
|
|
||||||
|
|
||||||
memcpy(out->accel_m2s, accel_out, sizeof(double[3]));
|
|
||||||
memcpy(out->gyro_rad_s, gyro_out, sizeof(double[3]));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int dev_iio_has_anglvel(const dev_iio_t* iio) {
|
int dev_iio_has_anglvel(const dev_iio_t* iio) {
|
||||||
return (iio->flags & DEV_IIO_HAS_ANGLVEL) != 0;
|
return (iio->flags & DEV_IIO_HAS_ANGLVEL) != 0;
|
||||||
}
|
}
|
||||||
|
|
@ -578,4 +364,4 @@ int dev_iio_has_accel(const dev_iio_t* iio) {
|
||||||
|
|
||||||
int dev_iio_get_buffer_fd(const dev_iio_t *const iio) {
|
int dev_iio_get_buffer_fd(const dev_iio_t *const iio) {
|
||||||
return iio->fd;
|
return iio->fd;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,6 @@ int dev_iio_has_anglvel(const dev_iio_t* iio);
|
||||||
|
|
||||||
int dev_iio_has_accel(const dev_iio_t* iio);
|
int dev_iio_has_accel(const dev_iio_t* iio);
|
||||||
|
|
||||||
int dev_iio_change_anglvel_sampling_freq(const dev_iio_t *const iio, uint16_t freq_hz, uint16_t freq_hz_frac);
|
int dev_iio_change_anglvel_sampling_freq(const dev_iio_t *const iio, const char *const freq_str_hz);
|
||||||
|
|
||||||
int dev_iio_change_accel_sampling_freq(const dev_iio_t *const iio, uint16_t freq_hz, uint16_t freq_hz_frac);
|
int dev_iio_change_accel_sampling_freq(const dev_iio_t *const iio, const char *const freq_str_hz);
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ int64_t get_timediff_usec(const struct timeval *const past, const struct timeval
|
||||||
struct timeval tdiff;
|
struct timeval tdiff;
|
||||||
timersub(now, past, &tdiff);
|
timersub(now, past, &tdiff);
|
||||||
|
|
||||||
const int64_t sgn = ((now->tv_sec > past->tv_sec) || ((now->tv_sec == past->tv_sec) && (now->tv_usec > past->tv_usec))) ? -1 : +1;
|
//const int64_t sgn = ((now->tv_sec > past->tv_sec) || ((now->tv_sec == past->tv_sec) && (now->tv_usec > past->tv_usec))) ? -1 : +1;
|
||||||
|
|
||||||
return (int64_t)(tdiff.tv_sec) * (int64_t)1000000 + (int64_t)(tdiff.tv_usec);
|
return (int64_t)(tdiff.tv_sec) * (int64_t)1000000 + (int64_t)(tdiff.tv_usec);
|
||||||
}
|
}
|
||||||
|
|
@ -198,8 +198,8 @@ void *dev_out_thread_func(void *ptr) {
|
||||||
gettimeofday(&now, NULL);
|
gettimeofday(&now, NULL);
|
||||||
|
|
||||||
struct timeval gamepad_last_hid_report_sent = now;
|
struct timeval gamepad_last_hid_report_sent = now;
|
||||||
struct timeval mouse_last_hid_report_sent = now;
|
//struct timeval mouse_last_hid_report_sent = now;
|
||||||
struct timeval keyboard_last_hid_report_sent = now;
|
//struct timeval keyboard_last_hid_report_sent = now;
|
||||||
|
|
||||||
uint8_t tmp_buf[256];
|
uint8_t tmp_buf[256];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,7 @@ typedef struct hidraw_callbacks {
|
||||||
} hidraw_callbacks_t;
|
} hidraw_callbacks_t;
|
||||||
|
|
||||||
typedef struct iio_settings {
|
typedef struct iio_settings {
|
||||||
uint16_t sampling_freq_hz;
|
const char* const sampling_freq_hz;
|
||||||
uint16_t sampling_freq_hz_frac;
|
|
||||||
int8_t post_matrix[3][3];
|
int8_t post_matrix[3][3];
|
||||||
} iio_settings_t;
|
} iio_settings_t;
|
||||||
|
|
||||||
|
|
|
||||||
17
legion_go.c
17
legion_go.c
|
|
@ -24,6 +24,16 @@ static input_dev_t in_iio_dev = {
|
||||||
.name = "gyro_3d",
|
.name = "gyro_3d",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.map = {
|
||||||
|
.iio_settings = {
|
||||||
|
.sampling_freq_hz = "70.000",
|
||||||
|
.post_matrix = {
|
||||||
|
{1, 0, 0},
|
||||||
|
{0, 1, 0},
|
||||||
|
{0, 0, 1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct llg_hidraw_data {
|
static struct llg_hidraw_data {
|
||||||
|
|
@ -40,7 +50,7 @@ static int llg_hidraw_map(int hidraw_fd, int in_messages_pipe_fd, void* user_dat
|
||||||
}
|
}
|
||||||
|
|
||||||
// here we have llg_data->last_packet filled with 64 bytes from the input device
|
// here we have llg_data->last_packet filled with 64 bytes from the input device
|
||||||
|
/*
|
||||||
const in_message_t current_message = {
|
const in_message_t current_message = {
|
||||||
.type = GAMEPAD_SET_ELEMENT,
|
.type = GAMEPAD_SET_ELEMENT,
|
||||||
.data = {
|
.data = {
|
||||||
|
|
@ -53,7 +63,6 @@ static int llg_hidraw_map(int hidraw_fd, int in_messages_pipe_fd, void* user_dat
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
// this does send messages to the output device
|
// this does send messages to the output device
|
||||||
|
|
||||||
const ssize_t in_message_pipe_write_res = write(in_messages_pipe_fd, (void*)¤t_message, sizeof(in_message_t));
|
const ssize_t in_message_pipe_write_res = write(in_messages_pipe_fd, (void*)¤t_message, sizeof(in_message_t));
|
||||||
|
|
@ -116,9 +125,9 @@ input_dev_composite_t legion_composite = {
|
||||||
.dev = {
|
.dev = {
|
||||||
&in_hidraw_dev,
|
&in_hidraw_dev,
|
||||||
&in_xbox_dev,
|
&in_xbox_dev,
|
||||||
// &in_iio_dev,
|
&in_iio_dev,
|
||||||
},
|
},
|
||||||
.dev_count = 2,
|
.dev_count = 3,
|
||||||
.init_fn = legion_platform_init,
|
.init_fn = legion_platform_init,
|
||||||
.leds_fn = legion_platform_leds,
|
.leds_fn = legion_platform_leds,
|
||||||
.deinit_fn = legion_platform_deinit,
|
.deinit_fn = legion_platform_deinit,
|
||||||
|
|
|
||||||
199
logic.c
199
logic.c
|
|
@ -1,199 +0,0 @@
|
||||||
#include "virt_ds4.h"
|
|
||||||
#include "virt_ds5.h"
|
|
||||||
#include "virt_evdev.h"
|
|
||||||
#include "virt_mouse_kbd.h"
|
|
||||||
|
|
||||||
static const char* configuration_file = "/etc/ROGueENEMY/config.cfg";
|
|
||||||
|
|
||||||
int logic_create(logic_t *const logic) {
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
logic->flags = 0x00000000U;
|
|
||||||
|
|
||||||
init_config(&logic->controller_settings);
|
|
||||||
const int fill_config_res = fill_config(&logic->controller_settings, configuration_file);
|
|
||||||
if (fill_config_res != 0) {
|
|
||||||
fprintf(stderr, "Unable to fill configuration from file %s -- defaults will be used\n", configuration_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
devices_status_init(&logic->dev_stats);
|
|
||||||
|
|
||||||
ret = pthread_mutex_init(&logic->dev_stats.mutex, NULL);
|
|
||||||
if (ret != 0) {
|
|
||||||
fprintf(stderr, "Unable to create mutex: %d\n", ret);
|
|
||||||
goto logic_create_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lizard_thread_started = false;
|
|
||||||
const int init_platform_res = init_platform(&logic->platform);
|
|
||||||
if (init_platform_res == 0) {
|
|
||||||
printf("RC71L platform correctly initialized\n");
|
|
||||||
|
|
||||||
logic->flags |= LOGIC_FLAGS_PLATFORM_ENABLE;
|
|
||||||
|
|
||||||
if (is_mouse_mode(&logic->platform)) {
|
|
||||||
printf("Device is in lizard mode\n");
|
|
||||||
// TODO: start the appropriate output thread
|
|
||||||
|
|
||||||
lizard_thread_started = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Unable to initialize Asus RC71L MCU: %d\n", init_platform_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lizard_thread_started) {
|
|
||||||
logic_start_output_dev_thread(logic);
|
|
||||||
}
|
|
||||||
|
|
||||||
logic_create_err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_rc71l_ready(const logic_t *const logic) {
|
|
||||||
return logic->flags & LOGIC_FLAGS_PLATFORM_ENABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void logic_terminate_output_thread(logic_t *const logic) {
|
|
||||||
if (logic->virt_dev_thread_running) {
|
|
||||||
void* thread_return = NULL;
|
|
||||||
pthread_join(logic->virt_dev_thread, &thread_return);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int logic_start_output_mouse_kbd_thread(logic_t *const logic) {
|
|
||||||
logic->dev_stats.kbd.connected = true;
|
|
||||||
|
|
||||||
const int ret = pthread_create(&logic->virt_dev_thread, NULL, virt_mouse_kbd_thread_func, (void*)(&logic->dev_stats));
|
|
||||||
|
|
||||||
logic->virt_dev_thread_running = ret == 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int logic_start_output_dev_thread(logic_t *const logic) {
|
|
||||||
logic->dev_stats.gamepad.connected = true;
|
|
||||||
|
|
||||||
int ret = -EINVAL;
|
|
||||||
switch (logic->controller_settings.gamepad_output_device) {
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
ret = pthread_create(&logic->virt_dev_thread, NULL, virt_evdev_thread_func, (void*)(&logic->dev_stats));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
ret = pthread_create(&logic->virt_dev_thread, NULL, virt_ds5_thread_func, (void*)(&logic->dev_stats));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
ret = pthread_create(&logic->virt_dev_thread, NULL, virt_ds4_thread_func, (void*)(&logic->dev_stats));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Invalid output device specified\n");
|
|
||||||
ret = -EINVAL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
logic->virt_dev_thread_running = ret == 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
int logic_copy_gamepad_status(logic_t *const logic, gamepad_status_t *const out) {
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
res = pthread_mutex_lock(&logic->gamepad_mutex);
|
|
||||||
if (res != 0) {
|
|
||||||
goto logic_copy_gamepad_status_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct timeval press_time;
|
|
||||||
if (logic->gamepad.flags & GAMEPAD_STATUS_FLAGS_PRESS_AND_REALEASE_CENTER) {
|
|
||||||
struct timeval now;
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
|
|
||||||
// Calculate elapsed time in milliseconds
|
|
||||||
int64_t elapsed_time = (now.tv_sec - press_time.tv_sec) * 1000 +
|
|
||||||
(now.tv_usec - press_time.tv_usec) / 1000;
|
|
||||||
|
|
||||||
if (logic->gamepad.center) {
|
|
||||||
// If the center button is pressed and at least X ms have passed
|
|
||||||
if (elapsed_time >= PRESS_AND_RELEASE_DURATION_FOR_CENTER_BUTTON_MS) {
|
|
||||||
logic->gamepad.center = 0;
|
|
||||||
logic->gamepad.flags &= ~GAMEPAD_STATUS_FLAGS_PRESS_AND_REALEASE_CENTER;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the center button is pressed
|
|
||||||
logic->gamepad.center = 1;
|
|
||||||
gettimeofday(&press_time, NULL);
|
|
||||||
}
|
|
||||||
} else if (logic->gamepad.flags & GAMEPAD_STATUS_FLAGS_OPEN_STEAM_QAM) {
|
|
||||||
struct timeval now;
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
|
|
||||||
static int releasing = 0;
|
|
||||||
|
|
||||||
// Calculate elapsed time in milliseconds
|
|
||||||
int64_t elapsed_time = (now.tv_sec - press_time.tv_sec) * 1000 +
|
|
||||||
(now.tv_usec - press_time.tv_usec) / 1000;
|
|
||||||
|
|
||||||
if ((logic->gamepad.center) && (!logic->gamepad.cross)) {
|
|
||||||
if ((!releasing) && (elapsed_time >= PRESS_TIME_BEFORE_CROSS_BUTTON_MS)) {
|
|
||||||
logic->gamepad.center = 1;
|
|
||||||
logic->gamepad.cross = 1;
|
|
||||||
press_time = now;
|
|
||||||
} else if ((releasing) && (elapsed_time >= PRESS_TIME_AFTER_CROSS_BUTTON_MS)) {
|
|
||||||
logic->gamepad.center = 0;
|
|
||||||
logic->gamepad.cross = 0;
|
|
||||||
press_time = now;
|
|
||||||
logic->gamepad.flags &= ~GAMEPAD_STATUS_FLAGS_OPEN_STEAM_QAM;
|
|
||||||
}
|
|
||||||
} else if ((logic->gamepad.center) && (logic->gamepad.cross)) {
|
|
||||||
if (elapsed_time >= PRESS_TIME_CROSS_BUTTON_MS) {
|
|
||||||
logic->gamepad.center = 1;
|
|
||||||
logic->gamepad.cross = 0;
|
|
||||||
releasing = 1;
|
|
||||||
press_time = now;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logic->gamepad.center = 1;
|
|
||||||
logic->gamepad.cross = 0;
|
|
||||||
releasing = 0;
|
|
||||||
gettimeofday(&press_time, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*out = logic->gamepad;
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&logic->gamepad_mutex);
|
|
||||||
|
|
||||||
logic_copy_gamepad_status_err:
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int logic_begin_status_update(logic_t *const logic) {
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
res = pthread_mutex_lock(&logic->gamepad_mutex);
|
|
||||||
if (res != 0) {
|
|
||||||
goto logic_begin_status_update_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
logic_begin_status_update_err:
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void logic_end_status_update(logic_t *const logic) {
|
|
||||||
pthread_mutex_unlock(&logic->gamepad_mutex);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void logic_request_termination(logic_t *const logic) {
|
|
||||||
logic->flags |= LOGIC_FLAGS_TERMINATION_REQUESTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
int logic_termination_requested(logic_t *const logic) {
|
|
||||||
return (logic->flags & LOGIC_FLAGS_TERMINATION_REQUESTED) != 0;
|
|
||||||
}
|
|
||||||
|
|
@ -539,8 +539,7 @@ static input_dev_t in_iio_dev = {
|
||||||
},
|
},
|
||||||
.map = {
|
.map = {
|
||||||
.iio_settings = {
|
.iio_settings = {
|
||||||
.sampling_freq_hz = 1600,
|
.sampling_freq_hz = "1600.000",
|
||||||
.sampling_freq_hz_frac = 000,
|
|
||||||
.post_matrix =
|
.post_matrix =
|
||||||
/*
|
/*
|
||||||
// this is the testing but "wrong" mount matrix
|
// this is the testing but "wrong" mount matrix
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
static const char* path = "/dev/uhid";
|
static const char* path = "/dev/uhid";
|
||||||
|
|
||||||
static const char* const MAC_ADDR_STR = "e8:47:3a:d6:e7:74";
|
//static const char* const MAC_ADDR_STR = "e8:47:3a:d6:e7:74";
|
||||||
static const uint8_t MAC_ADDR[] = { 0x74, 0xe7, 0xd6, 0x3a, 0x47, 0xe8 };
|
static const uint8_t MAC_ADDR[] = { 0x74, 0xe7, 0xd6, 0x3a, 0x47, 0xe8 };
|
||||||
|
|
||||||
static unsigned char rdesc[] = {
|
static unsigned char rdesc[] = {
|
||||||
|
|
@ -93,6 +93,8 @@ static int create(int fd)
|
||||||
ev.u.create.product = 0x0df2;
|
ev.u.create.product = 0x0df2;
|
||||||
ev.u.create.version = 0;
|
ev.u.create.version = 0;
|
||||||
ev.u.create.country = 0;
|
ev.u.create.country = 0;
|
||||||
|
memset(&ev.u.create.uniq, 0, sizeof(ev.u.create.uniq));
|
||||||
|
memcpy(&ev.u.create.uniq, (void*)MAC_ADDR, sizeof(MAC_ADDR));
|
||||||
|
|
||||||
return uhid_write(fd, &ev);
|
return uhid_write(fd, &ev);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
571
virt_evdev.c
571
virt_evdev.c
|
|
@ -1,571 +0,0 @@
|
||||||
#include "virt_evdev.h"
|
|
||||||
#include "devices_status.h"
|
|
||||||
|
|
||||||
static const char* uinput_path = "/dev/uinput";
|
|
||||||
|
|
||||||
static int create_gamepad_uinput(void) {
|
|
||||||
int fd = open(uinput_path, O_WRONLY | O_NONBLOCK);
|
|
||||||
if(fd < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_setup dev = {0};
|
|
||||||
strncpy(dev.name, OUTPUT_DEV_NAME, UINPUT_MAX_NAME_SIZE-1);
|
|
||||||
|
|
||||||
#if defined(OUTPUT_DEV_BUS_TYPE)
|
|
||||||
dev.id.bustype = OUTPUT_DEV_BUS_TYPE;
|
|
||||||
#else
|
|
||||||
dev.id.bustype = BUS_VIRTUAL;
|
|
||||||
#endif
|
|
||||||
dev.id.vendor = OUTPUT_DEV_VENDOR_ID;
|
|
||||||
dev.id.product = OUTPUT_DEV_PRODUCT_ID;
|
|
||||||
|
|
||||||
#if defined(OUTPUT_DEV_VERSION)
|
|
||||||
dev.id.version = OUTPUT_DEV_VERSION;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//if (ioctl(fd, /*UI_SET_PHYS_STR*/ 18, PHYS_STR) != 0) {
|
|
||||||
// fprintf(stderr, "Controller and gyroscope will NOT be recognized as a single device!\n");
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (ioctl(fd, UI_SET_PHYS, PHYS_STR) != 0) {
|
|
||||||
fprintf(stderr, "Error setting the phys of the virtual controller.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(UI_SET_PHYS_STR)
|
|
||||||
#warning Will not change the PHYS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(UI_SET_UNIQ_STR)
|
|
||||||
#warning Will not change the UNIQ
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UI_SET_PHYS_STR)
|
|
||||||
ioctl(fd, UI_SET_PHYS_STR(18), PHYS_STR);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "UI_SET_PHYS_STR unavailable.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UI_SET_UNIQ_STR)
|
|
||||||
ioctl(fd, UI_SET_UNIQ_STR(18), PHYS_STR);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "UI_SET_UNIQ_STR unavailable.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_BUTTONPAD);
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_ABS);
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_SYN);
|
|
||||||
#if defined(INCLUDE_TIMESTAMP)
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_MSC);
|
|
||||||
ioctl(fd, UI_SET_MSCBIT, MSC_TIMESTAMP);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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_ABSBIT, ABS_HAT0X);
|
|
||||||
ioctl(fd, UI_SET_ABSBIT, ABS_HAT0Y);
|
|
||||||
ioctl(fd, UI_SET_ABSBIT, ABS_HAT2X);
|
|
||||||
ioctl(fd, UI_SET_ABSBIT, ABS_HAT2Y);
|
|
||||||
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_SOUTH);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_EAST);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_NORTH);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_WEST);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_TL);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_TR);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_TL2);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_TR2);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_SELECT);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_START);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_MODE);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_THUMBL);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_THUMBR);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_GEAR_DOWN);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_GEAR_UP);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_UP);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_DOWN);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_LEFT);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_RIGHT);
|
|
||||||
|
|
||||||
const struct uinput_abs_setup devAbsX = {
|
|
||||||
.code = ABS_X,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = -32768,
|
|
||||||
.maximum = +32768,
|
|
||||||
.resolution = 1,
|
|
||||||
.fuzz = 16,
|
|
||||||
.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsX) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsY = {
|
|
||||||
.code = ABS_Y,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = -32768,
|
|
||||||
.maximum = +32768,
|
|
||||||
.resolution = 1,
|
|
||||||
.fuzz = 16,
|
|
||||||
.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsY) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsZ = {
|
|
||||||
.code = ABS_Z,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = 0,
|
|
||||||
.maximum = 255,
|
|
||||||
.resolution = 1,
|
|
||||||
//.fuzz = 16,
|
|
||||||
//.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsZ) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsRX = {
|
|
||||||
.code = ABS_RX,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = -32768,
|
|
||||||
.maximum = +32768,
|
|
||||||
.resolution = 1,
|
|
||||||
.fuzz = 16,
|
|
||||||
.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsRX) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsRY = {
|
|
||||||
.code = ABS_RY,
|
|
||||||
.absinfo = {
|
|
||||||
.value = -1,
|
|
||||||
.minimum = -32768,
|
|
||||||
.maximum = +32768,
|
|
||||||
.resolution = 1,
|
|
||||||
.fuzz = 16,
|
|
||||||
.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsRY) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsRZ = {
|
|
||||||
.code = ABS_RZ,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = 0,
|
|
||||||
.maximum = 255,
|
|
||||||
.resolution = 1,
|
|
||||||
//.fuzz = 16,
|
|
||||||
//.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsRZ) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsHat0X = {
|
|
||||||
.code = ABS_HAT0X,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = -1,
|
|
||||||
.maximum = 1,
|
|
||||||
.resolution = 1,
|
|
||||||
//.fuzz = 16,
|
|
||||||
//.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsHat0X) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsHat0Y = {
|
|
||||||
.code = ABS_HAT0Y,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = -1,
|
|
||||||
.maximum = 1,
|
|
||||||
.resolution = 1,
|
|
||||||
//.fuzz = 16,
|
|
||||||
//.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsHat0Y) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsHat2X = {
|
|
||||||
.code = ABS_HAT2X,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = 0,
|
|
||||||
.maximum = 255,
|
|
||||||
.resolution = 51,
|
|
||||||
//.fuzz = 16,
|
|
||||||
//.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsHat2X) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_abs_setup devAbsHat2Y = {
|
|
||||||
.code = ABS_HAT2Y,
|
|
||||||
.absinfo = {
|
|
||||||
.value = 0,
|
|
||||||
.minimum = 0,
|
|
||||||
.maximum = 255,
|
|
||||||
.resolution = 51,
|
|
||||||
//.fuzz = 16,
|
|
||||||
//.flat = 128,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if(ioctl(fd, UI_ABS_SETUP, &devAbsHat2Y) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ioctl(fd, UI_DEV_SETUP, &dev) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ioctl(fd, UI_DEV_CREATE) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_gamepad_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
create_gamepad_uinput_err:
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int create_imu_uinput() {
|
|
||||||
int fd = open(uinput_path, O_WRONLY | O_NONBLOCK);
|
|
||||||
if(fd < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_imu_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_setup dev = {0};
|
|
||||||
strncpy(dev.name, OUTPUT_DEV_NAME, UINPUT_MAX_NAME_SIZE-1);
|
|
||||||
|
|
||||||
#if defined(OUTPUT_DEV_BUS_TYPE)
|
|
||||||
dev.id.bustype = OUTPUT_DEV_BUS_TYPE;
|
|
||||||
#else
|
|
||||||
dev.id.bustype = BUS_VIRTUAL;
|
|
||||||
#endif
|
|
||||||
dev.id.vendor = OUTPUT_DEV_VENDOR_ID;
|
|
||||||
dev.id.product = OUTPUT_DEV_PRODUCT_ID;
|
|
||||||
|
|
||||||
#if defined(OUTPUT_DEV_VERSION)
|
|
||||||
dev.id.version = OUTPUT_DEV_VERSION;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//if (ioctl(fd, /*UI_SET_PHYS_STR*/ 18, PHYS_STR) != 0) {
|
|
||||||
// fprintf(stderr, "Controller and gyroscope will NOT be recognized as a single device!\n");
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (ioctl(fd, UI_SET_PHYS, PHYS_STR) != 0) {
|
|
||||||
fprintf(stderr, "Error setting the phys of the virtual controller.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(UI_SET_PHYS_STR)
|
|
||||||
#warning Will not change the PHYS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(UI_SET_UNIQ_STR)
|
|
||||||
#warning Will not change the UNIQ
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UI_SET_PHYS_STR)
|
|
||||||
ioctl(fd, UI_SET_PHYS_STR(18), PHYS_STR);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "UI_SET_PHYS_STR unavailable.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(UI_SET_UNIQ_STR)
|
|
||||||
ioctl(fd, UI_SET_UNIQ_STR(18), PHYS_STR);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "UI_SET_UNIQ_STR unavailable.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_ACCELEROMETER);
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_ABS);
|
|
||||||
#if defined(INCLUDE_TIMESTAMP)
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_MSC);
|
|
||||||
ioctl(fd, UI_SET_MSCBIT, MSC_TIMESTAMP);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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_uinput_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_uinput_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_uinput_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_uinput_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_uinput_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_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ioctl(fd, UI_DEV_SETUP, &dev) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_imu_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ioctl(fd, UI_DEV_CREATE) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_imu_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
create_imu_uinput_err:
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *virt_evdev_thread_func(void *ptr) {
|
|
||||||
devices_status_t *const stats = (devices_status_t*)ptr;
|
|
||||||
|
|
||||||
const int gamepad_fd = create_gamepad_uinput();
|
|
||||||
if (gamepad_fd < 0) {
|
|
||||||
fprintf(stderr, "Unable to create the virtual evdev gamepad device: %d\n", gamepad_fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int imu_fd = create_imu_uinput();
|
|
||||||
if (imu_fd < 0) {
|
|
||||||
fprintf(stderr, "Unable to create the virtual evdev imu device: %d\n", gamepad_fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
usleep(1250);
|
|
||||||
|
|
||||||
const int lock_res = pthread_mutex_lock(&stats->mutex);
|
|
||||||
if (lock_res != 0) {
|
|
||||||
printf("Unable to lock gamepad mutex: %d\n", lock_res);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// main virtual device logic
|
|
||||||
{
|
|
||||||
//event(fd, &stats->gamepad);
|
|
||||||
|
|
||||||
if (stats->gamepad.connected) {
|
|
||||||
// TODO: do whatever it takes...
|
|
||||||
} else {
|
|
||||||
pthread_mutex_unlock(&stats->mutex);
|
|
||||||
|
|
||||||
printf("kbd&mouse has been terminated: closing the device.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&stats->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
static void emit_ev(output_dev_t *const out_dev, const in_message_t *const msg) {
|
|
||||||
// if events are flagged as do not emit... Do NOT emit!
|
|
||||||
if (msg->flags & INPUT_FILTER_FLAGS_DO_NOT_EMIT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd = out_dev->gamepad_fd;
|
|
||||||
const uint32_t msg_flags = msg->data.event.ev_flags;
|
|
||||||
if ((msg_flags & EV_MESSAGE_FLAGS_IMU) != 0) {
|
|
||||||
fd = out_dev->imu_fd;
|
|
||||||
} else if ((msg_flags & EV_MESSAGE_FLAGS_MOUSE) != 0) {
|
|
||||||
fd = out_dev->mouse_fd;
|
|
||||||
} else {
|
|
||||||
fd = out_dev->gamepad_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < msg->data.event.ev_count; ++i) {
|
|
||||||
struct input_event ev = {
|
|
||||||
.code = msg->data.event.ev[i].code,
|
|
||||||
.type = msg->data.event.ev[i].type,
|
|
||||||
.value = msg->data.event.ev[i].value,
|
|
||||||
.time = msg->data.event.ev[i].time,
|
|
||||||
};
|
|
||||||
|
|
||||||
if ((msg_flags & EV_MESSAGE_FLAGS_PRESERVE_TIME) == 0) {
|
|
||||||
gettimeofday(&ev.time, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(INCLUDE_OUTPUT_DEBUG)
|
|
||||||
printf(
|
|
||||||
"Output: Received event %s (%s): %d\n",
|
|
||||||
libevdev_event_type_get_name(ev.type),
|
|
||||||
libevdev_event_code_get_name(ev.type, ev.code),
|
|
||||||
ev.value
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const ssize_t written = write(fd, (void*)&ev, sizeof(ev));
|
|
||||||
if (written != sizeof(ev)) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"Error writing event %s %s %d: written %ld bytes out of %ld\n",
|
|
||||||
libevdev_event_type_get_name(ev.type),
|
|
||||||
libevdev_event_code_get_name(ev.type, ev.code),
|
|
||||||
ev.value,
|
|
||||||
written,
|
|
||||||
sizeof(ev)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(INCLUDE_TIMESTAMP)
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
const struct input_event timestamp_ev = {
|
|
||||||
.code = MSC_TIMESTAMP,
|
|
||||||
.type = EV_MSC,
|
|
||||||
.value = (now.tv_sec - secAtInit)*1000000 + (now.tv_usec - usecAtInit),
|
|
||||||
.time = now,
|
|
||||||
};
|
|
||||||
const ssize_t timestamp_written = write(fd, (void*)×tamp_ev, sizeof(timestamp_ev));
|
|
||||||
if (timestamp_written != sizeof(timestamp_ev)) {
|
|
||||||
fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", timestamp_written, sizeof(timestamp_ev));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct timeval now = {0};
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
const struct input_event syn_ev = {
|
|
||||||
.code = SYN_REPORT,
|
|
||||||
.type = EV_SYN,
|
|
||||||
.value = 0,
|
|
||||||
.time = now,
|
|
||||||
};
|
|
||||||
const ssize_t sync_written = write(fd, (void*)&syn_ev, sizeof(syn_ev));
|
|
||||||
if (sync_written != sizeof(syn_ev)) {
|
|
||||||
fprintf(stderr, "Error in sync: written %ld bytes out of %ld\n", sync_written, sizeof(syn_ev));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
47
virt_evdev.h
47
virt_evdev.h
|
|
@ -1,47 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "rogue_enemy.h"
|
|
||||||
|
|
||||||
#undef VIRT_EVDEV_DEBUG
|
|
||||||
|
|
||||||
|
|
||||||
// Emulates a "Generic" controller:
|
|
||||||
#define OUTPUT_DEV_NAME "ROGueENEMY"
|
|
||||||
#define OUTPUT_DEV_VENDOR_ID 0x108c
|
|
||||||
#define OUTPUT_DEV_PRODUCT_ID 0x0323
|
|
||||||
#define OUTPUT_DEV_VERSION 0x0111
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Emulates a steam controller
|
|
||||||
#define OUTPUT_DEV_NAME "Steam Controller"
|
|
||||||
#define OUTPUT_DEV_VENDOR_ID 0x28de
|
|
||||||
#define OUTPUT_DEV_PRODUCT_ID 0x1102
|
|
||||||
#define OUTPUT_DEV_VERSION 0x0111
|
|
||||||
#define OUTPUT_DEV_BUS_TYPE BUS_USB
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
//Emulates an Xbox one wireless controller:
|
|
||||||
#define OUTPUT_DEV_NAME "Xbox Wireless Controller"
|
|
||||||
#define OUTPUT_DEV_VENDOR_ID 0x045e
|
|
||||||
#define OUTPUT_DEV_PRODUCT_ID 0x028e
|
|
||||||
#define OUTPUT_DEV_BUS_TYPE BUS_BLUETOOTH
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Emulates a DualShock controller
|
|
||||||
#define OUTPUT_DEV_NAME "Sony Interactive Entertainment DualSense Wireless Controller"
|
|
||||||
#define OUTPUT_DEV_VENDOR_ID 0x054c
|
|
||||||
#define OUTPUT_DEV_PRODUCT_ID 0x0ce6
|
|
||||||
#define OUTPUT_DEV_VERSION 0x8111
|
|
||||||
#define OUTPUT_DEV_BUS_TYPE BUS_USB
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PHYS_STR "00:11:22:33:44:55"
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
void *virt_evdev_thread_func(void *ptr);
|
|
||||||
126
virt_mouse_kbd.c
126
virt_mouse_kbd.c
|
|
@ -1,126 +0,0 @@
|
||||||
#include "virt_mouse_kbd.h"
|
|
||||||
#include "devices_status.h"
|
|
||||||
|
|
||||||
static const char* uinput_path = "/dev/uinput";
|
|
||||||
|
|
||||||
static int create_mouse_uinput(void) {
|
|
||||||
int fd = open(uinput_path, O_WRONLY | O_NONBLOCK);
|
|
||||||
if(fd < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_mouse_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct uinput_setup dev = {0};
|
|
||||||
strncpy(dev.name, OUTPUT_DEV_NAME, UINPUT_MAX_NAME_SIZE-1);
|
|
||||||
|
|
||||||
#if defined(OUTPUT_DEV_BUS_TYPE)
|
|
||||||
dev.id.bustype = OUTPUT_DEV_BUS_TYPE;
|
|
||||||
#else
|
|
||||||
dev.id.bustype = BUS_VIRTUAL;
|
|
||||||
#endif
|
|
||||||
dev.id.vendor = OUTPUT_DEV_VENDOR_ID;
|
|
||||||
dev.id.product = OUTPUT_DEV_PRODUCT_ID;
|
|
||||||
|
|
||||||
#if defined(OUTPUT_DEV_VERSION)
|
|
||||||
dev.id.version = OUTPUT_DEV_VERSION;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//if (ioctl(fd, /*UI_SET_PHYS_STR*/ 18, PHYS_STR) != 0) {
|
|
||||||
// fprintf(stderr, "Controller and gyroscope will NOT be recognized as a single device!\n");
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (ioctl(fd, UI_SET_PHYS, PHYS_STR) != 0) {
|
|
||||||
fprintf(stderr, "Error setting the phys of the virtual controller.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(UI_SET_PHYS_STR)
|
|
||||||
#warning Will not change the PHYS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(UI_SET_UNIQ_STR)
|
|
||||||
#warning Will not change the UNIQ
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_REL);
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_MSC);
|
|
||||||
ioctl(fd, UI_SET_EVBIT, EV_SYN);
|
|
||||||
#if defined(INCLUDE_TIMESTAMP)
|
|
||||||
ioctl(fd, UI_SET_MSCBIT, MSC_TIMESTAMP);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE);
|
|
||||||
ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT);
|
|
||||||
//ioctl(fd, UI_SET_KEYBIT, BTN_SIDE);
|
|
||||||
//ioctl(fd, UI_SET_KEYBIT, BTN_EXTRA);
|
|
||||||
|
|
||||||
ioctl(fd, UI_SET_RELBIT, REL_X);
|
|
||||||
ioctl(fd, UI_SET_RELBIT, REL_Y);
|
|
||||||
ioctl(fd, UI_SET_RELBIT, REL_WHEEL);
|
|
||||||
ioctl(fd, UI_SET_RELBIT, REL_WHEEL_HI_RES);
|
|
||||||
|
|
||||||
if(ioctl(fd, UI_DEV_SETUP, &dev) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_mouse_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ioctl(fd, UI_DEV_CREATE) < 0) {
|
|
||||||
fd = -1;
|
|
||||||
close(fd);
|
|
||||||
goto create_mouse_uinput_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
create_mouse_uinput_err:
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int create_kb_uinput(void) {
|
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *virt_mouse_kbd_thread_func(void *ptr) {
|
|
||||||
devices_status_t *const stats = (devices_status_t*)ptr;
|
|
||||||
|
|
||||||
const int mouse_fd = create_mouse_uinput();
|
|
||||||
if (mouse_fd < 0) {
|
|
||||||
fprintf(stderr, "Unable to create the mouse virtual evdev: %d\n", mouse_fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard_status_t prev_kbd_stats;
|
|
||||||
kbd_status_init(&prev_kbd_stats);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
usleep(1250);
|
|
||||||
|
|
||||||
const int lock_res = pthread_mutex_lock(&stats->mutex);
|
|
||||||
if (lock_res != 0) {
|
|
||||||
printf("Unable to lock gamepad mutex: %d\n", lock_res);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// main virtual device logic
|
|
||||||
{
|
|
||||||
//event(fd, &stats->gamepad);
|
|
||||||
|
|
||||||
if (stats->kbd.connected) {
|
|
||||||
// TODO: do whatever it takes...
|
|
||||||
} else {
|
|
||||||
pthread_mutex_unlock(&stats->mutex);
|
|
||||||
|
|
||||||
printf("kbd&mouse has been terminated: closing the device.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&stats->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "rogue_enemy.h"
|
|
||||||
|
|
||||||
#undef VIRT_EVDEV_DEBUG
|
|
||||||
|
|
||||||
// Emulates a "Generic" controller:
|
|
||||||
#define OUTPUT_DEV_NAME "ROGueENEMY"
|
|
||||||
#define OUTPUT_DEV_VENDOR_ID 0x108c
|
|
||||||
#define OUTPUT_DEV_PRODUCT_ID 0x0323
|
|
||||||
#define OUTPUT_DEV_VERSION 0x0111
|
|
||||||
|
|
||||||
#define PHYS_STR "00:11:22:33:44:55"
|
|
||||||
|
|
||||||
void *virt_mouse_kbd_thread_func(void *ptr);
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue