fx2lafw: Implemented hw_dev_acquisition_start

This commit is contained in:
Joel Holdsworth 2012-02-27 19:32:58 +00:00
parent 7cb621d418
commit 610dbb7091
2 changed files with 156 additions and 2 deletions

View File

@ -79,6 +79,8 @@ static struct sr_samplerates fx2lafw_samplerates = {
static GSList *dev_insts = NULL;
static libusb_context *usb_context = NULL;
static int hw_dev_acquisition_stop(int dev_index, gpointer session_dev_id);
/**
* Check the USB configuration to determine if this is an fx2lafw device.
*
@ -483,10 +485,160 @@ static int hw_dev_config_set(int dev_index, int hwcap, void *value)
return ret;
}
static int receive_data(int fd, int revents, void *user_data)
{
struct timeval tv;
/* Avoid compiler warnings. */
(void)fd;
(void)revents;
(void)user_data;
tv.tv_sec = tv.tv_usec = 0;
libusb_handle_events_timeout(usb_context, &tv);
return TRUE;
}
static void receive_transfer(struct libusb_transfer *transfer)
{
/* TODO: These statics have to move to the ctx struct. */
static int num_samples = 0;
static int empty_transfer_count = 0;
struct sr_datafeed_packet packet;
struct sr_datafeed_logic logic;
struct fx2lafw_device *ctx;
int cur_buflen;
unsigned char *cur_buf, *new_buf;
/* hw_dev_acquisition_stop() is telling us to stop. */
if (transfer == NULL)
num_samples = -1;
/*
* If acquisition has already ended, just free any queued up
* transfer that come in.
*/
if (num_samples == -1) {
if (transfer)
libusb_free_transfer(transfer);
return;
}
sr_info("fx2lafw: receive_transfer(): status %d received %d bytes",
transfer->status, transfer->actual_length);
/* Save incoming transfer before reusing the transfer struct. */
cur_buf = transfer->buffer;
cur_buflen = transfer->actual_length;
ctx = transfer->user_data;
/* Fire off a new request. */
if (!(new_buf = g_try_malloc(4096))) {
sr_err("fx2lafw: %s: new_buf malloc failed", __func__);
return; /* TODO: SR_ERR_MALLOC */
}
transfer->buffer = new_buf;
transfer->length = 4096;
if (libusb_submit_transfer(transfer) != 0) {
/* TODO: Stop session? */
/* TODO: Better error message. */
sr_err("fx2lafw: %s: libusb_submit_transfer error", __func__);
}
if (cur_buflen == 0) {
empty_transfer_count++;
if (empty_transfer_count > MAX_EMPTY_TRANSFERS) {
/*
* The FX2 gave up. End the acquisition, the frontend
* will work out that the samplecount is short.
*/
hw_dev_acquisition_stop(-1, ctx->session_data);
}
return;
} else {
empty_transfer_count = 0;
}
/* Send the incoming transfer to the session bus. */
packet.type = SR_DF_LOGIC;
packet.payload = &logic;
logic.length = cur_buflen;
logic.unitsize = 1;
logic.data = cur_buf;
sr_session_bus(ctx->session_data, &packet);
g_free(cur_buf);
num_samples += cur_buflen;
if (ctx->limit_samples &&
(unsigned int) num_samples > ctx->limit_samples) {
hw_dev_acquisition_stop(-1, ctx->session_data);
}
}
static int hw_dev_acquisition_start(int dev_index, gpointer session_data)
{
(void)dev_index;
(void)session_data;
struct sr_dev_inst *sdi;
struct sr_datafeed_packet *packet;
struct sr_datafeed_header *header;
struct fx2lafw_device *ctx;
struct libusb_transfer *transfer;
const struct libusb_pollfd **lupfd;
int size, i;
unsigned char *buf;
if (!(sdi = sr_dev_inst_get(dev_insts, dev_index)))
return SR_ERR;
ctx = sdi->priv;
ctx->session_data = session_data;
if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
sr_err("fx2lafw: %s: packet malloc failed", __func__);
return SR_ERR_MALLOC;
}
if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
sr_err("fx2lafw: %s: header malloc failed", __func__);
return SR_ERR_MALLOC;
}
/* Start with 2K transfer, subsequently increased to 4K. */
size = 2048;
for (i = 0; i < NUM_SIMUL_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);
if (libusb_submit_transfer(transfer) != 0) {
/* TODO: Free them all. */
libusb_free_transfer(transfer);
g_free(buf);
return SR_ERR;
}
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);
free(lupfd); /* NOT g_free()! */
packet->type = SR_DF_HEADER;
packet->payload = header;
header->feed_version = 1;
gettimeofday(&header->starttime, NULL);
header->samplerate = 24000000UL;
header->num_logic_probes = ctx->profile->num_probes;
sr_session_bus(session_data, packet);
g_free(header);
g_free(packet);
return SR_OK;
}

View File

@ -29,6 +29,8 @@
#define FIRMWARE_PID 0x3881
#define MAX_RENUM_DELAY 3000 /* ms */
#define NUM_SIMUL_TRANSFERS 10
#define MAX_EMPTY_TRANSFERS (NUM_SIMUL_TRANSFERS * 2)
struct fx2lafw_profile {
uint16_t vid;