summaryrefslogtreecommitdiffstats
path: root/host/utils
diff options
context:
space:
mode:
Diffstat (limited to 'host/utils')
-rw-r--r--host/utils/CMakeLists.txt4
-rw-r--r--host/utils/b2xx_fx3_utils.cpp908
-rw-r--r--host/utils/uhd_images_downloader.py.in63
-rw-r--r--host/utils/usrp_burn_mb_eeprom.cpp43
4 files changed, 388 insertions, 630 deletions
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index 92df0b7cf..f73690475 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -47,9 +47,11 @@ SET(util_share_sources
IF(ENABLE_USB)
LIST(APPEND util_share_sources
fx2_init_eeprom.cpp
- b2xx_fx3_utils.cpp
+ b2xx_fx3_utils
)
INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS})
+ # Additional include directories for b2xx_fx3_utils
+ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../lib/usrp/b200 ${CMAKE_CURRENT_SOURCE_DIR}/../lib/usrp/common)
ENDIF(ENABLE_USB)
IF(LINUX AND ENABLE_USB)
diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp
index 3664ecbbf..50a294359 100644
--- a/host/utils/b2xx_fx3_utils.cpp
+++ b/host/utils/b2xx_fx3_utils.cpp
@@ -34,39 +34,12 @@
#include <boost/thread/thread.hpp>
#include <boost/functional/hash.hpp>
+#include <b200_iface.hpp>
#include <uhd/config.hpp>
-#include <uhd/utils/msg.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;
-
+#include <uhd/transport/usb_control.hpp>
+#include <uhd/transport/usb_device_handle.hpp>
+#include <uhd/exception.hpp>
+#include <uhd/utils/images.hpp>
namespace po = boost::program_options;
namespace fs = boost::filesystem;
@@ -90,663 +63,409 @@ boost::uint16_t atoh(const std::string &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)
+int reset_usb()
{
- 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;
- }
+ /* 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/");
- if (sum == 0)
- return true;
- else
- return false;
-}
+ /* 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)) {
-/*!
- * 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;
-
- if (len >2 * (record->length() - 9)) // sanity check to prevent buffer overrun
- return false;
-
- for (i = 0; i < len; i++) {
- std::istringstream(record->substr(9 + 2 * i, 2)) >> std::hex >> val;
- data[i] = (unsigned char) val;
- }
+ fs::path devpath = *found;
- return true;
-}
+ 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());
+ }
-/*!
- * 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] << " ";
+ /* 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 = fs::path((*it).filename()).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();
+ }
+ }
}
-
- 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);
+ return 0;
}
-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);
+uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, const boost::uint16_t pid)
+{
+ std::vector<uhd::transport::usb_device_handle::sptr> handles;
+ uhd::transport::usb_device_handle::sptr handle;
- if(!file.good()) {
- std::cerr << "load_fpga: cannot open FPGA input file." << std::endl;
- exit(-1);
+ try {
+ handles = uhd::transport::usb_device_handle::get_device_list(vid, pid); // try caller's VID/PID first
+ if (handles.size() == 0)
+ handles = uhd::transport::usb_device_handle::get_device_list(FX3_VID, FX3_DEFAULT_PID); // try default Cypress FX3 VID/PID next
+ if (handles.size() == 0)
+ handles = uhd::transport::usb_device_handle::get_device_list(FX3_VID, FX3_REENUM_PID); // try reenumerated Cypress FX3 VID/PID next
+ if (handles.size() == 0)
+ handles = uhd::transport::usb_device_handle::get_device_list(B200_VENDOR_ID, B200_PRODUCT_ID); // try default B200 VID/PID last
+
+ if (handles.size() > 0)
+ handle = handles[0];
+
+ if (!handle)
+ std::cerr << "Cannot open device" << std::endl;
}
-
- 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;
- }
+ catch(const std::exception &e) {
+ std::cerr << "Failed to communicate with the device!" << std::endl;
+ #ifdef UHD_PLATFORM_WIN32
+ std::cerr << "The necessary drivers are not installed. Read the UHD Transport Application Notes for details." << std::endl;
+ #endif /* UHD_PLATFORM_WIN32 */
+ handle.reset();
}
- 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;
+ return handle;
}
+b200_iface::sptr make_b200_iface(const uhd::transport::usb_device_handle::sptr &handle)
+{
+ b200_iface::sptr b200;
-/*!
- * 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);
+ try {
+ uhd::transport::usb_control::sptr usb_ctrl = uhd::transport::usb_control::make(handle, 0);
+ b200 = b200_iface::make(usb_ctrl);
- if(!file.good()) {
- std::cerr << "fx3_load_firmware: cannot open firmware input file"
- << std::endl;
- exit(-1);
+ if (!b200)
+ std::cerr << "Cannot create device interface" << std::endl;
}
-
- std::cout << "Loading firmware image: " \
- << filestring << "..." << std::flush;
-
- while (!file.eof()) {
- boost::int32_t ret = 0;
- std::string record;
- file >> record;
-
- if (!record.length() > 0)
- continue;
-
- /* 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;
- }
+ catch(const std::exception &e) {
+ std::cerr << "Failed to communicate with the device!" << std::endl;
+ #ifdef UHD_PLATFORM_WIN32
+ std::cerr << "The necessary drivers are not installed. Read the UHD Transport Application Notes for details." << std::endl;
+ #endif /* UHD_PLATFORM_WIN32 */
+ b200.reset();
}
- /* There was no valid EOF. */
- std::cerr << "fx3_load_firmware: No EOF record found." << std::cout;
- return ~0;
+ return b200;
}
-
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()
+ po::options_description visible("Allowed options");
+ visible.add_options()
("help,h", "help message")
- ("vid,v", po::value<std::string>(&vid_str)->default_value("0x2500"),
+ ("vid,v", po::value<std::string>(&vid_str),
"Specify VID of device to use.")
- ("pid,p", po::value<std::string>(&pid_str)->default_value("0x0020"),
+ ("pid,p", po::value<std::string>(&pid_str),
"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-fw,W", po::value<std::string>(&fw_file),
"Load a firmware (hex) file into the FX3.")
- ("load-fpga,L", po::value<std::string>(&fpga_file)->default_value(""),
+ ("load-fpga,L", po::value<std::string>(&fpga_file),
"Load a FPGA (bin) file into the FPGA.")
;
+ // Hidden options provided for testing - use at your own risk!
+ po::options_description hidden("Hidden options");
+ hidden.add_options()
+ ("uninit-device,U", "Uninitialize a B2xx device.")
+ ("read-eeprom,R", "Read first 8 bytes of EEPROM")
+ ("erase-eeprom,E", "Erase first 8 bytes of EEPROM");
+
+ po::options_description desc;
+ desc.add(visible);
+ desc.add(hidden);
+
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;
+ try {
+ std::cout << boost::format("B2xx Utility Program %s") % visible << std::endl;
+ } catch(...) {}
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/");
+ return reset_usb();
+ }
- /* 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) {
+ uhd::transport::usb_device_handle::sptr handle;
+ b200_iface::sptr b200;
- if(fs::exists(*found)) {
+ vid = B200_VENDOR_ID; // Default
+ pid = B200_PRODUCT_ID; // Default
+ try {
+ if (vm.count("vid"))
+ vid = atoh(vid_str);
+ if (vm.count("pid"))
+ pid = atoh(pid_str);
+ } catch (std::exception &e) {
+ std::cerr << "Exception while parsing VID and PID" << e.what() << std:: endl;
+ return ~0;
+ }
- fs::path devpath = *found;
+ // open the device
+ handle = open_device(vid, pid);
+ if (!handle)
+ return -1;
+ std::cout << "B2xx detected..." << std::flush;
- std::set<fs::path> globbed;
+ // make the interface
+ b200 = make_b200_iface(handle);
+ if (!b200)
+ return -1;
+ std::cout << " Control of B2xx granted..." << std::endl << std::endl;
- /* 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());
- }
+ // if we are supposed to load a new firmware image and one already exists, reset the FX3 so we can load the new one
+ if (vm.count("load-fw") && handle->firmware_loaded())
+ {
+ std::cout << "Overwriting existing firmware" << std::endl;
- /* 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 = fs::path((*it).filename()).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();
- }
- }
- }
- }
+ // reset the device
+ b200->reset_fx3();
- return 0;
+ // re-open device
+ b200.reset();
+ handle.reset();
+ boost::this_thread::sleep(boost::posix_time::seconds(2)); // wait 2 seconds for FX3 to reset
+ handle = open_device(vid, pid);
+ if (!handle)
+ return -1;
+ b200 = make_b200_iface(handle);
+ if (!b200)
+ return -1;
}
- try {
- vid = atoh(vid_str);
- } catch (std::exception const& e) {
- std::cerr << std::flush << "Exception while parsing vid: "
- << e.what() << std::endl;
- return ~0;
- }
- try {
- pid = atoh(pid_str);
- } catch (std::exception const& e) {
- std::cerr << std::flush << "Exception while parsing pid: "
- << e.what() << std::endl;
- return ~0;
+ // Check to make sure firmware is loaded
+ if (!(handle->firmware_loaded()))
+ {
+ std::cout << "Loading firmware" << std::endl;
+
+ if (fw_file.empty())
+ fw_file = uhd::find_image_path(B200_FW_FILE_NAME);
+
+ if(fw_file.empty()) {
+ std::cerr << "Firmware image not found!" << std::endl;
+ return -1;
+ }
+
+ if(!(fs::exists(fw_file))) {
+ std::cerr << "Invalid filepath: " << fw_file << std::endl;
+ return -1;
+ }
+
+ // load firmware
+ try {
+ b200->load_firmware(fw_file);
+ } catch (std::exception &e) {
+ std::cerr << "Exception while loading firmware" << e.what() << std::endl;
+ return ~0;
+ }
+
+ // re-open device
+ b200.reset();
+ handle.reset();
+ handle = open_device(vid, pid);
+ if (!handle)
+ return -1;
+ b200 = make_b200_iface(handle);
+ if (!b200)
+ return -1;
}
- /* 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;
+ // Added for testing purposes - not exposed
+ if (vm.count("read-eeprom"))
+ {
+ uhd::byte_vector_t data;
+
+ try {
+ data = b200->read_eeprom(0x0, 0x0, 8);
+ } catch (std::exception &e) {
+ std::cerr << "Exception while reading EEPROM: " << e.what() << std::endl;
return -1;
- } else { std::cout << "Uninitialized B2xx detected..." << std::flush; }
- libusb_free_device_list(devs, 1);
+ }
+ for (int i = 0; i < 8; i++)
+ std::cout << i << ": " << boost::format("0x%X") % (int)data[i] << std::endl;
+
+ return 0;
+ }
- /* 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;
+ // Added for testing purposes - not exposed
+ if (vm.count("erase-eeprom"))
+ {
+ uhd::byte_vector_t bytes(8);
+ memset(&bytes[0], 0xFF, 8);
+ try {
+ b200->write_eeprom(0x0, 0x0, bytes);
+ } catch (uhd::exception &e) {
+ std::cerr << "Exception while writing to EEPROM: " << e.what() << std::endl;
+ return -1;
+ }
- if(libusb_detach_kernel_driver(dev_handle, 0) == 0) {
- std::cout << " Competing Driver Destroyed!" << std::flush;
+ // verify
+ uhd::byte_vector_t read_bytes(8);
+ try {
+ read_bytes = b200->read_eeprom(0x0, 0x0, 8);
+ } catch (uhd::exception &e) {
+ std::cerr << "Exception while reading from EEPROM: " << e.what() << std::endl;
+ return -1;
+ }
+ bool verified = true;
+ for (int i = 0; i < 8; i++) {
+ if (bytes[i] != read_bytes[i]) {
+ verified = false;
+ std::cerr << "Expected: " << bytes[i] << ", Got: " << read_bytes[i] << std::endl;
}
}
- 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;
+ if (!verified) {
+ std::cerr << "Verification failed" << std::endl;
+ return -1;
}
- /* 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;
+ std::cout << "Erase Successful!" << std::endl;
+
+ return 0;
+ }
+
+ // Added for testing purposes - not exposed
+ if (vm.count("uninit-device"))
+ {
+ // uninitialize the device
+ uhd::byte_vector_t bytes(8);
+ memset(&bytes[0], 0xFF, 8);
+
+ try {
+ b200->write_eeprom(0x0, 0x0, bytes);
+ } catch (uhd::exception &e) {
+ std::cerr << "Exception while writing to EEPROM: " << e.what() << 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;
+ std::cout << "EEPROM uninitialized, resetting device..."
+ << std::endl << std::endl;
+
+ // reset the device
+ try {
+ b200->reset_fx3();
+ } catch (uhd::exception &e) {
+ std::cerr << "Exception while resetting FX3: " << e.what() << std::endl;
+ return -1;
+ }
+
+ std::cout << "Uninitialization Process Complete."
+ << std::endl << std::endl;
+
+ return 0;
+ }
+
+ /* If we are initializing the device, the VID/PID should default to the
+ * Cypress VID/PID for the initial FW load, but we can initialize from any state. */
+ if (vm.count("init-device"))
+ {
/* Now, initialize the device. */
- byte_vector_t bytes(8);
+ uhd::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);
+ bytes[4] = (B200_PRODUCT_ID & 0xff);
+ bytes[5] = (B200_PRODUCT_ID >> 8);
+ bytes[6] = (B200_VENDOR_ID & 0xff);
+ bytes[7] = (B200_VENDOR_ID >> 8);
+
+ try {
+ b200->write_eeprom(0x0, 0x0, bytes);
+ } catch (uhd::exception &e) {
+ std::cerr << "Exception while writing to EEPROM: " << e.what() << std::endl;
+ return -1;
+ }
+
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);
+ try {
+ b200->reset_fx3();
+ } catch (const std::exception &e) {
+ std::cerr << "Exceptions while resetting device: " << e.what() << std::endl;
+ return -1;
+ }
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]);
-
+ boost::uint8_t speed;
+ try {speed = b200->get_usb_speed();}
+ catch (uhd::exception &e) {
+ std::cerr << "Exception while getting USB speed: " << e.what() << std::endl;
+ return -1;
+ }
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);
+ try {b200->reset_fx3();}
+ catch (uhd::exception &e) {
+ std::cerr << "Exception while resetting FX3: " << e.what() << std::endl;
+ return -1;
+ }
} 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;
+ try {b200->set_fpga_reset_pin(true);}
+ catch (uhd::exception &e) {
+ std::cerr << "Exception while resetting FPGA: " << e.what() << std::endl;
+ return -1;
}
+ } else if (vm.count("load-fw")) {
std::cout << "Firmware load complete, releasing USB interface..."
<< std::endl;
} else if (vm.count("load-fpga")) {
- try {
- error_code = (libusb_error) load_fpga(dev_handle, fpga_file);
- } catch (std::exception const& e) {
- std::cerr << std::flush << "Exception while loading FPGA: "
- << e.what() << std::endl;
- if (error_code == 0)
- error_code = LIBUSB_ERROR_OTHER;
+ std::cout << "Loading FPGA image (" << fpga_file << ")" << std::endl;
+ uint32_t fx3_state;
+ try {fx3_state = b200->load_fpga(fpga_file);} // returns 0 on success, or FX3 state on error
+ catch (uhd::exception &e) {
+ std::cerr << "Exception while loading FPGA: " << e.what() << std::endl;
+ return ~0;
}
- 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);
+ if (fx3_state != 0) {
+ std::cerr << std::flush << "Error loading FPGA. FX3 state: "
+ << fx3_state << std::endl;
return ~0;
}
@@ -755,19 +474,12 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) {
} else {
try {
- std::cout << boost::format("B2xx Utilitiy Program %s") % desc << std::endl;
- } catch (std::exception const& e) {}
- libusb_release_interface(dev_handle, 0);
- libusb_close(dev_handle);
- libusb_exit(ctx);
+ std::cout << boost::format("B2xx Utility Program %s") % visible << std::endl;
+ } catch(...) {}
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);
+ std::cout << "Operation complete! I did it! I did it!" << std::endl;
return 0;
}
diff --git a/host/utils/uhd_images_downloader.py.in b/host/utils/uhd_images_downloader.py.in
index e7fc9e8a5..bb082190c 100644
--- a/host/utils/uhd_images_downloader.py.in
+++ b/host/utils/uhd_images_downloader.py.in
@@ -44,13 +44,25 @@ class temp_dir():
self.name = tempfile.mkdtemp()
return self.name
def __exit__(self, type, value, traceback):
- os.removedirs(self.name)
+ try:
+ shutil.rmtree(self.name)
+ except OSError,e:
+ #Utility should have already detected this, but this is for safety
+ print str(e)
+ raise Exception("Could not install images! Make sure you have write permissions.")
if __name__ == "__main__":
+ print
+ if os.environ.get("UHD_IMAGES_DIR") != None and os.environ.get("UHD_IMAGES_DIR") != "":
+ default_images_dir = os.environ.get("UHD_IMAGES_DIR")
+ print "UHD_IMAGES_DIR environment variable is set. Default install location: %s" % default_images_dir
+ else:
+ default_images_dir = "@CMAKE_INSTALL_PREFIX@/share/uhd/images"
+
#Command line options
parser = OptionParser()
- parser.add_option("--install-location", type="string", default="", help="Set custom install location for images")
+ parser.add_option("--install-location", type="string", default=default_images_dir, help="Set custom install location for images")
parser.add_option("--buffer-size", type="int", default=8192, help="Set download buffer size, [default=%default]",)
(options, args) = parser.parse_args()
@@ -59,17 +71,27 @@ if __name__ == "__main__":
images_zip_md5sum = "@UHD_IMAGES_MD5SUM@"
filename = images_src.split("/")[-1]
+ #Use this directory with relative paths
+ current_directory = os.getcwd()
+
with temp_dir() as dirname:
os.chdir(dirname)
- #Configuring image destination
- if options.install_location != "":
+ if os.path.isabs(options.install_location):
+ #Custom absolute path given
images_dir = options.install_location
- elif os.environ.get("UHD_IMAGES_DIR") != "" and os.environ.get("UHD_IMAGES_DIR") != None:
- images_dir = os.environ.get("UHD_IMAGES_DIR")
else:
- images_dir = "@CMAKE_INSTALL_PREFIX@/share/uhd/images"
-
+ #Custom relative path given, so construct absolute path
+ images_dir = os.path.abspath(os.path.join(current_directory, options.install_location))
+
+ #Before doing anything, check for write permissions in parent directory
+ parent_directory = os.path.dirname(images_dir)
+ if os.access(parent_directory, os.W_OK):
+ print "Downloading images to: %s" % images_dir
+ else:
+ print "You do not have write permissions at the install location!"
+ sys.exit(1)
+
opener = urllib2.build_opener()
opener.add_headers = [('User-Agent', 'UHD Images Downloader')]
u = opener.open(images_src)
@@ -101,32 +123,37 @@ if __name__ == "__main__":
if images_zip_md5sum != downloaded_zip_md5sum:
print "\nMD5 checksum does not match!"
print "Expected %s, got %s" % (images_zip_md5sum, downloaded_zip_md5sum)
+ print "Images did not install. If problem persists, please contact support@ettus.com."
os.remove(filename)
os.chdir("/".join(images_dir.split("/")[:-1]))
+ sys.exit(1)
else:
+ temp_path = "tempdir"
+
#Extracting contents of zip file
- if os.path.exists("tempdir"):
- shutil.rmtree("tempdir")
- os.mkdir("tempdir")
+ if os.path.exists(temp_path):
+ shutil.rmtree(temp_path)
+ os.mkdir(temp_path)
images_zip = zipfile.ZipFile(filename)
- images_zip.extractall("tempdir")
+ images_zip.extractall(temp_path)
#Removing images currently in images_dir
if os.path.exists(images_dir):
try:
shutil.rmtree(images_dir)
- except:
- sys.stderr.write("\nMake sure you have write permissions in the images directory.\n")
- sys.exit(0)
+ except OSError,e:
+ print str(e)
+ print "Make sure you have write permissions in the images directory."
+ sys.exit(1)
#Copying downloaded images into images_dir
- shutil.copytree("tempdir/%s/share/uhd/images" % filename[:-4],images_dir)
+ shutil.copytree(os.path.join(temp_path, os.path.splitext(filename)[0], 'share', 'uhd', 'images'), images_dir)
#Removing tempdir and zip file
- shutil.rmtree("tempdir")
+ shutil.rmtree(temp_path)
images_zip.close()
os.remove(filename)
os.chdir(images_dir)
- print "\nImages successfully installed to: %s" % images_dir
+ print "\n\nImages successfully installed!"
diff --git a/host/utils/usrp_burn_mb_eeprom.cpp b/host/utils/usrp_burn_mb_eeprom.cpp
index 1b13fb615..ce0879c8e 100644
--- a/host/utils/usrp_burn_mb_eeprom.cpp
+++ b/host/utils/usrp_burn_mb_eeprom.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// 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
@@ -19,9 +19,11 @@
#include <uhd/device.hpp>
#include <uhd/property_tree.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
+#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <iostream>
+#include <vector>
namespace po = boost::program_options;
@@ -32,8 +34,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
- ("key", po::value<std::string>(&key), "the indentifier for a value in EEPROM")
- ("val", po::value<std::string>(&val), "the new value to set, omit for readback")
+ ("key", po::value<std::string>(&key), "identifiers for new values in EEPROM, separate multiple by \",\"")
+ ("val", po::value<std::string>(&val), "the new values to set, omit for readback, separate multiple by \",\"")
;
po::variables_map vm;
@@ -55,20 +57,35 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::property_tree::sptr tree = dev->get_tree();
std::cout << std::endl;
- if (true /*always readback*/){
- std::cout << "Fetching current settings from EEPROM..." << std::endl;
- 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;
+ //remove whitespace, split arguments and values
+ boost::algorithm::erase_all(key, " ");
+ boost::algorithm::erase_all(val, " ");
+
+ std::vector<std::string> keys_vec, vals_vec;
+ boost::split(keys_vec, key, boost::is_any_of("\"',"));
+ boost::split(vals_vec, val, boost::is_any_of("\"',"));
+
+ if((keys_vec.size() != vals_vec.size()) and val != "") {
+ //If zero values are given, then user just wants values read to them
+ throw std::runtime_error("Number of keys must match number of values!");
+ }
+
+ std::cout << "Fetching current settings from EEPROM..." << std::endl;
+ uhd::usrp::mboard_eeprom_t mb_eeprom = tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").get();
+ for(size_t i = 0; i < keys_vec.size(); i++){
+ if (not mb_eeprom.has_key(keys_vec[i])){
+ std::cerr << boost::format("Cannot find value for EEPROM[%s]") % keys_vec[i] << std::endl;
return EXIT_FAILURE;
}
- std::cout << boost::format(" EEPROM [\"%s\"] is \"%s\"") % key % mb_eeprom[key] << std::endl;
- std::cout << std::endl;
+ std::cout << boost::format(" EEPROM [\"%s\"] is \"%s\"") % keys_vec[i] % mb_eeprom[keys_vec[i]] << std::endl;
}
+ std::cout << std::endl;
if (vm.count("val")){
- uhd::usrp::mboard_eeprom_t mb_eeprom; mb_eeprom[key] = val;
- std::cout << boost::format("Setting EEPROM [\"%s\"] to \"%s\"...") % key % val << std::endl;
- tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").set(mb_eeprom);
+ for(size_t i = 0; i < vals_vec.size(); i++){
+ uhd::usrp::mboard_eeprom_t mb_eeprom; mb_eeprom[keys_vec[i]] = vals_vec[i];
+ std::cout << boost::format("Setting EEPROM [\"%s\"] to \"%s\"...") % keys_vec[i] % vals_vec[i] << std::endl;
+ tree->access<uhd::usrp::mboard_eeprom_t>("/mboards/0/eeprom").set(mb_eeprom);
+ }
std::cout << "Power-cycle the USRP device for the changes to take effect." << std::endl;
std::cout << std::endl;
}