static bool timer_tick(void *data) { struct sol_flow_node *node = data; struct boolean_generator_data *mdata = sol_flow_node_get_private_data(node); bool out_packet; if (*mdata->it == 'T') { out_packet = true; } else if (*mdata->it == 'F') { out_packet = false; } else { mdata->timer = NULL; sol_flow_send_error_packet(node, ECANCELED, "Unknown sample: %c. Option 'sequence' must be composed by 'T' and/or 'F' chars.", *mdata->it); return false; } sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_TEST_BOOLEAN_GENERATOR__OUT__OUT, out_packet); mdata->it++; return *mdata->it != '\0'; }
static void check_cb(void *data, int status, const struct sol_update_info *response) { struct sol_flow_node *node = data; struct update_data *mdata = sol_flow_node_get_private_data(node); if (status < 0) { sol_flow_send_error_packet(node, -status, "Error while checking for updates: %s", sol_util_strerrora(-status)); goto end; } #ifndef SOL_NO_API_VERSION if (SOL_UNLIKELY(response->api_version != SOL_UPDATE_INFO_API_VERSION)) { SOL_WRN("Update info config version '%u' is unexpected, expected '%u'", response->api_version, SOL_UPDATE_INFO_API_VERSION); return; } #endif sol_flow_send_string_packet(node, SOL_FLOW_NODE_TYPE_UPDATE_CHECK__OUT__VERSION, response->version); sol_flow_send_irange_value_packet(node, SOL_FLOW_NODE_TYPE_UPDATE_CHECK__OUT__SIZE, response->size); sol_flow_send_bool_packet(node, SOL_FLOW_NODE_TYPE_UPDATE_CHECK__OUT__NEED_UPDATE, response->need_update); end: mdata->handle = NULL; }
void service_status_cb(void *data, const struct sol_netctl_service *service) { struct sol_flow_node *node = data; struct network_service_data *mdata = sol_flow_node_get_private_data(node); enum sol_netctl_service_state current_state; const char *name; int r; name = sol_netctl_service_get_name(service); if (!name || strcmp(name, mdata->service_name)) return; current_state = sol_netctl_service_get_state(service); if (current_state == mdata->state) return; r = sol_flow_send_string_packet(node, SOL_FLOW_NODE_TYPE_NETCTL_SERVICE__OUT__OUT, sol_netctl_service_state_to_str(current_state)); SOL_INT_CHECK_GOTO(r, < 0, error); if (mdata->state == SOL_NETCTL_SERVICE_STATE_ONLINE) { r = sol_flow_send_bool_packet(node, SOL_FLOW_NODE_TYPE_NETCTL_SERVICE__OUT__ONLINE, false); SOL_INT_CHECK_GOTO(r, < 0, error); }
static void mark_done(const struct sol_flow_node *node) { struct test_result_data *d = sol_flow_node_get_private_data(node); if (!d->done) { d->done = true; return; } SOL_WRN("test/result node '%s' got more results than expected", sol_flow_node_get_id(node)); }
static void pass(const struct sol_flow_node *node) { struct test_result_data *d = sol_flow_node_get_private_data(node); if (!d->done) node_count--; mark_done(node); if (node_count == 0) sol_quit(); }
static bool on_timeout(void *data) { struct test_result_data *d; SOL_WRN("Timeout expired! Failing test..."); fail(data); d = sol_flow_node_get_private_data(data); d->timer = NULL; return false; }
/* GPIO READER ********************************************************************/ static void gpio_reader_event(void *data, struct sol_gpio *gpio) { int value; struct sol_flow_node *node = data; struct gpio_data *mdata = sol_flow_node_get_private_data(node); value = sol_gpio_read(mdata->gpio); SOL_INT_CHECK(value, < 0); sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_GPIO_READER__OUT__OUT, value); }
static bool timer_tick(void *data) { struct sol_flow_node *node = data; struct string_generator_data *mdata = sol_flow_node_get_private_data(node); struct sol_str_slice *val; val = sol_vector_get(&mdata->values, mdata->next_index); sol_flow_send_string_slice_packet (node, SOL_FLOW_NODE_TYPE_TEST_STRING_GENERATOR__OUT__OUT, *val); mdata->next_index++; return mdata->next_index != mdata->values.len; }
static void install_cb(void *data, int status) { struct sol_flow_node *node = data; struct update_data *mdata = sol_flow_node_get_private_data(node); if (status < 0) { sol_flow_send_error_packet(node, -status, "Error while installing update: %s", sol_util_strerrora(-status)); } sol_flow_send_bool_packet(node, SOL_FLOW_NODE_TYPE_UPDATE_INSTALL__OUT__SUCCESS, status == 0); mdata->handle = NULL; }
static bool timer_tick(void *data) { struct sol_flow_node *node = data; struct int_generator_data *mdata = sol_flow_node_get_private_data(node); struct sol_irange output = { }; int32_t *val; val = sol_vector_get(&mdata->values, mdata->next_index); output.val = *val; output.step = 1; sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TEST_INT_GENERATOR__OUT__OUT, &output); mdata->next_index++; return mdata->next_index != mdata->values.len; }
static bool reader_on_timeout(void *data) { /* we get the last parameter we used in sol_timeout_add() */ struct sol_flow_node *node = data; struct reader_data *mdata = sol_flow_node_get_private_data(node); int r; mdata->val++; /* create and send a new int packet on OUT port. * * Note that an 'int' port is actually an integer range or a * 'struct sol_irange', as it carries not only the value, but how * to interpret that integer such as minimum and maximum values * (so we can limit to only positive or negative, and smaller * precisions) as well how to increment or decrement the value * (steps). * * In this example we are only interested in the value, thus we * use the simpler packet sender. * * The port number macro (SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER__OUT__OUT) is * defined in the generated file custom-node-types-gen.h and is * based on the JSON array declaration. * * For efficiency matters soletta will only deal with port * indexes, the name is only used by node type description and * high-level API to resolve names to indexes. */ r = sol_flow_send_irange_value_packet(node, SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER__OUT__OUT, mdata->val); if (r < 0) { fprintf(stderr, "ERROR: could not send packet on port=%d, value=%d\n", SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_READER__OUT__OUT, mdata->val); /* we will stop running and mdata->timer will be deleted if we * return false, then invalidate the handler. */ mdata->timer = NULL; return false; /* stop running */ } return true; /* keep running */ }
static int segments_set(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { unsigned char byte; int r; struct segments_ctl_data *mdata = sol_flow_node_get_private_data(node); if (mdata->needs_clear) { _clear(node); mdata->needs_clear = false; } r = sol_flow_packet_get_byte(packet, &byte); SOL_INT_CHECK(r, < 0, r); _write_byte(node, _convert_order(byte)); return 0; }
static void _write_byte(struct sol_flow_node *node, unsigned char byte) { int i; struct segments_ctl_data *mdata = sol_flow_node_get_private_data(node); if (mdata->needs_clear) { _clear(node); mdata->needs_clear = false; } // Unless we set active_low on the data gpio, it expects 1 for the led // to be off, and 0 for on, so we invert the byte here. byte = ~byte; for (i = 0; i < 8; i++) { int val = (byte >> i) & 1; sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_CALAMARI_SEGMENTS_CTL__OUT__DATA, val); _tick(node); } _latch(node); }
static bool flow_send_idle(void *data) { struct sol_flow_node *flow = data; struct flow_static_data *fsd; struct sol_list tmplist; fsd = sol_flow_node_get_private_data(flow); /* If during packet processing more stuff is sent, we want a new idler * to be added, so make sure this pointer is NULL by then */ fsd->delay_send = NULL; sol_list_steal(&fsd->delayed_packets, &tmplist); while (!sol_list_is_empty(&tmplist)) { struct delayed_packet *dp; dp = SOL_LIST_GET_CONTAINER(tmplist.next, struct delayed_packet, list); sol_list_remove(&dp->list); flow_send_do(flow, fsd, dp->source_idx, dp->source_port_idx, dp->packet); free(dp); } return false; }
static bool on_timeout(void *data) { struct sol_flow_node *node = data; struct mytype_context *ctx = sol_flow_node_get_private_data(node); uint16_t port_idx; char buf[256]; printf("mytype tick... send packet. ctx=%p someint=%d, somebool=%d\n", ctx, ctx->someint, ctx->somebool); snprintf(buf, sizeof(buf), "%d/%s", ctx->someint, ctx->somebool ? "true" : "false"); /* this is to demo the discovery from name, but one could/should use the * port index for efficiency matters. */ port_idx = sol_flow_simplectype_get_port_out_index(mytype, "STRING"); sol_flow_send_string_packet(node, port_idx, buf); return true; }
static void humidity_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 humidity_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_HUMIDITY_SENSOR__OUT__OUT, out.val); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static bool humidity_create_channels(struct humidity_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_humidityrelative", &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/humidity node. Failed to open IIO device %d", device_id); sol_iio_close(mdata->device); return false; } static int humidity_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct humidity_data *mdata = data; const struct sol_flow_node_type_iio_humidity_sensor_options *opts; int device_id; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_HUMIDITY_SENSOR_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_iio_humidity_sensor_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 = humidity_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/humidity node. Failed to open IIO device %s", opts->iio_device); goto err; } if (!humidity_create_channels(mdata, device_id)) goto err; return 0; err: free((char *)mdata->config.trigger_name); return -EINVAL; }
static void accelerate_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 accelerate_data *mdata = sol_flow_node_get_private_data(node); struct sol_direction_vector out = { .min = mdata->out_range.min, .max = mdata->out_range.max }; bool b; b = sol_iio_read_channel_value(mdata->channel_x, &out.x); if (!b) goto error; b = sol_iio_read_channel_value(mdata->channel_y, &out.y); if (!b) goto error; b = sol_iio_read_channel_value(mdata->channel_z, &out.z); if (!b) goto error; sol_flow_send_direction_vector_packet(node, SOL_FLOW_NODE_TYPE_IIO_ACCELEROMETER__OUT__OUT, &out); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static bool accelerate_create_channels(struct accelerate_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(_axis) \ if (!mdata->use_device_default_scale) \ channel_config.scale = mdata->scale._axis; \ if (!mdata->use_device_default_offset) \ channel_config.offset = mdata->offset._axis; \ mdata->channel_ ## _axis = sol_iio_add_channel(mdata->device, "in_accel_" # _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->device); return true; error: SOL_WRN("Could not create iio/accelerate node. Failed to open IIO device %d", device_id); sol_iio_close(mdata->device); return false; } static int accelerate_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct accelerate_data *mdata = data; const struct sol_flow_node_type_iio_accelerometer_options *opts; int device_id; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_ACCELEROMETER_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_iio_accelerometer_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 = accelerate_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/accelerate node. Failed to open IIO device %s", opts->iio_device); goto err; } if (!accelerate_create_channels(mdata, device_id)) goto err; return 0; err: free((char *)mdata->config.trigger_name); return -EINVAL; }
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_DBG("Before mount_calibration: %f-%f-%f", out.x, out.y, out.z); // mount correction sol_iio_mount_calibration(device, &out); 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) { mdata->iio_base.device = sol_iio_open(device_id, &mdata->iio_base.config); SOL_NULL_CHECK(mdata->iio_base.device, false); mdata->channel_x = iio_add_channel(mdata->scale.x, mdata->offset.x, "in_anglvel_x", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_x, error); mdata->channel_y = iio_add_channel(mdata->scale.y, mdata->offset.y, "in_anglvel_y", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_y, error); mdata->channel_z = iio_add_channel(mdata->scale.z, mdata->offset.z, "in_anglvel_z", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_z, error); 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, ret; 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; 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); 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) { mdata->iio_base.device = sol_iio_open(device_id, &mdata->iio_base.config); SOL_NULL_CHECK(mdata->iio_base.device, false); mdata->channel_x = iio_add_channel(mdata->scale.x, mdata->offset.x, "in_magn_x", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_x, error); mdata->channel_y = iio_add_channel(mdata->scale.y, mdata->offset.y, "in_magn_y", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_y, error); mdata->channel_z = iio_add_channel(mdata->scale.z, mdata->offset.z, "in_magn_z", &mdata->iio_base); SOL_NULL_CHECK_GOTO(mdata->channel_z, error); 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 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 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 color_data *mdata = sol_flow_node_get_private_data(node); struct sol_rgb out = { .red_max = mdata->out_range.max, .green_max = mdata->out_range.max, .blue_max = mdata->out_range.max }; double tmp; bool b; b = sol_iio_read_channel_value(mdata->channel_red, &tmp); if (!b || tmp < 0 || tmp > UINT32_MAX) goto error; out.red = tmp; b = sol_iio_read_channel_value(mdata->channel_green, &tmp); if (!b || tmp < 0 || tmp > UINT32_MAX) goto error; out.green = tmp; b = sol_iio_read_channel_value(mdata->channel_blue, &tmp); if (!b || tmp < 0 || tmp > UINT32_MAX) goto error; out.blue = tmp; sol_flow_send_rgb_packet(node, SOL_FLOW_NODE_TYPE_IIO_COLOR_SENSOR__OUT__OUT, &out); return; error: sol_flow_send_error_packet_str(node, EIO, errmsg); SOL_WRN("%s", errmsg); } static bool color_create_channels(struct color_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(_axis) \ if (!mdata->use_device_default_scale) \ channel_config.scale = mdata->scale; \ if (!mdata->use_device_default_offset) \ channel_config.offset = mdata->offset; \ mdata->channel_ ## _axis = sol_iio_add_channel(mdata->device, "in_intensity_" # _axis, &channel_config); \ SOL_NULL_CHECK_GOTO(mdata->channel_ ## _axis, error); ADD_CHANNEL(red); ADD_CHANNEL(green); ADD_CHANNEL(blue); #undef ADD_CHANNEL sol_iio_device_start_buffer(mdata->device); return true; error: SOL_WRN("Could not create iio/color-sensor node. Failed to open IIO" " device %d", device_id); sol_iio_close(mdata->device); return false; } static int color_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct color_data *mdata = data; const struct sol_flow_node_type_iio_color_sensor_options *opts; int device_id; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_IIO_COLOR_SENSOR_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_iio_color_sensor_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 = color_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/color-sensor node. Failed to open" " IIO device %s", opts->iio_device); goto err; } if (!color_create_channels(mdata, device_id)) goto err; return 0; err: free((char *)mdata->config.trigger_name); return -EINVAL; }