static void iio_direction_vector_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 iio_direction_vector_data *mdata = sol_flow_node_get_private_data(node); struct sol_direction_vector out = { .min = mdata->iio_base.out_range.min, .max = mdata->iio_base.out_range.max }; int r; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); r = sol_iio_read_channel_value(mdata->channel_x, &out.x); SOL_INT_CHECK_GOTO(r, < 0, error); r = sol_iio_read_channel_value(mdata->channel_y, &out.y); SOL_INT_CHECK_GOTO(r, < 0, error); r = sol_iio_read_channel_value(mdata->channel_z, &out.z); SOL_INT_CHECK_GOTO(r, < 0, error); sol_flow_send_direction_vector_packet(node, type->out_port, &out); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static void iio_double_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 iio_double_data *mdata = sol_flow_node_get_private_data(node); struct sol_drange out = { .min = mdata->iio_base.out_range.min, .max = mdata->iio_base.out_range.max, .step = mdata->iio_base.out_range.step }; int r; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); r = sol_iio_read_channel_value(mdata->channel_val, &out.val); SOL_INT_CHECK_GOTO(r, < 0, error); sol_flow_send_drange_value_packet(node, type->out_port, out.val); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static void iio_color_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 iio_color_data *mdata = sol_flow_node_get_private_data(node); struct sol_rgb out = { .red_max = mdata->iio_base.out_range.max, .green_max = mdata->iio_base.out_range.max, .blue_max = mdata->iio_base.out_range.max }; double tmp; int r; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); r = sol_iio_read_channel_value(mdata->channel_red, &tmp); if (r < 0 || tmp < 0 || tmp > UINT32_MAX) goto error; out.red = tmp; r = sol_iio_read_channel_value(mdata->channel_green, &tmp); if (r < 0 || tmp < 0 || tmp > UINT32_MAX) goto error; out.green = tmp; r = sol_iio_read_channel_value(mdata->channel_blue, &tmp); if (r < 0 || tmp < 0 || tmp > UINT32_MAX) goto error; out.blue = tmp; sol_flow_send_rgb_packet(node, type->out_port, &out); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static bool gyroscope_create_channels(struct iio_direction_vector_data *mdata, int device_id) { struct sol_iio_channel_config channel_config = SOL_IIO_CHANNEL_CONFIG_INIT; mdata->iio_base.device = sol_iio_open(device_id, &mdata->iio_base.config); SOL_NULL_CHECK(mdata->iio_base.device, false); #define ADD_CHANNEL(_axis) \ if (!mdata->iio_base.use_device_default_scale) \ channel_config.scale = mdata->scale._axis; \ if (!mdata->iio_base.use_device_default_offset) \ channel_config.offset = mdata->offset._axis; \ mdata->channel_ ## _axis = sol_iio_add_channel(mdata->iio_base.device, "in_anglvel_" # _axis, &channel_config); \ SOL_NULL_CHECK_GOTO(mdata->channel_ ## _axis, error); ADD_CHANNEL(x); ADD_CHANNEL(y); ADD_CHANNEL(z); #undef ADD_CHANNEL sol_iio_device_start_buffer(mdata->iio_base.device); return true; error: SOL_WRN("Could not create iio/gyroscope node. Failed to open IIO device %d", device_id); sol_iio_close(mdata->iio_base.device); return false; } static int gyroscope_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct iio_direction_vector_data *mdata = data; const struct sol_flow_node_type_iio_gyroscope_options *opts; int device_id; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_GYROSCOPE_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_iio_gyroscope_options *)options; mdata->iio_base.buffer_enabled = opts->buffer_size > -1; SOL_SET_API_VERSION(mdata->iio_base.config.api_version = SOL_IIO_CONFIG_API_VERSION; ) if (opts->iio_trigger_name) { mdata->iio_base.config.trigger_name = strdup(opts->iio_trigger_name); SOL_NULL_CHECK(mdata->iio_base.config.trigger_name, -ENOMEM); } mdata->iio_base.config.buffer_size = opts->buffer_size; mdata->iio_base.config.sampling_frequency = opts->sampling_frequency; if (mdata->iio_base.buffer_enabled) { mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb; mdata->iio_base.config.data = node; } mdata->iio_base.use_device_default_scale = opts->use_device_default_scale; mdata->iio_base.use_device_default_offset = opts->use_device_default_offset; mdata->scale = opts->scale; mdata->offset = opts->offset; mdata->iio_base.out_range = opts->out_range; device_id = sol_iio_address_device(opts->iio_device); if (device_id < 0) { SOL_WRN("Could not create iio/gyroscope node. Failed to open IIO device %s", opts->iio_device); goto err; } if (!gyroscope_create_channels(mdata, device_id)) goto err; return 0; err: free((char *)mdata->iio_base.config.trigger_name); return -EINVAL; } static bool magnet_create_channels(struct iio_direction_vector_data *mdata, int device_id) { struct sol_iio_channel_config channel_config = SOL_IIO_CHANNEL_CONFIG_INIT; mdata->iio_base.device = sol_iio_open(device_id, &mdata->iio_base.config); SOL_NULL_CHECK(mdata->iio_base.device, false); #define ADD_CHANNEL(_axis) \ if (!mdata->iio_base.use_device_default_scale) \ channel_config.scale = mdata->scale._axis; \ if (!mdata->iio_base.use_device_default_offset) \ channel_config.offset = mdata->offset._axis; \ mdata->channel_ ## _axis = sol_iio_add_channel(mdata->iio_base.device, "in_magn_" # _axis, &channel_config); \ SOL_NULL_CHECK_GOTO(mdata->channel_ ## _axis, error); ADD_CHANNEL(x); ADD_CHANNEL(y); ADD_CHANNEL(z); #undef ADD_CHANNEL sol_iio_device_start_buffer(mdata->iio_base.device); return true; error: SOL_WRN("Could not create iio/magnet node. Failed to open IIO device %d", device_id); sol_iio_close(mdata->iio_base.device); return false; } static int magnet_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct iio_direction_vector_data *mdata = data; const struct sol_flow_node_type_iio_magnetometer_options *opts; int device_id; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_MAGNETOMETER_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_iio_magnetometer_options *)options; mdata->iio_base.buffer_enabled = opts->buffer_size > -1; SOL_SET_API_VERSION(mdata->iio_base.config.api_version = SOL_IIO_CONFIG_API_VERSION; ) if (opts->iio_trigger_name) { mdata->iio_base.config.trigger_name = strdup(opts->iio_trigger_name); SOL_NULL_CHECK(mdata->iio_base.config.trigger_name, -ENOMEM); } mdata->iio_base.config.buffer_size = opts->buffer_size; mdata->iio_base.config.sampling_frequency = opts->sampling_frequency; if (mdata->iio_base.buffer_enabled) { mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb; mdata->iio_base.config.data = node; } mdata->iio_base.use_device_default_scale = opts->use_device_default_scale; mdata->iio_base.use_device_default_offset = opts->use_device_default_offset; mdata->scale = opts->scale; mdata->offset = opts->offset; mdata->iio_base.out_range = opts->out_range; device_id = sol_iio_address_device(opts->iio_device); if (device_id < 0) { SOL_WRN("Could not create iio/magnet node. Failed to open IIO device %s", opts->iio_device); goto err; } if (!magnet_create_channels(mdata, device_id)) goto err; return 0; err: free((char *)mdata->iio_base.config.trigger_name); return -EINVAL; } static bool temp_create_channels(struct iio_double_data *mdata, int device_id) { struct sol_iio_channel_config channel_config = SOL_IIO_CHANNEL_CONFIG_INIT; mdata->iio_base.device = sol_iio_open(device_id, &mdata->iio_base.config); SOL_NULL_CHECK(mdata->iio_base.device, false); #define ADD_CHANNEL(_val) \ if (!mdata->iio_base.use_device_default_scale) \ channel_config.scale = mdata->scale; \ if (!mdata->iio_base.use_device_default_offset) \ channel_config.offset = mdata->offset; \ mdata->channel_ ## _val = sol_iio_add_channel(mdata->iio_base.device, "in_temp", &channel_config); \ SOL_NULL_CHECK_GOTO(mdata->channel_ ## _val, error); ADD_CHANNEL(val); #undef ADD_CHANNEL sol_iio_device_start_buffer(mdata->iio_base.device); return true; error: SOL_WRN("Could not create iio/thermometer node. Failed to open" " IIO device %d", device_id); sol_iio_close(mdata->iio_base.device); return false; } static int temperature_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct iio_double_data *mdata = data; const struct sol_flow_node_type_iio_thermometer_options *opts; int device_id; struct iio_node_type *type; type = (struct iio_node_type *)sol_flow_node_get_type(node); SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_THERMOMETER_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_iio_thermometer_options *)options; mdata->iio_base.buffer_enabled = opts->buffer_size > -1; SOL_SET_API_VERSION(mdata->iio_base.config.api_version = SOL_IIO_CONFIG_API_VERSION; ) if (opts->iio_trigger_name) { mdata->iio_base.config.trigger_name = strdup(opts->iio_trigger_name); SOL_NULL_CHECK(mdata->iio_base.config.trigger_name, -ENOMEM); } mdata->iio_base.config.buffer_size = opts->buffer_size; mdata->iio_base.config.sampling_frequency = opts->sampling_frequency; if (mdata->iio_base.buffer_enabled) { mdata->iio_base.config.sol_iio_reader_cb = type->reader_cb; mdata->iio_base.config.data = node; } mdata->iio_base.use_device_default_scale = opts->use_device_default_scale; mdata->iio_base.use_device_default_offset = opts->use_device_default_offset; mdata->scale = opts->scale; mdata->offset = opts->offset; mdata->iio_base.out_range = opts->out_range; device_id = sol_iio_address_device(opts->iio_device); if (device_id < 0) { SOL_WRN("Could not create iio/thermometer node. Failed to" " open IIO device %s", opts->iio_device); goto err; } if (!temp_create_channels(mdata, device_id)) goto err; return 0; err: free((char *)mdata->iio_base.config.trigger_name); return -EINVAL; }
static void temp_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 temperature_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_THERMOMETER__OUT__OUT, out.val); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static bool temp_create_channels(struct temperature_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_temp", &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/thermometer node. Failed to open" " IIO device %d", device_id); sol_iio_close(mdata->device); return false; } static int temperature_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct temperature_data *mdata = data; const struct sol_flow_node_type_iio_thermometer_options *opts; int device_id; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_THERMOMETER_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_iio_thermometer_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 = temp_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/thermometer node. Failed to" " open IIO device %s", opts->iio_device); goto err; } if (!temp_create_channels(mdata, device_id)) goto err; return 0; err: free((char *)mdata->config.trigger_name); return -EINVAL; }