#include <inttypes.h>
#include <libusb.h>
#include "config.h"
-#include "sigrok.h"
-#include "sigrok-internal.h"
+#include "libsigrok.h"
+#include "libsigrok-internal.h"
#include "fx2lafw.h"
#include "command.h"
{ 0x08a9, 0x0014, "CWAV", "USBee AX", NULL,
FIRMWARE_DIR "/fx2lafw-cwav-usbeeax.fw",
0 },
+ /*
+ * CWAV USBee DX
+ * XZL-Studio DX
+ */
+ { 0x08a9, 0x0015, "CWAV", "USBee DX", NULL,
+ FIRMWARE_DIR "/fx2lafw-cwav-usbeedx.fw",
+ DEV_CAPS_16BIT },
/*
* CWAV USBee SX
* API callbacks
*/
-static int hw_init(const char *devinfo)
+static int hw_init(void)
{
struct sr_dev_inst *sdi;
struct libusb_device_descriptor des;
int devcnt = 0;
int i, j;
- /* Avoid compiler warnings. */
- (void)devinfo;
-
if (libusb_init(&usb_context) != 0) {
sr_warn("fx2lafw: Failed to initialize libusb.");
return 0;
static void abort_acquisition(struct context *ctx)
{
+ int i;
+
ctx->num_samples = -1;
+
+ for (i = ctx->num_transfers - 1; i >= 0; i--) {
+ if (ctx->transfers[i])
+ libusb_cancel_transfer(ctx->transfers[i]);
+ }
}
static void finish_acquisition(struct context *ctx)
for (i = 0; lupfd[i]; i++)
sr_source_remove(lupfd[i]->fd);
free(lupfd); /* NOT g_free()! */
+
+ ctx->num_transfers = 0;
+ g_free(ctx->transfers);
}
static void free_transfer(struct libusb_transfer *transfer)
{
struct context *ctx = transfer->user_data;
+ unsigned int i;
g_free(transfer->buffer);
transfer->buffer = NULL;
libusb_free_transfer(transfer);
+ for (i = 0; i < ctx->num_transfers; i++) {
+ if (ctx->transfers[i] == transfer) {
+ ctx->transfers[i] = NULL;
+ break;
+ }
+ }
+
ctx->submitted_transfers--;
if (ctx->submitted_transfers == 0)
finish_acquisition(ctx);
static void resubmit_transfer(struct libusb_transfer *transfer)
{
- uint8_t *new_buf;
-
- /* Increase buffer size to 4096 */
- if (transfer->length != 4096) {
- new_buf = g_try_malloc(4096);
- /* If allocation of the new buffer fails, just vdo not bother and
- * continue to use the old one. */
- if (new_buf) {
- g_free(transfer->buffer);
- transfer->buffer = new_buf;
- transfer->length = 4096;
- }
- }
-
if (libusb_submit_transfer(transfer) != 0) {
free_transfer(transfer);
/* TODO: Stop session? */
static void receive_transfer(struct libusb_transfer *transfer)
{
- /* TODO: These statics have to move to the ctx struct. */
- static int empty_transfer_count = 0;
gboolean packet_has_error = FALSE;
struct sr_datafeed_packet packet;
struct sr_datafeed_logic logic;
}
if (transfer->actual_length == 0 || packet_has_error) {
- empty_transfer_count++;
- if (empty_transfer_count > MAX_EMPTY_TRANSFERS) {
+ ctx->empty_transfer_count++;
+ if (ctx->empty_transfer_count > MAX_EMPTY_TRANSFERS) {
/*
* The FX2 gave up. End the acquisition, the frontend
* will work out that the samplecount is short.
}
return;
} else {
- empty_transfer_count = 0;
+ ctx->empty_transfer_count = 0;
}
trigger_offset = 0;
if (ctx->limit_samples &&
(unsigned int)ctx->num_samples > ctx->limit_samples) {
abort_acquisition(ctx);
+ free_transfer(transfer);
+ return;
}
} else {
/*
resubmit_transfer(transfer);
}
+static unsigned int to_bytes_per_ms(unsigned int samplerate)
+{
+ return samplerate / 1000;
+}
+
+static size_t get_buffer_size(struct context *ctx)
+{
+ size_t s;
+
+ /* The buffer should be large enough to hold 10ms of data and a multiple
+ * of 512. */
+ s = 10 * to_bytes_per_ms(ctx->cur_samplerate);
+ return (s + 511) & ~511;
+}
+
+static unsigned int get_number_of_transfers(struct context *ctx)
+{
+ unsigned int n;
+
+ /* Total buffer size should be able to hold about 500ms of data */
+ n = 500 * to_bytes_per_ms(ctx->cur_samplerate) / get_buffer_size(ctx);
+
+ if (n > NUM_SIMUL_TRANSFERS)
+ return NUM_SIMUL_TRANSFERS;
+
+ return n;
+}
+
+static unsigned int get_timeout(struct context *ctx)
+{
+ size_t total_size;
+ unsigned int timeout;
+
+ total_size = get_buffer_size(ctx) * get_number_of_transfers(ctx);
+ timeout = total_size / to_bytes_per_ms(ctx->cur_samplerate);
+ return timeout + timeout / 4; /* Leave a headroom of 25% percent */
+}
+
static int hw_dev_acquisition_start(int dev_index, void *cb_data)
{
struct sr_dev_inst *sdi;
struct context *ctx;
struct libusb_transfer *transfer;
const struct libusb_pollfd **lupfd;
- int ret, size, i;
+ unsigned int i;
+ int ret;
unsigned char *buf;
if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
return SR_ERR;
ctx = sdi->priv;
+
+ if (ctx->submitted_transfers != 0)
+ return SR_ERR;
+
ctx->session_dev_id = cb_data;
ctx->num_samples = 0;
+ ctx->empty_transfer_count = 0;
+
+ const unsigned int timeout = get_timeout(ctx);
+ const unsigned int num_transfers = get_number_of_transfers(ctx);
+ const size_t size = get_buffer_size(ctx);
- /* Start with 2K transfer, subsequently increased to 4K. */
- size = 2048;
- for (i = 0; i < NUM_SIMUL_TRANSFERS; i++) {
+ ctx->transfers = g_try_malloc0(sizeof(*ctx->transfers) * num_transfers);
+ if (!ctx->transfers)
+ return SR_ERR;
+
+ ctx->num_transfers = num_transfers;
+
+ for (i = 0; i < num_transfers; i++) {
if (!(buf = g_try_malloc(size))) {
sr_err("fx2lafw: %s: buf malloc failed.", __func__);
return SR_ERR_MALLOC;
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, ctx->usb->devhdl,
2 | LIBUSB_ENDPOINT_IN, buf, size,
- receive_transfer, ctx, 40);
+ receive_transfer, ctx, timeout);
if (libusb_submit_transfer(transfer) != 0) {
- /* TODO: Free them all. */
libusb_free_transfer(transfer);
g_free(buf);
+ abort_acquisition(ctx);
return SR_ERR;
}
-
+ ctx->transfers[i] = transfer;
ctx->submitted_transfers++;
- size = 4096;
}
lupfd = libusb_get_pollfds(usb_context);
for (i = 0; lupfd[i]; i++)
sr_source_add(lupfd[i]->fd, lupfd[i]->events,
- 40, receive_data, NULL);
+ timeout, receive_data, NULL);
free(lupfd); /* NOT g_free()! */
packet.type = SR_DF_HEADER;
if ((ret = command_start_acquisition (ctx->usb->devhdl,
ctx->cur_samplerate, ctx->sample_wide)) != SR_OK) {
+ abort_acquisition(ctx);
return ret;
}