-struct dev_buffer {
- /** Total size of the buffer. */
- size_t size;
- /** Amount of data currently in the buffer. */
- size_t len;
- /** Offset where the data starts in the buffer. */
- size_t offset;
- /** Space for the data. */
- uint8_t data[];
-};
-
-static struct dev_buffer *dev_buffer_new(size_t size)
-{
- struct dev_buffer *dbuf;
-
- if (!(dbuf = g_try_malloc(sizeof(struct dev_buffer) + size))) {
- sr_err("Dev buffer malloc failed (size=%zu).", size);
- return NULL;
- }
-
- dbuf->size = size;
- dbuf->len = 0;
- dbuf->offset = 0;
-
- return dbuf;
-}
-
-static void dev_buffer_destroy(struct dev_buffer *dbuf)
-{
- g_free(dbuf);
-}
-
-static int dev_buffer_fill_serial(struct dev_buffer *dbuf,
- struct sr_dev_inst *sdi)
-{
- struct sr_serial_dev_inst *serial;
- int len;
-
- serial = sdi->conn;
-
- /* If we already have data, move it to the beginning of the buffer. */
- if (dbuf->len > 0 && dbuf->offset > 0)
- memmove(dbuf->data, dbuf->data + dbuf->offset, dbuf->len);
-
- dbuf->offset = 0;
-
- len = dbuf->size - dbuf->len;
- len = serial_read_nonblocking(serial, dbuf->data + dbuf->len, len);
- if (len < 0) {
- sr_err("Serial port read error: %d.", len);
- return len;
- }
-
- dbuf->len += len;
-
- return SR_OK;
-}
-
-static uint8_t *dev_buffer_packet_find(struct dev_buffer *dbuf,
- gboolean (*packet_valid)(const uint8_t *),
- size_t packet_size)
-{
- size_t offset;
-
- while (dbuf->len >= packet_size) {
- if (packet_valid(dbuf->data + dbuf->offset)) {
- offset = dbuf->offset;
- dbuf->offset += packet_size;
- dbuf->len -= packet_size;
- return dbuf->data + offset;
- }
- dbuf->offset++;
- dbuf->len--;
- }
-
- return NULL;
-}
-
-struct dev_sample_counter {
- /** The current number of already received samples. */
- uint64_t count;
- /** The current sampling limit (in number of samples). */
- uint64_t limit;
-};
-
-static void dev_sample_counter_start(struct dev_sample_counter *cnt)
-{
- cnt->count = 0;
-}
-
-static void dev_sample_counter_inc(struct dev_sample_counter *cnt)
-{
- cnt->count++;
-}
-
-static void dev_sample_limit_set(struct dev_sample_counter *cnt, uint64_t limit)
-{
- cnt->limit = limit;
-}
-
-static gboolean dev_sample_limit_reached(struct dev_sample_counter *cnt)
-{
- if (cnt->limit && cnt->count >= cnt->limit) {
- sr_info("Requested sample limit reached.");
- return TRUE;
- }
-
- return FALSE;
-}
-
-struct dev_time_counter {
- /** The starting time of current sampling run. */
- int64_t starttime;
- /** The time limit (in milliseconds). */
- uint64_t limit;
-};
-
-static void dev_time_counter_start(struct dev_time_counter *cnt)
-{
- cnt->starttime = g_get_monotonic_time();
-}
-
-static void dev_time_limit_set(struct dev_time_counter *cnt, uint64_t limit)
-{
- cnt->limit = limit;
-}
-
-static gboolean dev_time_limit_reached(struct dev_time_counter *cnt)
-{
- int64_t time;
-
- if (cnt->limit) {
- time = (g_get_monotonic_time() - cnt->starttime) / 1000;
- if (time > (int64_t)cnt->limit) {
- sr_info("Requested time limit reached.");
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static void serial_conf_get(GSList *options, const char *def_serialcomm,
- const char **conn, const char **serialcomm)
-{
- struct sr_config *src;
- GSList *l;
-
- *conn = *serialcomm = NULL;
- for (l = options; l; l = l->next) {
- src = l->data;
- switch (src->key) {
- case SR_CONF_CONN:
- *conn = g_variant_get_string(src->data, NULL);
- break;
- case SR_CONF_SERIALCOMM:
- *serialcomm = g_variant_get_string(src->data, NULL);
- break;
- }
- }
-
- if (*serialcomm == NULL)
- *serialcomm = def_serialcomm;
-}
-
-static struct sr_serial_dev_inst *serial_dev_new(GSList *options,
- const char *def_serialcomm)
-
-{
- const char *conn, *serialcomm;
-
- serial_conf_get(options, def_serialcomm, &conn, &serialcomm);
-
- if (!conn)
- return NULL;
-
- return sr_serial_dev_inst_new(conn, serialcomm);
-}
-
-static int serial_stream_check_buf(struct sr_serial_dev_inst *serial,
- uint8_t *buf, size_t buflen,
- size_t packet_size,
- packet_valid_callback is_valid,
- uint64_t timeout_ms, int baudrate)
-{
- size_t len, dropped;
- int ret;
-
- if ((ret = serial_open(serial, SERIAL_RDWR)) != SR_OK)
- return ret;
-
- serial_flush(serial);
-
- len = buflen;
- ret = serial_stream_detect(serial, buf, &len, packet_size,
- is_valid, timeout_ms, baudrate);
-
- serial_close(serial);
-
- if (ret != SR_OK)
- return ret;
-
- /*
- * If we dropped more than two packets worth of data, something is
- * wrong. We shouldn't quit however, since the dropped bytes might be
- * just zeroes at the beginning of the stream. Those can occur as a
- * combination of the nonstandard cable that ships with some devices
- * and the serial port or USB to serial adapter.
- */
- dropped = len - packet_size;
- if (dropped > 2 * packet_size)
- sr_warn("Had to drop too much data.");
-
- return SR_OK;
-}
-
-static int serial_stream_check(struct sr_serial_dev_inst *serial,
- size_t packet_size,
- packet_valid_callback is_valid,
- uint64_t timeout_ms, int baudrate)
-{
- uint8_t buf[128];
-
- return serial_stream_check_buf(serial, buf, sizeof(buf), packet_size,
- is_valid, timeout_ms, baudrate);
-}
-
-struct std_opt_desc {
- const uint32_t *scanopts;
- const int num_scanopts;
- const uint32_t *devopts;
- const int num_devopts;
-};
-
-static int std_config_list(uint32_t key, GVariant **data,
- const struct std_opt_desc *d)
-{
- switch (key) {
- case SR_CONF_SCAN_OPTIONS:
- *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
- d->scanopts, d->num_scanopts, sizeof(uint32_t));
- break;
- case SR_CONF_DEVICE_OPTIONS:
- *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
- d->devopts, d->num_devopts, sizeof(uint32_t));
- break;
- default:
- return SR_ERR_NA;
- }
-
- return SR_OK;
-}
-
-static int send_config_update(struct sr_dev_inst *sdi, struct sr_config *cfg)
-{
- struct sr_datafeed_packet packet;
- struct sr_datafeed_meta meta;
-
- memset(&meta, 0, sizeof(meta));
-
- packet.type = SR_DF_META;
- packet.payload = &meta;
-
- meta.config = g_slist_append(meta.config, cfg);
-
- return sr_session_send(sdi, &packet);
-}