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

Commit

Permalink
flow:iio: Add Proximity sensor Category support into iio node
Browse files Browse the repository at this point in the history
Signed-off-by: Yong Li <[email protected]>
  • Loading branch information
yongli3 committed May 9, 2016
1 parent 2a10cd7 commit 3c3b5a3
Show file tree
Hide file tree
Showing 2 changed files with 243 additions and 0 deletions.
89 changes: 89 additions & 0 deletions src/modules/flow/iio/iio.json
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,95 @@
}
],
"private_data_type": "light_data"
},
{
"category": "input/hw",
"description": "IIO based proximity input node. As any IIO device, it can use a buffer to get the readings. To use a buffer, define a size > 0 on buffer size. Readings are sent to the buffer via a trigger mechanism. Set iio_trigger_name to a valid iio trigger name in order to use buffer. If buffer is enabled but no iio_trigger_name was set, it will attempt to create a default trigger that will be activated when sending packets to TICK port.",
"in_ports": [
{
"data_type": "any",
"description": "Packets sent in here will trigger a proximity reading and produce packets on each of the the output ports. If buffer is enabled, current trigger must accept manual activation (default one, sysfs trigger, does).",
"name": "TICK",
"methods": {
"process": "proximity_tick"
}
}
],
"methods": {
"close": "proximity_close",
"open": "proximity_open"
},
"name": "iio/proximity",
"options": {
"members": [
{
"data_type": "string",
"description": "IIO device identifier. It's a space separated list of commands. For commands, if it's an integer value, will be interpreted as IIO device id. If it's a string starting with '/', will be interpreted as absolute path of IIO device on sysfs. If it's on the form 'i2c/X-YYYY', will evaluate to an i2c device on sysfs, where X is the bus number and YYYY is the device number, eg, 7-0069, for device 0x69 on bus 7. If it's on the form 'create,i2c,<rel_path>,<devnumber>,<devname>', where rel_path is the path of bus relative to '/sys/devices', them it will attempt to create an IIO device on that i2c bus and use it.",
"name": "iio_device"
},
{
"data_type": "int",
"description": "IIO buffer size. If -1, buffering is disabled. If 0, will use default buffer size. If enabled (> 0), a trigger is necessary to perform readings. Set it using 'iio_trigger_name'; if no trigger name is set, it will attempt to create a default one, which is activated via TICK port.",
"default": 0,
"name": "buffer_size"
},
{
"data_type": "string",
"description": "IIO trigger name. Name of IIO trigger that should be associated to this device for buffered readings. If not set and buffer enabled, will try to use device current trigger, if any. If none, will attempt to create a sysfs trigger",
"name": "iio_trigger_name",
"default": null
},
{
"data_type": "boolean",
"default": true,
"description": "If should use device own default scale. If false, it will attempt to use scale option.",
"name": "use_device_default_scale"
},
{
"data_type": "float",
"default": 0,
"description": "Scale to applied to device raw readings",
"name": "scale"
},
{
"data_type": "boolean",
"default": true,
"description": "If should use device own default offset. If false, it will attempt to use offset_x, offset_y and offset_z options.",
"name": "use_device_default_offset"
},
{
"data_type": "float",
"default": 0,
"description": "Offset to be added to device raw readings",
"name": "offset"
},
{
"data_type": "int",
"default": -1,
"description": "Sampling frequency of the sensor. If -1, use device default",
"name": "sampling_frequency"
},
{
"data_type": "drange-spec",
"default": {
"max": "DBL_MAX",
"min": "-DBL_MAX",
"step": "DBL_MIN"
},
"description": "Range of output packet. Usually, is the output range of used sensor. It'll be the 'min' and 'max' fields of drange packets sent on OUT port.",
"name": "out_range"
}
],
"version": 1
},
"out_ports": [
{
"data_type": "float",
"description": "proximity data read.",
"name": "OUT"
}
],
"private_data_type": "proximity_data"
}
]
}
154 changes: 154 additions & 0 deletions src/modules/flow/iio/nodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1429,4 +1429,158 @@ light_tick(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_
return -EIO;
}

struct proximity_data {
struct sol_iio_config config;
struct sol_drange_spec out_range;
double scale;
double offset;
struct sol_iio_device *device;
struct sol_iio_channel *channel_val;
bool buffer_enabled : 1;
bool use_device_default_scale : 1;
bool use_device_default_offset : 1;
};

static void
proximity_reader_cb(void *data, struct sol_iio_device *device)
{
static const char *errmsg = "Could not read channel buffer values";
struct sol_flow_node *node = data;
struct proximity_data *mdata = sol_flow_node_get_private_data(node);
struct sol_drange out = {
.min = mdata->out_range.min,
.max = mdata->out_range.max,
.step = mdata->out_range.step
};
bool b;

b = sol_iio_read_channel_value(mdata->channel_val, &out.val);
if (!b) goto error;

sol_flow_send_drange_value_packet(node,
SOL_FLOW_NODE_TYPE_IIO_PROXIMITY__OUT__OUT, out.val);

return;

error:
sol_flow_send_error_packet_str(node, EIO, errmsg);
SOL_WRN("%s", errmsg);
}

static bool
proximity_create_channels(struct proximity_data *mdata, int device_id)
{
struct sol_iio_channel_config channel_config = SOL_IIO_CHANNEL_CONFIG_INIT;

mdata->device = sol_iio_open(device_id, &mdata->config);
SOL_NULL_CHECK(mdata->device, false);

#define ADD_CHANNEL(_val) \
if (!mdata->use_device_default_scale) \
channel_config.scale = mdata->scale; \
if (!mdata->use_device_default_offset) \
channel_config.offset = mdata->offset; \
mdata->channel_ ## _val = sol_iio_add_channel(mdata->device, "in_proximity", &channel_config); \
if (!mdata->channel_ ## _val) \
mdata->channel_ ## _val = sol_iio_add_channel(mdata->device, "in_proximity2", &channel_config); \
SOL_NULL_CHECK_GOTO(mdata->channel_ ## _val, error);

ADD_CHANNEL(val);

#undef ADD_CHANNEL

sol_iio_device_start_buffer(mdata->device);

return true;

error:
SOL_WRN("Could not create iio/proximity node. Failed to open IIO device %d",
device_id);

sol_iio_close(mdata->device);
return false;
}

static int
proximity_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
struct proximity_data *mdata = data;
const struct sol_flow_node_type_iio_proximity_options *opts;
int device_id;

SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_PROXIMITY_OPTIONS_API_VERSION,
-EINVAL);
opts = (const struct sol_flow_node_type_iio_proximity_options *)options;

mdata->buffer_enabled = opts->buffer_size > -1;

SOL_SET_API_VERSION(mdata->config.api_version = SOL_IIO_CONFIG_API_VERSION; )

if (opts->iio_trigger_name) {
mdata->config.trigger_name = strdup(opts->iio_trigger_name);
SOL_NULL_CHECK(mdata->config.trigger_name, -ENOMEM);
}

mdata->config.buffer_size = opts->buffer_size;
mdata->config.sampling_frequency = opts->sampling_frequency;
if (mdata->buffer_enabled) {
mdata->config.sol_iio_reader_cb = proximity_reader_cb;
mdata->config.data = node;
}
mdata->use_device_default_scale = opts->use_device_default_scale;
mdata->use_device_default_offset = opts->use_device_default_offset;
mdata->scale = opts->scale;
mdata->offset = opts->offset;
mdata->out_range = opts->out_range;

device_id = sol_iio_address_device(opts->iio_device);
if (device_id < 0) {
SOL_WRN("Could not create iio/proximity node. Failed to open IIO device %s",
opts->iio_device);
goto err;
}

if (!proximity_create_channels(mdata, device_id))
goto err;

return 0;

err:
free((char *)mdata->config.trigger_name);
return -EINVAL;

}

static void
proximity_close(struct sol_flow_node *node, void *data)
{
struct proximity_data *mdata = data;

free((char *)mdata->config.trigger_name);
if (mdata->device)
sol_iio_close(mdata->device);
}

static int
proximity_tick(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
static const char *errmsg = "Could not read channel values";
struct proximity_data *mdata = data;

if (mdata->buffer_enabled) {
if (!sol_iio_device_trigger_now(mdata->device))
goto error;
} else {
proximity_reader_cb(node, mdata->device);
}

return 0;

error:
sol_flow_send_error_packet(node, EIO, "%s", errmsg);
SOL_WRN("%s", errmsg);

return -EIO;
}

#include "iio-gen.c"

0 comments on commit 3c3b5a3

Please sign in to comment.