chromium-twinkie: add analog VBUS channels
Retrieve VBUS voltage and current through packetized console commands if this interface exists and analog channels are enabled. Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
parent
6c71d32f27
commit
9492726042
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the libsigrok project.
|
* This file is part of the libsigrok project.
|
||||||
*
|
*
|
||||||
* Copyright 2014 Google, Inc
|
* Copyright 2017 Google, Inc
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -31,14 +31,21 @@
|
||||||
|
|
||||||
#define USB_INTERFACE 1
|
#define USB_INTERFACE 1
|
||||||
#define USB_CONFIGURATION 1
|
#define USB_CONFIGURATION 1
|
||||||
|
#define USB_COMMANDS_IFACE 2
|
||||||
|
|
||||||
#define MAX_RENUM_DELAY_MS 3000
|
#define MAX_RENUM_DELAY_MS 3000
|
||||||
#define NUM_SIMUL_TRANSFERS 32
|
#define NUM_SIMUL_TRANSFERS 32
|
||||||
|
|
||||||
#define SAMPLE_RATE SR_KHZ(2400)
|
#define SAMPLE_RATE SR_KHZ(2400)
|
||||||
|
|
||||||
|
static const char vbus_cmd[] = "tw vbus";
|
||||||
|
|
||||||
|
/* CC1 & CC2 are always present */
|
||||||
|
#define LOGIC_CHANNELS_COUNT 2
|
||||||
|
|
||||||
static const int32_t hwopts[] = {
|
static const int32_t hwopts[] = {
|
||||||
SR_CONF_CONN,
|
SR_CONF_CONN,
|
||||||
|
SR_CONF_NUM_ANALOG_CHANNELS,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int32_t hwcaps[] = {
|
static const int32_t hwcaps[] = {
|
||||||
|
@ -55,6 +62,8 @@ static const struct chan {
|
||||||
} chan_defs[] = {
|
} chan_defs[] = {
|
||||||
{"CC1", SR_CHANNEL_LOGIC},
|
{"CC1", SR_CHANNEL_LOGIC},
|
||||||
{"CC2", SR_CHANNEL_LOGIC},
|
{"CC2", SR_CHANNEL_LOGIC},
|
||||||
|
{"VBUS_V", SR_CHANNEL_ANALOG},
|
||||||
|
{"VBUS_A", SR_CHANNEL_ANALOG},
|
||||||
|
|
||||||
{NULL, 0}
|
{NULL, 0}
|
||||||
};
|
};
|
||||||
|
@ -66,13 +75,17 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
|
||||||
struct sr_dev_inst *sdi;
|
struct sr_dev_inst *sdi;
|
||||||
struct sr_usb_dev_inst *usb;
|
struct sr_usb_dev_inst *usb;
|
||||||
struct sr_channel *ch;
|
struct sr_channel *ch;
|
||||||
|
struct sr_channel_group *cc_grp, *vbus_grp[VBUS_GRP_COUNT];
|
||||||
struct sr_config *src;
|
struct sr_config *src;
|
||||||
GSList *l, *devices, *conn_devices;
|
GSList *l, *devices, *conn_devices;
|
||||||
struct libusb_device_descriptor des;
|
struct libusb_device_descriptor des;
|
||||||
|
struct libusb_config_descriptor *cfg;
|
||||||
libusb_device **devlist;
|
libusb_device **devlist;
|
||||||
int ret, i, j;
|
int ret, i, j;
|
||||||
const char *conn;
|
const char *conn;
|
||||||
char connection_id[64];
|
char connection_id[64];
|
||||||
|
/* By default, disable VBUS analog */
|
||||||
|
int vbus_channels = 0;
|
||||||
|
|
||||||
drvc = di->context;
|
drvc = di->context;
|
||||||
|
|
||||||
|
@ -83,6 +96,9 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
|
||||||
case SR_CONF_CONN:
|
case SR_CONF_CONN:
|
||||||
conn = g_variant_get_string(src->data, NULL);
|
conn = g_variant_get_string(src->data, NULL);
|
||||||
break;
|
break;
|
||||||
|
case SR_CONF_NUM_ANALOG_CHANNELS:
|
||||||
|
vbus_channels = MIN(2, g_variant_get_int32(src->data));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (conn)
|
if (conn)
|
||||||
|
@ -117,6 +133,12 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
|
||||||
if (des.idVendor != TWINKIE_VID || des.idProduct != TWINKIE_PID)
|
if (des.idVendor != TWINKIE_VID || des.idProduct != TWINKIE_PID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if ((ret = libusb_get_active_config_descriptor(devlist[i], &cfg)) != 0) {
|
||||||
|
sr_warn("Failed to get device configuraton: %s.",
|
||||||
|
libusb_error_name(ret));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
|
usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
|
||||||
|
|
||||||
sdi = g_malloc0(sizeof(struct sr_dev_inst));
|
sdi = g_malloc0(sizeof(struct sr_dev_inst));
|
||||||
|
@ -126,14 +148,53 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
|
||||||
sdi->driver = di;
|
sdi->driver = di;
|
||||||
sdi->connection_id = g_strdup(connection_id);
|
sdi->connection_id = g_strdup(connection_id);
|
||||||
|
|
||||||
for (j = 0; chan_defs[j].name; j++)
|
if (vbus_channels && cfg->bNumInterfaces < 3) {
|
||||||
if (!(ch = sr_channel_new(sdi, j, chan_defs[j].type,
|
sr_warn("VBUS channels not available in this firmware.");
|
||||||
TRUE, chan_defs[j].name)))
|
vbus_channels = 0;
|
||||||
return NULL;
|
}
|
||||||
|
|
||||||
if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
|
if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
|
||||||
return NULL;
|
return NULL;
|
||||||
sdi->priv = devc;
|
sdi->priv = devc;
|
||||||
|
|
||||||
|
cc_grp = g_malloc0(sizeof(struct sr_channel_group));
|
||||||
|
cc_grp->name = g_strdup("CCx");
|
||||||
|
for (j = 0; j < vbus_channels; j++) {
|
||||||
|
vbus_grp[j] = g_malloc0(sizeof(struct sr_channel_group));
|
||||||
|
vbus_grp[j]->name = g_strdup(j == VBUS_V ? "VBUS_V"
|
||||||
|
: "VBUS_A");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; chan_defs[j].name; j++) {
|
||||||
|
struct sr_channel_group *grp = cc_grp;
|
||||||
|
if (j >= LOGIC_CHANNELS_COUNT) { /* Analog channels */
|
||||||
|
if (j - LOGIC_CHANNELS_COUNT >= vbus_channels)
|
||||||
|
break;
|
||||||
|
grp = vbus_grp[j - LOGIC_CHANNELS_COUNT];
|
||||||
|
}
|
||||||
|
ch = sr_channel_new(sdi, j, chan_defs[j].type, TRUE,
|
||||||
|
chan_defs[j].name);
|
||||||
|
grp->channels = g_slist_append(grp->channels, ch);
|
||||||
|
}
|
||||||
|
sdi->channel_groups = g_slist_append(NULL, cc_grp);
|
||||||
|
for (j = 0; j < vbus_channels; j++) {
|
||||||
|
sdi->channel_groups = g_slist_append(sdi->channel_groups,
|
||||||
|
vbus_grp[j]);
|
||||||
|
sr_analog_init(&devc->vbus_packet[j],
|
||||||
|
&devc->vbus_encoding,
|
||||||
|
&devc->vbus_meaning[j],
|
||||||
|
&devc->vbus_spec, 3);
|
||||||
|
devc->vbus_meaning[j].channels = vbus_grp[j]->channels;
|
||||||
|
}
|
||||||
|
/* other encoding default settings in sr_analog_init are OK (eg float) */
|
||||||
|
devc->vbus_encoding.is_signed = TRUE;
|
||||||
|
devc->vbus_meaning[VBUS_V].mq = SR_MQ_VOLTAGE;
|
||||||
|
devc->vbus_meaning[VBUS_V].mqflags = SR_MQFLAG_DC;
|
||||||
|
devc->vbus_meaning[VBUS_V].unit = SR_UNIT_VOLT;
|
||||||
|
devc->vbus_meaning[VBUS_A].mq = SR_MQ_CURRENT;
|
||||||
|
devc->vbus_meaning[VBUS_A].unit = SR_UNIT_AMPERE;
|
||||||
|
|
||||||
|
devc->vbus_channels = vbus_channels;
|
||||||
drvc->instances = g_slist_append(drvc->instances, sdi);
|
drvc->instances = g_slist_append(drvc->instances, sdi);
|
||||||
devices = g_slist_append(devices, sdi);
|
devices = g_slist_append(devices, sdi);
|
||||||
|
|
||||||
|
@ -150,17 +211,19 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int twinkie_dev_open(struct sr_dev_inst *sdi)
|
static int dev_open(struct sr_dev_inst *sdi)
|
||||||
{
|
{
|
||||||
struct sr_dev_driver *di;
|
struct sr_dev_driver *di;
|
||||||
libusb_device **devlist;
|
libusb_device **devlist;
|
||||||
struct sr_usb_dev_inst *usb;
|
struct sr_usb_dev_inst *usb;
|
||||||
struct libusb_device_descriptor des;
|
struct libusb_device_descriptor des;
|
||||||
struct drv_context *drvc;
|
struct drv_context *drvc;
|
||||||
|
struct dev_context *devc;
|
||||||
int ret, i, device_count;
|
int ret, i, device_count;
|
||||||
char connection_id[64];
|
char connection_id[64];
|
||||||
|
|
||||||
di = sdi->driver;
|
di = sdi->driver;
|
||||||
|
devc = sdi->priv;
|
||||||
drvc = di->context;
|
drvc = di->context;
|
||||||
usb = sdi->conn;
|
usb = sdi->conn;
|
||||||
|
|
||||||
|
@ -222,6 +285,13 @@ static int twinkie_dev_open(struct sr_dev_inst *sdi)
|
||||||
libusb_error_name(ret));
|
libusb_error_name(ret));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (devc->vbus_channels &&
|
||||||
|
(ret = libusb_claim_interface(usb->devhdl, USB_COMMANDS_IFACE))) {
|
||||||
|
sr_err("Unable to claim commands interface %d/%s.", ret,
|
||||||
|
libusb_error_name(ret));
|
||||||
|
/* Cannot use the analog channels for VBUS. */
|
||||||
|
devc->vbus_channels = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((ret = twinkie_init_device(sdi)) != SR_OK) {
|
if ((ret = twinkie_init_device(sdi)) != SR_OK) {
|
||||||
sr_err("Failed to init device.");
|
sr_err("Failed to init device.");
|
||||||
|
@ -248,29 +318,19 @@ static int twinkie_dev_open(struct sr_dev_inst *sdi)
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dev_open(struct sr_dev_inst *sdi)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = twinkie_dev_open(sdi);
|
|
||||||
if (ret != SR_OK) {
|
|
||||||
sr_err("Unable to open device.");
|
|
||||||
return SR_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dev_close(struct sr_dev_inst *sdi)
|
static int dev_close(struct sr_dev_inst *sdi)
|
||||||
{
|
{
|
||||||
struct sr_usb_dev_inst *usb;
|
struct sr_usb_dev_inst *usb;
|
||||||
|
struct dev_context *devc;
|
||||||
|
|
||||||
usb = sdi->conn;
|
usb = sdi->conn;
|
||||||
if (usb->devhdl == NULL)
|
if (usb->devhdl == NULL)
|
||||||
return SR_ERR;
|
return SR_ERR;
|
||||||
|
|
||||||
sr_info("Closing device %d.%d interface %d.",
|
sr_info("Closing device %d.%d.", usb->bus, usb->address);
|
||||||
usb->bus, usb->address, USB_INTERFACE);
|
devc = sdi->priv;
|
||||||
|
if (devc->vbus_channels)
|
||||||
|
libusb_release_interface(usb->devhdl, USB_COMMANDS_IFACE);
|
||||||
libusb_release_interface(usb->devhdl, USB_INTERFACE);
|
libusb_release_interface(usb->devhdl, USB_INTERFACE);
|
||||||
libusb_close(usb->devhdl);
|
libusb_close(usb->devhdl);
|
||||||
usb->devhdl = NULL;
|
usb->devhdl = NULL;
|
||||||
|
@ -279,11 +339,6 @@ static int dev_close(struct sr_dev_inst *sdi)
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dev_clear(const struct sr_dev_driver *di)
|
|
||||||
{
|
|
||||||
return std_dev_clear(di, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int config_get(uint32_t key, GVariant **data,
|
static int config_get(uint32_t key, GVariant **data,
|
||||||
const struct sr_dev_inst *sdi,
|
const struct sr_dev_inst *sdi,
|
||||||
const struct sr_channel_group *cg)
|
const struct sr_channel_group *cg)
|
||||||
|
@ -414,7 +469,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
|
||||||
struct drv_context *drvc;
|
struct drv_context *drvc;
|
||||||
struct sr_usb_dev_inst *usb;
|
struct sr_usb_dev_inst *usb;
|
||||||
struct libusb_transfer *transfer;
|
struct libusb_transfer *transfer;
|
||||||
unsigned int i, timeout, num_transfers;
|
unsigned int i, timeout, num_transfers, cc_transfers;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
size_t size, convsize;
|
size_t size, convsize;
|
||||||
|
@ -431,10 +486,12 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
|
||||||
memset(devc->cc, 0, sizeof(devc->cc));
|
memset(devc->cc, 0, sizeof(devc->cc));
|
||||||
|
|
||||||
timeout = 1000;
|
timeout = 1000;
|
||||||
num_transfers = 10;
|
cc_transfers = num_transfers = 10;
|
||||||
size = 10*1024;
|
size = 10*1024;
|
||||||
convsize = size * 8 * 256 /* largest size : only rollbacks/no edges */;
|
convsize = size * 8 * 256 /* largest size : only rollbacks/no edges */;
|
||||||
devc->submitted_transfers = 0;
|
devc->submitted_transfers = 0;
|
||||||
|
if (devc->vbus_channels)
|
||||||
|
num_transfers += 2;
|
||||||
|
|
||||||
devc->convbuffer_size = convsize;
|
devc->convbuffer_size = convsize;
|
||||||
if (!(devc->convbuffer = g_try_malloc(convsize))) {
|
if (!(devc->convbuffer = g_try_malloc(convsize))) {
|
||||||
|
@ -451,7 +508,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
|
||||||
}
|
}
|
||||||
|
|
||||||
devc->num_transfers = num_transfers;
|
devc->num_transfers = num_transfers;
|
||||||
for (i = 0; i < num_transfers; i++) {
|
for (i = 0; i < cc_transfers; i++) {
|
||||||
if (!(buf = g_try_malloc(size))) {
|
if (!(buf = g_try_malloc(size))) {
|
||||||
sr_err("USB transfer buffer malloc failed.");
|
sr_err("USB transfer buffer malloc failed.");
|
||||||
if (devc->submitted_transfers)
|
if (devc->submitted_transfers)
|
||||||
|
@ -477,6 +534,28 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
|
||||||
devc->transfers[i] = transfer;
|
devc->transfers[i] = transfer;
|
||||||
devc->submitted_transfers++;
|
devc->submitted_transfers++;
|
||||||
}
|
}
|
||||||
|
if (devc->vbus_channels) {
|
||||||
|
struct libusb_transfer *out_xfer = libusb_alloc_transfer(0);
|
||||||
|
struct libusb_transfer *in_xfer = libusb_alloc_transfer(0);
|
||||||
|
libusb_fill_bulk_transfer(out_xfer, usb->devhdl,
|
||||||
|
2 | LIBUSB_ENDPOINT_OUT, (uint8_t *)vbus_cmd,
|
||||||
|
sizeof(vbus_cmd) - 1, twinkie_vbus_sent,
|
||||||
|
(void *)sdi, timeout);
|
||||||
|
libusb_fill_bulk_transfer(in_xfer, usb->devhdl,
|
||||||
|
2 | LIBUSB_ENDPOINT_IN, (uint8_t *)devc->vbus_data,
|
||||||
|
sizeof(devc->vbus_data),
|
||||||
|
twinkie_vbus_recv, (void *)sdi, timeout);
|
||||||
|
if ((ret = libusb_submit_transfer(out_xfer)) != 0) {
|
||||||
|
sr_err("Failed to submit VBUS transfer: %s.",
|
||||||
|
libusb_error_name(ret));
|
||||||
|
libusb_free_transfer(out_xfer);
|
||||||
|
abort_acquisition(devc);
|
||||||
|
return SR_ERR;
|
||||||
|
}
|
||||||
|
devc->transfers[cc_transfers + 0] = out_xfer;
|
||||||
|
devc->transfers[cc_transfers + 1] = in_xfer;
|
||||||
|
devc->submitted_transfers++;
|
||||||
|
}
|
||||||
|
|
||||||
devc->ctx = drvc->sr_ctx;
|
devc->ctx = drvc->sr_ctx;
|
||||||
|
|
||||||
|
@ -512,7 +591,7 @@ static struct sr_dev_driver chromium_twinkie_driver_info = {
|
||||||
.cleanup = std_cleanup,
|
.cleanup = std_cleanup,
|
||||||
.scan = scan,
|
.scan = scan,
|
||||||
.dev_list = std_dev_list,
|
.dev_list = std_dev_list,
|
||||||
.dev_clear = dev_clear,
|
.dev_clear = NULL,
|
||||||
.config_get = config_get,
|
.config_get = config_get,
|
||||||
.config_set = config_set,
|
.config_set = config_set,
|
||||||
.config_list = config_list,
|
.config_list = config_list,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the libsigrok project.
|
* This file is part of the libsigrok project.
|
||||||
*
|
*
|
||||||
* Copyright 2014 Google, Inc
|
* Copyright 2017 Google, Inc
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -28,9 +28,16 @@
|
||||||
#include "libsigrok-internal.h"
|
#include "libsigrok-internal.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
|
||||||
|
/* 'twinkie vbus' command output format */
|
||||||
|
#define VBUS_FORMAT "VBUS = %d mV ; %d mA"
|
||||||
|
|
||||||
SR_PRIV int twinkie_start_acquisition(const struct sr_dev_inst *sdi)
|
SR_PRIV int twinkie_start_acquisition(const struct sr_dev_inst *sdi)
|
||||||
{
|
{
|
||||||
(void)sdi;
|
struct dev_context *devc = sdi->priv;
|
||||||
|
struct timespec tsample;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_REALTIME, &tsample);
|
||||||
|
devc->vbus_t0 = tsample.tv_nsec + (uint64_t)tsample.tv_sec *1000000000ULL;
|
||||||
|
|
||||||
return SR_OK;
|
return SR_OK;
|
||||||
}
|
}
|
||||||
|
@ -246,3 +253,100 @@ resubmit:
|
||||||
if (libusb_submit_transfer(transfer) != LIBUSB_SUCCESS)
|
if (libusb_submit_transfer(transfer) != LIBUSB_SUCCESS)
|
||||||
free_transfer(transfer);
|
free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void export_vbus(const struct sr_dev_inst *sdi, int mv, int ma)
|
||||||
|
{
|
||||||
|
static float tmp_data[VBUS_GRP_COUNT][32768];
|
||||||
|
struct dev_context *devc = sdi->priv;
|
||||||
|
struct sr_datafeed_packet packet[VBUS_GRP_COUNT];
|
||||||
|
uint64_t tlen = devc->vbus_delta * 24 / 10000;
|
||||||
|
uint64_t len = MIN(32768, tlen);
|
||||||
|
unsigned i, g;
|
||||||
|
|
||||||
|
for (g = 0; g < devc->vbus_channels; g++) {
|
||||||
|
float val = g == VBUS_V ? mv/1000.0 : ma/1000.0;
|
||||||
|
packet[g].type = SR_DF_ANALOG;
|
||||||
|
packet[g].payload = &devc->vbus_packet[g];
|
||||||
|
devc->vbus_packet[g].data = tmp_data[g];
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
tmp_data[g][i] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
for (g = 0; g < devc->vbus_channels; g++) {
|
||||||
|
devc->vbus_packet[g].num_samples = len;
|
||||||
|
sr_session_send(sdi, &packet[g]);
|
||||||
|
}
|
||||||
|
tlen -= len;
|
||||||
|
len = MIN(32768, tlen);
|
||||||
|
} while (tlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
SR_PRIV void twinkie_vbus_sent(struct libusb_transfer *transfer)
|
||||||
|
{
|
||||||
|
struct sr_dev_inst *sdi = transfer->user_data;
|
||||||
|
struct dev_context *devc = sdi->priv;
|
||||||
|
struct libusb_transfer *in_xfer = devc->transfers[11];
|
||||||
|
struct timespec tsample;
|
||||||
|
uint64_t now;
|
||||||
|
|
||||||
|
/* acquisition has already ended */
|
||||||
|
if (devc->sent_samples < 0 || transfer->status == LIBUSB_TRANSFER_NO_DEVICE)
|
||||||
|
goto abort_vbus;
|
||||||
|
|
||||||
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
|
goto abort_vbus;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_REALTIME, &tsample);
|
||||||
|
now = tsample.tv_nsec + (uint64_t)tsample.tv_sec *1000000000ULL;
|
||||||
|
devc->vbus_delta = now - devc->vbus_t0;
|
||||||
|
devc->vbus_t0 = now;
|
||||||
|
if (libusb_submit_transfer(in_xfer) != LIBUSB_SUCCESS)
|
||||||
|
goto abort_vbus;
|
||||||
|
|
||||||
|
return;
|
||||||
|
abort_vbus:
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
libusb_free_transfer(in_xfer);
|
||||||
|
devc->transfers[10] = NULL;
|
||||||
|
devc->transfers[11] = NULL;
|
||||||
|
devc->submitted_transfers--;
|
||||||
|
if (devc->submitted_transfers == 0)
|
||||||
|
finish_acquisition(sdi);
|
||||||
|
}
|
||||||
|
|
||||||
|
SR_PRIV void twinkie_vbus_recv(struct libusb_transfer *transfer)
|
||||||
|
{
|
||||||
|
struct sr_dev_inst *sdi = transfer->user_data;
|
||||||
|
struct dev_context *devc = sdi->priv;
|
||||||
|
struct libusb_transfer *out_xfer = devc->transfers[10];
|
||||||
|
|
||||||
|
/* acquisition has already ended */
|
||||||
|
if (devc->sent_samples < 0 || transfer->status == LIBUSB_TRANSFER_NO_DEVICE)
|
||||||
|
goto abort_vbus;
|
||||||
|
|
||||||
|
if (transfer->status == LIBUSB_TRANSFER_COMPLETED &&
|
||||||
|
transfer->actual_length) {
|
||||||
|
int vbus_ma, vbus_mv;
|
||||||
|
int len = transfer->actual_length;
|
||||||
|
if (len > 63)
|
||||||
|
len = 63;
|
||||||
|
devc->vbus_data[len] = 0;
|
||||||
|
if (sscanf(devc->vbus_data, VBUS_FORMAT, &vbus_mv, &vbus_ma) == 2) {
|
||||||
|
export_vbus(sdi, vbus_mv, vbus_ma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libusb_submit_transfer(out_xfer) != LIBUSB_SUCCESS)
|
||||||
|
goto abort_vbus;
|
||||||
|
|
||||||
|
return;
|
||||||
|
abort_vbus:
|
||||||
|
libusb_free_transfer(transfer);
|
||||||
|
libusb_free_transfer(out_xfer);
|
||||||
|
devc->transfers[10] = NULL;
|
||||||
|
devc->transfers[11] = NULL;
|
||||||
|
devc->submitted_transfers--;
|
||||||
|
if (devc->submitted_transfers == 0)
|
||||||
|
finish_acquisition(sdi);
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,13 @@ struct cc_context {
|
||||||
uint8_t level;
|
uint8_t level;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum vbus_group_index {
|
||||||
|
VBUS_V = 0,
|
||||||
|
VBUS_A = 1,
|
||||||
|
|
||||||
|
VBUS_GRP_COUNT = 2
|
||||||
|
};
|
||||||
|
|
||||||
/** Private, per-device-instance driver context. */
|
/** Private, per-device-instance driver context. */
|
||||||
struct dev_context {
|
struct dev_context {
|
||||||
/** Maximum number of samples to capture, if nonzero. */
|
/** Maximum number of samples to capture, if nonzero. */
|
||||||
|
@ -50,10 +57,20 @@ struct dev_context {
|
||||||
struct sr_context *ctx;
|
struct sr_context *ctx;
|
||||||
|
|
||||||
struct cc_context cc[2];
|
struct cc_context cc[2];
|
||||||
|
int vbus_channels;
|
||||||
|
char vbus_data[64];
|
||||||
|
uint64_t vbus_t0;
|
||||||
|
uint64_t vbus_delta;
|
||||||
|
struct sr_datafeed_analog vbus_packet[VBUS_GRP_COUNT];
|
||||||
|
struct sr_analog_meaning vbus_meaning[VBUS_GRP_COUNT];
|
||||||
|
struct sr_analog_encoding vbus_encoding;
|
||||||
|
struct sr_analog_spec vbus_spec;
|
||||||
};
|
};
|
||||||
|
|
||||||
SR_PRIV int twinkie_start_acquisition(const struct sr_dev_inst *sdi);
|
SR_PRIV int twinkie_start_acquisition(const struct sr_dev_inst *sdi);
|
||||||
SR_PRIV int twinkie_init_device(const struct sr_dev_inst *sdi);
|
SR_PRIV int twinkie_init_device(const struct sr_dev_inst *sdi);
|
||||||
SR_PRIV void twinkie_receive_transfer(struct libusb_transfer *transfer);
|
SR_PRIV void twinkie_receive_transfer(struct libusb_transfer *transfer);
|
||||||
|
SR_PRIV void twinkie_vbus_sent(struct libusb_transfer *transfer);
|
||||||
|
SR_PRIV void twinkie_vbus_recv(struct libusb_transfer *transfer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue