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

IIO: Support oversampling_ratio configuration in IIO node #2354

Merged
merged 1 commit into from
Feb 16, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a public API. Do you really need to make this check here?

Copy link
Contributor Author

@guchaojie guchaojie Jan 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES, check the input parameter pointer in function "iio_set_sampling_frequency" too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as @cabelitos said this does not make sense. There is only one place where this function is called and you have already checked this parameter there. It's looking redundant.


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",
Copy link
Contributor

@laykuanloon laykuanloon Jan 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This "data_type" should be "sol_str_table" ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In iio.json, data_type cannot be sol_str_table here, please check https://github.com/solettaproject/soletta/blob/master/src/lib/common/include/sol-types.h

"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