static int scpi_tcp_rigol_read_data(void *priv, char *buf, int maxlen) { struct scpi_tcp *tcp = priv; int len; if (tcp->length_bytes_read < LENGTH_BYTES) { len = recv(tcp->socket, tcp->length_buf + tcp->length_bytes_read, LENGTH_BYTES - tcp->length_bytes_read, 0); if (len < 0) { sr_err("Receive error: %s", g_strerror(errno)); return SR_ERR; } tcp->length_bytes_read += len; if (tcp->length_bytes_read < LENGTH_BYTES) return 0; else tcp->response_length = RL32(tcp->length_buf); } if (tcp->response_bytes_read >= tcp->response_length) return SR_ERR; len = recv(tcp->socket, buf, maxlen, 0); if (len < 0) { sr_err("Receive error: %s", g_strerror(errno)); return SR_ERR; } tcp->response_bytes_read += len; return len; }
static int usbtmc_bulk_in_header_read(void *header, uint8_t MsgID, unsigned char bTag, int32_t *TransferSize, uint8_t *bmTransferAttributes) { if (R8(header+0) != MsgID || R8(header+1) != bTag || R8(header+2) != (unsigned char)~bTag) return SR_ERR; if (TransferSize) *TransferSize = RL32(header+4); if (bmTransferAttributes) *bmTransferAttributes = R8(header+8); return SR_OK; }
static int find_data_chunk(GString *buf, int initial_offset) { unsigned int offset, i; offset = initial_offset; while (offset < MIN(MAX_DATA_CHUNK_OFFSET, buf->len)) { if (!memcmp(buf->str + offset, "data", 4)) /* Skip into the samples. */ return offset + 8; for (i = 0; i < 4; i++) { if (!isalnum(buf->str[offset + i]) && !isblank(buf->str[offset + i])) /* Doesn't look like a chunk ID. */ return -1; } /* Skip past this chunk. */ offset += 8 + RL32(buf->str + offset + 4); } return offset; }
static int parse_wav_header(GString *buf, struct context *inc) { uint64_t samplerate; unsigned int fmt_code, samplesize, num_channels, unitsize; if (buf->len < MIN_DATA_CHUNK_OFFSET) return SR_ERR_NA; fmt_code = RL16(buf->str + 20); samplerate = RL32(buf->str + 24); samplesize = RL16(buf->str + 32); num_channels = RL16(buf->str + 22); if (num_channels == 0) return SR_ERR; unitsize = samplesize / num_channels; if (unitsize != 1 && unitsize != 2 && unitsize != 4) { sr_err("Only 8, 16 or 32 bits per sample supported."); return SR_ERR_DATA; } if (fmt_code == WAVE_FORMAT_PCM_) { } else if (fmt_code == WAVE_FORMAT_IEEE_FLOAT_) { if (unitsize != 4) { sr_err("only 32-bit floats supported."); return SR_ERR_DATA; } } else if (fmt_code == WAVE_FORMAT_EXTENSIBLE_) { if (buf->len < 70) /* Not enough for extensible header and next chunk. */ return SR_ERR_NA; if (RL16(buf->str + 16) != 40) { sr_err("WAV extensible format chunk must be 40 bytes."); return SR_ERR; } if (RL16(buf->str + 36) != 22) { sr_err("WAV extension must be 22 bytes."); return SR_ERR; } if (RL16(buf->str + 34) != RL16(buf->str + 38)) { sr_err("Reduced valid bits per sample not supported."); return SR_ERR_DATA; } /* Real format code is the first two bytes of the GUID. */ fmt_code = RL16(buf->str + 44); if (fmt_code != WAVE_FORMAT_PCM_ && fmt_code != WAVE_FORMAT_IEEE_FLOAT_) { sr_err("Only PCM and floating point samples are supported."); return SR_ERR_DATA; } if (fmt_code == WAVE_FORMAT_IEEE_FLOAT_ && unitsize != 4) { sr_err("only 32-bit floats supported."); return SR_ERR_DATA; } } else { sr_err("Only PCM and floating point samples are supported."); return SR_ERR_DATA; } if (inc) { inc->fmt_code = fmt_code; inc->samplerate = samplerate; inc->samplesize = samplesize; inc->num_channels = num_channels; inc->unitsize = unitsize; inc->found_data = FALSE; } 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; }