static int process_buffer(struct sr_input *in) { struct context *inc; struct sr_datafeed_meta meta; struct sr_datafeed_packet packet; struct sr_config *src; unsigned int offset, chunk_size; inc = in->priv; if (!inc->started) { std_session_send_df_header(in->sdi, LOG_PREFIX); if (inc->samplerate) { packet.type = SR_DF_META; packet.payload = &meta; src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(inc->samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); g_slist_free(meta.config); sr_config_free(src); } inc->started = TRUE; } /* Round down to the last channels * unitsize boundary. */ inc->analog.num_samples = CHUNK_SIZE / inc->samplesize; chunk_size = inc->analog.num_samples * inc->samplesize; offset = 0; while ((offset + chunk_size) < in->buf->len) { inc->analog.data = in->buf->str + offset; sr_session_send(in->sdi, &inc->packet); offset += chunk_size; } inc->analog.num_samples = (in->buf->len - offset) / inc->samplesize; chunk_size = inc->analog.num_samples * inc->samplesize; if (chunk_size > 0) { inc->analog.data = in->buf->str + offset; sr_session_send(in->sdi, &inc->packet); offset += chunk_size; } if ((unsigned int)offset < in->buf->len) { /* * The incoming buffer wasn't processed completely. Stash * the leftover data for next time. */ g_string_erase(in->buf, 0, offset); } else { g_string_truncate(in->buf, 0); } return SR_OK; }
static int process_buffer(struct sr_input *in) { struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_datafeed_logic logic; struct sr_config *src; struct context *inc; gsize chunk_size, i; gsize chunk; uint16_t unitsize; inc = in->priv; unitsize = (g_slist_length(in->sdi->channels) + 7) / 8; if (!inc->started) { std_session_send_df_header(in->sdi); if (inc->samplerate) { packet.type = SR_DF_META; packet.payload = &meta; src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(inc->samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); g_slist_free(meta.config); sr_config_free(src); } inc->samples_remain = CHRONOVU_LA8_DATASIZE; inc->samples_remain /= unitsize; inc->started = TRUE; } packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.unitsize = unitsize; /* Cut off at multiple of unitsize. Avoid sending the "header". */ chunk_size = in->buf->len / logic.unitsize * logic.unitsize; chunk_size = MIN(chunk_size, inc->samples_remain * unitsize); for (i = 0; i < chunk_size; i += chunk) { logic.data = in->buf->str + i; chunk = MIN(CHUNK_SIZE, chunk_size - i); if (chunk) { logic.length = chunk; sr_session_send(in->sdi, &packet); inc->samples_remain -= chunk / unitsize; } } g_string_erase(in->buf, 0, chunk_size); return SR_OK; }
static int loadfile(struct sr_input *in, const char *filename) { struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_datafeed_logic logic; struct sr_config *src; unsigned char buffer[CHUNKSIZE]; int fd, size, num_probes; struct context *ctx; ctx = in->internal; packet.status = SR_PKT_OK; if ((fd = open(filename, O_RDONLY)) == -1) return SR_ERR; num_probes = g_slist_length(in->sdi->channels); /* Send header packet to the session bus. */ std_session_send_df_header(in->sdi, LOG_PREFIX); if (ctx->samplerate) { packet.type = SR_DF_META; packet.payload = &meta; src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(ctx->samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); sr_config_free(src); } /* Chop up the input file into chunks & send it to the session bus. */ packet.type = SR_DF_LOGIC; packet.payload = &logic; logic.unitsize = (num_probes + 7) / 8; logic.data = buffer; while ((size = read(fd, buffer, CHUNKSIZE)) > 0) { logic.length = size; sr_session_send(in->sdi, &packet); } close(fd); /* Send end packet to the session bus. */ packet.type = SR_DF_END; sr_session_send(in->sdi, &packet); g_free(ctx); in->internal = NULL; return SR_OK; }
static int loadfile(struct sr_input *in, const char *filename) { struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_config *src; FILE *file; struct context *ctx; uint64_t samplerate; ctx = in->internal; if ((file = fopen(filename, "r")) == NULL) return SR_ERR; if (!parse_header(file, ctx)) { sr_err("VCD parsing failed"); fclose(file); return SR_ERR; } /* Send header packet to the session bus. */ std_session_send_df_header(in->sdi, LOG_PREFIX); /* Send metadata about the SR_DF_LOGIC packets to come. */ packet.type = SR_DF_META; packet.payload = &meta; samplerate = ctx->samplerate / ctx->downsample; src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); sr_config_free(src); /* Parse the contents of the VCD file */ parse_contents(file, in->sdi, ctx); /* Send end packet to the session bus. */ packet.type = SR_DF_END; sr_session_send(in->sdi, &packet); fclose(file); release_context(ctx); in->internal = NULL; return SR_OK; }
static int process_buffer(struct sr_input *in) { struct context *inc; struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_config *src; int offset, chunk_samples, total_samples, processed, max_chunk_samples; int num_samples, i; char channelname[8]; inc = in->priv; if (!inc->started) { for (i = 0; i < inc->num_channels; i++) { snprintf(channelname, 8, "CH%d", i + 1); sr_channel_new(in->sdi, i, SR_CHANNEL_ANALOG, TRUE, channelname); } std_session_send_df_header(in->sdi, LOG_PREFIX); packet.type = SR_DF_META; packet.payload = &meta; src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(inc->samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); sr_config_free(src); inc->started = TRUE; } if (!inc->found_data) { /* Skip past size of 'fmt ' chunk. */ i = 20 + RL32(in->buf->str + 16); offset = find_data_chunk(in->buf, i); if (offset < 0) { if (in->buf->len > MAX_DATA_CHUNK_OFFSET) { sr_err("Couldn't find data chunk."); return SR_ERR; } } inc->found_data = TRUE; } else offset = 0; /* Round off up to the last channels * unitsize boundary. */ chunk_samples = (in->buf->len - offset) / inc->num_channels / inc->unitsize; max_chunk_samples = CHUNK_SIZE / inc->num_channels / inc->unitsize; processed = 0; total_samples = chunk_samples; while (processed < total_samples) { if (chunk_samples > max_chunk_samples) num_samples = max_chunk_samples; else num_samples = chunk_samples; send_chunk(in, offset, num_samples); offset += num_samples * inc->unitsize; chunk_samples -= num_samples; processed += num_samples; } if ((unsigned int)offset < in->buf->len) { /* * The incoming buffer wasn't processed completely. Stash * the leftover data for next time. */ g_string_erase(in->buf, 0, offset); } else g_string_truncate(in->buf, 0); return SR_OK; }
static int loadfile(struct sr_input *in, const char *filename) { int res; struct context *ctx; struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_config *cfg; GIOStatus status; gboolean read_new_line; gsize term_pos; char **columns; gsize num_columns; int max_columns; (void)filename; ctx = in->internal; /* Send header packet to the session bus. */ std_session_send_df_header(in->sdi, LOG_PREFIX); if (ctx->samplerate) { packet.type = SR_DF_META; packet.payload = &meta; cfg = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(ctx->samplerate)); meta.config = g_slist_append(NULL, cfg); sr_session_send(in->sdi, &packet); sr_config_free(cfg); } read_new_line = FALSE; /* Limit the number of columns to parse. */ if (ctx->multi_column_mode) max_columns = ctx->num_probes; else max_columns = 1; while (TRUE) { /* * Skip reading a new line for the first time if the last read * line was not a header because the sample data is not parsed * yet. */ if (read_new_line || ctx->header) { ctx->line_number++; status = g_io_channel_read_line_string(ctx->channel, ctx->buffer, &term_pos, NULL); if (status == G_IO_STATUS_EOF) break; if (status != G_IO_STATUS_NORMAL) { sr_err("Error while reading line %zu.", ctx->line_number); free_context(ctx); return SR_ERR; } /* Remove line termination character(s). */ g_string_truncate(ctx->buffer, term_pos); } read_new_line = TRUE; if (!ctx->buffer->len) { sr_spew("Blank line %zu skipped.", ctx->line_number); continue; } /* Remove trailing comment. */ strip_comment(ctx->buffer, ctx->comment); if (!ctx->buffer->len) { sr_spew("Comment-only line %zu skipped.", ctx->line_number); continue; } if (!(columns = parse_line(ctx, max_columns))) { sr_err("Error while parsing line %zu.", ctx->line_number); free_context(ctx); return SR_ERR; } num_columns = g_strv_length(columns); /* Ensure that the first column is not out of bounds. */ if (!num_columns) { sr_err("Column %zu in line %zu is out of bounds.", ctx->first_column, ctx->line_number); g_strfreev(columns); free_context(ctx); return SR_ERR; } /* * Ensure that the number of probes does not exceed the number * of columns in multi column mode. */ if (ctx->multi_column_mode && num_columns < ctx->num_probes) { sr_err("Not enough columns for desired number of probes in line %zu.", ctx->line_number); g_strfreev(columns); free_context(ctx); return SR_ERR; } if (ctx->multi_column_mode) res = parse_multi_columns(columns, ctx); else res = parse_single_column(columns[0], ctx); if (res != SR_OK) { g_strfreev(columns); free_context(ctx); return SR_ERR; } g_strfreev(columns); /* * TODO: Parse sample numbers / timestamps and use it for * decompression. */ /* Send sample data to the session bus. */ res = send_samples(in->sdi, ctx->sample_buffer, ctx->sample_buffer_size, 1); if (res != SR_OK) { sr_err("Sending samples failed."); free_context(ctx); return SR_ERR; } } /* Send end packet to the session bus. */ packet.type = SR_DF_END; sr_session_send(in->sdi, &packet); free_context(ctx); return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi) { struct sr_dev_driver *di = sdi->driver; struct drv_context *drvc; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_config *src; struct sr_usb_dev_inst *usb; GVariant *gvar, *rational[2]; const uint64_t *si; int req_len, buf_len, len, ret; unsigned char buf[9]; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; drvc = di->context; devc = sdi->priv; usb = sdi->conn; devc->num_samples = 0; std_session_send_df_header(sdi); if (devc->data_source == DATA_SOURCE_LIVE) { /* Force configuration. */ kecheng_kc_330b_configure(sdi); if (kecheng_kc_330b_status_get(sdi, &ret) != SR_OK) return SR_ERR; if (ret != DEVICE_ACTIVE) { sr_err("Device is inactive"); /* Still continue though, since the device will * just return 30.0 until the user hits the button * on the device -- and then start feeding good * samples back. */ } } else { if (kecheng_kc_330b_log_info_get(sdi, buf) != SR_OK) return SR_ERR; devc->mqflags = buf[4] ? SR_MQFLAG_SPL_TIME_WEIGHT_S : SR_MQFLAG_SPL_TIME_WEIGHT_F; devc->mqflags |= buf[5] ? SR_MQFLAG_SPL_FREQ_WEIGHT_C : SR_MQFLAG_SPL_FREQ_WEIGHT_A; devc->stored_samples = (buf[7] << 8) | buf[8]; if (devc->stored_samples == 0) { /* Notify frontend of empty log by sending start/end packets. */ std_session_send_df_end(sdi); return SR_OK; } if (devc->limit_samples && devc->limit_samples < devc->stored_samples) devc->stored_samples = devc->limit_samples; si = kecheng_kc_330b_sample_intervals[buf[1]]; rational[0] = g_variant_new_uint64(si[0]); rational[1] = g_variant_new_uint64(si[1]); gvar = g_variant_new_tuple(rational, 2); src = sr_config_new(SR_CONF_SAMPLE_INTERVAL, gvar); packet.type = SR_DF_META; packet.payload = &meta; meta.config = g_slist_append(NULL, src); sr_session_send(sdi, &packet); g_free(src); } if (!(devc->xfer = libusb_alloc_transfer(0))) return SR_ERR; usb_source_add(sdi->session, drvc->sr_ctx, 10, kecheng_kc_330b_handle_events, (void *)sdi); if (devc->data_source == DATA_SOURCE_LIVE) { buf[0] = CMD_GET_LIVE_SPL; buf_len = 1; devc->state = LIVE_SPL_WAIT; devc->last_live_request = g_get_monotonic_time() / 1000; req_len = 3; } else { buf[0] = CMD_GET_LOG_DATA; buf[1] = 0; buf[2] = 0; buf_len = 4; devc->state = LOG_DATA_WAIT; if (devc->stored_samples < 63) buf[3] = devc->stored_samples; else buf[3] = 63; /* Command ack byte + 2 bytes per sample. */ req_len = 1 + buf[3] * 2; } ret = libusb_bulk_transfer(usb->devhdl, EP_OUT, buf, buf_len, &len, 5); if (ret != 0 || len != 1) { sr_dbg("Failed to start acquisition: %s", libusb_error_name(ret)); libusb_free_transfer(devc->xfer); return SR_ERR; } libusb_fill_bulk_transfer(devc->xfer, usb->devhdl, EP_IN, devc->buf, req_len, kecheng_kc_330b_receive_transfer, (void *)sdi, 15); if (libusb_submit_transfer(devc->xfer) != 0) { libusb_free_transfer(devc->xfer); return SR_ERR; } return SR_OK; }
static int loadfile(struct sr_input *in, const char *filename) { struct sr_datafeed_packet packet; struct sr_datafeed_meta meta; struct sr_datafeed_analog analog; struct sr_config *src; struct context *ctx; float fdata[CHUNK_SIZE]; uint64_t sample; int num_samples, chunk_samples, s, c, fd, l; char buf[CHUNK_SIZE]; ctx = in->sdi->priv; /* Send header packet to the session bus. */ std_session_send_df_header(in->sdi, LOG_PREFIX); packet.type = SR_DF_META; packet.payload = &meta; src = sr_config_new(SR_CONF_SAMPLERATE, g_variant_new_uint64(ctx->samplerate)); meta.config = g_slist_append(NULL, src); sr_session_send(in->sdi, &packet); sr_config_free(src); if ((fd = open(filename, O_RDONLY)) == -1) return SR_ERR; lseek(fd, 40, SEEK_SET); l = read(fd, buf, 4); num_samples = GUINT32_FROM_LE((uint32_t)*(buf)); num_samples /= ctx->samplesize / ctx->num_channels; while (TRUE) { if ((l = read(fd, buf, CHUNK_SIZE)) < 1) break; chunk_samples = l / ctx->samplesize / ctx->num_channels; for (s = 0; s < chunk_samples; s++) { for (c = 0; c < ctx->num_channels; c++) { sample = 0; memcpy(&sample, buf + s * ctx->samplesize + c, ctx->samplesize); switch (ctx->samplesize) { case 1: /* 8-bit PCM samples are unsigned. */ fdata[s + c] = (uint8_t)sample / 255.0; break; case 2: fdata[s + c] = GINT16_FROM_LE(sample) / 32767.0; break; case 4: fdata[s + c] = GINT32_FROM_LE(sample) / 65535.0; break; } } } packet.type = SR_DF_ANALOG; packet.payload = &analog; analog.probes = in->sdi->probes; analog.num_samples = chunk_samples; analog.mq = 0; analog.unit = 0; analog.data = fdata; sr_session_send(in->sdi, &packet); } close(fd); packet.type = SR_DF_END; sr_session_send(in->sdi, &packet); return SR_OK; }