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';
}
Exemple #2
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;
}
Exemple #3
0
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);
    }
Exemple #4
0
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));
}
Exemple #5
0
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();
}
Exemple #6
0
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;
}
Exemple #7
0
/* 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;
}
Exemple #9
0
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;
}
Exemple #10
0
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 */
}
Exemple #12
0
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;
}
Exemple #13
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;
}
Exemple #15
0
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;
}
Exemple #16
0
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;

}
Exemple #17
0
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;
}
Exemple #18
0
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;
}
Exemple #19
0
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;

}
Exemple #20
0
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;
}