int main(int argc, char *argv[]) { int r = 0; if (sol_init() < 0) return EXIT_FAILURE; printf("Initial platform state: %d\n", sol_platform_get_state()); sol_platform_add_state_monitor(on_state_change, NULL); if (argc > 2) { cmds = argv + 1; n_cmds = argc - 1; timeout_handle = sol_timeout_add(CMD_TICK, on_timeout_cmd, NULL); } sol_run(); if (timeout_handle) sol_timeout_del(timeout_handle); sol_platform_del_state_monitor(on_state_change, NULL); sol_shutdown(); return r; }
static void flow_node_close(struct sol_flow_node *node, void *data) { struct flow_static_type *type = (struct flow_static_type *)node->type; struct flow_static_data *fsd = data; int i; if (fsd->delay_send) sol_timeout_del(fsd->delay_send); while (!sol_list_is_empty(&fsd->delayed_packets)) { struct delayed_packet *dp; struct sol_list *itr = fsd->delayed_packets.next; dp = SOL_LIST_GET_CONTAINER(itr, struct delayed_packet, list); sol_list_remove(itr); sol_flow_packet_del(dp->packet); free(dp); } teardown_connections(type, fsd); for (i = type->node_count - 1; i >= 0; i--) sol_flow_node_fini(fsd->nodes[i]); free(fsd->node_storage); free(fsd->nodes); if (type->owned_by_node) sol_flow_static_del_type(&type->base.base); }
/** * This destructor method is called when the node is finished. * * When this method returns the memory pointed by 'data' is released * and should stop being referenced. */ static void reader_close(struct sol_flow_node *node, void *data) { struct reader_data *mdata = data; /* stop the timer */ sol_timeout_del(mdata->timer); }
void test_result_close(struct sol_flow_node *node, void *data) { struct test_result_data *d = data; if (d->timer) sol_timeout_del(d->timer); }
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"); }
void int_generator_close(struct sol_flow_node *node, void *data) { struct int_generator_data *mdata = data; if (mdata->values.len != mdata->next_index) sol_timeout_del(mdata->timer); sol_vector_clear(&mdata->values); }
void boolean_generator_close(struct sol_flow_node *node, void *data) { struct boolean_generator_data *mdata = data; if (*mdata->it != '\0') sol_timeout_del(mdata->timer); free(mdata->sequence); }
static int stop_timer(struct timer_data *mdata) { if (!mdata->timer) return 0; sol_timeout_del(mdata->timer); mdata->timer = NULL; return 0; }
static bool on_timeout_del_and_new(void *data) { struct sol_timeout *timeout_to_del = data; timeout_called++; ASSERT_INT_EQ(sol_timeout_del(timeout_to_del), 1); sol_timeout_add(250, on_timeout_quit, NULL); sol_timeout_add(200, on_timeout_chained, NULL); return false; }
static void gyroscope_l3g4200d_close(struct sol_flow_node *node, void *data) { struct gyroscope_l3g4200d_data *mdata = data; if (mdata->timer) sol_timeout_del(mdata->timer); if (mdata->i2c) sol_i2c_close(mdata->i2c); }
SOL_API void sol_spi_close(struct sol_spi *spi) { SOL_NULL_CHECK(spi); if (spi->transfer.timeout) { sol_timeout_del(spi->transfer.timeout); spi_transfer_dispatch(spi); } spi_poweroff(spi->bus); free(spi); }
static int tune_stop(struct piezo_speaker_data *mdata) { if (!mdata->timer) return 0; sol_timeout_del(mdata->timer); mdata->timer = NULL; return sol_pwm_set_enabled(mdata->pwm, false); }
static void _reset(void *data) { struct irange_buffer_data *mdata = data; mdata->cur_len = 0; if (mdata->timer) sol_timeout_del(mdata->timer); if (mdata->timeout) mdata->timer = sol_timeout_add(mdata->timeout, _timeout, mdata); }
static void irange_buffer_close(struct sol_flow_node *node, void *data) { struct irange_buffer_data *mdata = data; if (mdata->timer) { sol_timeout_del(mdata->timer); mdata->timer = NULL; } free(mdata->input_queue); }
static void accelerometer_lsm303_close(struct sol_flow_node *node, void *data) { struct accelerometer_lsm303_data *mdata = data; if (mdata->timer) sol_timeout_del(mdata->timer); if (mdata->i2c_pending) sol_i2c_pending_cancel(mdata->i2c, mdata->i2c_pending); if (mdata->i2c) sol_i2c_close(mdata->i2c); }
static void shutdown(void) { const char **itr; if (gpio) sol_gpio_close(gpio); sol_timeout_del(timeout); for (itr = services; *itr != NULL; itr++) sol_platform_del_service_monitor(on_service_change, *itr, NULL); sol_platform_del_state_monitor(on_platform_state_change, NULL); }
static void temperature_stts751_close(struct sol_flow_node *node, void *data) { struct stts751_data *mdata = data; if (mdata->i2c_pending) sol_i2c_pending_cancel(mdata->i2c, mdata->i2c_pending); if (mdata->i2c) sol_i2c_close(mdata->i2c); if (mdata->timer) sol_timeout_del(mdata->timer); }
static void thingspeak_execute_close(struct sol_flow_node *node, void *data) { struct thingspeak_execute_data *mdata = data; struct sol_http_client_connection *connection; uint16_t i; sol_timeout_del(mdata->timeout); free_talkback(&mdata->talkback); SOL_PTR_VECTOR_FOREACH_IDX (&mdata->pending_conns, connection, i) sol_http_client_connection_cancel(connection); sol_ptr_vector_clear(&mdata->pending_conns); }
static void aio_close(struct sol_flow_node *node, void *data) { struct aio_data *mdata = data; SOL_NULL_CHECK(mdata); free(mdata->pin); if (mdata->aio) sol_aio_close(mdata->aio); if (mdata->timer) sol_timeout_del(mdata->timer); }
static void on_fork_exit(void *data, uint64_t pid, int status) { if (check_timeout) { sol_timeout_del(check_timeout); check_timeout = NULL; } SOL_DBG("dbus-daemon pid=%" PRIu64 " exited with status=%d", pid, status); if (status) sol_platform_linux_micro_inform_service_state(name, SOL_PLATFORM_SERVICE_STATE_FAILED); else sol_platform_linux_micro_inform_service_state(name, SOL_PLATFORM_SERVICE_STATE_INACTIVE); }
static int start_timer(struct timer_data *mdata) { if (mdata->timer) { sol_timeout_del(mdata->timer); mdata->timer = NULL; } if (mdata->interval < 1) return 0; mdata->timer = sol_timeout_add(mdata->interval, timer_tick, mdata); SOL_NULL_CHECK(mdata->timer, -errno); return 0; }
static int watchdog_stop(const struct sol_platform_linux_micro_module *module, const char *service, bool force_immediate) { if (watchdog_fd < 0) return 0; sol_timeout_del(watchdog_timeout); watchdog_timeout = NULL; close(watchdog_fd); watchdog_fd = -1; sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_INACTIVE); service_name = NULL; return 0; }
static int gyro_timer_resched(struct gyroscope_l3g4200d_data *mdata, unsigned int timeout_ms, bool (*cb)(void *data), const void *cb_data) { SOL_NULL_CHECK(cb, -EINVAL); if (mdata->timer) sol_timeout_del(mdata->timer); mdata->timer = sol_timeout_add(timeout_ms, cb, cb_data); SOL_NULL_CHECK(mdata->timer, -ENOMEM); return 0; }
SOL_API void sol_spi_close(struct sol_spi *spi) { SOL_NULL_CHECK(spi); #ifdef PTHREAD if (spi->transfer.worker) { sol_worker_thread_cancel(spi->transfer.worker); } #else if (spi->transfer.timeout) { sol_timeout_del(spi->transfer.timeout); spi_transfer_dispatch(spi); } #endif close(spi->fd); free(spi); }
static void thingspeak_channel_update_close(struct sol_flow_node *node, void *data) { struct thingspeak_channel_update_data *mdata = data; struct sol_http_client_connection *connection; uint16_t i; for (i = 0; i < ARRAY_SIZE(mdata->fields); i++) free(mdata->fields[i]); free(mdata->status); free(mdata->api_key); free(mdata->endpoint); sol_timeout_del(mdata->timeout); SOL_PTR_VECTOR_FOREACH_IDX (&mdata->pending_conns, connection, i) sol_http_client_connection_cancel(connection); sol_ptr_vector_clear(&mdata->pending_conns); }
static int dbus_stop(const struct sol_platform_linux_micro_module *mod, const char *service, bool force_immediate) { int err = 0; if (!fork_run) return 0; if (!force_immediate) err = sol_platform_linux_fork_run_send_signal(fork_run, SIGTERM); else { sol_platform_linux_fork_run_stop(fork_run); fork_run = NULL; } if (check_timeout) { sol_timeout_del(check_timeout); check_timeout = NULL; } return err; }
static int irange_buffer_timeout(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { int r; int32_t timeout; struct irange_buffer_data *mdata = data; r = sol_flow_packet_get_irange_value(packet, &timeout); SOL_INT_CHECK(r, < 0, r); if (timeout < 0) SOL_WRN("Invalid 'timeout' value: '%" PRId32 "'. Skipping it.", timeout); mdata->timeout = timeout; if (mdata->timer) sol_timeout_del(mdata->timer); if (mdata->timeout) mdata->timer = sol_timeout_add(mdata->timeout, _timeout, mdata); return r; }
static int mytype_func(struct sol_flow_node *node, const struct sol_flow_simplectype_event *ev, void *data) { struct mytype_context *ctx = data; switch (ev->type) { case SOL_FLOW_SIMPLECTYPE_EVENT_TYPE_OPEN: { if (ev->options #ifndef SOL_NO_API_VERSION && ev->options->sub_api == MYTYPE_OPTIONS_SUB_API #endif ) { struct mytype_options *opt = (struct mytype_options *)ev->options; ctx->someint = opt->someint; ctx->somebool = opt->somebool; } /* every 500ms send out a string representing our someint + somebool */ ctx->timer = sol_timeout_add(500, on_timeout, node); if (!ctx->timer) return -ENOMEM; printf("simplectype opened ctx=%p, someint=%d, somebool=%d\n", ctx, ctx->someint, ctx->somebool); return 0; } case SOL_FLOW_SIMPLECTYPE_EVENT_TYPE_CLOSE: { printf("simplectype closed ctx=%p\n", ctx); sol_timeout_del(ctx->timer); return 0; } case SOL_FLOW_SIMPLECTYPE_EVENT_TYPE_PORT_IN_PROCESS: { /* this is to show the port names, ideally one would keep the * indexes and use them here, doing integer comparisons * instead of strcmp() */ if (strcmp(ev->port_name, "IRANGE") == 0) { int32_t val; if (sol_flow_packet_get_irange_value(ev->packet, &val) == 0) { printf("simplectype updated integer from %d to %d\n", ctx->someint, val); ctx->someint = val; return 0; } } else if (strcmp(ev->port_name, "BOOLEAN") == 0) { bool val; if (sol_flow_packet_get_boolean(ev->packet, &val) == 0) { printf("simplectype updated boolean from %d to %d\n", ctx->somebool, val); ctx->somebool = val; return 0; } } printf("simplectype port '%s' got unexpected data!\n", ev->port_name); return -EINVAL; } case SOL_FLOW_SIMPLECTYPE_EVENT_TYPE_PORT_IN_CONNECT: printf("simplectype port IN '%s' id=%d conn=%d connected ctx=%p\n", ev->port_name, ev->port, ev->conn_id, ctx); return 0; case SOL_FLOW_SIMPLECTYPE_EVENT_TYPE_PORT_IN_DISCONNECT: printf("simplectype port IN '%s' id=%d conn=%d disconnected ctx=%p\n", ev->port_name, ev->port, ev->conn_id, ctx); return 0; case SOL_FLOW_SIMPLECTYPE_EVENT_TYPE_PORT_OUT_CONNECT: printf("simplectype port OUT '%s' id=%d conn=%d connected ctx=%p\n", ev->port_name, ev->port, ev->conn_id, ctx); return 0; case SOL_FLOW_SIMPLECTYPE_EVENT_TYPE_PORT_OUT_DISCONNECT: printf("simplectype port OUT '%s' id=%d conn=%d disconnected ctx=%p\n", ev->port_name, ev->port, ev->conn_id, ctx); return 0; } return -EINVAL; }
static void i2c_read_data_cb(void *cb_data, struct sol_i2c *i2c, uint8_t reg, uint8_t *data, ssize_t status) { struct gyroscope_l3g4200d_data *mdata = cb_data; double scale = mdata->use_rad ? GYRO_SCALE_R_S * DEG_TO_RAD : GYRO_SCALE_R_S; uint8_t num_samples_available; struct sol_direction_vector val = { .min = -GYRO_RANGE, .max = GYRO_RANGE, .x = mdata->reading[0], .y = mdata->reading[1], .z = mdata->reading[2] }; mdata->i2c_pending = NULL; if (status < 0) { SOL_WRN("Failed to read L3G4200D gyro fifo status"); return; } num_samples_available = status / (sizeof(int16_t) * 3); /* raw readings, with only the sensor-provided filtering */ for (uint8_t i = 0; i < num_samples_available; i++) { mdata->reading[0] = mdata->gyro_data.buffer[i][0] * scale; mdata->reading[1] = -mdata->gyro_data.buffer[i][1] * scale; mdata->reading[2] = -mdata->gyro_data.buffer[i][2] * scale; } sol_flow_send_direction_vector_packet(mdata->node, SOL_FLOW_NODE_TYPE_GYROSCOPE_L3G4200D__OUT__OUT, &val); mdata->pending_ticks--; if (mdata->pending_ticks) gyro_tick_do(mdata); } static void i2c_read_fifo_status_cb(void *cb_data, struct sol_i2c *i2c, uint8_t reg, uint8_t *data, ssize_t status) { struct gyroscope_l3g4200d_data *mdata = cb_data; uint8_t num_samples_available; uint8_t fifo_status = mdata->common.buffer[0]; mdata->i2c_pending = NULL; if (status < 0) { SOL_WRN("Failed to read L3G4200D gyro fifo status"); return; } if (fifo_status & GYRO_REG_FIFO_SRC_OVERRUN) { num_samples_available = 32; } else if (fifo_status & GYRO_REG_FIFO_SRC_EMPTY) { num_samples_available = 0; } else { num_samples_available = fifo_status & GYRO_REG_FIFO_SRC_ENTRIES_MASK; } if (!num_samples_available) { SOL_INF("No samples available"); return; } SOL_DBG("%d samples available", num_samples_available); /* Read *all* the entries in one go, using AUTO_INCREMENT */ mdata->i2c_pending = sol_i2c_read_register(mdata->i2c, GYRO_REG_XL | GYRO_REG_AUTO_INCREMENT, (uint8_t *)&mdata->gyro_data.buffer[0][0], sizeof(mdata->gyro_data.buffer), i2c_read_data_cb, mdata); if (!mdata->i2c_pending) SOL_WRN("Failed to read L3G4200D gyro samples"); } static bool gyro_tick_do(void *data) { struct gyroscope_l3g4200d_data *mdata = data; mdata->timer = NULL; if (sol_i2c_busy(mdata->i2c)) { gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_tick_do); return false; } if (!sol_i2c_set_slave_address(mdata->i2c, GYRO_ADDRESS)) { SOL_WRN("Failed to set slave at address 0x%02x\n", GYRO_ADDRESS); return false; } mdata->common.buffer[0] = 0; mdata->i2c_pending = sol_i2c_read_register(mdata->i2c, GYRO_REG_FIFO_SRC, mdata->common.buffer, 1, i2c_read_fifo_status_cb, mdata); if (!mdata->i2c_pending) SOL_WRN("Failed to read L3G4200D gyro fifo status"); return false; } static bool gyro_ready(void *data) { struct gyroscope_l3g4200d_data *mdata = data; mdata->ready = true; SOL_DBG("gyro is ready for reading"); if (mdata->pending_ticks) gyro_tick_do(mdata); return false; } static void i2c_write_fifo_ctl_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 stream mode"); return; } if (gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_ready) < 0) SOL_WRN("error in scheduling a L3G4200D gyro's init command"); } static bool gyro_init_stream(void *data) { struct gyroscope_l3g4200d_data *mdata = data; mdata->timer = NULL; if (sol_i2c_busy(mdata->i2c)) { gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init_stream); return false; } if (!sol_i2c_set_slave_address(mdata->i2c, GYRO_ADDRESS)) { SOL_WRN("Failed to set slave at address 0x%02x\n", GYRO_ADDRESS); return false; } /* enable FIFO in stream mode */ mdata->common.buffer[0] = GYRO_REG_FIFO_CTL_STREAM; mdata->i2c_pending = sol_i2c_write_register(mdata->i2c, GYRO_REG_FIFO_CTL, mdata->common.buffer, 1, i2c_write_fifo_ctl_cb, mdata); if (!mdata->i2c_pending) SOL_WRN("could not set L3G4200D gyro sensor's stream mode"); return false; } static void i2c_write_ctrl_reg5_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 fifo mode"); return; } if (gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init_stream) < 0) SOL_WRN("error in scheduling a L3G4200D gyro's init command"); } static bool gyro_init_fifo(void *data) { struct gyroscope_l3g4200d_data *mdata = data; mdata->timer = NULL; if (sol_i2c_busy(mdata->i2c)) { gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init_fifo); return false; } if (!sol_i2c_set_slave_address(mdata->i2c, GYRO_ADDRESS)) { SOL_WRN("Failed to set slave at address 0x%02x\n", GYRO_ADDRESS); return false; } mdata->common.buffer[0] = GYRO_REG_CTRL_REG5_FIFO_EN; mdata->i2c_pending = sol_i2c_write_register(mdata->i2c, GYRO_REG_CTRL_REG5, mdata->common.buffer, 1, i2c_write_ctrl_reg5_cb, mdata); if (!mdata->i2c_pending) SOL_WRN("could not set L3G4200D gyro sensor's fifo mode"); return false; } static void i2c_write_ctrl_reg4_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 resolution"); return; } if (gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init_fifo) < 0) SOL_WRN("error in scheduling a L3G4200D gyro's init command"); } static bool gyro_init_range(void *data) { struct gyroscope_l3g4200d_data *mdata = data; mdata->timer = NULL; if (sol_i2c_busy(mdata->i2c)) { gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init_range); return false; } if (!sol_i2c_set_slave_address(mdata->i2c, GYRO_ADDRESS)) { SOL_WRN("Failed to set slave at address 0x%02x\n", GYRO_ADDRESS); return false; } /* setup for 2000 degrees/sec */ mdata->common.buffer[0] = GYRO_REG_CTRL_REG4_FS_2000; mdata->i2c_pending = sol_i2c_write_register(mdata->i2c, GYRO_REG_CTRL_REG4, mdata->common.buffer, 1, i2c_write_ctrl_reg4_cb, mdata); if (!mdata->i2c_pending) SOL_WRN("could not set L3G4200D gyro sensor's resolution"); return false; } static bool gyro_init_sampling(void *data); 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"); } } /* meant to run 3 times */ static bool gyro_init_sampling(void *data) { struct gyroscope_l3g4200d_data *mdata = data; mdata->timer = NULL; if (sol_i2c_busy(mdata->i2c)) { gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init_sampling); return false; } if (!sol_i2c_set_slave_address(mdata->i2c, GYRO_ADDRESS)) { SOL_WRN("Failed to set slave at address 0x%02x\n", GYRO_ADDRESS); return false; } /* setup for 800Hz sampling with 110Hz filter */ mdata->common.buffer[0] = GYRO_REG_CTRL_REG1_DRBW_800_110 | GYRO_REG_CTRL_REG1_PD | GYRO_REG_CTRL_REG1_XYZ_ENABLE; mdata->i2c_pending = sol_i2c_write_register(mdata->i2c, GYRO_REG_CTRL_REG1, mdata->common.buffer, 1, i2c_write_ctrl_reg1_cb, mdata); if (!mdata->i2c_pending) SOL_WRN("could not set L3G4200D gyro sensor's sampling rate"); return false; } 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); } static bool gyro_init(void *data) { struct gyroscope_l3g4200d_data *mdata = data; mdata->timer = NULL; if (sol_i2c_busy(mdata->i2c)) { gyro_timer_resched(mdata, GYRO_INIT_STEP_TIME, gyro_init); return false; } if (!sol_i2c_set_slave_address(mdata->i2c, GYRO_ADDRESS)) { SOL_WRN("Failed to set slave at address 0x%02x\n", GYRO_ADDRESS); return false; } mdata->i2c_pending = sol_i2c_read_register(mdata->i2c, GYRO_REG_WHO_AM_I, mdata->common.buffer, 1, i2c_read_who_am_i_cb, mdata); if (!mdata->i2c_pending) SOL_WRN("Failed to read i2c register"); return false; } static int gyroscope_l3g4200d_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct gyroscope_l3g4200d_data *mdata = data; const struct sol_flow_node_type_gyroscope_l3g4200d_options *opts = (const struct sol_flow_node_type_gyroscope_l3g4200d_options *)options; SOL_NULL_CHECK(options, -EINVAL); mdata->i2c = sol_i2c_open(opts->i2c_bus, I2C_SPEED); SOL_NULL_CHECK_MSG(mdata->i2c, -EIO, "Failed to open i2c bus"); mdata->use_rad = opts->output_radians; mdata->init_sampling_cnt = 3; mdata->node = node; gyro_init(mdata); return 0; } static void gyroscope_l3g4200d_close(struct sol_flow_node *node, void *data) { struct gyroscope_l3g4200d_data *mdata = data; if (mdata->i2c_pending) sol_i2c_pending_cancel(mdata->i2c, mdata->i2c_pending); if (mdata->i2c) sol_i2c_close(mdata->i2c); if (mdata->timer) sol_timeout_del(mdata->timer); } static int gyroscope_l3g4200d_tick(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct gyroscope_l3g4200d_data *mdata = data; if (!mdata->ready || mdata->pending_ticks) { mdata->pending_ticks++; return 0; } gyro_tick_do(mdata); return 0; }