Read data from the old bmc150-accel-i2c modified driver

This commit is contained in:
Denis 2024-01-15 03:11:32 +01:00
parent 35bbaa4f2d
commit 749b184d13
No known key found for this signature in database
GPG key ID: DD9B63F805CF5C03

View file

@ -3,6 +3,9 @@
#include "dev_hidraw.h"
#include "message.h"
#include "xbox360.h"
#include <stdio.h>
static const char iio_base_path[] = "/sys/bus/iio/devices/iio:device0/";
enum rc71l_leds_mode {
ROG_ALLY_MODE_STATIC = 0,
@ -1486,6 +1489,516 @@ static int rc71l_platform_leds(const dev_in_settings_t *const conf, uint8_t r, u
return 0;
}
typedef struct dev_iio {
char* path;
char* name;
uint32_t flags;
FILE* accel_x_fd;
FILE* accel_y_fd;
FILE* accel_z_fd;
double accel_scale_x;
double accel_scale_y;
double accel_scale_z;
FILE* anglvel_x_fd;
FILE* anglvel_y_fd;
FILE* anglvel_z_fd;
double anglvel_scale_x;
double anglvel_scale_y;
double anglvel_scale_z;
double temp_scale;
double outer_temp_scale;
double mount_matrix[3][3];
double sampling_rate_hz;
} dev_old_iio_t;
static char* read_file(const char* base_path, const char *file) {
char* res = NULL;
char* fdir = NULL;
long len = 0;
len = strlen(base_path) + strlen(file) + 1;
fdir = malloc(len);
if (fdir == NULL) {
fprintf(stderr, "Cannot allocate %ld bytes for device path, device skipped.\n", len);
goto read_file_err;
}
strcpy(fdir, base_path);
strcat(fdir, file);
if (access(fdir, F_OK) == 0) {
FILE* fp = fopen(fdir, "r");
if (fp != NULL) {
fseek(fp, 0L, SEEK_END);
len = ftell(fp);
rewind(fp);
len += 1;
res = malloc(len);
if (res != NULL) {
unsigned long read_bytes = fread(res, 1, len, fp);
printf("Read %lu bytes from file %s\n", read_bytes, fdir);
} else {
fprintf(stderr, "Cannot allocate %ld bytes for %s content.\n", len, fdir);
}
fclose(fp);
} else {
fprintf(stderr, "Cannot open file %s.\n", fdir);
}
} else {
fprintf(stderr, "File %s does not exists.\n", fdir);
}
free(fdir);
fdir = NULL;
read_file_err:
return res;
}
int write_file(const char* base_path, const char *file, const void* buf, size_t buf_sz) {
char* fdir = NULL;
int res = 0;
const size_t len = strlen(base_path) + strlen(file) + 1;
fdir = malloc(len);
if (fdir == NULL) {
fprintf(stderr, "Cannot allocate %ld bytes for device path, device skipped.\n", len);
goto write_file_err;
}
strcpy(fdir, base_path);
strcat(fdir, file);
if (access(fdir, F_OK) == 0) {
FILE* fp = fopen(fdir, "w");
if (fp != NULL) {
res = fwrite(buf, 1, buf_sz, fp);
if (res >= buf_sz) {
printf("Written %d bytes to file %s\n", res, fdir);
} else {
fprintf(stderr, "Cannot write to %s: %d.\n", fdir, res);
}
fclose(fp);
} else {
fprintf(stderr, "Cannot open file %s.\n", fdir);
}
} else {
fprintf(stderr, "File %s does not exists.\n", fdir);
}
free(fdir);
fdir = NULL;
write_file_err:
return res;
}
dev_old_iio_t* dev_old_iio_create(const char* path) {
dev_old_iio_t *iio = malloc(sizeof(dev_old_iio_t));
if (iio == NULL) {
return NULL;
}
iio->anglvel_x_fd = NULL;
iio->anglvel_y_fd = NULL;
iio->anglvel_z_fd = NULL;
iio->accel_x_fd = NULL;
iio->accel_y_fd = NULL;
iio->accel_z_fd = NULL;
iio->accel_scale_x = 0.0f;
iio->accel_scale_y = 0.0f;
iio->accel_scale_z = 0.0f;
iio->anglvel_scale_x = 0.0f;
iio->anglvel_scale_y = 0.0f;
iio->anglvel_scale_z = 0.0f;
iio->temp_scale = 0.0f;
iio->outer_temp_scale = 0.0;
double mm[3][3] =
// this is the correct matrix:
{
{-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}
};
// store the mount matrix
memcpy(iio->mount_matrix, mm, sizeof(mm));
const long path_len = strlen(path) + 1;
iio->path = malloc(path_len);
if (iio->path == NULL) {
fprintf(stderr, "Cannot allocate %ld bytes for device name, device skipped.\n", path_len);
free(iio);
iio = NULL;
goto dev_old_iio_create_err;
}
strcpy(iio->path, path);
// ============================================= DEVICE NAME ================================================
iio->name = read_file(iio->path, "/name");
if (iio->name == NULL) {
fprintf(stderr, "Unable to read iio device name.\n");
free(iio);
iio = NULL;
goto dev_old_iio_create_err;
} else {
int idx = strlen(iio->name) - 1;
if ((iio->name[idx] == '\n') || ((iio->name[idx] == '\t'))) {
iio->name[idx] = '\0';
}
}
// ==========================================================================================================
// ========================================== in_anglvel_scale ==============================================
{
const char* preferred_scale = LSB_PER_RAD_S_2000_DEG_S_STR;
const char *scale_main_file = "/in_anglvel_scale";
char* const anglvel_scale = read_file(iio->path, scale_main_file);
if (anglvel_scale != NULL) {
iio->anglvel_scale_x = iio->anglvel_scale_y = iio->anglvel_scale_z = strtod(anglvel_scale, NULL);
free((void*)anglvel_scale);
if (write_file(iio->path, scale_main_file, preferred_scale, strlen(preferred_scale)) >= 0) {
iio->anglvel_scale_x = iio->anglvel_scale_y = iio->anglvel_scale_z = LSB_PER_RAD_S_2000_DEG_S;
printf("anglvel scale changed to %f for device %s\n", iio->anglvel_scale_x, iio->name);
} else {
fprintf(stderr, "Unable to set preferred in_anglvel_scale for device %s.\n", iio->name);
}
} else {
// 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", iio->path, scale_main_file);
free(iio);
iio = NULL;
goto dev_old_iio_create_err;
}
}
// ==========================================================================================================
// =========================================== in_accel_scale ===============================================
{
const char* preferred_scale = LSB_PER_16G_STR;
const char *scale_main_file = "/in_accel_scale";
char* const accel_scale = read_file(iio->path, scale_main_file);
if (accel_scale != NULL) {
iio->accel_scale_x = iio->accel_scale_y = iio->accel_scale_z = strtod(accel_scale, NULL);
free((void*)accel_scale);
if (write_file(iio->path, scale_main_file, preferred_scale, strlen(preferred_scale)) >= 0) {
iio->accel_scale_x = iio->accel_scale_y = iio->accel_scale_z = LSB_PER_16G;
printf("accel scale changed to %f for device %s\n", iio->accel_scale_x, iio->name);
} else {
fprintf(stderr, "Unable to set preferred in_accel_scale for device %s.\n", iio->name);
}
} else {
// 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", iio->path, scale_main_file);
free(iio);
iio = NULL;
goto dev_old_iio_create_err;
}
}
// ==========================================================================================================
// ============================================= temp_scale =================================================
{
char* const accel_scale = read_file(iio->path, "/in_temp_scale");
if (accel_scale != NULL) {
iio->temp_scale = strtod(accel_scale, NULL);
free((void*)accel_scale);
} else {
fprintf(stderr, "Unable to read in_accel_scale file from path %s%s.\n", iio->path, "/in_accel_scale");
free(iio);
iio = NULL;
goto dev_old_iio_create_err;
}
}
// ==========================================================================================================
// ============================================ sampling_rate ================================================
{
char* const accel_scale = read_file(iio->path, "/in_temp_scale");
if (accel_scale != NULL) {
iio->temp_scale = strtod(accel_scale, NULL);
free((void*)accel_scale);
} else {
fprintf(stderr, "Unable to read in_accel_scale file from path %s%s.\n", iio->path, "/in_accel_scale");
free(iio);
iio = NULL;
goto dev_old_iio_create_err;
}
}
// ==========================================================================================================
const size_t tmp_sz = path_len + 128 + 1;
char* const tmp = malloc(tmp_sz);
memset(tmp, 0, tmp_sz);
strcat(tmp, iio->path);
strcat(tmp, "/in_accel_x_raw");
iio->accel_x_fd = fopen(tmp, "r");
memset(tmp, 0, tmp_sz);
strcat(tmp, iio->path);
strcat(tmp, "/in_accel_y_raw");
iio->accel_y_fd = fopen(tmp, "r");
memset(tmp, 0, tmp_sz);
strcat(tmp, iio->path);
strcat(tmp, "/in_accel_z_raw");
iio->accel_z_fd = fopen(tmp, "r");
memset(tmp, 0, tmp_sz);
strcat(tmp, iio->path);
strcat(tmp, "/in_anglvel_x_raw");
iio->anglvel_x_fd = fopen(tmp, "r");
memset(tmp, 0, tmp_sz);
strcat(tmp, iio->path);
strcat(tmp, "/in_anglvel_y_raw");
iio->anglvel_y_fd = fopen(tmp, "r");
memset(tmp, 0, tmp_sz);
strcat(tmp, iio->path);
strcat(tmp, "/in_anglvel_z_raw");
iio->anglvel_z_fd = fopen(tmp, "r");
free(tmp);
printf(
"anglvel scale: x=%f, y=%f, z=%f | accel scale: x=%f, y=%f, z=%f\n",
iio->anglvel_scale_x,
iio->anglvel_scale_y,
iio->anglvel_scale_z,
iio->accel_scale_x,
iio->accel_scale_y,
iio->accel_scale_z
);
// give time to change the scale
sleep(4);
dev_old_iio_create_err:
return iio;
}
void dev_old_iio_destroy(dev_old_iio_t* iio) {
fclose(iio->accel_x_fd);
fclose(iio->accel_y_fd);
fclose(iio->accel_z_fd);
fclose(iio->anglvel_x_fd);
fclose(iio->anglvel_y_fd);
fclose(iio->anglvel_z_fd);
free(iio->name);
free(iio->path);
free(iio);
}
const char* dev_old_iio_get_name(const dev_old_iio_t* iio) {
return iio->name;
}
const char* dev_old_iio_get_path(const dev_old_iio_t* iio) {
return iio->path;
}
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_old_iio_read_imu(const dev_old_iio_t *const iio, in_message_t *const messages) {
int res = 0;
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
perror("Error getting time");
return res; // Handle the error appropriately in your application
}
const uint64_t nanoseconds = (tp.tv_sec * 1000000000ULL) + tp.tv_nsec;
uint16_t accel_x_raw = 0, accel_y_raw = 0, accel_z_raw = 0;
uint16_t gyro_x_raw = 0, gyro_y_raw = 0, gyro_z_raw = 0;
char tmp[128];
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) {
accel_x_raw = strtol(&tmp[0], NULL, 10);
} else {
fprintf(stderr, "While reading accel(x): %d\n", tmp_read);
goto dev_old_iio_read_imu_err;
}
}
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) {
accel_y_raw = strtol(&tmp[0], NULL, 10);
} else {
fprintf(stderr, "While reading accel(y): %d\n", tmp_read);
goto dev_old_iio_read_imu_err;
}
}
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) {
accel_z_raw = strtol(&tmp[0], NULL, 10);
} else {
fprintf(stderr, "While reading accel(z): %d\n", tmp_read);
goto dev_old_iio_read_imu_err;
}
}
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) {
gyro_x_raw = strtol(&tmp[0], NULL, 10);
} else {
fprintf(stderr, "While reading anglvel(x): %d\n", tmp_read);
goto dev_old_iio_read_imu_err;
}
}
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) {
gyro_y_raw = strtol(&tmp[0], NULL, 10);
} else {
fprintf(stderr, "While reading anglvel(y): %d\n", tmp_read);
goto dev_old_iio_read_imu_err;
}
}
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) {
gyro_z_raw = strtol(&tmp[0], NULL, 10);
} else {
fprintf(stderr, "While reading anglvel(z): %d\n", tmp_read);
goto dev_old_iio_read_imu_err;
}
}
messages[0].type = GAMEPAD_SET_ELEMENT;
messages[0].data.gamepad_set.element = GAMEPAD_ACCELEROMETER;
messages[1].data.gamepad_set.status.accel.sample_timestamp_ns = nanoseconds;
messages[0].data.gamepad_set.status.accel.x = (uint16_t)(-1) * accel_x_raw;
messages[0].data.gamepad_set.status.accel.y = accel_y_raw;
messages[0].data.gamepad_set.status.accel.z = accel_z_raw;
messages[1].type = GAMEPAD_SET_ELEMENT;
messages[1].data.gamepad_set.element = GAMEPAD_GYROSCOPE;
messages[1].data.gamepad_set.status.gyro.sample_timestamp_ns = nanoseconds;
messages[1].data.gamepad_set.status.gyro.x = (uint16_t)(-1) * gyro_x_raw;
messages[1].data.gamepad_set.status.gyro.y = gyro_y_raw;
messages[1].data.gamepad_set.status.gyro.z = gyro_z_raw;
res = 2;
dev_old_iio_read_imu_err:
return res;
}
typedef struct bmc150_accel_user_data {
dev_old_iio_t *iio;
char* name;
uint64_t errors;
} bmc150_accel_user_data_t;
static bmc150_accel_user_data_t bmc15_timer_data = {
.iio = NULL,
.name = NULL,
.errors = 0,
};
int rc71l_bmc150_accel_timer_map(const dev_in_settings_t *const conf, int timer_fd, uint64_t expirations, in_message_t *const messages, size_t messages_len, void* user_data) {
bmc150_accel_user_data_t *const timer_data = (bmc150_accel_user_data_t*)user_data;
static const uint64_t max_attempts = 250000000;
if (timer_data == NULL) {
return 0;
}
if (timer_data->iio == NULL) {
if (timer_data->errors < max_attempts) {
// try to open the device and give up after some errors
timer_data->iio = dev_old_iio_create(iio_base_path);
if (timer_data->iio == NULL) {
timer_data->errors++;
if (timer_data->errors == max_attempts) {
fprintf(stderr, "Max attempts to acquire bmc150 accel driver reached.\n");
}
}
}
return 0;
} else {
// read the device and fill data from that
return dev_old_iio_read_imu(timer_data->iio, messages);
}
return 0;
}
input_dev_t bmc150_timer_dev = {
.dev_type = input_dev_type_timer,
.filters = {
.timer = {
.name = "RC71L_bmc150-accel_timer",
.ticktime_ms = 0,
.ticktime_ns = 625000
}
},
.user_data = &bmc15_timer_data,
.map = {
.timer_callbacks = {
.map_fn = rc71l_bmc150_accel_timer_map,
}
}
};
int rc71l_timer_map(const dev_in_settings_t *const conf, int timer_fd, uint64_t expirations, in_message_t *const messages, size_t messages_len, void* user_data) {
rc71l_timer_user_data_t *const timer_data = (rc71l_timer_user_data_t*)user_data;
rc71l_platform_t *const platform_data = timer_data->parent;
@ -1513,41 +2026,6 @@ input_dev_t timer_dev = {
}
};
typedef struct bmc150_accel_user_data {
} bmc150_accel_user_data_t;
static bmc150_accel_user_data_t bmc15_timer_data = {
};
int rc71l_bmc150_accel_timer_map(const dev_in_settings_t *const conf, int timer_fd, uint64_t expirations, in_message_t *const messages, size_t messages_len, void* user_data) {
bmc150_accel_user_data_t *const timer_data = (bmc150_accel_user_data_t*)user_data;
if (timer_data == NULL) {
return 0;
}
return 0;
}
input_dev_t bmc150_timer_dev = {
.dev_type = input_dev_type_timer,
.filters = {
.timer = {
.name = "RC71L_bmc150-accel_timer",
.ticktime_ms = 0,
.ticktime_ns = 625000
}
},
.user_data = &bmc15_timer_data,
.map = {
.timer_callbacks = {
.map_fn = rc71l_bmc150_accel_timer_map,
}
}
};
input_dev_composite_t rc71l_composite = {
.dev = {
&in_xbox_dev,
@ -1564,9 +2042,12 @@ input_dev_composite_t rc71l_composite = {
input_dev_composite_t* rog_ally_device_def(const dev_in_settings_t *const conf) {
if (conf->enable_imu) {
if (false) {
bmc15_timer_data.name = read_file(iio_base_path, "name");
if ((bmc15_timer_data.name != NULL) && (strcmp(bmc15_timer_data.name, "bmi323"))) {
printf("Old bmc150-accel-i2c for bmi323 device has been selected! Are you running a neptune kernel?\n");
rc71l_composite.dev[rc71l_composite.dev_count++] = &bmc150_timer_dev;
} else {
printf("Using the newer upstreamed bmi323-imu driver\n");
rc71l_composite.dev[rc71l_composite.dev_count++] = &in_iio_dev;
}
}