SOL_API struct sol_i2c_pending * sol_i2c_write_quick(struct sol_i2c *i2c, bool rw, void (*write_quick_cb)(void *cb_data, struct sol_i2c *i2c, ssize_t status), const void *cb_data) { SOL_WRN("Unsupported"); return NULL; }
static bool _load_mux(const char *name) { #ifdef ENABLE_DYNAMIC_MODULES int r; void *handle; char path[PATH_MAX]; const struct sol_pin_mux *p_sym; r = snprintf(path, sizeof(path), "%s/%s.so", PINMUXDIR, name); SOL_INT_CHECK(r, >= (int)sizeof(path), false); SOL_INT_CHECK(r, < 0, false); handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); if (!handle) { SOL_INF("Could not load platform pin multiplexer '%s': %s", path, dlerror()); return true; // Not find a mux isn't necessarily an error, so we are returning true here } p_sym = dlsym(handle, "SOL_PIN_MUX"); if (!p_sym) { SOL_WRN("Could not find symbol SOL_PIN_MUX in module '%s': %s", path, dlerror()); goto error; } if (p_sym->api_version != SOL_PIN_MUX_API_VERSION) { SOL_WRN("Mux '%s' has incorrect api_version: %lu expected %lu", path, p_sym->api_version, SOL_PIN_MUX_API_VERSION); goto error; } if (dl_handle) dlclose(dl_handle); mux = p_sym; dl_handle = handle; SOL_INF("Loaded pin multiplexer '%s' from '%s'", mux->plat_name, path); return true; error: dlclose(handle); #endif return false; }
SOL_API int sol_rgb_set_max(struct sol_rgb *color, uint32_t max_value) { uint64_t val; if (!max_value) { SOL_WRN("Max value can't be zero"); return -EINVAL; } if (!color->red_max || !color->green_max || !color->blue_max) { SOL_WRN("Color max values can't be zero."); return -EINVAL; } if (color->red > color->red_max) { SOL_WRN("Red component out of range: %" PRId32 " > %" PRId32 ". " "Assuming max value.", color->red, color->red_max); color->red = color->red_max; } if (color->green > color->green_max) { SOL_WRN("Green component out of range: %" PRId32 " > %" PRId32 ". " "Assuming max value.", color->green, color->green_max); color->green = color->green_max; } if (color->blue > color->blue_max) { SOL_WRN("Blue component out of range: %" PRId32 " > %" PRId32 ". " "Assuming max value.", color->blue, color->blue_max); color->blue = color->blue_max; } val = (uint64_t)color->red * max_value / color->red_max; color->red = val; color->red_max = max_value; val = (uint64_t)color->green * max_value / color->green_max; color->green = val; color->green_max = max_value; val = (uint64_t)color->blue * max_value / color->blue_max; color->blue = val; color->blue_max = max_value; return 0; }
int main(int argc, char *argv[]) { struct light_context context = { .resource = &light }; struct sol_coap_server *server; char old_led_state; sol_init(); server = sol_coap_server_new(DEFAULT_UDP_PORT); if (!server) { SOL_WRN("Could not create a coap server using port %d.", DEFAULT_UDP_PORT); return -1; } if (!sol_coap_server_register_resource(server, &light, server)) { SOL_WRN("Could not register resource for the light"); return -1; } console_fd = open("/dev/console", O_RDWR); if (console_fd < 0) { perror("Could not open '/dev/console'"); return -1; } if (ioctl(console_fd, KDGETLED, (char *)&old_led_state)) { perror("Could not get the keyboard leds state"); return -1; } context.server = server; sol_timeout_add(5000, update_light, &context); sol_run(); sol_coap_server_unref(server); if (ioctl(console_fd, KDSETLED, old_led_state)) { perror("Could not return the leds to the old state"); return -1; } return 0; }
SOL_API struct sol_i2c * sol_i2c_open_raw(uint8_t bus, enum sol_i2c_speed speed) { int len, dev; struct sol_i2c *i2c; unsigned long funcs; char i2c_dev_path[PATH_MAX]; SOL_LOG_INTERNAL_INIT_ONCE; len = snprintf(i2c_dev_path, sizeof(i2c_dev_path), "/dev/i2c-%u", bus); if (len < 0 || len >= PATH_MAX) { SOL_WRN("i2c #%u: could not format device path", bus); return NULL; } i2c = calloc(1, sizeof(*i2c)); if (!i2c) { SOL_WRN("i2c #%u: could not allocate i2c context", bus); errno = ENOMEM; return NULL; } dev = open(i2c_dev_path, O_RDWR | O_CLOEXEC); if (dev < 0) { SOL_WRN("i2c #%u: could not open device file", bus); goto open_error; } i2c->bus = bus; i2c->dev = dev; /* check if the given I2C adapter supports plain-i2c messages */ if (ioctl(i2c->dev, I2C_FUNCS, &funcs) == -1) goto ioctl_error; i2c->plain_i2c = (funcs & I2C_FUNC_I2C); return i2c; ioctl_error: close(i2c->dev); open_error: free(i2c); return NULL; }
static void i2c_read_who_am_i_cb(void *cb_data, struct sol_i2c *i2c, uint8_t reg, uint8_t *data, ssize_t status) { struct gyroscope_l3g4200d_data *mdata = cb_data; mdata->i2c_pending = NULL; if (status < 0) { SOL_WRN("Failed to read i2c register"); return; } if (mdata->common.buffer[0] != GYRO_REG_WHO_AM_I_VALUE) { SOL_WRN("could not find L3G4200D gyro sensor"); return; } gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init_sampling); }
/* * do things getty would do to spawn a shell, basically become the * session leader of the given tty, then make stdio/stdout/stderr use * it. */ static void do_shell(const char *tty) { char term_buf[128]; const char *envp[] = { term_buf, "HOME=/", NULL, }; char tty_path[PATH_MAX]; pid_t pid, tsid; int r; SOL_INF("no getty, exec shell: %s", shell); r = snprintf(term_buf, sizeof(term_buf), "TERM=%s", term ? term : get_term_for_tty(tty)); if (r < 0 || r >= (int)sizeof(term_buf)) envp[0] = "TERM=vt102"; pid = setsid(); if (pid < 0) { int fd; SOL_WRN("could not setsid(): %s", sol_util_strerrora(errno)); pid = getpid(); fd = open("/dev/tty", O_RDWR | O_NONBLOCK); if (fd >= 0) { sighandler_t oldsig; /* man:tty(4) * TIOCNOTTY: * Detach the calling process from its controlling terminal. * * If the process is the session leader, then SIGHUP and * SIGCONT signals are sent to the foreground process * group and all processes in the current session lose * their controlling tty. */ oldsig = signal(SIGHUP, SIG_IGN); ioctl(fd, TIOCNOTTY); close(fd); signal(SIGHUP, oldsig); } } r = snprintf(tty_path, sizeof(tty_path), "/dev/%s", tty); SOL_INT_CHECK_GOTO(r, < 0, end); SOL_INT_CHECK_GOTO(r, >= (int)sizeof(tty_path), end); close(STDIN_FILENO); r = open(tty_path, O_RDWR | O_NONBLOCK); SOL_INT_CHECK_GOTO(r, < 0, end); if (r != 0) { r = dup2(r, 0); SOL_INT_CHECK_GOTO(r, < 0, end); }
static void startup(void) { session = sol_bt_enable(enabled, NULL); if (!session) { SOL_WRN("Couldn't create a Bluetooth session"); sol_quit_with_code(-ENOMEM); } }
static void _aio_get_value(struct sol_aio *aio, unsigned int *val) { rewind(aio->fp); if (fscanf(aio->fp, "%u", val) < 1) { SOL_WRN("AIO #%d,%d: Could not read value.", aio->device, aio->pin); *val = -EIO; } }
static void i2c_write_ctrl_reg1_cb(void *cb_data, struct sol_i2c *i2c, uint8_t reg, uint8_t *data, ssize_t status) { struct gyroscope_l3g4200d_data *mdata = cb_data; mdata->i2c_pending = NULL; if (status < 0) { SOL_WRN("could not set L3G4200D gyro sensor's sampling rate"); return; } mdata->init_sampling_cnt--; if (gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, mdata->init_sampling_cnt ? gyro_init_sampling : gyro_init_range) < 0) { SOL_WRN("error in scheduling a L3G4200D gyro's init command"); } }
static void spi_transfer_initial_reset(void *cb_data, struct sol_spi *spi, const uint8_t *tx, uint8_t *rx, ssize_t status) { struct lcd_strip_lpd8806_data *mdata = cb_data; mdata->spi_busy = false; if (status < 0) SOL_WRN("SPI error when writing initial value of pixels."); }
static int gyro_init(struct gyroscope_l3g4200d_data *mdata) { ssize_t r; uint8_t data = 0; r = sol_i2c_read_register(mdata->i2c, GYRO_REG_WHO_AM_I, &data, 1); if (r < 0) { SOL_WRN("Failed to read i2c register"); return r; } if (data != GYRO_REG_WHO_AM_I_VALUE) { SOL_WRN("could not find L3G4200D gyro sensor"); return -EIO; } return gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init_sampling, mdata) == 0; }
static int slider_setup(struct gtk_common_data *data, const struct sol_flow_node_options *options) { int min = 0; int max = 100; int step = 1; struct gtk_common_data *mdata = (struct gtk_common_data *)data; const struct sol_flow_node_type_gtk_slider_options *opts = (const struct sol_flow_node_type_gtk_slider_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_GTK_SLIDER_OPTIONS_API_VERSION, -EINVAL); min = opts->range.min; max = opts->range.max; step = opts->range.step; if (min > max) { SOL_WRN("invalid range min=%d max=%d for slider id=%s\n", min, max, sol_flow_node_get_id(mdata->node)); return -EINVAL; } if (step <= 0) { SOL_WRN("invalid step=%d for slider id=%s\n", step, sol_flow_node_get_id(mdata->node)); return -EINVAL; } mdata->widget = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, min, max, step); g_signal_connect(mdata->widget, "value-changed", G_CALLBACK(on_slider_changed), mdata); g_object_set(mdata->widget, "hexpand", true, NULL); // GtkScale natural size is too small, give it a better default. gtk_widget_set_size_request(mdata->widget, 300, -1); return 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); }
static void common_close(struct sol_flow_node *node, void *data) { struct update_data *mdata = data; if (mdata->handle) { if (!sol_update_cancel(mdata->handle)) SOL_WRN("Could not cancel ongoing task: %p", mdata->handle); } }
static void thingspeak_channel_update_queue(struct thingspeak_channel_update_data *mdata) { if (mdata->timeout) sol_timeout_del(mdata->timeout); mdata->timeout = sol_timeout_add(500, thingspeak_channel_update_send, mdata); if (!mdata->timeout) SOL_WRN("Could not create timeout to update Thingspeak channel"); }
static void i2c_write_configuration_cb(void *cb_data, struct sol_i2c *i2c, uint8_t reg, uint8_t *data, ssize_t status) { struct stts751_data *mdata = cb_data; mdata->i2c_pending = NULL; if (status < 0) SOL_WRN("Could not enable STTS751 temperature sensor"); }
static bool sol_mavlink_fd_handler(void *data, int fd, uint32_t cond) { struct sol_mavlink *mavlink = data; mavlink_message_t msg = { 0 }; mavlink_status_t status; uint8_t buf[MAVLINK_MAX_PACKET_LEN] = { 0 }; int i, res; res = recv(mavlink->fd, buf, MAVLINK_MAX_PACKET_LEN, 0); if (res == -1) { if (errno == EINTR) { SOL_INF("Could not read socket, retrying."); return true; } else { SOL_WRN("Could not read socket. %s", sol_util_strerrora(errno)); return false; } } for (i = 0; i < res; ++i) { if (!mavlink_parse_char(MAVLINK_COMM_0, buf[i], &msg, &status)) continue; switch (msg.msgid) { case MAVLINK_MSG_ID_GPS_RAW_INT: sol_mavlink_position_handler(mavlink, &msg); break; case MAVLINK_MSG_ID_HEARTBEAT: sol_mavlink_heartbeat_handler(mavlink, &msg); break; case MAVLINK_MSG_ID_STATUSTEXT: sol_mavlink_statustext_handler(&msg); break; case MAVLINK_MSG_ID_HOME_POSITION: sol_mavlink_home_position_handler(mavlink, &msg); break; case MAVLINK_MSG_ID_MISSION_ITEM_REACHED: sol_mavlink_mission_reached_handler(mavlink); break; default: SOL_INF("Unhandled event, msgid: %d", msg.msgid); } } if (mavlink->status == SOL_MAVLINK_STATUS_FULL_SETUP) { mavlink->status = SOL_MAVLINK_STATUS_READY; if (CHECK_HANDLER(mavlink, connect)) HANDLERS(mavlink)->connect((void *)mavlink->data, mavlink); } return true; }
SOL_API struct sol_message_digest * sol_message_digest_new(const struct sol_message_digest_config *config) { const struct sol_message_digest_info *dinfo; struct sol_message_digest *handle; struct sol_message_digest_common_new_params params; struct sol_str_slice algorithm; errno = EINVAL; SOL_NULL_CHECK(config, NULL); SOL_NULL_CHECK(config->on_digest_ready, NULL); SOL_NULL_CHECK(config->algorithm, NULL); #ifndef SOL_NO_API_VERSION if (config->api_version != SOL_MESSAGE_DIGEST_CONFIG_API_VERSION) { SOL_WRN("sol_message_digest_config->api_version=%" PRIu16 ", " "expected version is %" PRIu16 ".", config->api_version, SOL_MESSAGE_DIGEST_CONFIG_API_VERSION); return NULL; } #endif algorithm = sol_str_slice_from_str(config->algorithm); if (!sol_str_table_ptr_lookup(_available_digests, algorithm, &dinfo)) { SOL_WRN("failed to get digest algorithm \"%s\".", config->algorithm); return NULL; } params.config = config; params.ops = &dinfo->ops; params.context_size = dinfo->context_size; params.digest_size = dinfo->digest_size; params.context_template = NULL; handle = sol_message_digest_common_new(params); SOL_NULL_CHECK(handle, NULL); dinfo->init(handle); return handle; }
static int hostname_start(const struct sol_platform_linux_micro_module *mod, const char *service) { struct sol_file_reader *reader; struct sol_str_slice str; const char *s, *p, *end; int err = 0; reader = sol_file_reader_open("/etc/hostname"); SOL_NULL_CHECK_MSG(reader, -errno, "could not read /etc/hostname"); str = sol_file_reader_get_all(reader); s = p = str.data; end = s + str.len; for (; s < end; s++) { if (!isblank(*s)) break; } for (p = end - 1; p > s; p--) { if (!isblank(*p)) break; } if (s >= p) { SOL_WRN("no hostname in /etc/hostname"); err = -ENOENT; } else if (sethostname(s, p - s) < 0) { SOL_WRN("could not set hostname: %s", sol_util_strerrora(errno)); err = -errno; } sol_file_reader_close(reader); if (err == 0) sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_ACTIVE); else sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_FAILED); return err; }
static bool watchdog_keep_alive(void *data) { int reply, err; SOL_DBG("keep watchdog alive"); err = ioctl(watchdog_fd, WDIOC_KEEPALIVE, &reply); if (reply != WDIOF_KEEPALIVEPING) SOL_WRN("unexpected watchdog keepalive reply=%#x, expected=%#x. Ignored.", reply, WDIOF_KEEPALIVEPING); if (err == 0) return true; SOL_WRN("failed to keep watchdog alive: %s", sol_util_strerrora(errno)); close(watchdog_fd); watchdog_fd = -1; watchdog_timeout = NULL; sol_platform_linux_micro_inform_service_state(service_name, SOL_PLATFORM_SERVICE_STATE_FAILED); return false; }
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 int _populate_values(void *data, const char *sequence) { struct byte_validator_data *mdata = data; const char *it; char *tail; unsigned char *val; sol_vector_init(&mdata->values, sizeof(unsigned char)); it = sequence; do { int int_val; val = sol_vector_append(&mdata->values); SOL_NULL_CHECK_GOTO(val, no_memory); errno = 0; int_val = strtol(it, &tail, 10); if (errno) { SOL_WRN("Failed do convert option 'sequence' to int %s: %d", it, errno); return -errno; } if (int_val < 0 || int_val > 255) { SOL_WRN("Byte value out of range %d", int_val); return -ERANGE; } if (it == tail) { SOL_WRN("Failed to convert option 'sequence' to int %s", it); return -EINVAL; } it = tail; *val = int_val; } while (*tail != '\0'); return 0; no_memory: sol_vector_clear(&mdata->values); return -ENOMEM; }
static void on_connect(void *data, struct sol_mqtt *mqtt) { if (sol_mqtt_get_connection_status(mqtt) != SOL_MQTT_CONNECTED) { SOL_WRN("Unable to connect, retrying..."); sol_timeout_add(1000, try_reconnect, mqtt); return; } if (sol_mqtt_subscribe(mqtt, topic, SOL_MQTT_QOS_AT_MOST_ONCE)) SOL_ERR("Unable to subscribe to topic %s", topic); }
static void shutdown(void) { if (!did_idle) SOL_WRN("failed to do idle"); if (!did_timeout) SOL_WRN("failed to do timeout"); if (!did_fd) SOL_WRN("failed to do fd"); if (fork_run) sol_platform_linux_fork_run_stop(fork_run); if (pfd[0] > 0) { close(pfd[0]); close(pfd[1]); } if (!did_idle || !did_timeout || !did_fd) exit(EXIT_FAILURE); }
int sol_pin_mux_init(void) { sol_log_domain_init_level(SOL_LOG_DOMAIN); if (!sol_pin_mux_select_mux(sol_platform_get_board_name())) { SOL_WRN("Pin Multiplexer found, but failed to be loaded."); return -1; } return 0; }
static void lsm303_scale_bit_set(struct accelerometer_lsm303_data *mdata) { int r; r = sol_i2c_set_slave_address(mdata->i2c, mdata->slave); if (r < 0) { SOL_WRN("Failed to set slave at address 0x%02x\n", mdata->slave); return; } switch (mdata->scale) { case 2: mdata->i2c_buffer[0] = 0x00; mdata->sensitivity = 1.0 / 1000; break; case 4: mdata->i2c_buffer[0] = 0x01; mdata->sensitivity = 2.0 / 1000; break; case 8: mdata->i2c_buffer[0] = 0x02; mdata->sensitivity = 4.0 / 1000; break; case 16: mdata->i2c_buffer[0] = 0x03; mdata->sensitivity = 12.0 / 1000; break; default: SOL_WRN("Invalid scale. Expected one of 2, 4, 8 or 16"); return; } mdata->i2c_pending = sol_i2c_write_register(mdata->i2c, LSM303_ACCEL_REG_CTRL_REG4_A, mdata->i2c_buffer, 1, lsm303_i2c_write_scale_cb, mdata); if (!mdata->i2c_pending) SOL_WRN("Could not set scale to LSM303 accelerometer"); }
static void flow_send_do(struct sol_flow_node *flow, struct flow_static_data *fsd, uint16_t src_idx, uint16_t source_out_port_idx, struct sol_flow_packet *packet) { struct flow_static_type *type = (struct flow_static_type *)flow->type; const struct sol_flow_static_conn_spec *spec; unsigned int i; bool is_error_packet, dispatched; is_error_packet = sol_flow_packet_get_type(packet) == SOL_FLOW_PACKET_TYPE_ERROR; dispatched = false; for (i = type->node_infos[src_idx].first_conn_idx, spec = type->conn_specs + i; spec->src == src_idx; spec++, i++) { const struct sol_flow_port_type_in *dst_port_type; struct sol_flow_node *dst; struct conn_info *ci; if (spec->src_port != source_out_port_idx) continue; dst = fsd->nodes[spec->dst]; dst_port_type = sol_flow_node_type_get_port_in(dst->type, spec->dst_port); ci = &type->conn_infos[i]; dispatch_process(dst, spec->dst_port, ci->in_conn_id, dst_port_type, packet); dispatched = true; } if (type->ports_out_count > 0) { const struct sol_flow_static_port_spec *pspec; uint16_t exported_out; for (pspec = type->exported_out_specs, exported_out = 0; pspec->node < UINT16_MAX; pspec++, exported_out++) { if (pspec->node == src_idx && pspec->port == source_out_port_idx) { /* Export the packet. Note that ownership of packet * will pass to the send() function. */ sol_flow_send_packet(flow, exported_out, packet); return; } } } if (is_error_packet && !dispatched) { const char *msg; int code; if (sol_flow_packet_get_error(packet, &code, &msg) == 0) { SOL_WRN("Error packet \'%d (%s)\' sent from \'%s (%p)\' was not handled", code, msg, flow->id, flow); } } sol_flow_packet_del(packet); }
SOL_API int sol_json_token_get_int64(const struct sol_json_token *token, int64_t *value) { SOL_NULL_CHECK(token, -EINVAL); SOL_NULL_CHECK(value, -EINVAL); *value = 0; if (token->start >= token->end) { SOL_WRN("invalid token: start=%p, end=%p", token->start, token->end); return -EINVAL; } if (sol_json_token_get_type(token) != SOL_JSON_TYPE_NUMBER) { SOL_WRN("expected number, got token type '%c' for token \"%.*s\"", sol_json_token_get_type(token), (int)sol_json_token_get_size(token), token->start); return -EINVAL; } return token_get_int64(token, value); }
void sol_worker_thread_impl_feedback(void *handle) { struct sol_worker_thread_posix *thread = handle; SOL_NULL_CHECK(thread); SOL_NULL_CHECK(thread->config.feedback); if (sol_worker_thread_impl_cancel_check(thread)) { SOL_WRN("worker thread %p is not running.", thread); return; } if (thread->thread != pthread_self()) { SOL_WRN("trying to feedback from different worker thread %p.", thread); return; } if (sol_worker_thread_lock(thread)) { if (!thread->idler) thread->idler = sol_idle_add(sol_worker_thread_feedback_dispatch, thread); sol_worker_thread_unlock(thread); } }