summaryrefslogtreecommitdiffstats
path: root/host/utils
diff options
context:
space:
mode:
Diffstat (limited to 'host/utils')
-rw-r--r--host/utils/CMakeLists.txt2
-rw-r--r--host/utils/b2xx_fx3_utils.cpp746
-rw-r--r--host/utils/fx2_init_eeprom.cpp8
-rw-r--r--host/utils/query_gpsdo_sensors.cpp3
-rw-r--r--host/utils/uhd-usrp.rules6
-rw-r--r--host/utils/uhd_cal_rx_iq_balance.cpp5
-rw-r--r--host/utils/uhd_cal_tx_dc_offset.cpp4
-rw-r--r--host/utils/uhd_cal_tx_iq_balance.cpp5
-rw-r--r--host/utils/uhd_find_devices.cpp7
-rw-r--r--host/utils/uhd_usrp_probe.cpp26
-rw-r--r--host/utils/usrp_burn_db_eeprom.cpp4
-rw-r--r--host/utils/usrp_burn_mb_eeprom.cpp6
-rw-r--r--host/utils/usrp_cal_utils.hpp6
13 files changed, 799 insertions, 29 deletions
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index b04d0e1b9..92df0b7cf 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -47,7 +47,9 @@ SET(util_share_sources
IF(ENABLE_USB)
LIST(APPEND util_share_sources
fx2_init_eeprom.cpp
+ b2xx_fx3_utils.cpp
)
+ INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS})
ENDIF(ENABLE_USB)
IF(LINUX AND ENABLE_USB)
diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp
new file mode 100644
index 000000000..c99ce1e01
--- /dev/null
+++ b/host/utils/b2xx_fx3_utils.cpp
@@ -0,0 +1,746 @@
+//
+// Copyright 2010-2013 Ettus Research LLC
+//
+// 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 <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <libusb.h>
+#include <sstream>
+#include <string>
+#include <cmath>
+#include <cstring>
+
+#include <boost/cstdint.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/format.hpp>
+#include <boost/program_options.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/functional/hash.hpp>
+
+#include <uhd/config.hpp>
+
+const static boost::uint16_t FX3_VID = 0x04b4;
+const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3;
+const static boost::uint16_t FX3_REENUM_PID = 0x00f0;
+const static boost::uint16_t B2XX_VID = 0x2500;
+const static boost::uint16_t B2XX_PID = 0x0020;
+
+const static boost::uint8_t VRT_VENDOR_OUT = (LIBUSB_REQUEST_TYPE_VENDOR
+ | LIBUSB_ENDPOINT_OUT);
+const static boost::uint8_t VRT_VENDOR_IN = (LIBUSB_REQUEST_TYPE_VENDOR
+ | LIBUSB_ENDPOINT_IN);
+const static boost::uint8_t FX3_FIRMWARE_LOAD = 0xA0;
+
+const static boost::uint8_t B2XX_VREQ_FPGA_START = 0x02;
+const static boost::uint8_t B2XX_VREQ_FPGA_DATA = 0x12;
+const static boost::uint8_t B2XX_VREQ_SET_FPGA_HASH = 0x1C;
+const static boost::uint8_t B2XX_VREQ_GET_FPGA_HASH = 0x1D;
+const static boost::uint8_t B2XX_VREQ_FPGA_RESET = 0x62;
+const static boost::uint8_t B2XX_VREQ_GET_USB = 0x80;
+const static boost::uint8_t B2XX_VREQ_GET_STATUS = 0x83;
+const static boost::uint8_t B2XX_VREQ_FX3_RESET = 0x99;
+const static boost::uint8_t B2XX_VREQ_EEPROM_WRITE = 0xBA;
+
+const static boost::uint8_t FX3_STATE_FPGA_READY = 0x00;
+const static boost::uint8_t FX3_STATE_CONFIGURING_FPGA = 0x01;
+const static boost::uint8_t FX3_STATE_BUSY = 0x02;
+const static boost::uint8_t FX3_STATE_RUNNING = 0x03;
+
+typedef boost::uint32_t hash_type;
+typedef std::vector<boost::uint8_t> byte_vector_t;
+
+
+namespace po = boost::program_options;
+namespace fs = boost::filesystem;
+
+
+//!used with lexical cast to parse a hex string
+template <class T> struct to_hex{
+ T value;
+ operator T() const {return value;}
+ friend std::istream& operator>>(std::istream& in, to_hex& out){
+ in >> std::hex >> out.value;
+ return in;
+ }
+};
+
+//!parse hex-formatted ASCII text into an int
+boost::uint16_t atoh(const std::string &string){
+ if (string.substr(0, 2) == "0x"){
+ return boost::lexical_cast<to_hex<boost::uint16_t> >(string);
+ }
+ return boost::lexical_cast<boost::uint16_t>(string);
+}
+
+
+/*!
+ * Create a file hash
+ * The hash will be used to identify the loaded firmware and fpga image
+ * \param filename file used to generate hash value
+ * \return hash value in a size_t type
+ */
+static hash_type generate_hash(const char *filename)
+{
+ std::ifstream file(filename);
+ if (not file){
+ std::cerr << std::string("cannot open input file ") + filename
+ << std::endl;
+ }
+
+ size_t hash = 0;
+
+ char ch;
+ while (file.get(ch)) {
+ boost::hash_combine(hash, ch);
+ }
+
+ if (not file.eof()){
+ std::cerr << std::string("file error ") + filename << std::endl;
+ }
+
+ file.close();
+ return hash_type(hash);
+}
+
+/*!
+ * Verify checksum of a Intel HEX record
+ * \param record a line from an Intel HEX file
+ * \return true if record is valid, false otherwise
+ */
+bool checksum(std::string *record) {
+
+ size_t len = record->length();
+ unsigned int i;
+ unsigned char sum = 0;
+ unsigned int val;
+
+ for (i = 1; i < len; i += 2) {
+ std::istringstream(record->substr(i, 2)) >> std::hex >> val;
+ sum += val;
+ }
+
+ if (sum == 0)
+ return true;
+ else
+ return false;
+}
+
+
+/*!
+ * Parse Intel HEX record
+ *
+ * \param record a line from an Intel HEX file
+ * \param len output length of record
+ * \param addr output address
+ * \param type output type
+ * \param data output data
+ * \return true if record is sucessfully read, false on error
+ */
+bool parse_record(std::string *record, boost::uint16_t &len, boost::uint16_t &addr,
+ uint16_t &type, unsigned char* data) {
+
+ unsigned int i;
+ std::string _data;
+ unsigned int val;
+
+ if (record->substr(0, 1) != ":")
+ return false;
+
+ std::istringstream(record->substr(1, 2)) >> std::hex >> len;
+ std::istringstream(record->substr(3, 4)) >> std::hex >> addr;
+ std::istringstream(record->substr(7, 2)) >> std::hex >> type;
+
+ for (i = 0; i < len; i++) {
+ std::istringstream(record->substr(9 + 2 * i, 2)) >> std::hex >> val;
+ data[i] = (unsigned char) val;
+ }
+
+ return true;
+}
+
+
+/*!
+ * Write data to the FX3.
+ *
+ * \param dev_handle the libusb-1.0 device handle
+ * \param request the usb transfer request type
+ * \param value the USB bValue
+ * \param index the USB bIndex
+ * \param buff the data to write
+ * \param length the number of bytes to write
+ * \return the number of bytes written
+ */
+libusb_error fx3_control_write(libusb_device_handle *dev_handle, boost::uint8_t request,
+ boost::uint16_t value, boost::uint16_t index, unsigned char *buff,
+ boost::uint16_t length, boost::uint32_t timeout = 0) {
+
+#if 0
+ if(DEBUG) {
+ std::cout << "Writing: <" << std::hex << std::setw(6) << std::showbase \
+ << std::internal << std::setfill('0') << (int) request \
+ << ", " << std::setw(6) << (int) VRT_VENDOR_OUT \
+ << ", " << std::setw(6) << value \
+ << ", " << std::setw(6) << index \
+ << ", " << std::dec << std::setw(2) << length \
+ << ">" << std::endl;
+
+ std::cout << "\t\tData: 0x " << std::noshowbase;
+
+ for(int count = 0; count < length; count++) {
+ std::cout << std::hex << std::setw(2) << (int) buff[count] << " ";
+ }
+
+ std::cout << std::showbase << std::endl;
+ }
+#endif
+
+ return (libusb_error) libusb_control_transfer(dev_handle, VRT_VENDOR_OUT, request, \
+ value, index, buff, length, timeout);
+}
+
+
+/*!
+ * Read data from the FX3.
+ *
+ * \param dev_handle the libusb-1.0 device handle
+ * \param request the usb transfer request type
+ * \param value the USB bValue
+ * \param index the USB bIndex
+ * \param buff a buffer to store the read bytes to
+ * \param length the number of bytes to read
+ * \return the number of bytes read
+ */
+libusb_error fx3_control_read(libusb_device_handle *dev_handle, boost::uint8_t request,
+ boost::uint16_t value, boost::uint16_t index, unsigned char *buff,
+ boost::uint16_t length, boost::uint32_t timeout = 0) {
+
+#if 0
+ if(DEBUG) {
+ std::cout << "Reading: <" << std::hex << std::setw(6) << std::showbase \
+ << std::internal << std::setfill('0') << (int) request \
+ << ", " << std::setw(6) << (int) VRT_VENDOR_IN \
+ << ", " << std::setw(6) << value \
+ << ", " << std::setw(6) << index \
+ << ", " << std::dec << std::setw(2) << length \
+ << ">" << std::endl << std::endl;
+ }
+#endif
+
+ return (libusb_error) libusb_control_transfer(dev_handle, VRT_VENDOR_IN, request, \
+ value, index, buff, length, timeout);
+}
+
+
+void write_eeprom(libusb_device_handle *dev_handle, boost::uint8_t addr,
+ boost::uint8_t offset, const byte_vector_t &bytes) {
+ fx3_control_write(dev_handle, B2XX_VREQ_EEPROM_WRITE,
+ 0, offset | (boost::uint16_t(addr) << 8),
+ (unsigned char *) &bytes[0],
+ bytes.size());
+}
+
+
+boost::uint8_t get_fx3_status(libusb_device_handle *dev_handle) {
+
+ unsigned char rx_data[1];
+
+ fx3_control_read(dev_handle, B2XX_VREQ_GET_STATUS, 0x00, 0x00, rx_data, 1);
+
+ return boost::lexical_cast<boost::uint8_t>(rx_data[0]);
+}
+
+void usrp_get_fpga_hash(libusb_device_handle *dev_handle, hash_type &hash) {
+ fx3_control_read(dev_handle, B2XX_VREQ_GET_FPGA_HASH, 0x00, 0x00,
+ (unsigned char*) &hash, 4, 500);
+}
+
+void usrp_set_fpga_hash(libusb_device_handle *dev_handle, hash_type hash) {
+ fx3_control_write(dev_handle, B2XX_VREQ_SET_FPGA_HASH, 0x00, 0x00,
+ (unsigned char*) &hash, 4);
+}
+
+boost::int32_t load_fpga(libusb_device_handle *dev_handle,
+ const std::string filestring) {
+
+ if (filestring.empty())
+ {
+ std::cerr << "load_fpga: input file is empty." << std::endl;
+ exit(-1);
+ }
+
+ boost::uint8_t fx3_state = 0;
+
+ const char *filename = filestring.c_str();
+
+ hash_type hash = generate_hash(filename);
+ hash_type loaded_hash; usrp_get_fpga_hash(dev_handle, loaded_hash);
+ if (hash == loaded_hash) return 0;
+
+ size_t file_size = 0;
+ {
+ std::ifstream file(filename, std::ios::in | std::ios::binary | std::ios::ate);
+ file_size = file.tellg();
+ }
+
+ std::ifstream file;
+ file.open(filename, std::ios::in | std::ios::binary);
+
+ if(!file.good()) {
+ std::cerr << "load_fpga: cannot open FPGA input file." << std::endl;
+ exit(-1);
+ }
+
+ do {
+ fx3_state = get_fx3_status(dev_handle);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+ } while(fx3_state != FX3_STATE_FPGA_READY);
+
+ std::cout << "Loading FPGA image: " \
+ << filestring << "..." << std::flush;
+
+ unsigned char out_buff[64];
+ memset(out_buff, 0x00, sizeof(out_buff));
+ fx3_control_write(dev_handle, B2XX_VREQ_FPGA_START, 0, 0, out_buff, 1, 1000);
+
+ do {
+ fx3_state = get_fx3_status(dev_handle);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+ } while(fx3_state != FX3_STATE_CONFIGURING_FPGA);
+
+
+ size_t bytes_sent = 0;
+ while(!file.eof()) {
+ file.read((char *) out_buff, sizeof(out_buff));
+ const std::streamsize n = file.gcount();
+ if(n == 0) continue;
+
+ boost::uint16_t transfer_count = boost::uint16_t(n);
+
+ /* Send the data to the device. */
+ fx3_control_write(dev_handle, B2XX_VREQ_FPGA_DATA, 0, 0, out_buff,
+ transfer_count, 5000);
+
+ if (bytes_sent == 0) std::cout << " 0%" << std::flush;
+ const size_t percent_before = size_t((bytes_sent*100)/file_size);
+ bytes_sent += transfer_count;
+ const size_t percent_after = size_t((bytes_sent*100)/file_size);
+ if (percent_before/10 != percent_after/10) {
+ std::cout << "\b\b\b\b" << std::setw(3) << percent_after
+ << "%" << std::flush;
+ }
+ }
+
+ file.close();
+
+ do {
+ fx3_state = get_fx3_status(dev_handle);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+ } while(fx3_state != FX3_STATE_RUNNING);
+
+ usrp_set_fpga_hash(dev_handle, hash);
+
+ std::cout << "\b\b\b\b done" << std::endl;
+
+ return 0;
+}
+
+
+/*!
+ * Program the FX3 with a firmware file (Intel HEX format)
+ *
+ * \param dev_handle the libusb-1.0 device handle
+ * \param filestring the filename of the firmware file
+ * \return 0 for success, otherwise error code
+ */
+boost::int32_t fx3_load_firmware(libusb_device_handle *dev_handle, \
+ std::string filestring) {
+
+ if (filestring.empty())
+ {
+ std::cerr << "fx3_load_firmware: input file is empty." << std::endl;
+ exit(-1);
+ }
+
+ const char *filename = filestring.c_str();
+
+ /* Fields used in each USB control transfer. */
+ boost::uint16_t len = 0;
+ boost::uint16_t type = 0;
+ boost::uint16_t lower_address_bits = 0x0000;
+ unsigned char data[512];
+
+ /* Can be set by the Intel HEX record 0x04, used for all 0x00 records
+ * thereafter. Note this field takes the place of the 'index' parameter in
+ * libusb calls, and is necessary for FX3's 32-bit addressing. */
+ boost::uint16_t upper_address_bits = 0x0000;
+
+ std::ifstream file;
+ file.open(filename, std::ifstream::in);
+
+ if(!file.good()) {
+ std::cerr << "fx3_load_firmware: cannot open firmware input file"
+ << std::endl;
+ exit(-1);
+ }
+
+ std::cout << "Loading firmware image: " \
+ << filestring << "..." << std::flush;
+
+ while (!file.eof()) {
+ boost::int32_t ret = 0;
+ std::string record;
+ file >> record;
+
+ /* Check for valid Intel HEX record. */
+ if (!checksum(&record) || !parse_record(&record, len, \
+ lower_address_bits, type, data)) {
+ std::cerr << "fx3_load_firmware: bad intel hex record checksum"
+ << std::endl;
+ }
+
+ /* Type 0x00: Data. */
+ if (type == 0x00) {
+ ret = fx3_control_write(dev_handle, FX3_FIRMWARE_LOAD, \
+ lower_address_bits, upper_address_bits, data, len);
+
+ if (ret < 0) {
+ std::cerr << "usrp_load_firmware: usrp_control_write failed"
+ << std::endl;
+ }
+ }
+
+ /* Type 0x01: EOF. */
+ else if (type == 0x01) {
+ if (lower_address_bits != 0x0000 || len != 0 ) {
+ std::cerr << "fx3_load_firmware: For EOF record, address must be 0, length must be 0." << std::endl;
+ }
+
+ /* Successful termination! */
+ file.close();
+
+ /* Let the system settle. */
+ boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
+ return 0;
+ }
+
+ /* Type 0x04: Extended Linear Address Record. */
+ else if (type == 0x04) {
+ if (lower_address_bits != 0x0000 || len != 2 ) {
+ std::cerr << "fx3_load_firmware: For ELA record, address must be 0, length must be 2." << std::endl;
+ }
+
+ upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\
+ + ((boost::uint16_t)(data[1] & 0x00FF));
+ }
+
+ /* Type 0x05: Start Linear Address Record. */
+ else if (type == 0x05) {
+ if (lower_address_bits != 0x0000 || len != 4 ) {
+ std::cerr << "fx3_load_firmware: For SLA record, address must be 0, length must be 4." << std::endl;
+ }
+
+ /* The firmware load is complete. We now need to tell the CPU
+ * to jump to an execution address start point, now contained within
+ * the data field. Parse these address bits out, and then push the
+ * instruction. */
+ upper_address_bits = ((boost::uint16_t)((data[0] & 0x00FF) << 8))\
+ + ((boost::uint16_t)(data[1] & 0x00FF));
+ lower_address_bits = ((boost::uint16_t)((data[2] & 0x00FF) << 8))\
+ + ((boost::uint16_t)(data[3] & 0x00FF));
+
+ fx3_control_write(dev_handle, FX3_FIRMWARE_LOAD, lower_address_bits, \
+ upper_address_bits, 0, 0);
+
+ std::cout << " done" << std::endl;
+ }
+
+ /* If we receive an unknown record type, error out. */
+ else {
+ std::cerr << "fx3_load_firmware: unsupported record type." << std::endl;
+ }
+ }
+
+ /* There was no valid EOF. */
+ std::cerr << "fx3_load_firmware: No EOF record found." << std::cout;
+ return ~0;
+}
+
+
+boost::int32_t main(boost::int32_t argc, char *argv[]) {
+ boost::uint16_t vid, pid;
+ std::string pid_str, vid_str, fw_file, fpga_file;
+
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help,h", "help message")
+ ("vid,v", po::value<std::string>(&vid_str)->default_value("0x2500"),
+ "Specify VID of device to use.")
+ ("pid,p", po::value<std::string>(&pid_str)->default_value("0x0020"),
+ "Specify PID of device to use.")
+ ("speed,S", "Read back the USB mode currently in use.")
+ ("reset-device,D", "Reset the B2xx Device.")
+ ("reset-fpga,F", "Reset the FPGA (does not require re-programming.")
+ ("reset-usb,U", "Reset the USB subsystem on your host computer.")
+ ("init-device,I", "Initialize a B2xx device.")
+ ("load-fw,W", po::value<std::string>(&fw_file)->default_value(""),
+ "Load a firmware (hex) file into the FX3.")
+ ("load-fpga,L", po::value<std::string>(&fpga_file)->default_value(""),
+ "Load a FPGA (bin) file into the FPGA.")
+ ;
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help")){
+ std::cout << boost::format("B2xx Utilitiy Program %s") % desc << std::endl;
+ return ~0;
+ } else if (vm.count("reset-usb")) {
+ /* Okay, first, we need to discover what the path is to the ehci and
+ * xhci device files. */
+ std::set<fs::path> path_list;
+ path_list.insert("/sys/bus/pci/drivers/xhci-pci/");
+ path_list.insert("/sys/bus/pci/drivers/ehci-pci/");
+ path_list.insert("/sys/bus/pci/drivers/xhci_hcd/");
+ path_list.insert("/sys/bus/pci/drivers/ehci_hcd/");
+
+ /* Check each of the possible paths above to find which ones this system
+ * uses. */
+ for(std::set<fs::path>::iterator found = path_list.begin();
+ found != path_list.end(); ++found) {
+
+ if(fs::exists(*found)) {
+
+ fs::path devpath = *found;
+
+ std::set<fs::path> globbed;
+
+ /* Now, glob all of the files in the directory. */
+ fs::directory_iterator end_itr;
+ for(fs::directory_iterator itr(devpath); itr != end_itr; ++itr) {
+ globbed.insert((*itr).path());
+ }
+
+ /* Check each file path string to see if it is a device file. */
+ for(std::set<fs::path>::iterator it = globbed.begin();
+ it != globbed.end(); ++it) {
+
+ std::string file = (*it).string();
+
+ if(file.compare(0, 5, "0000:") == 0) {
+ /* Un-bind the device. */
+ std::fstream unbind((devpath.string() + "unbind").c_str(),
+ std::fstream::out);
+ unbind << file;
+ unbind.close();
+
+ /* Re-bind the device. */
+ std::cout << "Re-binding: " << file << " in "
+ << devpath.string() << std::endl;
+ std::fstream bind((devpath.string() + "bind").c_str(),
+ std::fstream::out);
+ bind << file;
+ bind.close();
+ }
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ vid = atoh(vid_str);
+ pid = atoh(pid_str);
+
+ /* Pointer to pointer of device, used to retrieve a list of devices. */
+ libusb_device **devs;
+ libusb_device_handle *dev_handle;
+ libusb_context *ctx = NULL;
+ libusb_error error_code;
+
+ libusb_init(&ctx);
+ libusb_set_debug(ctx, 3);
+ libusb_get_device_list(ctx, &devs);
+
+ /* If we are initializing the device, the VID/PID will default to the
+ * Cypress VID/PID for the initial FW load. */
+ if (vm.count("init-device")) {
+ dev_handle = libusb_open_device_with_vid_pid(ctx, FX3_VID,
+ FX3_DEFAULT_PID);
+ if(dev_handle == NULL) {
+ std::cerr << "Cannot open device with vid: " << vid << " and pid: "
+ << pid << std::endl;
+ return -1;
+ } else { std::cout << "Uninitialized B2xx detected..." << std::flush; }
+ libusb_free_device_list(devs, 1);
+
+ /* Find out if kernel driver is attached, and if so, detach it. */
+ if(libusb_kernel_driver_active(dev_handle, 0) == 1) {
+ std::cout << " Competing Driver Identified... " << std::flush;
+
+ if(libusb_detach_kernel_driver(dev_handle, 0) == 0) {
+ std::cout << " Competing Driver Destroyed!" << std::flush;
+ }
+ }
+ libusb_claim_interface(dev_handle, 0);
+ std::cout << " Control of B2xx granted..." << std::endl << std::endl;
+
+ /* Load the FW. */
+ error_code = (libusb_error) fx3_load_firmware(dev_handle, fw_file);
+ if(error_code != 0) {
+ std::cerr << std::flush << "Error loading firmware. Error code: "
+ << error_code << std::endl;
+ libusb_release_interface(dev_handle, 0);
+ libusb_close(dev_handle);
+ libusb_exit(ctx);
+ return ~0;
+ }
+
+ /* Let the device re-enumerate. */
+ libusb_release_interface(dev_handle, 0);
+ libusb_close(dev_handle);
+ dev_handle = libusb_open_device_with_vid_pid(ctx, FX3_VID,
+ FX3_REENUM_PID);
+ if(dev_handle == NULL) {
+ std::cerr << "Cannot open device with vid: " << vid << " and pid: "
+ << pid << std::endl;
+ return -1;
+ } else {
+ std::cout << "Detected in-progress init of B2xx..." << std::flush;
+ }
+ //libusb_free_device_list(devs, 1);
+ libusb_claim_interface(dev_handle, 0);
+ std::cout << " Reenumeration complete, Device claimed..."
+ << std::endl;
+
+ /* Now, initialize the device. */
+ byte_vector_t bytes(8);
+ bytes[0] = 0x43;
+ bytes[1] = 0x59;
+ bytes[2] = 0x14;
+ bytes[3] = 0xB2;
+ bytes[4] = (B2XX_PID & 0xff);
+ bytes[5] = (B2XX_PID >> 8);
+ bytes[6] = (B2XX_VID & 0xff);
+ bytes[7] = (B2XX_VID >> 8);
+ write_eeprom(dev_handle, 0x0, 0x0, bytes);
+ std::cout << "EEPROM initialized, resetting device..."
+ << std::endl << std::endl;
+
+ /* Reset the device! */
+ boost::uint8_t data_buffer[1];
+ fx3_control_write(dev_handle, B2XX_VREQ_FX3_RESET,
+ 0x00, 0x00, data_buffer, 1, 5000);
+
+ std::cout << "Initialization Process Complete."
+ << std::endl << std::endl;
+ libusb_release_interface(dev_handle, 0);
+ libusb_close(dev_handle);
+ libusb_exit(ctx);
+ return 0;
+ }
+
+ dev_handle = libusb_open_device_with_vid_pid(ctx, vid, pid);
+ if(dev_handle == NULL) {
+ std::cerr << "Cannot open device with vid: " << vid << " and pid: "
+ << pid << std::endl;
+ return -1;
+ } else { std::cout << "Reactor Core Online..." << std::flush; }
+ libusb_free_device_list(devs, 1);
+
+ /* Find out if kernel driver is attached, and if so, detach it. */
+ if(libusb_kernel_driver_active(dev_handle, 0) == 1) {
+ std::cout << " Competing Driver Identified... " << std::flush;
+
+ if(libusb_detach_kernel_driver(dev_handle, 0) == 0) {
+ std::cout << " Competing Driver Destroyed!" << std::flush;
+ }
+ }
+
+ /* Claim interface 0 of device. */
+ error_code = (libusb_error) libusb_claim_interface(dev_handle, 0);
+ std::cout << " All Systems Nominal..." << std::endl << std::endl;
+
+ boost::uint8_t data_buffer[16];
+ memset(data_buffer, 0x0, sizeof(data_buffer));
+
+ if (vm.count("speed")){
+ error_code = fx3_control_read(dev_handle, B2XX_VREQ_GET_USB,
+ 0x00, 0x00, data_buffer, 1, 5000);
+
+ boost::uint8_t speed = boost::lexical_cast<boost::uint8_t>(data_buffer[0]);
+
+ std::cout << "Currently operating at USB " << (int) speed << std::endl;
+
+ } else if (vm.count("reset-device")) {
+ error_code = fx3_control_write(dev_handle, B2XX_VREQ_FX3_RESET,
+ 0x00, 0x00, data_buffer, 1, 5000);
+
+ } else if (vm.count("reset-fpga")) {
+ error_code = fx3_control_write(dev_handle, B2XX_VREQ_FPGA_RESET,
+ 0x00, 0x00, data_buffer, 1, 5000);
+
+ } else if (vm.count("load-fw")) {
+ error_code = (libusb_error) fx3_load_firmware(dev_handle, fw_file);
+
+ if(error_code != 0) {
+ std::cerr << std::flush << "Error loading firmware. Error code: "
+ << error_code << std::endl;
+ libusb_release_interface(dev_handle, 0);
+ libusb_close(dev_handle);
+ libusb_exit(ctx);
+ return ~0;
+ }
+
+ std::cout << "Firmware load complete, releasing USB interface..."
+ << std::endl;
+
+ } else if (vm.count("load-fpga")) {
+ error_code = (libusb_error) load_fpga(dev_handle, fpga_file);
+
+ if(error_code != 0) {
+ std::cerr << std::flush << "Error loading FPGA. Error code: "
+ << error_code << std::endl;
+ libusb_release_interface(dev_handle, 0);
+ libusb_close(dev_handle);
+ libusb_exit(ctx);
+ return ~0;
+ }
+
+ std::cout << "FPGA load complete, releasing USB interface..."
+ << std::endl;
+
+ } else {
+ std::cout << boost::format("B2xx Utilitiy Program %s") % desc << std::endl;
+ libusb_release_interface(dev_handle, 0);
+ libusb_close(dev_handle);
+ libusb_exit(ctx);
+ return ~0;
+ }
+
+ std::cout << std::endl << "Reactor Shutting Down..." << std::endl;
+
+ error_code = (libusb_error) libusb_release_interface(dev_handle, 0);
+ libusb_close(dev_handle);
+ libusb_exit(ctx);
+
+ return 0;
+}
+
diff --git a/host/utils/fx2_init_eeprom.cpp b/host/utils/fx2_init_eeprom.cpp
index c210ae575..701092a5d 100644
--- a/host/utils/fx2_init_eeprom.cpp
+++ b/host/utils/fx2_init_eeprom.cpp
@@ -41,12 +41,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
+ po::notify(vm);
//print the help message
if (vm.count("help")){
std::cout << boost::format("USRP EEPROM initialization %s") % desc << std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
//cant find a uninitialized usrp with this mystery module in the way...
@@ -76,7 +76,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (found_addrs.size() == 0){
std::cerr << "No USRP devices found" << std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
for (size_t i = 0; i < found_addrs.size(); i++){
@@ -89,5 +89,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << "Power-cycle the usrp for the changes to take effect." << std::endl;
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/host/utils/query_gpsdo_sensors.cpp b/host/utils/query_gpsdo_sensors.cpp
index 8e34bb3d5..91088112c 100644
--- a/host/utils/query_gpsdo_sensors.cpp
+++ b/host/utils/query_gpsdo_sensors.cpp
@@ -27,6 +27,7 @@
#include <boost/thread.hpp>
#include <string>
#include <cmath>
+#include <ctime>
#include <cstdlib>
namespace po = boost::program_options;
@@ -102,6 +103,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//Check PPS and compare UHD device time to GPS time
boost::this_thread::sleep(boost::posix_time::seconds(1));
uhd::sensor_value_t gps_time = usrp->get_mboard_sensor("gps_time");
+ const time_t pc_clock_time = time(NULL);
const uhd::time_spec_t last_pps_time = usrp->get_time_last_pps();
if (last_pps_time.to_ticks(1.0) == gps_time.to_int()) {
std::cout << boost::format("GPS and UHD Device time are aligned.\n");
@@ -114,6 +116,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::sensor_value_t rmc_string = usrp->get_mboard_sensor("gps_gprmc");
std::cout << boost::format("%s\n%s\n%s\n") % gga_string.to_pp_string() % rmc_string.to_pp_string() % gps_time.to_pp_string();
std::cout << boost::format("UHD Device time: %.0f seconds\n") % (last_pps_time.get_real_secs());
+ std::cout << boost::format("PC Clock time: %.0f seconds\n") % pc_clock_time;
//finished
std::cout << boost::format("\nDone!\n\n");
diff --git a/host/utils/uhd-usrp.rules b/host/utils/uhd-usrp.rules
index 56d9a8c43..2f5198d64 100644
--- a/host/utils/uhd-usrp.rules
+++ b/host/utils/uhd-usrp.rules
@@ -15,5 +15,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+#USRP1
SUBSYSTEMS=="usb", ATTRS{idVendor}=="fffe", ATTRS{idProduct}=="0002", MODE:="0666"
+
+#B100
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0002", MODE:="0666"
+
+#B200
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0020", MODE:="0666"
diff --git a/host/utils/uhd_cal_rx_iq_balance.cpp b/host/utils/uhd_cal_rx_iq_balance.cpp
index 68d0443da..5fb494114 100644
--- a/host/utils/uhd_cal_rx_iq_balance.cpp
+++ b/host/utils/uhd_cal_rx_iq_balance.cpp
@@ -29,6 +29,7 @@
#include <complex>
#include <cmath>
#include <ctime>
+#include <cstdlib>
namespace po = boost::program_options;
@@ -120,7 +121,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout <<
"This application measures leakage between RX and TX on an XCVR daughterboard to self-calibrate.\n"
<< std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
//create a usrp device
@@ -239,5 +240,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
store_results(usrp, results, "RX", "rx", "iq");
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/host/utils/uhd_cal_tx_dc_offset.cpp b/host/utils/uhd_cal_tx_dc_offset.cpp
index 8f69b3ce1..c9cf757f4 100644
--- a/host/utils/uhd_cal_tx_dc_offset.cpp
+++ b/host/utils/uhd_cal_tx_dc_offset.cpp
@@ -123,7 +123,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout <<
"This application measures leakage between RX and TX on an XCVR daughterboard to self-calibrate.\n"
<< std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
//create a usrp device
@@ -237,5 +237,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
store_results(usrp, results, "TX", "tx", "dc");
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/host/utils/uhd_cal_tx_iq_balance.cpp b/host/utils/uhd_cal_tx_iq_balance.cpp
index 5478b07e3..20d018edf 100644
--- a/host/utils/uhd_cal_tx_iq_balance.cpp
+++ b/host/utils/uhd_cal_tx_iq_balance.cpp
@@ -28,6 +28,7 @@
#include <iostream>
#include <complex>
#include <ctime>
+#include <cstdlib>
namespace po = boost::program_options;
@@ -123,7 +124,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout <<
"This application measures leakage between RX and TX on an XCVR daughterboard to self-calibrate.\n"
<< std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
//create a usrp device
@@ -242,5 +243,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
store_results(usrp, results, "TX", "tx", "iq");
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/host/utils/uhd_find_devices.cpp b/host/utils/uhd_find_devices.cpp
index b778eeb68..c258c580e 100644
--- a/host/utils/uhd_find_devices.cpp
+++ b/host/utils/uhd_find_devices.cpp
@@ -20,6 +20,7 @@
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <iostream>
+#include <cstdlib>
namespace po = boost::program_options;
@@ -37,7 +38,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//print the help message
if (vm.count("help")){
std::cout << boost::format("UHD Find Devices %s") % desc << std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
//discover the usrps and print the results
@@ -45,7 +46,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (device_addrs.size() == 0){
std::cerr << "No UHD Devices Found" << std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
for (size_t i = 0; i < device_addrs.size(); i++){
@@ -56,5 +57,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//uhd::device::make(device_addrs[i]); //test make
}
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp
index 5b3702fb4..98ed84850 100644
--- a/host/utils/uhd_usrp_probe.cpp
+++ b/host/utils/uhd_usrp_probe.cpp
@@ -30,6 +30,7 @@
#include <iostream>
#include <sstream>
#include <vector>
+#include <cstdlib>
namespace po = boost::program_options;
using namespace uhd;
@@ -114,13 +115,16 @@ static std::string get_dboard_pp_string(const std::string &type, property_tree::
ss << boost::format("%s Dboard: %s") % type % path.leaf() << std::endl;
//ss << std::endl;
const std::string prefix = (type == "RX")? "rx" : "tx";
- usrp::dboard_eeprom_t db_eeprom = tree->access<usrp::dboard_eeprom_t>(path / (prefix + "_eeprom")).get();
- if (db_eeprom.id != usrp::dboard_id_t::none()) ss << boost::format("ID: %s") % db_eeprom.id.to_pp_string() << std::endl;
- if (not db_eeprom.serial.empty()) ss << boost::format("Serial: %s") % db_eeprom.serial << std::endl;
- if (type == "TX"){
- usrp::dboard_eeprom_t gdb_eeprom = tree->access<usrp::dboard_eeprom_t>(path / "gdb_eeprom").get();
- if (gdb_eeprom.id != usrp::dboard_id_t::none()) ss << boost::format("ID: %s") % gdb_eeprom.id.to_pp_string() << std::endl;
- if (not gdb_eeprom.serial.empty()) ss << boost::format("Serial: %s") % gdb_eeprom.serial << std::endl;
+ if (tree->exists(path / (prefix + "_eeprom")))
+ {
+ usrp::dboard_eeprom_t db_eeprom = tree->access<usrp::dboard_eeprom_t>(path / (prefix + "_eeprom")).get();
+ if (db_eeprom.id != usrp::dboard_id_t::none()) ss << boost::format("ID: %s") % db_eeprom.id.to_pp_string() << std::endl;
+ if (not db_eeprom.serial.empty()) ss << boost::format("Serial: %s") % db_eeprom.serial << std::endl;
+ if (type == "TX"){
+ usrp::dboard_eeprom_t gdb_eeprom = tree->access<usrp::dboard_eeprom_t>(path / "gdb_eeprom").get();
+ if (gdb_eeprom.id != usrp::dboard_id_t::none()) ss << boost::format("ID: %s") % gdb_eeprom.id.to_pp_string() << std::endl;
+ if (not gdb_eeprom.serial.empty()) ss << boost::format("Serial: %s") % gdb_eeprom.serial << std::endl;
+ }
}
BOOST_FOREACH(const std::string &name, tree->list(path / (prefix + "_frontends"))){
ss << make_border(get_frontend_pp_string(type, tree, path / (prefix + "_frontends") / name));
@@ -197,12 +201,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//print the help message
if (vm.count("help")){
std::cout << boost::format("UHD USRP Probe %s") % desc << std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
if (vm.count("version")){
std::cout << uhd::get_version_string() << std::endl;
- return 0;
+ return EXIT_SUCCESS;
}
device::sptr dev = device::make(vm["args"].as<std::string>());
@@ -210,11 +214,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (vm.count("string")){
std::cout << tree->access<std::string>(vm["string"].as<std::string>()).get() << std::endl;
- return 0;
+ return EXIT_SUCCESS;
}
if (vm.count("tree") != 0) print_tree("/", tree);
else std::cout << make_border(get_device_pp_string(tree)) << std::endl;
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/host/utils/usrp_burn_db_eeprom.cpp b/host/utils/usrp_burn_db_eeprom.cpp
index b6b2dc4d6..3ca953115 100644
--- a/host/utils/usrp_burn_db_eeprom.cpp
+++ b/host/utils/usrp_burn_db_eeprom.cpp
@@ -58,7 +58,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
"Omit the ID argument to perform readback,\n"
"Or specify a new ID to burn into the EEPROM.\n"
) << std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
//make the device and extract the dboard w/ property
@@ -96,5 +96,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << boost::format(" Current revision: \"%s\"") % db_eeprom.revision << std::endl;
std::cout << " Done" << std::endl << std::endl;
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/host/utils/usrp_burn_mb_eeprom.cpp b/host/utils/usrp_burn_mb_eeprom.cpp
index ca9a6c8ba..1b13fb615 100644
--- a/host/utils/usrp_burn_mb_eeprom.cpp
+++ b/host/utils/usrp_burn_mb_eeprom.cpp
@@ -47,7 +47,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
"Omit the value argument to perform a readback,\n"
"Or specify a new value to burn into the EEPROM.\n"
) << std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
std::cout << "Creating USRP device from address: " + args << std::endl;
@@ -60,7 +60,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::usrp::mboard_eeprom_t mb_eeprom = tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").get();
if (not mb_eeprom.has_key(key)){
std::cerr << boost::format("Cannot find value for EEPROM[%s]") % key << std::endl;
- return ~0;
+ return EXIT_FAILURE;
}
std::cout << boost::format(" EEPROM [\"%s\"] is \"%s\"") % key % mb_eeprom[key] << std::endl;
std::cout << std::endl;
@@ -74,5 +74,5 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
}
std::cout << "Done" << std::endl;
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/host/utils/usrp_cal_utils.hpp b/host/utils/usrp_cal_utils.hpp
index bda6fc31b..bab6ddd91 100644
--- a/host/utils/usrp_cal_utils.hpp
+++ b/host/utils/usrp_cal_utils.hpp
@@ -77,6 +77,9 @@ static inline void set_optimum_defaults(uhd::usrp::multi_usrp::sptr usrp){
else if (tx_name.find("SBX") != std::string::npos){
usrp->set_tx_gain(0);
}
+ else if (tx_name.find("CBX") != std::string::npos){
+ usrp->set_tx_gain(0);
+ }
else if (tx_name.find("RFX") != std::string::npos){
usrp->set_tx_gain(0);
}
@@ -92,6 +95,9 @@ static inline void set_optimum_defaults(uhd::usrp::multi_usrp::sptr usrp){
else if (rx_name.find("SBX") != std::string::npos){
usrp->set_rx_gain(25);
}
+ else if (rx_name.find("CBX") != std::string::npos){
+ usrp->set_rx_gain(25);
+ }
else if (rx_name.find("RFX") != std::string::npos){
usrp->set_rx_gain(25);
}