forked from Ivasoft/DSView
v0.3
This commit is contained in:
@@ -1,177 +1,208 @@
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libusb.h>
|
||||
#include "command.h"
|
||||
//#include "libsigrok.h"
|
||||
#include "libsigrok-internal.h"
|
||||
#include "dslogic.h"
|
||||
|
||||
SR_PRIV int command_get_fw_version(libusb_device_handle *devhdl,
|
||||
struct version_info *vi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_IN, CMD_GET_FW_VERSION, 0x0000, 0x0000,
|
||||
(unsigned char *)vi, sizeof(struct version_info), 100);
|
||||
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to get version info: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_get_revid_version(libusb_device_handle *devhdl,
|
||||
uint8_t *revid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_IN, CMD_GET_REVID_VERSION, 0x0000, 0x0000,
|
||||
revid, 1, 100);
|
||||
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to get REVID: %s.", libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl,
|
||||
uint64_t samplerate, gboolean samplewide)
|
||||
{
|
||||
struct cmd_start_acquisition cmd;
|
||||
int delay = 0, ret;
|
||||
|
||||
/* Compute the sample rate. */
|
||||
// if (samplewide && samplerate > MAX_16BIT_SAMPLE_RATE) {
|
||||
// sr_err("Unable to sample at %" PRIu64 "Hz "
|
||||
// "when collecting 16-bit samples.", samplerate);
|
||||
// return SR_ERR;
|
||||
// }
|
||||
|
||||
// if ((SR_MHZ(48) % samplerate) == 0) {
|
||||
// cmd.flags = CMD_START_FLAGS_CLK_48MHZ;
|
||||
// delay = SR_MHZ(48) / samplerate - 1;
|
||||
// if (delay > MAX_SAMPLE_DELAY)
|
||||
// delay = 0;
|
||||
// }
|
||||
|
||||
// if (delay == 0 && (SR_MHZ(30) % samplerate) == 0) {
|
||||
// cmd.flags = CMD_START_FLAGS_CLK_30MHZ;
|
||||
// delay = SR_MHZ(30) / samplerate - 1;
|
||||
// }
|
||||
cmd.flags = CMD_START_FLAGS_CLK_30MHZ;
|
||||
delay = 0;
|
||||
|
||||
sr_info("GPIF delay = %d, clocksource = %sMHz.", delay,
|
||||
(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);
|
||||
// return SR_ERR;
|
||||
// }
|
||||
|
||||
cmd.sample_delay_h = (delay >> 8) & 0xff;
|
||||
cmd.sample_delay_l = delay & 0xff;
|
||||
|
||||
/* Select the sampling width. */
|
||||
cmd.flags |= samplewide ? CMD_START_FLAGS_SAMPLE_16BIT :
|
||||
CMD_START_FLAGS_SAMPLE_8BIT;
|
||||
|
||||
/* Send the control message. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
|
||||
(unsigned char *)&cmd, sizeof(cmd), 3000);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send start command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_stop_acquisition(libusb_device_handle *devhdl)
|
||||
{
|
||||
struct cmd_start_acquisition cmd;
|
||||
int ret;
|
||||
|
||||
/* stop acquisition command */
|
||||
cmd.flags = CMD_START_FLAGS_STOP;
|
||||
cmd.sample_delay_h = 0;
|
||||
cmd.sample_delay_l = 0;
|
||||
|
||||
/* Send the control message. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
|
||||
(unsigned char *)&cmd, sizeof(cmd), 3000);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send stop command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_fpga_config(libusb_device_handle *devhdl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Send the control message. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_CONFIG, 0x0000, 0x0000,
|
||||
NULL, 0, 3000);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send FPGA configure command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_fpga_setting(libusb_device_handle *devhdl, uint32_t setting_count)
|
||||
{
|
||||
struct cmd_setting_count cmd;
|
||||
int ret;
|
||||
|
||||
/* ... */
|
||||
cmd.byte0 = (uint8_t)setting_count;
|
||||
cmd.byte1 = (uint8_t)(setting_count >> 8);
|
||||
cmd.byte2 = (uint8_t)(setting_count >> 16);
|
||||
|
||||
/* Send the control message. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_SETTING, 0x0000, 0x0000,
|
||||
(unsigned char *)&cmd, sizeof(cmd), 100);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send FPGA setting command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libusb.h>
|
||||
#include "command.h"
|
||||
//#include "libsigrok.h"
|
||||
#include "libsigrok-internal.h"
|
||||
#include "dslogic.h"
|
||||
|
||||
SR_PRIV int command_get_fw_version(libusb_device_handle *devhdl,
|
||||
struct version_info *vi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_IN, CMD_GET_FW_VERSION, 0x0000, 0x0000,
|
||||
(unsigned char *)vi, sizeof(struct version_info), 100);
|
||||
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to get version info: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_get_revid_version(libusb_device_handle *devhdl,
|
||||
uint8_t *revid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_IN, CMD_GET_REVID_VERSION, 0x0000, 0x0000,
|
||||
revid, 1, 100);
|
||||
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to get REVID: %s.", libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl,
|
||||
uint64_t samplerate, gboolean samplewide)
|
||||
{
|
||||
struct cmd_start_acquisition cmd;
|
||||
int delay = 0, ret;
|
||||
|
||||
/* Compute the sample rate. */
|
||||
// if (samplewide && samplerate > MAX_16BIT_SAMPLE_RATE) {
|
||||
// sr_err("Unable to sample at %" PRIu64 "Hz "
|
||||
// "when collecting 16-bit samples.", samplerate);
|
||||
// return SR_ERR;
|
||||
// }
|
||||
|
||||
// if ((SR_MHZ(48) % samplerate) == 0) {
|
||||
// cmd.flags = CMD_START_FLAGS_CLK_48MHZ;
|
||||
// delay = SR_MHZ(48) / samplerate - 1;
|
||||
// if (delay > MAX_SAMPLE_DELAY)
|
||||
// delay = 0;
|
||||
// }
|
||||
|
||||
// if (delay == 0 && (SR_MHZ(30) % samplerate) == 0) {
|
||||
// cmd.flags = CMD_START_FLAGS_CLK_30MHZ;
|
||||
// delay = SR_MHZ(30) / samplerate - 1;
|
||||
// }
|
||||
cmd.flags = CMD_START_FLAGS_CLK_30MHZ;
|
||||
delay = 0;
|
||||
|
||||
sr_info("GPIF delay = %d, clocksource = %sMHz.", delay,
|
||||
(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);
|
||||
// return SR_ERR;
|
||||
// }
|
||||
|
||||
cmd.sample_delay_h = (delay >> 8) & 0xff;
|
||||
cmd.sample_delay_l = delay & 0xff;
|
||||
|
||||
/* Select the sampling width. */
|
||||
cmd.flags |= samplewide ? CMD_START_FLAGS_SAMPLE_16BIT :
|
||||
CMD_START_FLAGS_SAMPLE_8BIT;
|
||||
|
||||
/* Send the control message. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
|
||||
(unsigned char *)&cmd, sizeof(cmd), 3000);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send start command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_stop_acquisition(libusb_device_handle *devhdl)
|
||||
{
|
||||
struct cmd_start_acquisition cmd;
|
||||
int ret;
|
||||
|
||||
/* stop acquisition command */
|
||||
cmd.flags = CMD_START_FLAGS_STOP;
|
||||
cmd.sample_delay_h = 0;
|
||||
cmd.sample_delay_l = 0;
|
||||
|
||||
/* Send the control message. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
|
||||
(unsigned char *)&cmd, sizeof(cmd), 3000);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send stop command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_fpga_config(libusb_device_handle *devhdl)
|
||||
{
|
||||
struct cmd_cfg_count cmd;
|
||||
int ret;
|
||||
|
||||
/* ... */
|
||||
cmd.byte0 = (uint8_t)XC6SLX9_BYTE_CNT;
|
||||
cmd.byte1 = (uint8_t)(XC6SLX9_BYTE_CNT >> 8);
|
||||
cmd.byte2 = (uint8_t)(XC6SLX9_BYTE_CNT >> 16);
|
||||
|
||||
/* Send the control message. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_CONFIG, 0x0000, 0x0000,
|
||||
(unsigned char *)&cmd, sizeof(cmd), 3000);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send FPGA configure command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_fpga_setting(libusb_device_handle *devhdl, uint32_t setting_count)
|
||||
{
|
||||
struct cmd_setting_count cmd;
|
||||
int ret;
|
||||
|
||||
/* ... */
|
||||
cmd.byte0 = (uint8_t)setting_count;
|
||||
cmd.byte1 = (uint8_t)(setting_count >> 8);
|
||||
cmd.byte2 = (uint8_t)(setting_count >> 16);
|
||||
|
||||
/* Send the control message. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_SETTING, 0x0000, 0x0000,
|
||||
(unsigned char *)&cmd, sizeof(cmd), 3000);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send FPGA setting command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
SR_PRIV int command_dso_ctrl(libusb_device_handle *devhdl, uint32_t command)
|
||||
{
|
||||
struct cmd_control cmd;
|
||||
int ret;
|
||||
|
||||
/* ... */
|
||||
cmd.byte0 = (uint8_t)command;
|
||||
cmd.byte1 = (uint8_t)(command >> 8);
|
||||
cmd.byte2 = (uint8_t)(command >> 16);
|
||||
cmd.byte3 = (uint8_t)(command >> 24);
|
||||
|
||||
|
||||
/* Send the control command. */
|
||||
ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, CMD_CONTROL, 0x0000, 0x0000,
|
||||
(unsigned char *)&cmd, sizeof(cmd), 3000);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send oscilloscope control command: %s.",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
@@ -1,79 +1,93 @@
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBDSLOGIC_HARDWARE_COMMAND_H
|
||||
#define LIBDSLOGIC_HARDWARE_COMMAND_H
|
||||
|
||||
#include <glib.h>
|
||||
#include "libsigrok.h"
|
||||
|
||||
/* Protocol commands */
|
||||
#define CMD_GET_FW_VERSION 0xb0
|
||||
#define CMD_GET_REVID_VERSION 0xb1
|
||||
#define CMD_START 0xb2
|
||||
#define CMD_CONFIG 0xb3
|
||||
#define CMD_SETTING 0xb4
|
||||
|
||||
|
||||
#define CMD_START_FLAGS_WIDE_POS 5
|
||||
#define CMD_START_FLAGS_CLK_SRC_POS 6
|
||||
#define CMD_START_FLAGS_STOP_POS 7
|
||||
|
||||
#define CMD_START_FLAGS_SAMPLE_8BIT (0 << CMD_START_FLAGS_WIDE_POS)
|
||||
#define CMD_START_FLAGS_SAMPLE_16BIT (1 << CMD_START_FLAGS_WIDE_POS)
|
||||
|
||||
#define CMD_START_FLAGS_CLK_30MHZ (0 << CMD_START_FLAGS_CLK_SRC_POS)
|
||||
#define CMD_START_FLAGS_CLK_48MHZ (1 << CMD_START_FLAGS_CLK_SRC_POS)
|
||||
|
||||
#define CMD_START_FLAGS_STOP (1 << CMD_START_FLAGS_STOP_POS)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct version_info {
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
};
|
||||
|
||||
struct cmd_start_acquisition {
|
||||
uint8_t flags;
|
||||
uint8_t sample_delay_h;
|
||||
uint8_t sample_delay_l;
|
||||
};
|
||||
|
||||
struct cmd_setting_count {
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
uint8_t byte2;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
SR_PRIV int command_get_fw_version(libusb_device_handle *devhdl,
|
||||
struct version_info *vi);
|
||||
SR_PRIV int command_get_revid_version(libusb_device_handle *devhdl,
|
||||
uint8_t *revid);
|
||||
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl,
|
||||
uint64_t samplerate, gboolean samplewide);
|
||||
SR_PRIV int command_stop_acquistition(libusb_device_handle *devhdl);
|
||||
|
||||
SR_PRIV int command_fpga_config(libusb_device_handle *devhdl);
|
||||
|
||||
SR_PRIV int command_fpga_setting(libusb_device_handle *devhdl, uint32_t setting_count);
|
||||
|
||||
#endif
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBDSLOGIC_HARDWARE_COMMAND_H
|
||||
#define LIBDSLOGIC_HARDWARE_COMMAND_H
|
||||
|
||||
#include <glib.h>
|
||||
#include "libsigrok.h"
|
||||
|
||||
/* Protocol commands */
|
||||
#define CMD_GET_FW_VERSION 0xb0
|
||||
#define CMD_GET_REVID_VERSION 0xb1
|
||||
#define CMD_START 0xb2
|
||||
#define CMD_CONFIG 0xb3
|
||||
#define CMD_SETTING 0xb4
|
||||
#define CMD_CONTROL 0xb5
|
||||
|
||||
#define CMD_START_FLAGS_WIDE_POS 5
|
||||
#define CMD_START_FLAGS_CLK_SRC_POS 6
|
||||
#define CMD_START_FLAGS_STOP_POS 7
|
||||
|
||||
#define CMD_START_FLAGS_SAMPLE_8BIT (0 << CMD_START_FLAGS_WIDE_POS)
|
||||
#define CMD_START_FLAGS_SAMPLE_16BIT (1 << CMD_START_FLAGS_WIDE_POS)
|
||||
|
||||
#define CMD_START_FLAGS_CLK_30MHZ (0 << CMD_START_FLAGS_CLK_SRC_POS)
|
||||
#define CMD_START_FLAGS_CLK_48MHZ (1 << CMD_START_FLAGS_CLK_SRC_POS)
|
||||
|
||||
#define CMD_START_FLAGS_STOP (1 << CMD_START_FLAGS_STOP_POS)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct version_info {
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
};
|
||||
|
||||
struct cmd_start_acquisition {
|
||||
uint8_t flags;
|
||||
uint8_t sample_delay_h;
|
||||
uint8_t sample_delay_l;
|
||||
};
|
||||
|
||||
struct cmd_setting_count {
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
uint8_t byte2;
|
||||
};
|
||||
|
||||
struct cmd_cfg_count {
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
uint8_t byte2;
|
||||
};
|
||||
|
||||
struct cmd_control {
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
uint8_t byte2;
|
||||
uint8_t byte3;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
SR_PRIV int command_get_fw_version(libusb_device_handle *devhdl,
|
||||
struct version_info *vi);
|
||||
SR_PRIV int command_get_revid_version(libusb_device_handle *devhdl,
|
||||
uint8_t *revid);
|
||||
SR_PRIV int command_start_acquisition(libusb_device_handle *devhdl,
|
||||
uint64_t samplerate, gboolean samplewide);
|
||||
SR_PRIV int command_stop_acquistition(libusb_device_handle *devhdl);
|
||||
|
||||
SR_PRIV int command_fpga_config(libusb_device_handle *devhdl);
|
||||
SR_PRIV int command_fpga_setting(libusb_device_handle *devhdl, uint32_t setting_count);
|
||||
|
||||
SR_PRIV int command_dso_ctrl(libusb_device_handle *devhdl, uint32_t command);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,196 +1,212 @@
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBDSLOGIC_HARDWARE_DSLOGIC_H
|
||||
#define LIBDSLOGIC_HARDWARE_DSLOGIC_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* Message logging helpers with subsystem-specific prefix string. */
|
||||
#define LOG_PREFIX "DSLogic Hardware: "
|
||||
#define ds_log(l, s, args...) ds_log(l, LOG_PREFIX s, ## args)
|
||||
#define ds_spew(s, args...) ds_spew(LOG_PREFIX s, ## args)
|
||||
#define ds_dbg(s, args...) ds_dbg(LOG_PREFIX s, ## args)
|
||||
#define ds_info(s, args...) ds_info(LOG_PREFIX s, ## args)
|
||||
#define ds_warn(s, args...) ds_warn(LOG_PREFIX s, ## args)
|
||||
#define ds_err(s, args...) ds_err(LOG_PREFIX s, ## args)
|
||||
|
||||
#define USB_INTERFACE 0
|
||||
#define USB_CONFIGURATION 1
|
||||
#define NUM_TRIGGER_STAGES 16
|
||||
#define TRIGGER_TYPE "01"
|
||||
|
||||
#define MAX_RENUM_DELAY_MS 3000
|
||||
#define NUM_SIMUL_TRANSFERS 64
|
||||
#define MAX_EMPTY_TRANSFERS (NUM_SIMUL_TRANSFERS * 2)
|
||||
|
||||
#define DSLOGIC_REQUIRED_VERSION_MAJOR 1
|
||||
|
||||
#define MAX_8BIT_SAMPLE_RATE DS_MHZ(24)
|
||||
#define MAX_16BIT_SAMPLE_RATE DS_MHZ(12)
|
||||
|
||||
/* 6 delay states of up to 256 clock ticks */
|
||||
#define MAX_SAMPLE_DELAY (6 * 256)
|
||||
|
||||
/* Software trigger implementation: positive values indicate trigger stage. */
|
||||
#define TRIGGER_FIRED -1
|
||||
|
||||
#define DEV_CAPS_16BIT_POS 0
|
||||
|
||||
#define DEV_CAPS_16BIT (1 << DEV_CAPS_16BIT_POS)
|
||||
|
||||
#define XC3S250E_BYTE_CNT 169216
|
||||
//#define XC6SLX9_BYTE_CNT 340884
|
||||
#define XC6SLX9_BYTE_CNT 340604
|
||||
|
||||
#define MAX_ANALOG_PROBES_NUM 9
|
||||
#define MAX_DSO_PROBES_NUM 2
|
||||
|
||||
struct DSLogic_profile {
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
|
||||
const char *vendor;
|
||||
const char *model;
|
||||
const char *model_version;
|
||||
|
||||
const char *firmware;
|
||||
|
||||
const char *fpga_bit;
|
||||
|
||||
uint32_t dev_caps;
|
||||
};
|
||||
|
||||
static const struct DSLogic_profile supported_fx2[3] = {
|
||||
/*
|
||||
* DSLogic
|
||||
*/
|
||||
{0x2A0E, 0x0001, NULL, "DSLogic", NULL,
|
||||
"DSLogic.fw",
|
||||
"DSLogic.bin",
|
||||
DEV_CAPS_16BIT},
|
||||
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
enum {
|
||||
DSLOGIC_ERROR = -1,
|
||||
DSLOGIC_INIT = 0,
|
||||
DSLOGIC_START = 1,
|
||||
DSLOGIC_TRIGGERED = 2,
|
||||
DSLOGIC_DATA = 3,
|
||||
DSLOGIC_STOP = 4,
|
||||
};
|
||||
|
||||
struct dev_context {
|
||||
const struct DSLogic_profile *profile;
|
||||
/*
|
||||
* Since we can't keep track of an DSLogic device after upgrading
|
||||
* the firmware (it renumerates into a different device address
|
||||
* after the upgrade) this is like a global lock. No device will open
|
||||
* until a proper delay after the last device was upgraded.
|
||||
*/
|
||||
int64_t fw_updated;
|
||||
|
||||
/* Device/capture settings */
|
||||
uint64_t cur_samplerate;
|
||||
uint64_t limit_samples;
|
||||
|
||||
/* Operational settings */
|
||||
gboolean sample_wide;
|
||||
gboolean clock_type;
|
||||
uint16_t op_mode;
|
||||
uint16_t trigger_mask[NUM_TRIGGER_STAGES];
|
||||
uint16_t trigger_value[NUM_TRIGGER_STAGES];
|
||||
int trigger_stage;
|
||||
uint16_t trigger_buffer[NUM_TRIGGER_STAGES];
|
||||
|
||||
int num_samples;
|
||||
int submitted_transfers;
|
||||
int empty_transfer_count;
|
||||
|
||||
void *cb_data;
|
||||
unsigned int num_transfers;
|
||||
struct libusb_transfer **transfers;
|
||||
int *usbfd;
|
||||
|
||||
int status;
|
||||
};
|
||||
|
||||
struct DSLogic_setting {
|
||||
uint32_t sync;
|
||||
uint16_t mode_header; // 0
|
||||
uint16_t mode;
|
||||
uint32_t divider_header; // 1-2
|
||||
uint32_t divider;
|
||||
uint32_t count_header; // 3-4
|
||||
uint32_t count;
|
||||
uint32_t trig_pos_header; // 5-6
|
||||
uint32_t trig_pos;
|
||||
uint16_t trig_glb_header; // 7
|
||||
uint16_t trig_glb;
|
||||
uint32_t trig_adp_header; // 10-11
|
||||
uint32_t trig_adp;
|
||||
uint32_t trig_sda_header; // 12-13
|
||||
uint32_t trig_sda;
|
||||
uint32_t trig_mask0_header; // 16
|
||||
uint16_t trig_mask0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_mask1_header; // 17
|
||||
uint16_t trig_mask1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_mask2_header; // 18
|
||||
//uint16_t trig_mask2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_mask3_header; // 19
|
||||
//uint16_t trig_mask3[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_value0_header; // 20
|
||||
uint16_t trig_value0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_value1_header; // 21
|
||||
uint16_t trig_value1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_value2_header; // 22
|
||||
//uint16_t trig_value2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_value3_header; // 23
|
||||
//uint16_t trig_value3[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_edge0_header; // 24
|
||||
uint16_t trig_edge0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_edge1_header; // 25
|
||||
uint16_t trig_edge1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_edge2_header; // 26
|
||||
//uint16_t trig_edge2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_edge3_header; // 27
|
||||
//uint16_t trig_edge3[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_count0_header; // 28
|
||||
uint16_t trig_count0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_count1_header; // 29
|
||||
uint16_t trig_count1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_count2_header; // 30
|
||||
//uint16_t trig_count2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_count3_header; // 31
|
||||
//uint16_t trig_count3[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_logic0_header; // 32
|
||||
uint16_t trig_logic0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_logic1_header; // 33
|
||||
uint16_t trig_logic1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_logic2_header; // 34
|
||||
//uint16_t trig_logic2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_logic3_header; // 35
|
||||
//uint16_t trig_logic3[NUM_TRIGGER_STAGES];
|
||||
uint32_t end_sync;
|
||||
};
|
||||
|
||||
#endif
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBDSLOGIC_HARDWARE_DSLOGIC_H
|
||||
#define LIBDSLOGIC_HARDWARE_DSLOGIC_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* Message logging helpers with subsystem-specific prefix string. */
|
||||
#define LOG_PREFIX "DSLogic Hardware: "
|
||||
#define ds_log(l, s, args...) ds_log(l, LOG_PREFIX s, ## args)
|
||||
#define ds_spew(s, args...) ds_spew(LOG_PREFIX s, ## args)
|
||||
#define ds_dbg(s, args...) ds_dbg(LOG_PREFIX s, ## args)
|
||||
#define ds_info(s, args...) ds_info(LOG_PREFIX s, ## args)
|
||||
#define ds_warn(s, args...) ds_warn(LOG_PREFIX s, ## args)
|
||||
#define ds_err(s, args...) ds_err(LOG_PREFIX s, ## args)
|
||||
|
||||
#define USB_INTERFACE 0
|
||||
#define USB_CONFIGURATION 1
|
||||
#define NUM_TRIGGER_STAGES 16
|
||||
#define TRIGGER_TYPE "01"
|
||||
|
||||
#define MAX_RENUM_DELAY_MS 3000
|
||||
#define NUM_SIMUL_TRANSFERS 64
|
||||
#define MAX_EMPTY_TRANSFERS (NUM_SIMUL_TRANSFERS * 2)
|
||||
|
||||
#define DSLOGIC_REQUIRED_VERSION_MAJOR 1
|
||||
|
||||
#define MAX_8BIT_SAMPLE_RATE DS_MHZ(24)
|
||||
#define MAX_16BIT_SAMPLE_RATE DS_MHZ(12)
|
||||
|
||||
/* 6 delay states of up to 256 clock ticks */
|
||||
#define MAX_SAMPLE_DELAY (6 * 256)
|
||||
|
||||
/* Software trigger implementation: positive values indicate trigger stage. */
|
||||
#define TRIGGER_FIRED -1
|
||||
|
||||
#define DEV_CAPS_16BIT_POS 0
|
||||
|
||||
#define DEV_CAPS_16BIT (1 << DEV_CAPS_16BIT_POS)
|
||||
|
||||
#define XC3S250E_BYTE_CNT 169216
|
||||
//#define XC6SLX9_BYTE_CNT 341160
|
||||
#define XC6SLX9_BYTE_CNT 340884
|
||||
//#define XC6SLX9_BYTE_CNT 340604
|
||||
|
||||
#define MAX_ANALOG_PROBES_NUM 9
|
||||
#define MAX_DSO_PROBES_NUM 2
|
||||
|
||||
struct DSLogic_profile {
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
|
||||
const char *vendor;
|
||||
const char *model;
|
||||
const char *model_version;
|
||||
|
||||
const char *firmware;
|
||||
|
||||
const char *fpga_bit;
|
||||
|
||||
uint32_t dev_caps;
|
||||
};
|
||||
|
||||
static const struct DSLogic_profile supported_fx2[3] = {
|
||||
/*
|
||||
* DSLogic
|
||||
*/
|
||||
{0x2A0E, 0x0001, NULL, "DSLogic", NULL,
|
||||
"DSLogic.fw",
|
||||
"DSLogic.bin",
|
||||
DEV_CAPS_16BIT},
|
||||
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
enum {
|
||||
DSLOGIC_ERROR = -1,
|
||||
DSLOGIC_INIT = 0,
|
||||
DSLOGIC_START = 1,
|
||||
DSLOGIC_TRIGGERED = 2,
|
||||
DSLOGIC_DATA = 3,
|
||||
DSLOGIC_STOP = 4,
|
||||
};
|
||||
|
||||
struct dev_context {
|
||||
const struct DSLogic_profile *profile;
|
||||
/*
|
||||
* Since we can't keep track of an DSLogic device after upgrading
|
||||
* the firmware (it renumerates into a different device address
|
||||
* after the upgrade) this is like a global lock. No device will open
|
||||
* until a proper delay after the last device was upgraded.
|
||||
*/
|
||||
int64_t fw_updated;
|
||||
|
||||
/* Device/capture settings */
|
||||
uint64_t cur_samplerate;
|
||||
uint64_t limit_samples;
|
||||
|
||||
/* Operational settings */
|
||||
gboolean sample_wide;
|
||||
gboolean clock_type;
|
||||
uint16_t op_mode;
|
||||
uint16_t trigger_mask[NUM_TRIGGER_STAGES];
|
||||
uint16_t trigger_value[NUM_TRIGGER_STAGES];
|
||||
int trigger_stage;
|
||||
uint16_t trigger_buffer[NUM_TRIGGER_STAGES];
|
||||
uint64_t vdiv0;
|
||||
uint64_t vdiv1;
|
||||
uint64_t timebase;
|
||||
gboolean coupling0;
|
||||
gboolean coupling1;
|
||||
gboolean en_ch0;
|
||||
gboolean en_ch1;
|
||||
uint8_t trigger_slope;
|
||||
uint8_t trigger_source;
|
||||
uint16_t trigger_vpos;
|
||||
uint32_t trigger_hpos;
|
||||
gboolean zero;
|
||||
|
||||
int num_samples;
|
||||
int submitted_transfers;
|
||||
int empty_transfer_count;
|
||||
|
||||
void *cb_data;
|
||||
unsigned int num_transfers;
|
||||
struct libusb_transfer **transfers;
|
||||
int *usbfd;
|
||||
|
||||
int pipe_fds[2];
|
||||
GIOChannel *channel;
|
||||
|
||||
int status;
|
||||
};
|
||||
|
||||
struct DSLogic_setting {
|
||||
uint32_t sync;
|
||||
uint16_t mode_header; // 0
|
||||
uint16_t mode;
|
||||
uint32_t divider_header; // 1-2
|
||||
uint32_t divider;
|
||||
uint32_t count_header; // 3-4
|
||||
uint32_t count;
|
||||
uint32_t trig_pos_header; // 5-6
|
||||
uint32_t trig_pos;
|
||||
uint16_t trig_glb_header; // 7
|
||||
uint16_t trig_glb;
|
||||
uint32_t trig_adp_header; // 10-11
|
||||
uint32_t trig_adp;
|
||||
uint32_t trig_sda_header; // 12-13
|
||||
uint32_t trig_sda;
|
||||
uint32_t trig_mask0_header; // 16
|
||||
uint16_t trig_mask0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_mask1_header; // 17
|
||||
uint16_t trig_mask1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_mask2_header; // 18
|
||||
//uint16_t trig_mask2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_mask3_header; // 19
|
||||
//uint16_t trig_mask3[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_value0_header; // 20
|
||||
uint16_t trig_value0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_value1_header; // 21
|
||||
uint16_t trig_value1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_value2_header; // 22
|
||||
//uint16_t trig_value2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_value3_header; // 23
|
||||
//uint16_t trig_value3[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_edge0_header; // 24
|
||||
uint16_t trig_edge0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_edge1_header; // 25
|
||||
uint16_t trig_edge1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_edge2_header; // 26
|
||||
//uint16_t trig_edge2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_edge3_header; // 27
|
||||
//uint16_t trig_edge3[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_count0_header; // 28
|
||||
uint16_t trig_count0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_count1_header; // 29
|
||||
uint16_t trig_count1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_count2_header; // 30
|
||||
//uint16_t trig_count2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_count3_header; // 31
|
||||
//uint16_t trig_count3[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_logic0_header; // 32
|
||||
uint16_t trig_logic0[NUM_TRIGGER_STAGES];
|
||||
uint32_t trig_logic1_header; // 33
|
||||
uint16_t trig_logic1[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_logic2_header; // 34
|
||||
//uint16_t trig_logic2[NUM_TRIGGER_STAGES];
|
||||
//uint32_t trig_logic3_header; // 35
|
||||
//uint16_t trig_logic3[NUM_TRIGGER_STAGES];
|
||||
uint32_t end_sync;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,143 +1,143 @@
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Helper functions for the Cypress EZ-USB / FX2 series chips.
|
||||
*/
|
||||
|
||||
#include <libusb.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "libsigrok.h"
|
||||
#include "libsigrok-internal.h"
|
||||
|
||||
/* Message logging helpers with subsystem-specific prefix string. */
|
||||
#define LOG_PREFIX "ezusb: "
|
||||
#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
|
||||
#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
|
||||
#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
|
||||
#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
|
||||
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
|
||||
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
|
||||
|
||||
SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1];
|
||||
|
||||
sr_info("setting CPU reset mode %s...",
|
||||
set_clear ? "on" : "off");
|
||||
buf[0] = set_clear ? 1 : 0;
|
||||
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR, 0xa0,
|
||||
0xe600, 0x0000, buf, 1, 100);
|
||||
if (ret < 0)
|
||||
sr_err("Unable to send control request: %s.",
|
||||
libusb_error_name(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int ezusb_install_firmware(libusb_device_handle *hdl,
|
||||
const char *filename)
|
||||
{
|
||||
FILE *fw;
|
||||
int offset, chunksize, ret, result;
|
||||
unsigned char buf[4096];
|
||||
|
||||
sr_info("Uploading firmware at %s", filename);
|
||||
if ((fw = g_fopen(filename, "rb")) == NULL) {
|
||||
sr_err("Unable to open firmware file %s for reading: %s",
|
||||
filename, strerror(errno));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
result = SR_OK;
|
||||
offset = 0;
|
||||
while (1) {
|
||||
chunksize = fread(buf, 1, 4096, fw);
|
||||
if (chunksize == 0)
|
||||
break;
|
||||
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, 0xa0, offset,
|
||||
0x0000, buf, chunksize, 100);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send firmware to device: %s.",
|
||||
libusb_error_name(ret));
|
||||
result = SR_ERR;
|
||||
break;
|
||||
}
|
||||
sr_info("Uploaded %d bytes", chunksize);
|
||||
offset += chunksize;
|
||||
}
|
||||
fclose(fw);
|
||||
sr_info("Firmware upload done");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SR_PRIV int ezusb_upload_firmware(libusb_device *dev, int configuration,
|
||||
const char *filename)
|
||||
{
|
||||
struct libusb_device_handle *hdl;
|
||||
int ret;
|
||||
|
||||
sr_info("uploading firmware to device on %d.%d",
|
||||
libusb_get_bus_number(dev), libusb_get_device_address(dev));
|
||||
|
||||
if ((ret = libusb_open(dev, &hdl)) < 0) {
|
||||
sr_err("failed to open device: %s.", libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* The libusbx darwin backend is broken: it can report a kernel driver being
|
||||
* active, but detaching it always returns an error.
|
||||
*/
|
||||
#if !defined(__APPLE__)
|
||||
if (libusb_kernel_driver_active(hdl, 0) == 1) {
|
||||
if ((ret = libusb_detach_kernel_driver(hdl, 0)) < 0) {
|
||||
sr_err("failed to detach kernel driver: %s",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ret = libusb_set_configuration(hdl, configuration)) < 0) {
|
||||
sr_err("Unable to set configuration: %s",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
if ((ezusb_reset(hdl, 1)) < 0)
|
||||
return SR_ERR;
|
||||
|
||||
if (ezusb_install_firmware(hdl, filename) < 0)
|
||||
return SR_ERR;
|
||||
|
||||
if ((ezusb_reset(hdl, 0)) < 0)
|
||||
return SR_ERR;
|
||||
|
||||
libusb_close(hdl);
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Helper functions for the Cypress EZ-USB / FX2 series chips.
|
||||
*/
|
||||
|
||||
#include <libusb.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "libsigrok.h"
|
||||
#include "libsigrok-internal.h"
|
||||
|
||||
/* Message logging helpers with subsystem-specific prefix string. */
|
||||
#define LOG_PREFIX "ezusb: "
|
||||
#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
|
||||
#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
|
||||
#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
|
||||
#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
|
||||
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
|
||||
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
|
||||
|
||||
SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[1];
|
||||
|
||||
sr_info("setting CPU reset mode %s...",
|
||||
set_clear ? "on" : "off");
|
||||
buf[0] = set_clear ? 1 : 0;
|
||||
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR, 0xa0,
|
||||
0xe600, 0x0000, buf, 1, 100);
|
||||
if (ret < 0)
|
||||
sr_err("Unable to send control request: %s.",
|
||||
libusb_error_name(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int ezusb_install_firmware(libusb_device_handle *hdl,
|
||||
const char *filename)
|
||||
{
|
||||
FILE *fw;
|
||||
int offset, chunksize, ret, result;
|
||||
unsigned char buf[4096];
|
||||
|
||||
sr_info("Uploading firmware at %s", filename);
|
||||
if ((fw = g_fopen(filename, "rb")) == NULL) {
|
||||
sr_err("Unable to open firmware file %s for reading: %s",
|
||||
filename, strerror(errno));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
result = SR_OK;
|
||||
offset = 0;
|
||||
while (1) {
|
||||
chunksize = fread(buf, 1, 4096, fw);
|
||||
if (chunksize == 0)
|
||||
break;
|
||||
ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR |
|
||||
LIBUSB_ENDPOINT_OUT, 0xa0, offset,
|
||||
0x0000, buf, chunksize, 100);
|
||||
if (ret < 0) {
|
||||
sr_err("Unable to send firmware to device: %s.",
|
||||
libusb_error_name(ret));
|
||||
result = SR_ERR;
|
||||
break;
|
||||
}
|
||||
sr_info("Uploaded %d bytes", chunksize);
|
||||
offset += chunksize;
|
||||
}
|
||||
fclose(fw);
|
||||
sr_info("Firmware upload done");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SR_PRIV int ezusb_upload_firmware(libusb_device *dev, int configuration,
|
||||
const char *filename)
|
||||
{
|
||||
struct libusb_device_handle *hdl;
|
||||
int ret;
|
||||
|
||||
sr_info("uploading firmware to device on %d.%d",
|
||||
libusb_get_bus_number(dev), libusb_get_device_address(dev));
|
||||
|
||||
if ((ret = libusb_open(dev, &hdl)) < 0) {
|
||||
sr_err("failed to open device: %s.", libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* The libusbx darwin backend is broken: it can report a kernel driver being
|
||||
* active, but detaching it always returns an error.
|
||||
*/
|
||||
#if !defined(__APPLE__)
|
||||
if (libusb_kernel_driver_active(hdl, 0) == 1) {
|
||||
if ((ret = libusb_detach_kernel_driver(hdl, 0)) < 0) {
|
||||
sr_err("failed to detach kernel driver: %s",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ret = libusb_set_configuration(hdl, configuration)) < 0) {
|
||||
sr_err("Unable to set configuration: %s",
|
||||
libusb_error_name(ret));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
if ((ezusb_reset(hdl, 1)) < 0)
|
||||
return SR_ERR;
|
||||
|
||||
if (ezusb_install_firmware(hdl, filename) < 0)
|
||||
return SR_ERR;
|
||||
|
||||
if ((ezusb_reset(hdl, 0)) < 0)
|
||||
return SR_ERR;
|
||||
|
||||
libusb_close(hdl);
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
@@ -1,245 +1,245 @@
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <libusb.h>
|
||||
#include "libsigrok.h"
|
||||
#include "libsigrok-internal.h"
|
||||
|
||||
/* SR_CONF_CONN takes one of these: */
|
||||
#define CONN_USB_VIDPID "^([0-9a-z]{4})\\.([0-9a-z]{4})$"
|
||||
#define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$"
|
||||
|
||||
/* Some USBTMC-specific enums, as defined in the USBTMC standard. */
|
||||
#define SUBCLASS_USBTMC 0x03
|
||||
#define USBTMC_USB488 0x01
|
||||
|
||||
/* Message logging helpers with subsystem-specific prefix string. */
|
||||
#define LOG_PREFIX "usb: "
|
||||
#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
|
||||
#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
|
||||
#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
|
||||
#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
|
||||
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
|
||||
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
|
||||
|
||||
/**
|
||||
* Find USB devices according to a connection string.
|
||||
*
|
||||
* @param usb_ctx libusb context to use while scanning.
|
||||
* @param conn Connection string specifying the device(s) to match. This
|
||||
* can be of the form "<bus>.<address>", or "<vendorid>.<productid>".
|
||||
*
|
||||
* @return A GSList of struct sr_usb_dev_inst, with bus and address fields
|
||||
* matching the device that matched the connection string. The GSList and
|
||||
* its contents must be freed by the caller.
|
||||
*/
|
||||
SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn)
|
||||
{
|
||||
struct sr_usb_dev_inst *usb;
|
||||
struct libusb_device **devlist;
|
||||
struct libusb_device_descriptor des;
|
||||
GSList *devices;
|
||||
GRegex *reg;
|
||||
GMatchInfo *match;
|
||||
int vid, pid, bus, addr, b, a, ret, i;
|
||||
char *mstr;
|
||||
|
||||
vid = pid = bus = addr = 0;
|
||||
reg = g_regex_new(CONN_USB_VIDPID, 0, 0, NULL);
|
||||
if (g_regex_match(reg, conn, 0, &match)) {
|
||||
if ((mstr = g_match_info_fetch(match, 1)))
|
||||
vid = strtoul(mstr, NULL, 16);
|
||||
g_free(mstr);
|
||||
|
||||
if ((mstr = g_match_info_fetch(match, 2)))
|
||||
pid = strtoul(mstr, NULL, 16);
|
||||
g_free(mstr);
|
||||
sr_dbg("Trying to find USB device with VID:PID = %04x:%04x.",
|
||||
vid, pid);
|
||||
} else {
|
||||
//g_match_info_unref(match);
|
||||
g_match_info_free(match);
|
||||
g_regex_unref(reg);
|
||||
reg = g_regex_new(CONN_USB_BUSADDR, 0, 0, NULL);
|
||||
if (g_regex_match(reg, conn, 0, &match)) {
|
||||
if ((mstr = g_match_info_fetch(match, 1)))
|
||||
bus = strtoul(mstr, NULL, 10);
|
||||
g_free(mstr);
|
||||
|
||||
if ((mstr = g_match_info_fetch(match, 2)))
|
||||
addr = strtoul(mstr, NULL, 10);
|
||||
g_free(mstr);
|
||||
sr_dbg("Trying to find USB device with bus.address = "
|
||||
"%d.%d.", bus, addr);
|
||||
}
|
||||
}
|
||||
//g_match_info_unref(match);
|
||||
g_match_info_free(match);
|
||||
g_regex_unref(reg);
|
||||
|
||||
if (vid + pid + bus + addr == 0) {
|
||||
sr_err("Neither VID:PID nor bus.address was specified.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bus > 64) {
|
||||
sr_err("Invalid bus specified: %d.", bus);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (addr > 127) {
|
||||
sr_err("Invalid address specified: %d.", addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Looks like a valid USB device specification, but is it connected? */
|
||||
devices = NULL;
|
||||
libusb_get_device_list(usb_ctx, &devlist);
|
||||
for (i = 0; devlist[i]; i++) {
|
||||
if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
|
||||
sr_err("Failed to get device descriptor: %s.",
|
||||
libusb_error_name(ret));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vid + pid && (des.idVendor != vid || des.idProduct != pid))
|
||||
continue;
|
||||
|
||||
b = libusb_get_bus_number(devlist[i]);
|
||||
a = libusb_get_device_address(devlist[i]);
|
||||
if (bus + addr && (b != bus || a != addr))
|
||||
continue;
|
||||
|
||||
sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = "
|
||||
"%d.%d).", des.idVendor, des.idProduct, b, a);
|
||||
|
||||
usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
|
||||
libusb_get_device_address(devlist[i]), NULL);
|
||||
devices = g_slist_append(devices, usb);
|
||||
}
|
||||
libusb_free_device_list(devlist, 1);
|
||||
|
||||
sr_dbg("Found %d device(s).", g_slist_length(devices));
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find USB devices supporting the USBTMC class
|
||||
*
|
||||
* @param usb_ctx libusb context to use while scanning.
|
||||
*
|
||||
* @return A GSList of struct sr_usb_dev_inst, with bus and address fields
|
||||
* indicating devices with USBTMC support.
|
||||
*/
|
||||
SR_PRIV GSList *sr_usb_find_usbtmc(libusb_context *usb_ctx)
|
||||
{
|
||||
struct sr_usb_dev_inst *usb;
|
||||
struct libusb_device **devlist;
|
||||
struct libusb_device_descriptor des;
|
||||
struct libusb_config_descriptor *confdes;
|
||||
const struct libusb_interface_descriptor *intfdes;
|
||||
GSList *devices;
|
||||
int confidx, intfidx, ret, i;
|
||||
|
||||
devices = NULL;
|
||||
libusb_get_device_list(usb_ctx, &devlist);
|
||||
for (i = 0; devlist[i]; i++) {
|
||||
if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
|
||||
sr_err("Failed to get device descriptor: %s.",
|
||||
libusb_error_name(ret));
|
||||
continue;
|
||||
}
|
||||
|
||||
for (confidx = 0; confidx < des.bNumConfigurations; confidx++) {
|
||||
if (libusb_get_config_descriptor(devlist[i], confidx, &confdes) != 0) {
|
||||
sr_err("Failed to get configuration descriptor.");
|
||||
break;
|
||||
}
|
||||
for (intfidx = 0; intfidx < confdes->bNumInterfaces; intfidx++) {
|
||||
intfdes = confdes->interface[intfidx].altsetting;
|
||||
if (intfdes->bInterfaceClass != LIBUSB_CLASS_APPLICATION
|
||||
|| intfdes->bInterfaceSubClass != SUBCLASS_USBTMC
|
||||
|| intfdes->bInterfaceProtocol != USBTMC_USB488)
|
||||
continue;
|
||||
sr_dbg("Found USBTMC device (VID:PID = %04x:%04x, bus.address = "
|
||||
"%d.%d).", des.idVendor, des.idProduct,
|
||||
libusb_get_bus_number(devlist[i]),
|
||||
libusb_get_device_address(devlist[i]));
|
||||
|
||||
usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
|
||||
libusb_get_device_address(devlist[i]), NULL);
|
||||
devices = g_slist_append(devices, usb);
|
||||
}
|
||||
libusb_free_config_descriptor(confdes);
|
||||
}
|
||||
}
|
||||
libusb_free_device_list(devlist, 1);
|
||||
|
||||
sr_dbg("Found %d device(s).", g_slist_length(devices));
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb)
|
||||
{
|
||||
struct libusb_device **devlist;
|
||||
struct libusb_device_descriptor des;
|
||||
int ret, r, cnt, i, a, b;
|
||||
|
||||
sr_dbg("Trying to open USB device %d.%d.", usb->bus, usb->address);
|
||||
|
||||
if ((cnt = libusb_get_device_list(usb_ctx, &devlist)) < 0) {
|
||||
sr_err("Failed to retrieve device list: %s.",
|
||||
libusb_error_name(cnt));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
ret = SR_ERR;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if ((r = libusb_get_device_descriptor(devlist[i], &des)) < 0) {
|
||||
sr_err("Failed to get device descriptor: %s.",
|
||||
libusb_error_name(r));
|
||||
continue;
|
||||
}
|
||||
|
||||
b = libusb_get_bus_number(devlist[i]);
|
||||
a = libusb_get_device_address(devlist[i]);
|
||||
if (b != usb->bus || a != usb->address)
|
||||
continue;
|
||||
|
||||
if ((r = libusb_open(devlist[i], &usb->devhdl)) < 0) {
|
||||
sr_err("Failed to open device: %s.",
|
||||
libusb_error_name(r));
|
||||
break;
|
||||
}
|
||||
|
||||
sr_dbg("Opened USB device (VID:PID = %04x:%04x, bus.address = "
|
||||
"%d.%d).", des.idVendor, des.idProduct, b, a);
|
||||
|
||||
ret = SR_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
libusb_free_device_list(devlist, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <libusb.h>
|
||||
#include "libsigrok.h"
|
||||
#include "libsigrok-internal.h"
|
||||
|
||||
/* SR_CONF_CONN takes one of these: */
|
||||
#define CONN_USB_VIDPID "^([0-9a-z]{4})\\.([0-9a-z]{4})$"
|
||||
#define CONN_USB_BUSADDR "^(\\d+)\\.(\\d+)$"
|
||||
|
||||
/* Some USBTMC-specific enums, as defined in the USBTMC standard. */
|
||||
#define SUBCLASS_USBTMC 0x03
|
||||
#define USBTMC_USB488 0x01
|
||||
|
||||
/* Message logging helpers with subsystem-specific prefix string. */
|
||||
#define LOG_PREFIX "usb: "
|
||||
#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
|
||||
#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
|
||||
#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
|
||||
#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
|
||||
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
|
||||
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
|
||||
|
||||
/**
|
||||
* Find USB devices according to a connection string.
|
||||
*
|
||||
* @param usb_ctx libusb context to use while scanning.
|
||||
* @param conn Connection string specifying the device(s) to match. This
|
||||
* can be of the form "<bus>.<address>", or "<vendorid>.<productid>".
|
||||
*
|
||||
* @return A GSList of struct sr_usb_dev_inst, with bus and address fields
|
||||
* matching the device that matched the connection string. The GSList and
|
||||
* its contents must be freed by the caller.
|
||||
*/
|
||||
SR_PRIV GSList *sr_usb_find(libusb_context *usb_ctx, const char *conn)
|
||||
{
|
||||
struct sr_usb_dev_inst *usb;
|
||||
struct libusb_device **devlist;
|
||||
struct libusb_device_descriptor des;
|
||||
GSList *devices;
|
||||
GRegex *reg;
|
||||
GMatchInfo *match;
|
||||
int vid, pid, bus, addr, b, a, ret, i;
|
||||
char *mstr;
|
||||
|
||||
vid = pid = bus = addr = 0;
|
||||
reg = g_regex_new(CONN_USB_VIDPID, 0, 0, NULL);
|
||||
if (g_regex_match(reg, conn, 0, &match)) {
|
||||
if ((mstr = g_match_info_fetch(match, 1)))
|
||||
vid = strtoul(mstr, NULL, 16);
|
||||
g_free(mstr);
|
||||
|
||||
if ((mstr = g_match_info_fetch(match, 2)))
|
||||
pid = strtoul(mstr, NULL, 16);
|
||||
g_free(mstr);
|
||||
sr_dbg("Trying to find USB device with VID:PID = %04x:%04x.",
|
||||
vid, pid);
|
||||
} else {
|
||||
//g_match_info_unref(match);
|
||||
g_match_info_free(match);
|
||||
g_regex_unref(reg);
|
||||
reg = g_regex_new(CONN_USB_BUSADDR, 0, 0, NULL);
|
||||
if (g_regex_match(reg, conn, 0, &match)) {
|
||||
if ((mstr = g_match_info_fetch(match, 1)))
|
||||
bus = strtoul(mstr, NULL, 10);
|
||||
g_free(mstr);
|
||||
|
||||
if ((mstr = g_match_info_fetch(match, 2)))
|
||||
addr = strtoul(mstr, NULL, 10);
|
||||
g_free(mstr);
|
||||
sr_dbg("Trying to find USB device with bus.address = "
|
||||
"%d.%d.", bus, addr);
|
||||
}
|
||||
}
|
||||
//g_match_info_unref(match);
|
||||
g_match_info_free(match);
|
||||
g_regex_unref(reg);
|
||||
|
||||
if (vid + pid + bus + addr == 0) {
|
||||
sr_err("Neither VID:PID nor bus.address was specified.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bus > 64) {
|
||||
sr_err("Invalid bus specified: %d.", bus);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (addr > 127) {
|
||||
sr_err("Invalid address specified: %d.", addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Looks like a valid USB device specification, but is it connected? */
|
||||
devices = NULL;
|
||||
libusb_get_device_list(usb_ctx, &devlist);
|
||||
for (i = 0; devlist[i]; i++) {
|
||||
if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
|
||||
sr_err("Failed to get device descriptor: %s.",
|
||||
libusb_error_name(ret));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vid + pid && (des.idVendor != vid || des.idProduct != pid))
|
||||
continue;
|
||||
|
||||
b = libusb_get_bus_number(devlist[i]);
|
||||
a = libusb_get_device_address(devlist[i]);
|
||||
if (bus + addr && (b != bus || a != addr))
|
||||
continue;
|
||||
|
||||
sr_dbg("Found USB device (VID:PID = %04x:%04x, bus.address = "
|
||||
"%d.%d).", des.idVendor, des.idProduct, b, a);
|
||||
|
||||
usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
|
||||
libusb_get_device_address(devlist[i]), NULL);
|
||||
devices = g_slist_append(devices, usb);
|
||||
}
|
||||
libusb_free_device_list(devlist, 1);
|
||||
|
||||
sr_dbg("Found %d device(s).", g_slist_length(devices));
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find USB devices supporting the USBTMC class
|
||||
*
|
||||
* @param usb_ctx libusb context to use while scanning.
|
||||
*
|
||||
* @return A GSList of struct sr_usb_dev_inst, with bus and address fields
|
||||
* indicating devices with USBTMC support.
|
||||
*/
|
||||
SR_PRIV GSList *sr_usb_find_usbtmc(libusb_context *usb_ctx)
|
||||
{
|
||||
struct sr_usb_dev_inst *usb;
|
||||
struct libusb_device **devlist;
|
||||
struct libusb_device_descriptor des;
|
||||
struct libusb_config_descriptor *confdes;
|
||||
const struct libusb_interface_descriptor *intfdes;
|
||||
GSList *devices;
|
||||
int confidx, intfidx, ret, i;
|
||||
|
||||
devices = NULL;
|
||||
libusb_get_device_list(usb_ctx, &devlist);
|
||||
for (i = 0; devlist[i]; i++) {
|
||||
if ((ret = libusb_get_device_descriptor(devlist[i], &des))) {
|
||||
sr_err("Failed to get device descriptor: %s.",
|
||||
libusb_error_name(ret));
|
||||
continue;
|
||||
}
|
||||
|
||||
for (confidx = 0; confidx < des.bNumConfigurations; confidx++) {
|
||||
if (libusb_get_config_descriptor(devlist[i], confidx, &confdes) != 0) {
|
||||
sr_err("Failed to get configuration descriptor.");
|
||||
break;
|
||||
}
|
||||
for (intfidx = 0; intfidx < confdes->bNumInterfaces; intfidx++) {
|
||||
intfdes = confdes->interface[intfidx].altsetting;
|
||||
if (intfdes->bInterfaceClass != LIBUSB_CLASS_APPLICATION
|
||||
|| intfdes->bInterfaceSubClass != SUBCLASS_USBTMC
|
||||
|| intfdes->bInterfaceProtocol != USBTMC_USB488)
|
||||
continue;
|
||||
sr_dbg("Found USBTMC device (VID:PID = %04x:%04x, bus.address = "
|
||||
"%d.%d).", des.idVendor, des.idProduct,
|
||||
libusb_get_bus_number(devlist[i]),
|
||||
libusb_get_device_address(devlist[i]));
|
||||
|
||||
usb = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
|
||||
libusb_get_device_address(devlist[i]), NULL);
|
||||
devices = g_slist_append(devices, usb);
|
||||
}
|
||||
libusb_free_config_descriptor(confdes);
|
||||
}
|
||||
}
|
||||
libusb_free_device_list(devlist, 1);
|
||||
|
||||
sr_dbg("Found %d device(s).", g_slist_length(devices));
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
SR_PRIV int sr_usb_open(libusb_context *usb_ctx, struct sr_usb_dev_inst *usb)
|
||||
{
|
||||
struct libusb_device **devlist;
|
||||
struct libusb_device_descriptor des;
|
||||
int ret, r, cnt, i, a, b;
|
||||
|
||||
sr_dbg("Trying to open USB device %d.%d.", usb->bus, usb->address);
|
||||
|
||||
if ((cnt = libusb_get_device_list(usb_ctx, &devlist)) < 0) {
|
||||
sr_err("Failed to retrieve device list: %s.",
|
||||
libusb_error_name(cnt));
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
ret = SR_ERR;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if ((r = libusb_get_device_descriptor(devlist[i], &des)) < 0) {
|
||||
sr_err("Failed to get device descriptor: %s.",
|
||||
libusb_error_name(r));
|
||||
continue;
|
||||
}
|
||||
|
||||
b = libusb_get_bus_number(devlist[i]);
|
||||
a = libusb_get_device_address(devlist[i]);
|
||||
if (b != usb->bus || a != usb->address)
|
||||
continue;
|
||||
|
||||
if ((r = libusb_open(devlist[i], &usb->devhdl)) < 0) {
|
||||
sr_err("Failed to open device: %s.",
|
||||
libusb_error_name(r));
|
||||
break;
|
||||
}
|
||||
|
||||
sr_dbg("Opened USB device (VID:PID = %04x:%04x, bus.address = "
|
||||
"%d.%d).", des.idVendor, des.idProduct, b, a);
|
||||
|
||||
ret = SR_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
libusb_free_device_list(devlist, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -85,6 +85,13 @@ struct dev_context {
|
||||
void *cb_data;
|
||||
int64_t starttime;
|
||||
int stop;
|
||||
gboolean en_ch0;
|
||||
gboolean en_ch1;
|
||||
uint64_t vdiv0;
|
||||
uint64_t vdiv1;
|
||||
uint64_t timebase;
|
||||
gboolean coupling0;
|
||||
gboolean coupling1;
|
||||
|
||||
int trigger_stage;
|
||||
uint16_t trigger_mask;
|
||||
@@ -192,6 +199,11 @@ static GSList *hw_scan(GSList *options)
|
||||
devc->limit_samples = 0;
|
||||
devc->limit_msec = 0;
|
||||
devc->sample_generator = PATTERN_SINE;
|
||||
devc->vdiv0 = 1000;
|
||||
devc->vdiv1 = 1000;
|
||||
devc->timebase = 100;
|
||||
devc->coupling0 = FALSE;
|
||||
devc->coupling1 = FALSE;
|
||||
|
||||
sdi->priv = devc;
|
||||
|
||||
@@ -290,6 +302,27 @@ static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
|
||||
case SR_CONF_PATTERN_MODE:
|
||||
*data = g_variant_new_string(pattern_strings[devc->sample_generator]);
|
||||
break;
|
||||
case SR_CONF_VDIV0:
|
||||
*data = g_variant_new_uint64(devc->vdiv0);
|
||||
break;
|
||||
case SR_CONF_VDIV1:
|
||||
*data = g_variant_new_uint64(devc->vdiv1);
|
||||
break;
|
||||
case SR_CONF_TIMEBASE:
|
||||
*data = g_variant_new_uint64(devc->timebase);
|
||||
break;
|
||||
case SR_CONF_COUPLING0:
|
||||
*data = g_variant_new_uint64(devc->coupling0);
|
||||
break;
|
||||
case SR_CONF_COUPLING1:
|
||||
*data = g_variant_new_uint64(devc->coupling1);
|
||||
break;
|
||||
case SR_CONF_EN_CH0:
|
||||
*data = g_variant_new_uint64(devc->en_ch0);
|
||||
break;
|
||||
case SR_CONF_EN_CH1:
|
||||
*data = g_variant_new_uint64(devc->en_ch1);
|
||||
break;
|
||||
default:
|
||||
return SR_ERR_NA;
|
||||
}
|
||||
@@ -380,7 +413,42 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi)
|
||||
}
|
||||
sr_dbg("%s: setting pattern to %d",
|
||||
__func__, devc->sample_generator);
|
||||
} else {
|
||||
} else if (id == SR_CONF_EN_CH0) {
|
||||
devc->en_ch0 = g_variant_get_boolean(data);
|
||||
sr_dbg("%s: setting ENABLE of channel 0 to %d", __func__,
|
||||
devc->en_ch0);
|
||||
ret = SR_OK;
|
||||
} else if (id == SR_CONF_EN_CH1) {
|
||||
devc->en_ch1 = g_variant_get_boolean(data);
|
||||
sr_dbg("%s: setting ENABLE of channel 1 to %d", __func__,
|
||||
devc->en_ch1);
|
||||
ret = SR_OK;
|
||||
} else if (id == SR_CONF_VDIV0) {
|
||||
devc->vdiv0 = g_variant_get_uint64(data);
|
||||
sr_dbg("%s: setting VDIV of channel 0 to %" PRIu64, __func__,
|
||||
devc->vdiv0);
|
||||
ret = SR_OK;
|
||||
} else if (id == SR_CONF_VDIV1) {
|
||||
devc->vdiv1 = g_variant_get_uint64(data);
|
||||
sr_dbg("%s: setting VDIV of channel 1 to %" PRIu64, __func__,
|
||||
devc->vdiv1);
|
||||
ret = SR_OK;
|
||||
} else if (id == SR_CONF_TIMEBASE) {
|
||||
devc->timebase = g_variant_get_uint64(data);
|
||||
sr_dbg("%s: setting TIMEBASE to %" PRIu64, __func__,
|
||||
devc->timebase);
|
||||
ret = SR_OK;
|
||||
} else if (id == SR_CONF_COUPLING0) {
|
||||
devc->coupling0 = g_variant_get_boolean(data);
|
||||
sr_dbg("%s: setting AC COUPLING of channel 0 to %d", __func__,
|
||||
devc->coupling0);
|
||||
ret = SR_OK;
|
||||
} else if (id == SR_CONF_COUPLING1) {
|
||||
devc->coupling1 = g_variant_get_boolean(data);
|
||||
sr_dbg("%s: setting AC COUPLING of channel 1 to %d", __func__,
|
||||
devc->coupling1);
|
||||
ret = SR_OK;
|
||||
} else {
|
||||
ret = SR_ERR_NA;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user