Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

Commit

Permalink
IIO: Support oversampling_ratio configuration in IIO node
Browse files Browse the repository at this point in the history
Signed-off-by: Gu Chaojie <[email protected]>
  • Loading branch information
guchaojie committed Feb 3, 2017
1 parent 80a008e commit fc1ceb1
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 17 deletions.
3 changes: 3 additions & 0 deletions src/lib/io/include/sol-iio.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <sol-buffer.h>
#include <sol-common-buildopts.h>
#include <sol-str-table.h>

#include <linux/limits.h>

Expand Down Expand Up @@ -80,6 +81,8 @@ typedef struct sol_iio_config {
int buffer_size; /**< The size of reading buffer. 0: use device default; -1: disable buffer and readings will be performed on channel files on sysfs. */
int sampling_frequency; /**< Device sampling frequency. -1 uses device default */
char sampling_frequency_name[NAME_MAX]; /**< Sampling frequency sysfs node name. Some drivers expose the sampling frequency that is shared by channel type. Such as in_magn_sampling_frequency, in_accel_sampling_frequency. */
struct sol_str_table *oversampling_ratio_table; /**< Hardware applied number of measurements for acquiring one data point. The HW will do [_name]_oversampling_ratio measurements and return the average value as output data. */

} sol_iio_config;

/**
Expand Down
35 changes: 35 additions & 0 deletions src/lib/io/sol-iio.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ static struct sol_vector iio_opened_devices = SOL_VECTOR_INIT(struct iio_opened_
#define SAMPLING_FREQUENCY_DEVICE_PATH SYSFS_DEVICES_PATH "/iio:device%d/sampling_frequency"
#define CHANNEL_SAMPLING_FREQUENCY_DEVICE_PATH SYSFS_DEVICES_PATH "/iio:device%d/%ssampling_frequency"

#define CHANNEL_OVERSAMPLING_RATIO_DEVICE_PATH SYSFS_DEVICES_PATH "/iio:device%d/%soversampling_ratio"

#define SAMPLING_FREQUENCY_BUFFER_PATH SYSFS_DEVICES_PATH "/iio:device%d/buffer/sampling_frequency"
#define SAMPLING_FREQUENCY_TRIGGER_PATH SYSFS_DEVICES_PATH "/trigger%d/sampling_frequency"

Expand Down Expand Up @@ -653,6 +655,34 @@ channel_get_pure_name(const char *name)
return NULL;
}

static bool
iio_set_oversampling_ratio(struct sol_iio_device *device, const struct sol_iio_config *config)
{
char path[PATH_MAX];
struct sol_str_table *iter;

SOL_NULL_CHECK(device, false);

for (iter = config->oversampling_ratio_table; iter->key; iter++) {
if (!iter->val)
continue;

if (!craft_filename_path(path, sizeof(path), CHANNEL_OVERSAMPLING_RATIO_DEVICE_PATH,
device->device_id, iter->key)) {
SOL_WRN("Could not set oversampling ratio");
return false;
}

if (sol_util_write_file(path, "%d", iter->val) <= 0) {
SOL_WRN("Could not set oversampling ratio to %d at '%s'",
iter->val, path);
return false;
}
}

return true;
}

static bool
iio_set_sampling_frequency(struct sol_iio_device *device, const struct sol_iio_config *config)
{
Expand Down Expand Up @@ -949,6 +979,11 @@ sol_iio_open(int device_id, const struct sol_iio_config *config)
SOL_WRN("Could not set device%d sampling frequency", device->device_id);
}

if (config->oversampling_ratio_table) {
if (!iio_set_oversampling_ratio(device, config))
SOL_WRN("Could not set device%d oversampling ratio", device->device_id);
}

device->mount_matrix = calloc(MOUNT_MATRIX_LEN, sizeof(double));
SOL_NULL_CHECK_GOTO(device->mount_matrix, error);

Expand Down
18 changes: 18 additions & 0 deletions src/modules/flow/iio/iio.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@
"description": "Offset to be added to device raw readings",
"name": "offset"
},
{
"data_type": "direction-vector",
"default": {},
"description": "Oversampling ratio measurement of the sensor",
"name": "oversampling_ratio"
},
{
"data_type": "int",
"default": -1,
Expand Down Expand Up @@ -344,6 +350,12 @@
"description": "Offset to be added to device raw readings",
"name": "offset"
},
{
"data_type": "int",
"default": 0,
"description": "Oversampling ratio measurement of the sensor",
"name": "oversampling_ratio"
},
{
"data_type": "int",
"default": -1,
Expand Down Expand Up @@ -471,6 +483,12 @@
"description": "Offset to be added to device raw readings",
"name": "offset"
},
{
"data_type": "int",
"default": 0,
"description": "Oversampling ratio measurement of the sensor",
"name": "oversampling_ratio"
},
{
"data_type": "int",
"default": -1,
Expand Down
78 changes: 61 additions & 17 deletions src/modules/flow/iio/nodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,20 @@
if (_id >= 0) { \
int _ret; \
_ret = snprintf(_channel_name, sizeof(_channel_name), _name "%d", _id); \
SOL_INT_CHECK_GOTO(_ret, >= (int)sizeof(_channel_name), _error); \
SOL_INT_CHECK_GOTO(_ret, < 0, _error); \
SOL_EXP_CHECK_GOTO(_ret < 0 || _ret >= (int)sizeof(_channel_name), _error); \
} else { \
strncpy(_channel_name, _name, sizeof(_channel_name) - 1); \
_channel_name[sizeof(_channel_name) - 1] = '\0'; \
}

#define GEN_SOL_STR_TABLE(key, len, val, name, value) \
do { \
key = strdup(name); \
SOL_NULL_CHECK(key, -ENOMEM); \
len = strlen(key); \
val = value; \
} while (0)

struct iio_device_config {
struct sol_iio_config config;
struct sol_drange_spec out_range;
Expand Down Expand Up @@ -111,9 +118,19 @@ static void
iio_common_close(struct sol_flow_node *node, void *data)
{
struct iio_device_config *mdata = data;
struct sol_str_table *iter;

free((char *)mdata->config.trigger_name);

if (!mdata->config.oversampling_ratio_table)
goto end;

for (iter = mdata->config.oversampling_ratio_table; iter->key; iter++)
free(iter->key);

free(mdata->config.oversampling_ratio_table);

end:
if (mdata->device)
sol_iio_close(mdata->device);
}
Expand Down Expand Up @@ -418,8 +435,7 @@ gyroscope_open(struct sol_flow_node *node, void *data, const struct sol_flow_nod
mdata->iio_base.config.sampling_frequency = opts->sampling_frequency;
ret = snprintf(mdata->iio_base.config.sampling_frequency_name,
sizeof(mdata->iio_base.config.sampling_frequency_name), "%s", "in_anglvel_");
SOL_INT_CHECK_GOTO(ret, >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);
SOL_INT_CHECK_GOTO(ret, < 0, err);
SOL_EXP_CHECK_GOTO(ret < 0 || ret >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);

if (mdata->iio_base.buffer_enabled) {
mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb;
Expand Down Expand Up @@ -481,6 +497,7 @@ magnet_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_o
const struct sol_flow_node_type_iio_magnetometer_options *opts;
int device_id, ret;
struct iio_node_type *type;
struct sol_str_table *table;

type = (struct iio_node_type *)sol_flow_node_get_type(node);

Expand All @@ -502,8 +519,20 @@ magnet_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_o
mdata->iio_base.config.sampling_frequency = opts->sampling_frequency;
ret = snprintf(mdata->iio_base.config.sampling_frequency_name,
sizeof(mdata->iio_base.config.sampling_frequency_name), "%s", "in_magn_");
SOL_INT_CHECK_GOTO(ret, >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);
SOL_INT_CHECK_GOTO(ret, < 0, err);
SOL_EXP_CHECK_GOTO(ret < 0 || ret >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);

mdata->iio_base.config.oversampling_ratio_table = calloc(4, sizeof(struct sol_str_table));
SOL_NULL_CHECK(mdata->iio_base.config.oversampling_ratio_table, -ENOMEM);

table = mdata->iio_base.config.oversampling_ratio_table;
GEN_SOL_STR_TABLE(table->key, table->len, table->val,
"in_magn_x_", (int16_t)opts->oversampling_ratio.x);
table++;
GEN_SOL_STR_TABLE(table->key, table->len, table->val,
"in_magn_y_", (int16_t)opts->oversampling_ratio.y);
table++;
GEN_SOL_STR_TABLE(table->key, table->len, table->val,
"in_magn_z_", (int16_t)opts->oversampling_ratio.z);

if (mdata->iio_base.buffer_enabled) {
mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb;
Expand Down Expand Up @@ -558,8 +587,9 @@ temperature_open(struct sol_flow_node *node, void *data, const struct sol_flow_n
{
struct iio_double_data *mdata = data;
const struct sol_flow_node_type_iio_thermometer_options *opts;
int device_id;
int device_id, ret;
struct iio_node_type *type;
struct sol_str_table *table;

type = (struct iio_node_type *)sol_flow_node_get_type(node);

Expand All @@ -579,6 +609,17 @@ temperature_open(struct sol_flow_node *node, void *data, const struct sol_flow_n
mdata->iio_base.data_type = DOUBLE;
mdata->iio_base.config.buffer_size = opts->buffer_size;
mdata->iio_base.config.sampling_frequency = opts->sampling_frequency;
ret = snprintf(mdata->iio_base.config.sampling_frequency_name,
sizeof(mdata->iio_base.config.sampling_frequency_name), "%s", "in_temp_");
SOL_EXP_CHECK_GOTO(ret < 0 || ret >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);

mdata->iio_base.config.oversampling_ratio_table = calloc(2, sizeof(struct sol_str_table));
SOL_NULL_CHECK(mdata->iio_base.config.oversampling_ratio_table, -ENOMEM);

table = mdata->iio_base.config.oversampling_ratio_table;
GEN_SOL_STR_TABLE(table->key, table->len, table->val,
"in_temp_", opts->oversampling_ratio);

if (mdata->iio_base.buffer_enabled) {
mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb;
mdata->iio_base.config.data = node;
Expand Down Expand Up @@ -635,6 +676,7 @@ pressure_open(struct sol_flow_node *node, void *data, const struct sol_flow_node
const struct sol_flow_node_type_iio_pressure_sensor_options *opts;
int device_id, ret;
struct iio_node_type *type;
struct sol_str_table *table;

type = (struct iio_node_type *)sol_flow_node_get_type(node);

Expand All @@ -656,8 +698,14 @@ pressure_open(struct sol_flow_node *node, void *data, const struct sol_flow_node
mdata->iio_base.config.sampling_frequency = opts->sampling_frequency;
ret = snprintf(mdata->iio_base.config.sampling_frequency_name,
sizeof(mdata->iio_base.config.sampling_frequency_name), "%s", "in_pressure_");
SOL_INT_CHECK_GOTO(ret, >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);
SOL_INT_CHECK_GOTO(ret, < 0, err);
SOL_EXP_CHECK_GOTO(ret < 0 || ret >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);

mdata->iio_base.config.oversampling_ratio_table = calloc(2, sizeof(struct sol_str_table));
SOL_NULL_CHECK(mdata->iio_base.config.oversampling_ratio_table, -ENOMEM);

table = mdata->iio_base.config.oversampling_ratio_table;
GEN_SOL_STR_TABLE(table->key, table->len, table->val,
"in_pressure_", opts->oversampling_ratio);

if (mdata->iio_base.buffer_enabled) {
mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb;
Expand Down Expand Up @@ -828,8 +876,7 @@ accelerate_open(struct sol_flow_node *node, void *data, const struct sol_flow_no
mdata->iio_base.config.sampling_frequency = opts->sampling_frequency;
ret = snprintf(mdata->iio_base.config.sampling_frequency_name,
sizeof(mdata->iio_base.config.sampling_frequency_name), "%s", "in_accel_");
SOL_INT_CHECK_GOTO(ret, >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);
SOL_INT_CHECK_GOTO(ret, < 0, err);
SOL_EXP_CHECK_GOTO(ret < 0 || ret >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);

if (mdata->iio_base.buffer_enabled) {
mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb;
Expand Down Expand Up @@ -1065,8 +1112,7 @@ light_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_op
mdata->iio_base.config.sampling_frequency = opts->sampling_frequency;
ret = snprintf(mdata->iio_base.config.sampling_frequency_name,
sizeof(mdata->iio_base.config.sampling_frequency_name), "%s", "in_illuminance_");
SOL_INT_CHECK_GOTO(ret, >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);
SOL_INT_CHECK_GOTO(ret, < 0, err);
SOL_EXP_CHECK_GOTO(ret < 0 || ret >= (int)sizeof(mdata->iio_base.config.sampling_frequency_name), err);

if (mdata->iio_base.buffer_enabled) {
mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb;
Expand Down Expand Up @@ -1107,8 +1153,7 @@ intensity_both_create_channels(struct iio_double_data *mdata, int device_id, con

if (channel_id >= 0) {
ret = snprintf(channel_name, sizeof(channel_name), "in_intensity%d_both", channel_id);
SOL_INT_CHECK_GOTO(ret, >= (int)sizeof(channel_name), error);
SOL_INT_CHECK_GOTO(ret, < 0, error);
SOL_EXP_CHECK_GOTO(ret < 0 || ret >= (int)sizeof(channel_name), error);
} else {
strncpy(channel_name, "in_intensity_both", sizeof(channel_name) - 1);
channel_name[sizeof(channel_name) - 1] = '\0';
Expand Down Expand Up @@ -1194,8 +1239,7 @@ intensity_ir_create_channels(struct iio_double_data *mdata, int device_id, const

if (channel_id >= 0) {
ret = snprintf(channel_name, sizeof(channel_name), "in_intensity%d_ir", channel_id);
SOL_INT_CHECK_GOTO(ret, >= (int)sizeof(channel_name), error);
SOL_INT_CHECK_GOTO(ret, < 0, error);
SOL_EXP_CHECK_GOTO(ret < 0 || ret >= (int)sizeof(channel_name), error);
} else {
strncpy(channel_name, "in_intensity_ir", sizeof(channel_name) - 1);
channel_name[sizeof(channel_name) - 1] = '\0';
Expand Down

0 comments on commit fc1ceb1

Please sign in to comment.