示例#1
0
static int
operator_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct irange_arithmetic_data *mdata = data;
    struct sol_irange value;
    int r;

    r = sol_flow_packet_get_irange(packet, &value);
    SOL_INT_CHECK(r, < 0, r);

    if (port == 0) {
        if (mdata->var0_initialized &&
            sol_irange_equal(&mdata->var0, &value))
            return 0;
        mdata->var0 = value;
        mdata->var0_initialized = true;
    } else {
        if (mdata->var1_initialized &&
            sol_irange_equal(&mdata->var1, &value))
            return 0;
        mdata->var1 = value;
        mdata->var1_initialized = true;
    }

    if (!(mdata->var0_initialized && mdata->var1_initialized))
        return 0;

    r = mdata->func(&mdata->var0, &mdata->var1, &value);
    if (r < 0) {
        sol_flow_send_error_packet(node, -r, sol_util_strerrora(-r));
        return r;
    }

    return sol_flow_send_irange_packet(node, mdata->port, &value);
}
示例#2
0
文件: aio.c 项目: NilayNigam/soletta
static void
read_cb(void *cb_data, struct sol_aio *aio, int32_t ret)
{
    struct sol_irange i;
    struct aio_data *mdata = cb_data;

    SOL_NULL_CHECK(mdata);

    i.val = ret;
    if (i.val < 0) {
        sol_flow_send_error_packet(mdata->node, EINVAL,
            "AIO (%s): Failed on read operation: %s.", mdata->pin,
            sol_util_strerrora(i.val));
        return;
    }

    if (mdata->is_first || i.val != mdata->last_value) {
        mdata->is_first = false;
        mdata->last_value = i.val;
        i.max = mdata->mask;
        i.min = 0;
        i.step = 1;
        sol_flow_send_irange_packet(mdata->node,
            SOL_FLOW_NODE_TYPE_AIO_READER__OUT__OUT, &i);
    }

    mdata->pending = NULL;
}
示例#3
0
static int
common_get_progress(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct update_data *mdata = data;
    struct update_node_type *type;
    struct sol_irange irange = {
        .step = 1,
        .min = 0,
        .max = 100
    };

    type = (struct update_node_type *)sol_flow_node_get_type(node);

    if (mdata->handle) {
        irange.val = sol_update_get_progress(mdata->handle);
        if (irange.val >= 0 && irange.val <= 100)
            sol_flow_send_irange_packet(node, type->progress_port, &irange);
        else
            sol_flow_send_error_packet(node, EINVAL,
                "Could not get progress of task");
    } else {
        SOL_DBG("No current operation in process, ignoring request to get progress");
    }

    return 0;
}
示例#4
0
static int
irange_map_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct irange_map_data *mdata = data;
    struct sol_irange in_value;
    int32_t out_value;
    int r;

    r = sol_flow_packet_get_irange(packet, &in_value);
    SOL_INT_CHECK(r, < 0, r);

    if (mdata->use_input_range) {
        if (in_value.min >= in_value.max) {
            SOL_WRN("Invalid range: input max must to be bigger than min");
            return -EINVAL;
        }
        r = _map(in_value.val, in_value.min, in_value.max, mdata->output.min,
            mdata->output.max, mdata->output_value.step, &out_value);
    } else
        r = _map(in_value.val, mdata->input.min, mdata->input.max,
            mdata->output.min, mdata->output.max, mdata->output_value.step,
            &out_value);

    SOL_INT_CHECK(r, < 0, r);

    mdata->output_value.val = out_value;

    return sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_INT_MAP__OUT__OUT,
        &mdata->output_value);
}
示例#5
0
文件: ipm.c 项目: Learn-iot/soletta
static void
int_receiver(void *data, uint32_t id, struct sol_blob *message)
{
    struct sol_flow_node *node = data;

    sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_IPM_INT_READER__OUT__OUT, message->mem);
    sol_blob_unref(message);
}
示例#6
0
static int
reset_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id,
    const struct sol_flow_packet *packet)
{
    struct accumulator_data *mdata = data;

    mdata->val.val = mdata->init_val;

    return sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR__OUT__OUT,
        &mdata->val);
}
示例#7
0
/*
 *----------------------- int --------------------------
 */
static void
int_read_data(void *data, int fd)
{
    struct unix_socket_data *mdata = data;
    struct sol_irange val;

    if (FILL_BUFFER(fd, val) < 0)
        return;

    sol_flow_send_irange_packet(mdata->node,
        SOL_FLOW_NODE_TYPE_UNIX_SOCKET_INT_READER__OUT__OUT, &val);
}
示例#8
0
/*
 * WARNING: Do NOT use it for anything else than test purposes.
 */
static int
random_int_generate(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct sol_irange value = { 0, 0, INT32_MAX, 1 };
    struct random_node_data *mdata = data;
    int r;

    r = sol_random_get_int32(mdata->engine, &value.val);
    if (r < 0)
        return r;

    return sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_RANDOM_INT__OUT__OUT,
        &value);
}
示例#9
0
static int
counter_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id,
    const struct sol_flow_packet *packet)
{
    struct sol_irange val = { 0, 0, INT32_MAX, 1 };
    struct counter_data *mdata = data;
    enum state *s;
    bool packet_val;
    int r;

    r = sol_flow_packet_get_boolean(packet, &packet_val);
    SOL_INT_CHECK(r, < 0, r);
    s = sol_vector_get(&mdata->map, conn_id);

    if (*s == packet_val)
        return 0;

    if (packet_val) {
        mdata->true_count++;
        if (*s != NA)
            mdata->false_count--;
    } else {
        mdata->false_count++;
        if (*s != NA)
            mdata->true_count--;
    }
    *s = packet_val;

    val.val = mdata->true_count;
    sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_BOOLEAN_COUNTER__OUT__TRUE, &val);

    val.val = mdata->false_count;
    sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_BOOLEAN_COUNTER__OUT__FALSE, &val);

    return 0;
}
示例#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;
}
示例#11
0
文件: slider.c 项目: Achint08/soletta
static void
on_slider_changed(GtkRange *range, gpointer data)
{
    struct gtk_common_data *mdata = data;
    GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(mdata->widget));
    struct sol_irange val;

    val.val = gtk_range_get_value(GTK_RANGE(mdata->widget));
    val.min = (int)gtk_adjustment_get_lower(adj);
    val.max = (int)gtk_adjustment_get_upper(adj);
    val.step = (int)gtk_adjustment_get_step_increment(adj);

    sol_flow_send_irange_packet(mdata->node,
        SOL_FLOW_NODE_TYPE_GTK_SLIDER__OUT__OUT,
        &val);
}
示例#12
0
static int
inc_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id,
    const struct sol_flow_packet *packet)
{
    struct accumulator_data *mdata = data;

    mdata->val.val += mdata->val.step;
    if (mdata->val.val > mdata->val.max) {
        mdata->val.val = mdata->val.min;
        sol_flow_send_empty_packet(node, SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR__OUT__OVERFLOW);
    }

    return sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR__OUT__OUT,
        &mdata->val);
}
示例#13
0
static int
constant_irange_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    const struct sol_flow_node_type_constant_int_options *opts;
    struct sol_irange value;
    int r;

    SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options,
        SOL_FLOW_NODE_TYPE_CONSTANT_INT_OPTIONS_API_VERSION, -EINVAL);
    opts = (const struct sol_flow_node_type_constant_int_options *)options;

    r = sol_irange_compose(&opts->value_spec, opts->value, &value);
    SOL_INT_CHECK(r, < 0, r);

    return sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_CONSTANT_INT__OUT__OUT, &value);
}
示例#14
0
static int
accumulator_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    int32_t tmp;
    struct accumulator_data *mdata = data;
    const struct sol_flow_node_type_int_accumulator_options *opts =
        (const struct sol_flow_node_type_int_accumulator_options *)options;

    SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK
        (options, SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR_OPTIONS_API_VERSION, -EINVAL);
    mdata->val = opts->setup_value;

    // Sanitizing options input
    if (mdata->val.max < mdata->val.min) {
        SOL_WRN("Max (%" PRId32 ") should be greater than Min (%" PRId32 "). Switching both values.",
            mdata->val.max, mdata->val.min);
        tmp = mdata->val.max;
        mdata->val.max = mdata->val.min;
        mdata->val.min = tmp;
    }

    if (mdata->val.val > mdata->val.max || mdata->val.val < mdata->val.min) {
        SOL_WRN("Value (%" PRId32 ") should be in %" PRId32 " - %" PRId32 " range,"
            " switching it to %" PRId32 "", mdata->val.val, mdata->val.min,
            mdata->val.max, mdata->val.min);
        mdata->val.val = mdata->val.min;
    }

    if (!mdata->val.step) {
        mdata->val.step = 1;
        SOL_WRN("Step can't be zero. Using (%" PRId32 ") instead.", mdata->val.step);
    } else if (mdata->val.step < 0) {
        mdata->val.step = -mdata->val.step;
        SOL_WRN("Step (-%" PRId32 ") can't be a negative value. Using (%" PRId32 ") instead.",
            mdata->val.step, mdata->val.step);
    }

    mdata->init_val = opts->setup_value.val;

    return sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR__OUT__OUT,
        &mdata->val);
}
示例#15
0
static int
int_filter_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct  sol_flow_packet *packet)
{
    struct sol_irange value;
    int r;
    struct int_filter_data *mdata = data;

    r = sol_flow_packet_get_irange(packet, &value);
    SOL_INT_CHECK(r, < 0, r);

    if (value.val >= mdata->min && value.val <= mdata->max ) {
        if (mdata->range_override) {
            value.min = mdata->min;
            value.max = mdata->max;
            value.step = 1;
        }
        return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_FILTER__OUT__OUT, &value);
    }
    return 0;
}
示例#16
0
static int
system_clock_send(const void *timestamp, struct sol_flow_node *node)
{
    struct sol_irange irange = SOL_IRANGE_INIT();
    int r;

    if (!timestamp) {
        int64_t ts;
        ts = sol_platform_get_system_clock();
        if (ts > INT32_MAX) {
            sol_flow_send_error_packet(node, EOVERFLOW,
                "The timestamp %" PRId64 " can not be expressed using 32 bits", ts);
            return -EOVERFLOW;
        }
        irange.val = ts;
    } else
        irange.val = (*((int64_t *)timestamp));

    r = sol_flow_send_irange_packet(node, 0, &irange);
    SOL_INT_CHECK(r, < 0, r);
    return 0;
}
示例#17
0
static int
irange_constrain_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct irange_constrain_data *mdata = data;
    int r;
    struct sol_irange value;

    r = sol_flow_packet_get_irange(packet, &value);
    SOL_INT_CHECK(r, < 0, r);

    if (!mdata->use_input_range) {
        value.min = mdata->val.min;
        value.max = mdata->val.max;
        value.step = mdata->val.step;
    }

    irange_constrain(&value);
    mdata->val = value;

    return sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_INT_CONSTRAIN__OUT__OUT,
        &mdata->val);
}
示例#18
0
static int
localtime_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct timespec value;
    struct tm split_time;
    struct sol_irange year = { 0, 0, INT32_MAX, 1 };
    struct sol_irange mon = { 0, 0, 11, 1 };
    struct sol_irange mday = { 0, 1, 31, 1 };
    struct sol_irange hour = { 0, 0, 23, 1 };
    struct sol_irange min = { 0, 0, 59, 1 };
    struct sol_irange sec = { 0, 0, 59, 1 };
    struct sol_irange nsec = { 0, 0, 999999999, 1 };
    struct sol_irange wday = { 0, 0, 6, 1 };
    struct sol_irange yday = { 0, 0, 365, 1 };
    int r;

    r = sol_flow_packet_get_timestamp(packet, &value);
    SOL_INT_CHECK(r, < 0, r);

    tzset();
    if (!localtime_r(&value.tv_sec, &split_time)) {
        sol_flow_send_error_packet(node, EINVAL,
            "Could not convert time.");
        return 0;
    }

    year.val = split_time.tm_year + 1900;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__YEAR,
        &year);
    SOL_INT_CHECK(r, < 0, r);

    mon.val = split_time.tm_mon + 1;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MONTH,
        &mon);
    SOL_INT_CHECK(r, < 0, r);

    mday.val = split_time.tm_mday;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MONTH_DAY,
        &mday);
    SOL_INT_CHECK(r, < 0, r);

    hour.val = split_time.tm_hour;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__HOUR,
        &hour);
    SOL_INT_CHECK(r, < 0, r);

    min.val = split_time.tm_min;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MINUTE,
        &min);
    SOL_INT_CHECK(r, < 0, r);

    sec.val = split_time.tm_sec;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__SECOND,
        &sec);
    SOL_INT_CHECK(r, < 0, r);

    nsec.val = value.tv_nsec;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__NANO_SECOND,
        &nsec);
    SOL_INT_CHECK(r, < 0, r);

    wday.val = split_time.tm_wday;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__WEEK_DAY,
        &wday);
    SOL_INT_CHECK(r, < 0, r);

    yday.val = split_time.tm_yday;
    r = sol_flow_send_irange_packet(node,
        SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__YEAR_DAY,
        &yday);
    SOL_INT_CHECK(r, < 0, r);

    if (split_time.tm_isdst < 0)
        SOL_DBG("Daylight saving time information not available.");
    else {
        r = sol_flow_send_boolean_packet(node,
            SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__DAYLIGHT_SAVING_TIME,
            !!split_time.tm_isdst);
        SOL_INT_CHECK(r, < 0, r);
    }

    return 0;
}
示例#19
0
static int
not_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    int r;
    struct sol_irange in_value;
    struct sol_irange out_value = { .min = INT32_MIN, .step = 1, .max = INT32_MAX };

    r = sol_flow_packet_get_irange(packet, &in_value);
    SOL_INT_CHECK(r, < 0, r);

    out_value.val = ~in_value.val;
    return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_BITWISE_NOT__OUT__OUT, &out_value);
}


// =============================================================================
// IRANGE COMPARISON
// =============================================================================

struct irange_comparison_data {
    bool (*func) (int32_t var0, int32_t var1);
    int32_t var0;
    int32_t var1;
    uint16_t port;
    bool var0_initialized : 1;
    bool var1_initialized : 1;
};

static bool
irange_val_equal(int32_t var0, int32_t var1)
{
    return var0 == var1;
}

static int
equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_EQUAL__OUT__OUT;
    mdata->func = irange_val_equal;

    return 0;
}

static bool
irange_val_less(int32_t var0, int32_t var1)
{
    return var0 < var1;
}

static int
less_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_LESS__OUT__OUT;
    mdata->func = irange_val_less;

    return 0;
}

static bool
irange_val_less_or_equal(int32_t var0, int32_t var1)
{
    return var0 <= var1;
}

static int
less_or_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_LESS_OR_EQUAL__OUT__OUT;
    mdata->func = irange_val_less_or_equal;

    return 0;
}

static bool
irange_val_greater(int32_t var0, int32_t var1)
{
    return var0 > var1;
}

static int
greater_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_GREATER__OUT__OUT;
    mdata->func = irange_val_greater;

    return 0;
}

static bool
irange_val_greater_or_equal(int32_t var0, int32_t var1)
{
    return var0 >= var1;
}

static int
greater_or_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_EQUAL__OUT__OUT;
    mdata->func = irange_val_greater_or_equal;

    return 0;
}

static bool
irange_val_not_equal(int32_t var0, int32_t var1)
{
    return var0 != var1;
}

static int
not_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_comparison_data *mdata = data;

    mdata->port = SOL_FLOW_NODE_TYPE_INT_NOT_EQUAL__OUT__OUT;
    mdata->func = irange_val_not_equal;

    return 0;
}

static int
comparison_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct irange_comparison_data *mdata = data;
    int r;
    struct sol_irange in_value;
    bool output;

    r = sol_flow_packet_get_irange(packet, &in_value);
    SOL_INT_CHECK(r, < 0, r);

    if (port == 0) {
        mdata->var0_initialized = true;
        mdata->var0 = in_value.val;
    } else if (port == 1) {
        mdata->var1_initialized = true;
        mdata->var1 = in_value.val;
    }

    /* only send something after both variables values are received */
    if (!(mdata->var0_initialized && mdata->var1_initialized))
        return 0;

    output = mdata->func(mdata->var0, mdata->var1);

    return sol_flow_send_boolean_packet(node, mdata->port, output);
}

// =============================================================================
// IRANGE MAP
// =============================================================================


struct irange_map_data {
    struct sol_irange input;
    struct sol_irange output;
    struct sol_irange output_value;
    bool use_input_range : 1;
};

static int
irange_map_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    struct irange_map_data *mdata = data;
    const struct sol_flow_node_type_int_map_options *opts;

    SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_INT_MAP_OPTIONS_API_VERSION, -EINVAL);

    opts = (const struct sol_flow_node_type_int_map_options *)options;

    mdata->use_input_range = opts->use_input_range;

    mdata->input = opts->input_range;

    if (!mdata->use_input_range && (mdata->input.min >= mdata->input.max)) {
        SOL_WRN("Invalid range: input max must to be bigger than min");
        return -EINVAL;
    }

    mdata->output = opts->output_range;

    /* We allow output.min > output.max to invert range, but
     * when sending the packet, min and max must to be in correct
     * order */
    if (mdata->output.min < mdata->output.max) {
        mdata->output_value.min = mdata->output.min;
        mdata->output_value.max = mdata->output.max;
    } else {
        mdata->output_value.max = mdata->output.min;
        mdata->output_value.min = mdata->output.max;
    }

    if (opts->output_range.step < 1) {
        SOL_WRN("Output step need to be > 0");
        return -EDOM;
    }
    mdata->output_value.step = opts->output_range.step;

    return 0;
}

static int
_map(int64_t in_value, int64_t in_min, int64_t in_max, int64_t out_min, int64_t out_max, int64_t out_step, int32_t *out_value)
{
    int64_t result;

    if ((in_max - in_min) == out_min) {
        SOL_WRN("Input max - input min == output min");
        return -EDOM;
    }

    result = (in_value - in_min) * (out_max - out_min) /
             (in_max - in_min) + out_min;
    result -= (result - out_min) % out_step;
    *out_value = result;

    return 0;
}
示例#20
0
static int
two_port_process(struct sol_flow_node *node, void *data, uint16_t port_in, uint16_t port_out, const struct sol_flow_packet *packet, int (*func)(int, int))
{
    struct bitwise_data *mdata = data;
    int r;
    struct sol_irange in_value;
    struct sol_irange out_value = { .min = INT32_MIN, .step = 1, .max = INT32_MAX };

    r = sol_flow_packet_get_irange(packet, &in_value);
    SOL_INT_CHECK(r, < 0, r);

    if (port_in) {
        mdata->in1 = in_value.val;
        mdata->in1_init = true;
    } else {
        mdata->in0 = in_value.val;
        mdata->in0_init = true;
    }

    if (!(mdata->in0_init && mdata->in1_init))
        return 0;

    out_value.val = func(mdata->in0, mdata->in1);
    if (out_value.val == mdata->result && mdata->sent_first)
        return 0;

    mdata->result = out_value.val;
    mdata->sent_first = true;

    return sol_flow_send_irange_packet(node, port_out, &out_value);
}

static int
and_func(int in0, int in1)
{
    return in0 & in1;
}

static int
and_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    return two_port_process(node, data, port, SOL_FLOW_NODE_TYPE_INT_BITWISE_AND__OUT__OUT, packet, and_func);
}

static int
or_func(int in0, int in1)
{
    return in0 | in1;
}

static int
or_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    return two_port_process(node, data, port, SOL_FLOW_NODE_TYPE_INT_BITWISE_OR__OUT__OUT, packet, or_func);
}

static int
xor_func(int in0, int in1)
{
    return in0 ^ in1;
}

static int
xor_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    return two_port_process(node, data, port, SOL_FLOW_NODE_TYPE_INT_BITWISE_XOR__OUT__OUT, packet, xor_func);
}

static int
validate_shift(const struct sol_flow_packet *packet)
{
    struct sol_irange in;
    int r;

    r = sol_flow_packet_get_irange(packet, &in);
    SOL_INT_CHECK(r, < 0, r);
    if ((unsigned)in.val > (sizeof(in.val) * CHAR_BIT - 1) || in.val < 0)
        return -EINVAL;
    return 0;
}

static int
shift_left_func(int in0, int in1)
{
    return in0 << in1;
}

static int
shift_left_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet)
{
    int r = 0;

    if (port == SOL_FLOW_NODE_TYPE_INT_SHIFT_LEFT__IN__SHIFT)
        r = validate_shift(packet);
    if (r < 0)
        return r;
    return two_port_process(node, data, port, SOL_FLOW_NODE_TYPE_INT_SHIFT_LEFT__OUT__OUT, packet, shift_left_func);
}