Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 61 additions & 18 deletions src/ezusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)

SR_PRIV int ezusb_install_firmware(struct sr_context *ctx,
libusb_device_handle *hdl,
const char *name)
const char *name, gboolean fx3)
{
unsigned char *firmware;
size_t length, offset, chunksize;
Expand All @@ -64,39 +64,82 @@ SR_PRIV int ezusb_install_firmware(struct sr_context *ctx,
* which holds the firmware offset, is only 16 bit wide.
*/
firmware = sr_resource_load(ctx, SR_RESOURCE_FIRMWARE,
name, &length, 1 << 16);
name, &length, (fx3? 536 << 10 : 1 << 16));
if (!firmware)
return SR_ERR;

sr_info("Uploading firmware '%s'.", name);

result = SR_OK;
offset = 0;
while (offset < length) {
chunksize = MIN(length - offset, FW_CHUNKSIZE);

ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, 0xa0, offset,
0x0000, firmware + offset,
chunksize, 100);
if (ret < 0) {
sr_err("Unable to send firmware to device: %s.",
libusb_error_name(ret));
if (fx3) {
if (length < 4 ||
firmware[0] != 'C' || firmware[1] != 'Y' ||
firmware[3] != 0xb0) {
sr_err("Invalid signature on firmware");
g_free(firmware);
return SR_ERR;
}
sr_info("Uploaded %zu bytes.", chunksize);
offset += chunksize;
offset = 4;
}
while (offset < length) {
size_t addr, sublength, suboffset;

if (fx3) {
if (offset + 4 == length) {
/* Skip checksum */
offset += 4;
break;
}
if (length < offset + 8) {
break;
}
sublength = RL32(firmware + offset) << 2;
offset += 4;
addr = RL32(firmware + offset);
offset += 4;
if (sublength > length - offset) {
break;
}
} else {
sublength = length - offset;
addr = 0;
}
suboffset = 0;

do {
chunksize = MIN(sublength - suboffset, FW_CHUNKSIZE);

ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT, 0xa0, (addr + suboffset) & 0xffff,
(addr + suboffset) >> 16, firmware + offset + suboffset,
chunksize, 100);
if (ret < 0) {
sr_err("Unable to send firmware to device: %s.",
libusb_error_name(ret));
g_free(firmware);
return SR_ERR;
}
sr_info("Uploaded %zu bytes.", chunksize);
suboffset += chunksize;
} while (suboffset < sublength);

offset += sublength;
}
g_free(firmware);

if (offset < length) {
sr_err("Firmware file is truncated.");
return SR_ERR;
}

sr_info("Firmware upload done.");

return result;
}

SR_PRIV int ezusb_upload_firmware(struct sr_context *ctx, libusb_device *dev,
int configuration, const char *name)
int configuration, const char *name, gboolean fx3)
{
struct libusb_device_handle *hdl;
int ret;
Expand Down Expand Up @@ -129,13 +172,13 @@ SR_PRIV int ezusb_upload_firmware(struct sr_context *ctx, libusb_device *dev,
return SR_ERR;
}

if ((ezusb_reset(hdl, 1)) < 0)
if (!fx3 && (ezusb_reset(hdl, 1)) < 0)
return SR_ERR;

if (ezusb_install_firmware(ctx, hdl, name) < 0)
if (ezusb_install_firmware(ctx, hdl, name, fx3) < 0)
return SR_ERR;

if ((ezusb_reset(hdl, 0)) < 0)
if (!fx3 && (ezusb_reset(hdl, 0)) < 0)
return SR_ERR;

libusb_close(hdl);
Expand Down
2 changes: 1 addition & 1 deletion src/hardware/dreamsourcelab-dslogic/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
libusb_get_device_address(devlist[i]), NULL);
} else {
if (ezusb_upload_firmware(drvc->sr_ctx, devlist[i],
USB_CONFIGURATION, prof->firmware) == SR_OK) {
USB_CONFIGURATION, prof->firmware, FALSE) == SR_OK) {
/* Store when this device's FW was updated. */
devc->fw_updated = g_get_monotonic_time();
} else {
Expand Down
23 changes: 21 additions & 2 deletions src/hardware/fx2lafw/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ static const struct fx2lafw_profile supported_fx2[] = {
"fx2lafw-usb-c-grok.fw",
0, NULL, NULL},

/*
* Cypress SuperSpeed Explorer Kit (CYUSB3KIT-003)
*/
{ 0x04b4, 0x00f3, "Cypress", "SuperSpeed Explorer Kit", NULL,
"fx3lafw-cypress-fx3.fw",
DEV_CAPS_FX3 | DEV_CAPS_32BIT, NULL, NULL },

ALL_ZERO
};

Expand Down Expand Up @@ -158,7 +165,13 @@ static const uint64_t samplerates[] = {
SR_MHZ(12),
SR_MHZ(16),
SR_MHZ(24),
/* FX3 only rates below here */
SR_MHZ(32),
SR_MHZ(48),
SR_MHZ(64),
SR_MHZ(96),
SR_MHZ(192),
#define NUM_FX3_RATES 5
};

static gboolean is_plausible(const struct libusb_device_descriptor *des)
Expand Down Expand Up @@ -302,7 +315,10 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
sdi->connection_id = g_strdup(connection_id);

/* Fill in channellist according to this device's profile. */
num_logic_channels = prof->dev_caps & DEV_CAPS_16BIT ? 16 : 8;
num_logic_channels =
prof->dev_caps & DEV_CAPS_32BIT ? 32 :
(prof->dev_caps & DEV_CAPS_24BIT ? 24 :
(prof->dev_caps & DEV_CAPS_16BIT ? 16 : 8));
num_analog_channels = prof->dev_caps & DEV_CAPS_AX_ANALOG ? 1 : 0;

/* Logic channels, all in one channel group. */
Expand Down Expand Up @@ -335,6 +351,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)

devc->samplerates = samplerates;
devc->num_samplerates = ARRAY_SIZE(samplerates);
if (!(prof->dev_caps & DEV_CAPS_FX3))
devc->num_samplerates -= NUM_FX3_RATES;
has_firmware = usb_match_manuf_prod(devlist[i],
"sigrok", "fx2lafw");

Expand All @@ -347,7 +365,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
libusb_get_device_address(devlist[i]), NULL);
} else {
if (ezusb_upload_firmware(drvc->sr_ctx, devlist[i],
USB_CONFIGURATION, prof->firmware) == SR_OK) {
USB_CONFIGURATION, prof->firmware,
(prof->dev_caps & DEV_CAPS_FX3) != 0) == SR_OK) {
/* Store when this device's FW was updated. */
devc->fw_updated = g_get_monotonic_time();
} else {
Expand Down
70 changes: 54 additions & 16 deletions src/hardware/fx2lafw/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,25 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi)
samplerate = devc->cur_samplerate;

/* Compute the sample rate. */
if (devc->sample_wide && samplerate > MAX_16BIT_SAMPLE_RATE) {
if (!(devc->profile->dev_caps & DEV_CAPS_FX3) &&
devc->unitsize > 1 && samplerate > MAX_16BIT_SAMPLE_RATE) {
sr_err("Unable to sample at %" PRIu64 "Hz "
"when collecting 16-bit samples.", samplerate);
return SR_ERR;
}

delay = 0;
cmd.flags = cmd.sample_delay_h = cmd.sample_delay_l = 0;
if ((SR_MHZ(48) % samplerate) == 0) {

if ((devc->profile->dev_caps & DEV_CAPS_FX3) &&
(SR_MHZ(192) % samplerate) == 0) {
cmd.flags = CMD_START_FLAGS_CLK_192MHZ;
delay = SR_MHZ(192) / samplerate - 1;
if (delay > 0xffff)
delay = 0;
}

if (delay == 0 && (SR_MHZ(48) % samplerate) == 0) {
cmd.flags = CMD_START_FLAGS_CLK_48MHZ;
delay = SR_MHZ(48) / samplerate - 1;
if (delay > MAX_SAMPLE_DELAY)
Expand All @@ -110,7 +120,8 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi)
}

sr_dbg("GPIF delay = %d, clocksource = %sMHz.", delay,
(cmd.flags & CMD_START_FLAGS_CLK_48MHZ) ? "48" : "30");
(cmd.flags & CMD_START_FLAGS_CLK_192MHZ? "192" :
(cmd.flags & CMD_START_FLAGS_CLK_48MHZ) ? "48" : "30"));

if (delay < 0 || delay > MAX_SAMPLE_DELAY) {
sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate);
Expand All @@ -121,8 +132,10 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi)
cmd.sample_delay_l = delay & 0xff;

/* Select the sampling width. */
cmd.flags |= devc->sample_wide ? CMD_START_FLAGS_SAMPLE_16BIT :
CMD_START_FLAGS_SAMPLE_8BIT;
cmd.flags |= devc->unitsize == 4 ? CMD_START_FLAGS_SAMPLE_32BIT :
(devc->unitsize == 3 ? CMD_START_FLAGS_SAMPLE_24BIT :
(devc->unitsize == 2 ? CMD_START_FLAGS_SAMPLE_16BIT :
CMD_START_FLAGS_SAMPLE_8BIT));
/* Enable CTL2 clock. */
cmd.flags |= (g_slist_length(devc->enabled_analog_channels) > 0) ? CMD_START_FLAGS_CLK_CTL2 : 0;

Expand Down Expand Up @@ -177,9 +190,19 @@ SR_PRIV int fx2lafw_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
if (usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)) < 0)
continue;

if (strcmp(sdi->connection_id, connection_id))
char const * _sdi_connection_id = sdi->connection_id;
char const * _connection_id = connection_id;

if (devc->profile->dev_caps & DEV_CAPS_FX3) {
_sdi_connection_id = strchr(_sdi_connection_id, '-');
_connection_id = strchr(connection_id, '-');
}

if (strcmp(_sdi_connection_id, _connection_id)) {
/* This is not the one. */
sr_info("Connection mismatch: %s vs. %s", sdi->connection_id, connection_id);
continue;
}
}

if (!(ret = libusb_open(devlist[i], &usb->devhdl))) {
Expand Down Expand Up @@ -260,7 +283,7 @@ SR_PRIV struct dev_context *fx2lafw_dev_new(void)
devc->limit_frames = 1;
devc->limit_samples = 0;
devc->capture_ratio = 0;
devc->sample_wide = FALSE;
devc->unitsize = 1;
devc->num_frames = 0;
devc->stl = NULL;

Expand Down Expand Up @@ -435,7 +458,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
libusb_error_name(transfer->status), transfer->actual_length);

/* Save incoming transfer before reusing the transfer struct. */
unitsize = devc->sample_wide ? 2 : 1;
unitsize = devc->unitsize;
cur_sample_count = transfer->actual_length / unitsize;
processed_samples = 0;

Expand Down Expand Up @@ -476,6 +499,8 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
num_samples = cur_sample_count - processed_samples;
if (devc->limit_samples && devc->sent_samples + num_samples > devc->limit_samples)
num_samples = devc->limit_samples - devc->sent_samples;
else
num_samples = cur_sample_count;

devc->send_data_proc(sdi, (uint8_t *)transfer->buffer + processed_samples * unitsize,
num_samples * unitsize, unitsize);
Expand Down Expand Up @@ -564,14 +589,16 @@ static int configure_channels(const struct sr_dev_inst *sdi)
* Use wide sampling if either any of the LA channels 8..15 is enabled,
* and/or at least one analog channel is enabled.
*/
devc->sample_wide = channel_mask > 0xff || num_analog > 0;
devc->unitsize = channel_mask > 0xffffff? 4 :
(channel_mask > 0xffff? 3 :
(channel_mask > 0xff || num_analog > 0? 2 : 1));

return SR_OK;
}

static unsigned int to_bytes_per_ms(unsigned int samplerate)
static unsigned int to_bytes_per_ms(unsigned int samplerate, unsigned int unitsize)
{
return samplerate / 1000;
return samplerate * unitsize / 1000;
}

static size_t get_buffer_size(struct dev_context *devc)
Expand All @@ -580,20 +607,31 @@ static size_t get_buffer_size(struct dev_context *devc)

/*
* The buffer should be large enough to hold 10ms of data and
* a multiple of 512.
* a multiple of 1024.
*/
s = 10 * to_bytes_per_ms(devc->cur_samplerate);
return (s + 511) & ~511;
s = 10 * to_bytes_per_ms(devc->cur_samplerate, devc->unitsize);
if (devc->unitsize == 3) {
/* Make it a multiple of 3K, to make sure we have an
integral number of samples */
s += 3*1024;
s -= s % (3*1024);
}
return (s + 1023) & ~1023;
}

static unsigned int get_number_of_transfers(struct dev_context *devc)
{
unsigned int n;

/* Total buffer size should be able to hold about 500ms of data. */
n = (500 * to_bytes_per_ms(devc->cur_samplerate) /
n = (500 * to_bytes_per_ms(devc->cur_samplerate, devc->unitsize) /
get_buffer_size(devc));

/* But no larger than 16M */
unsigned int nmax = MAX_BULK_REQUEST_SIZE / get_buffer_size(devc);
if (n > nmax)
n = nmax;

if (n > NUM_SIMUL_TRANSFERS)
return NUM_SIMUL_TRANSFERS;

Expand All @@ -607,7 +645,7 @@ static unsigned int get_timeout(struct dev_context *devc)

total_size = get_buffer_size(devc) *
get_number_of_transfers(devc);
timeout = total_size / to_bytes_per_ms(devc->cur_samplerate);
timeout = total_size / to_bytes_per_ms(devc->cur_samplerate, devc->unitsize);
return timeout + timeout / 4; /* Leave a headroom of 25% percent. */
}

Expand Down
Loading