Skip to content

Commit

Permalink
Refactor for multi-device support (#29)
Browse files Browse the repository at this point in the history
* WIP refactor, mostly working
* Fixed issues with calibration state
* Solved issue with duplicate free() calls
* Hide all device-specific functionality behind generic interfaces
* Reduce default look-ahead multiplier for XREAL
  • Loading branch information
wheaney authored Nov 29, 2023
1 parent f6f1de2 commit aac35c0
Show file tree
Hide file tree
Showing 21 changed files with 1,026 additions and 706 deletions.
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ add_subdirectory(modules/xrealInterfaceLibrary/interface_lib)

add_executable(xrealAirLinuxDriver
src/buffer.c
src/config.c
src/driver.c
src/files.c
src/ipc.c
src/multitap.c
src/driver.c
src/outputs.c
src/strings.c
src/xreal.c
)

target_include_directories(xrealAirLinuxDriver
Expand Down
10 changes: 9 additions & 1 deletion bin/xreal_driver_setup
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ if [ "$(id -u)" != "0" ]; then
exit 1
fi

start_dir=$(pwd)

# create temp directory
tmp_dir=$(mktemp -d -t xreal-air-XXXXXXXXXX)
pushd $tmp_dir > /dev/null
Expand All @@ -23,7 +25,13 @@ then
echo "Downloading latest release to: ${tmp_dir}/xrealAirLinuxDriver.tar.gz"
curl -L -O https://github.com/wheaney/xrealAirLinuxDriver/releases/latest/download/xrealAirLinuxDriver.tar.gz
else
cp $1 $tmp_dir
if [[ "$1" = /* ]]; then
abs_path="$1"
else
# Convert relative path to absolute path
abs_path=$(realpath "$start_dir/$1")
fi
cp $abs_path $tmp_dir
fi

echo "Extracting to: ${tmp_dir}/driver_air_glasses"
Expand Down
2 changes: 2 additions & 0 deletions include/buffer.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#pragma once

#include <stdbool.h>

struct buffer_t {
Expand Down
31 changes: 31 additions & 0 deletions include/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <stdbool.h>

struct driver_config_t {
bool disabled;
bool use_roll_axis;
int mouse_sensitivity;
char *output_mode;
float look_ahead_override;
float external_zoom;

bool debug_threads;
bool debug_joystick;
bool debug_multi_tap;
bool debug_ipc;
};

typedef struct driver_config_t driver_config_type;

extern const char *joystick_output_mode;
extern const char *mouse_output_mode;
extern const char *external_only_output_mode;

driver_config_type *default_config();
void update_config(driver_config_type **config, driver_config_type *new_config);

bool is_joystick_mode(driver_config_type *config);
bool is_mouse_mode(driver_config_type *config);
bool is_external_mode(driver_config_type *config);
bool is_evdev_output_mode(driver_config_type *config);
28 changes: 28 additions & 0 deletions include/device.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
#pragma once

#include "driver.h"

#include <stdbool.h>

typedef bool (*device_connect_func)(imu_event_handler handler);
typedef void (*block_on_device_func)(should_disconnect_callback should_disconnect_func);
typedef bool (*device_is_sbs_mode_func)();
typedef bool (*device_set_sbs_mode_func)(bool enabled);
typedef void (*device_cleanup_func)();

struct device_properties_t {
// resolution width and height
int resolution_w;
Expand All @@ -10,6 +22,22 @@ struct device_properties_t {
float lens_distance_ratio;

int calibration_wait_s;

int imu_cycles_per_s;

// how many events to buffer for velocity smoothing
int imu_buffer_size;

// look-ahead = look_ahead_ftm * frametime + look_ahead_constant
// where frametime is the duration of a frame e.g. 33ms for 30Hz framerate
float look_ahead_constant;
float look_ahead_frametime_multiplier;

device_connect_func device_connect_func;
block_on_device_func block_on_device_func;
device_is_sbs_mode_func device_is_sbs_mode_func;
device_set_sbs_mode_func device_set_sbs_mode_func;
device_cleanup_func device_cleanup_func;
};

typedef struct device_properties_t device_properties_type;
9 changes: 9 additions & 0 deletions include/driver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "imu.h"

#include <stdbool.h>
#include <stdint.h>

typedef void (*imu_event_handler)(uint32_t timestamp_ms, imu_quat_type quat, imu_vector_type euler);
typedef bool (*should_disconnect_callback)();
8 changes: 8 additions & 0 deletions include/files.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <stdio.h>
#include <stdbool.h>

// creates a file, if it doesn't already exist, in the user home directory with home directory permissions and ownership.
// this is helpful since the driver may be run with sudo, so we don't create files owned by root:root
FILE* get_or_create_home_file(char *filename, char *mode, char *full_path, bool *created);
17 changes: 17 additions & 0 deletions include/imu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

struct imu_vector_t {
float x;
float y;
float z;
};

struct imu_quat_t {
float x;
float y;
float z;
float w;
};

typedef struct imu_vector_t imu_vector_type;
typedef struct imu_quat_t imu_quat_type;
35 changes: 33 additions & 2 deletions include/ipc.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
#pragma once

#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>

void set_ipc_file_prefix(char *new_prefix);
// TODO - this is specific to the sombrero integration, either provide no default or move to a plug-in system where
// the plug-in library would be expected to provide this default, if this functionality is used
extern const char *sombrero_ipc_file_prefix;

extern const char *imu_data_ipc_name;
extern const char *imu_data_mutex_ipc_name;
extern const char *imu_data_period_name;
extern const char *look_ahead_cfg_ipc_name;
extern const char *display_res_ipc_name;
extern const char *display_fov_ipc_name;
extern const char *lens_distance_ratio_ipc_name;
extern const char *zoom_ipc_name;
extern const char *disabled_ipc_name;
extern const char *date_ipc_name;

struct ipc_values_t {
float *imu_data;
pthread_mutex_t *imu_data_mutex;
float *imu_data_period;
float *look_ahead_cfg;
unsigned int *display_res;
float *display_fov;
float *lens_distance_ratio;
float *zoom;
bool *disabled;
float *date;
};

typedef struct ipc_values_t ipc_values_type;

char *get_ipc_file_prefix();
bool setup_ipc_values(ipc_values_type *ipc_values, bool debug);

void setup_ipc_value(const char *name, void **shmemValue, size_t size, bool debug);

Expand Down
9 changes: 7 additions & 2 deletions include/multitap.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#include "device3.h"
#pragma once

#include "imu.h"

#include <stdbool.h>
#include <stdint.h>

void init_multi_tap(int init_imu_cycles_per_s);

int detect_multi_tap(device3_vec3_type velocities, uint64_t timestamp, const int cycles_per_second, bool debug_multi_tap);
int detect_multi_tap(imu_vector_type velocities, uint32_t timestamp, bool debug);
22 changes: 22 additions & 0 deletions include/outputs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "config.h"
#include "device.h"
#include "imu.h"
#include "ipc.h"

#include <stdbool.h>

void init_outputs(device_properties_type *device, driver_config_type *config);

void deinit_outputs(driver_config_type *config);

imu_vector_type get_euler_deltas(imu_vector_type euler);

imu_vector_type get_euler_velocities(device_properties_type *device, imu_vector_type euler_deltas);

void handle_imu_update(imu_quat_type quat, imu_vector_type euler_deltas, imu_quat_type screen_center,
bool ipc_enabled, bool imu_calibrated, ipc_values_type *ipc_values, device_properties_type *device,
driver_config_type *config);

void reset_imu_data(ipc_values_type *ipc_values);
7 changes: 7 additions & 0 deletions include/strings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include <stdlib.h>

void copy_string(const char *source, char **destination, size_t size);

void free_and_clear(char **str_ptr);
10 changes: 3 additions & 7 deletions include/xreal.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
static const device_properties_type xreal_air_properties = {
.resolution_w = 1920,
.resolution_h = 1080,
.fov = 46.0,
.lens_distance_ratio = 0.035,
.calibration_wait_s = 15
};
#pragma once

extern const device_properties_type xreal_air_properties;
56 changes: 56 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "config.h"
#include "device.h"
#include "string.h"

#include <stdbool.h>
#include <stdio.h>

const char *joystick_output_mode = "joystick";
const char *mouse_output_mode = "mouse";
const char *external_only_output_mode = "external_only";


driver_config_type *default_config() {
driver_config_type *config = malloc(sizeof(driver_config_type));
if (config == NULL) {
fprintf(stderr, "Error allocating config");
exit(1);
}

config->disabled = false;
config->use_roll_axis = false;
config->mouse_sensitivity = 30;
config->output_mode = NULL;
config->look_ahead_override = 0.0;
config->external_zoom = 1.0;
config->debug_threads = false;
config->debug_joystick = false;
config->debug_multi_tap = false;
config->debug_ipc = false;

copy_string(mouse_output_mode, &config->output_mode, strlen(mouse_output_mode) + 1);

return config;
}

void update_config(driver_config_type **config, driver_config_type *new_config) {
free((*config)->output_mode);
free(*config);
*config = new_config;
}

bool is_joystick_mode(driver_config_type *config) {
return strcmp(config->output_mode, joystick_output_mode) == 0;
}

bool is_mouse_mode(driver_config_type *config) {
return strcmp(config->output_mode, mouse_output_mode) == 0;
}

bool is_external_mode(driver_config_type *config) {
return strcmp(config->output_mode, external_only_output_mode) == 0;
}

bool is_evdev_output_mode(driver_config_type *config) {
return is_mouse_mode(config) || is_joystick_mode(config);
}
Loading

0 comments on commit aac35c0

Please sign in to comment.