summaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/AUTHORS.txt40
-rw-r--r--host/CMakeLists.txt9
-rw-r--r--host/LICENSE (renamed from host/LICENSE.txt)0
-rw-r--r--host/README.txt43
-rw-r--r--host/apps/omap_debug/README1
-rw-r--r--host/cmake/Modules/FindUSB1.cmake3
-rw-r--r--host/cmake/Modules/UHDPackage.cmake5
-rw-r--r--host/cmake/Modules/UHDVersion.cmake4
-rw-r--r--host/docs/uhd_find_devices.13
-rw-r--r--host/docs/uhd_images_downloader.13
-rw-r--r--host/docs/uhd_usrp_probe.12
-rw-r--r--host/examples/network_relay.cpp3
-rw-r--r--host/lib/usrp/README15
-rw-r--r--host/lib/usrp/b200/b200_iface.cpp264
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp4
-rw-r--r--host/lib/usrp/b200/b200_io_impl.cpp4
-rw-r--r--host/lib/usrp/cores/radio_ctrl_core_3000.cpp23
-rw-r--r--host/utils/uhd_images_downloader.py.in435
-rw-r--r--host/utils/usrp_n2xx_simple_net_burner.cpp12
19 files changed, 539 insertions, 334 deletions
diff --git a/host/AUTHORS.txt b/host/AUTHORS.txt
deleted file mode 100644
index 44b7516cd..000000000
--- a/host/AUTHORS.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-Matt Ettus - matt@ettus.com
- USRP1 FPGA code
- USRP2/N200 FPGA code
- USRP-E100 FPGA code
-
-Josh Blum - josh@ettus.com
- driver framework
- USRP2/N200 firmware
- USRP2/N200 host code
- USRP-E100 host code
- Basic/LF host code
- XCVR2450 host code
- RFX Series host code
-
-Jason Abele - jason@ettus.com
- RFX Series host code
- WBX host code
- DBSRX host code
- DBSRX2 host code
-
-Eric Blossom - eb@comsec.com
- USRP1 firmware
- USRP2 firmware
-
-Tom Tsou - ttsou@vt.edu
- UHD-USB framework
- LIBUSB host code
- USRP1 host code
- USRP1 firmware
-
-Nick Foster - nick@ettus.com
- LIBUSB host code
- USRP1 host code
- TVRX host code
- USRP-N200 firmware
- USRP-N200 host code
-
-Philip Balister - philip@opensdr.com
- USRP-E100 kernel module
- USRP-E100 utilities
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index 15fd283f7..103266edd 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -201,9 +201,8 @@ ADD_CUSTOM_TARGET(uninstall
# Install Package Docs
########################################################################
UHD_INSTALL(FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/README.txt
- ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt
- ${CMAKE_CURRENT_SOURCE_DIR}/AUTHORS.txt
+ ${CMAKE_CURRENT_SOURCE_DIR}/../README.md
+ ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE
DESTINATION ${PKG_DOC_DIR}
COMPONENT readme
)
@@ -212,8 +211,8 @@ UHD_INSTALL(FILES
# Images download directory for utils/uhd_images_downloader.py
########################################################################
-SET(UHD_IMAGES_MD5SUM "50e68637ae6e08b6e2b3557516bc115b")
-SET(UHD_IMAGES_DOWNLOAD_SRC "http://files.ettus.com/binaries/maint_images/archive/uhd-images_003.006.000-release.zip")
+SET(UHD_IMAGES_MD5SUM "61db1170aaaadd787f5150b3eceab6f2")
+SET(UHD_IMAGES_DOWNLOAD_SRC "http://files.ettus.com/binaries/maint_images/archive/uhd-images_003.006.002-rc1.zip")
########################################################################
# Register top level components
diff --git a/host/LICENSE.txt b/host/LICENSE
index 9aa03b39b..9aa03b39b 100644
--- a/host/LICENSE.txt
+++ b/host/LICENSE
diff --git a/host/README.txt b/host/README.txt
deleted file mode 100644
index 0e8e62ac1..000000000
--- a/host/README.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-###############################################
-# Ettus Research - USRP Hardware Driver
-###############################################
-The hardware driver for Ettus Research products.
-
-###############################################
-# Supported USRP Motherboards
-###############################################
-USRP1
-USRP2
-N200
-N210
-E100
-E110
-B100
-B200
-
-###############################################
-# Supported USRP Daughterboards
-###############################################
-Basic RX
-Basic TX
-LF RX
-LF TX
-RFX Series
-XCVR 2450
-WBX + Simple GDB
-DBSRX
-DBSRX2
-TVRX
-TVRX2
-SBX
-CBX
-
-###############################################
-# Documentation
-###############################################
-Online documentation available at:
-http://code.ettus.com/redmine/ettus/projects/uhd/wiki
-
-The build system can generate the html for the manual and Doxygen.
-Docutils and Doxygen are required to build the html docs.
-See the docs directory for the manual source (reStructuredText).
diff --git a/host/apps/omap_debug/README b/host/apps/omap_debug/README
deleted file mode 100644
index bbe0c2cc4..000000000
--- a/host/apps/omap_debug/README
+++ /dev/null
@@ -1 +0,0 @@
-OMAP development tools go here
diff --git a/host/cmake/Modules/FindUSB1.cmake b/host/cmake/Modules/FindUSB1.cmake
index a494e1350..b2e4d118c 100644
--- a/host/cmake/Modules/FindUSB1.cmake
+++ b/host/cmake/Modules/FindUSB1.cmake
@@ -8,7 +8,8 @@ PKG_CHECK_MODULES(PC_LIBUSB QUIET libusb-1.0)
FIND_PATH(LIBUSB_INCLUDE_DIRS
NAMES libusb.h
- HINTS $ENV{LIBUSB_DIR}/include ${PC_LIBUSB_INCLUDEDIR}
+ HINTS $ENV{LIBUSB_DIR}/include $ENV{LIBUSB_DIR}/include/libusb-1.0
+ ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDEDIR}/libusb-1.0
PATHS /usr/local/include/libusb-1.0 /usr/local/include
/usr/include/libusb-1.0 /usr/include
/opt/local/include/libusb-1.0
diff --git a/host/cmake/Modules/UHDPackage.cmake b/host/cmake/Modules/UHDPackage.cmake
index 6af474f7a..4968571b5 100644
--- a/host/cmake/Modules/UHDPackage.cmake
+++ b/host/cmake/Modules/UHDPackage.cmake
@@ -99,9 +99,8 @@ SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Ettus Research - USRP Hardware Driver")
SET(CPACK_PACKAGE_VENDOR "Ettus Research LLC")
SET(CPACK_PACKAGE_CONTACT "Ettus Research <support@ettus.com>")
SET(CPACK_PACKAGE_VERSION "${UHD_VERSION}")
-SET(CPACK_RESOURCE_FILE_WELCOME ${CMAKE_SOURCE_DIR}/README.txt)
-SET(CPACK_RESOURCE_FILE_README ${CMAKE_SOURCE_DIR}/AUTHORS.txt)
-SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt)
+SET(CPACK_RESOURCE_FILE_WELCOME ${CMAKE_SOURCE_DIR}/../README.md)
+SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE)
########################################################################
# Setup CPack Source
diff --git a/host/cmake/Modules/UHDVersion.cmake b/host/cmake/Modules/UHDVersion.cmake
index c07b18f01..b0d04fe70 100644
--- a/host/cmake/Modules/UHDVersion.cmake
+++ b/host/cmake/Modules/UHDVersion.cmake
@@ -27,7 +27,7 @@ FIND_PACKAGE(Git QUIET)
########################################################################
SET(UHD_VERSION_MAJOR 003)
SET(UHD_VERSION_MINOR 006)
-SET(UHD_VERSION_PATCH 000)
+SET(UHD_VERSION_PATCH 002)
########################################################################
# Set up trimmed version numbers for DLL resource files and packages
@@ -87,7 +87,7 @@ IF(UHD_RELEASE_MODE)
#Ignore UHD_GIT_COUNT in UHD_VERSION if the string 'release' is in UHD_RELEASE_MODE
EXECUTE_PROCESS(
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- COMMAND ${PYTHON_EXECUTABLE} -c "print 'release' in '${UHD_RELEASE_MODE}'"
+ COMMAND ${PYTHON_EXECUTABLE} -c "print ('release' in '${UHD_RELEASE_MODE}') or ('rc' in '${UHD_RELEASE_MODE}')"
OUTPUT_VARIABLE TRIM_UHD_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE
)
ENDIF()
diff --git a/host/docs/uhd_find_devices.1 b/host/docs/uhd_find_devices.1
index 7dc0dd470..08f9a789c 100644
--- a/host/docs/uhd_find_devices.1
+++ b/host/docs/uhd_find_devices.1
@@ -9,9 +9,6 @@ The UHD package is the universal hardware driver for Ettus Research
products. The goal is to provide a host driver and API for
current and future Ettus Research products. Users will be able to use
the UHD driver standalone or with 3rd party applications.
-.LP
-Hardware supporting UHD drivers includes the Universal Software Radio
-Peripheral, or USRP, available in several models.
.SH SYNOPSIS
.B uhd_find_devices [OPTIONS]
.SH OPTIONS
diff --git a/host/docs/uhd_images_downloader.1 b/host/docs/uhd_images_downloader.1
index ece826cb5..28310dd37 100644
--- a/host/docs/uhd_images_downloader.1
+++ b/host/docs/uhd_images_downloader.1
@@ -7,9 +7,6 @@ products. The goal of the UHD is to provide a host driver and API for
current and future Ettus Research products. Users will be able to use
the UHD driver standalone or with 3rd party applications.
.LP
-Hardware supporting UHD drivers includes the Universal Software Radio
-Peripheral, or USRP, available in several models.
-.LP
This program installs the firmware and FPGA binaries from Ettus Research
matching this UHD driver release onto the host system. If the uhd-images
package is installed, there is no need to run this installer.
diff --git a/host/docs/uhd_usrp_probe.1 b/host/docs/uhd_usrp_probe.1
index 7e82bf99a..a6c7150ee 100644
--- a/host/docs/uhd_usrp_probe.1
+++ b/host/docs/uhd_usrp_probe.1
@@ -1,6 +1,6 @@
.TH "uhd_usrp_probe" 1 "3.5.1" UHD "User Commands"
.SH NAME
-uhd_usrp_probe \- Universal Hardware Driver Peripheral Report Utility
+uhd_usrp_probe \- USRP Hardware Driver Peripheral Report Utility
.SH DESCRIPTION
Report detailed information on UHD-supported Software Radio Peripherals
attached by USB, network, or embedded configuration.
diff --git a/host/examples/network_relay.cpp b/host/examples/network_relay.cpp
index fc1ebd91d..0a67bbf09 100644
--- a/host/examples/network_relay.cpp
+++ b/host/examples/network_relay.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010-2012 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
@@ -18,6 +18,7 @@
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/safe_main.hpp>
#include <boost/program_options.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <boost/thread/thread.hpp>
#include <boost/format.hpp>
#include <boost/asio.hpp>
diff --git a/host/lib/usrp/README b/host/lib/usrp/README
deleted file mode 100644
index 344209179..000000000
--- a/host/lib/usrp/README
+++ /dev/null
@@ -1,15 +0,0 @@
-########################################################################
-# lib USRP directories:
-########################################################################
-
-dboard:
- Daughterboard implementation code for all USRP daughterboards
-
-usrp1:
- Implementation code for the USB-based USRP Classic motherboard.
-
-usrp2:
- Implementation code for USRP2, USRP-N200, and USRP-N210.
-
-usrp_e100:
- Implementation code for USRP-E100.
diff --git a/host/lib/usrp/b200/b200_iface.cpp b/host/lib/usrp/b200/b200_iface.cpp
index a2e23cf1b..5361ecaa0 100644
--- a/host/lib/usrp/b200/b200_iface.cpp
+++ b/host/lib/usrp/b200/b200_iface.cpp
@@ -63,6 +63,7 @@ const static boost::uint8_t B200_VREQ_FX3_RESET = 0x99;
const static boost::uint8_t B200_VREQ_EEPROM_WRITE = 0xBA;
const static boost::uint8_t B200_VREQ_EEPROM_READ = 0xBB;
+const static boost::uint8_t FX3_STATE_UNDEFINED = 0x00;
const static boost::uint8_t FX3_STATE_FPGA_READY = 0x01;
const static boost::uint8_t FX3_STATE_CONFIGURING_FPGA = 0x02;
const static boost::uint8_t FX3_STATE_BUSY = 0x03;
@@ -89,6 +90,9 @@ typedef boost::uint32_t hash_type;
*/
static hash_type generate_hash(const char *filename)
{
+ if (filename == NULL)
+ return hash_type(0);
+
std::ifstream file(filename);
if (not file){
throw uhd::io_error(std::string("cannot open input file ") + filename);
@@ -121,15 +125,15 @@ static hash_type generate_hash(const char *filename)
* \param record a line from an Intel HEX file
* \return true if record is valid, false otherwise
*/
-bool checksum(std::string *record) {
+bool checksum(const std::string& record) {
- size_t len = record->length();
+ 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;
+ std::istringstream(record.substr(i, 2)) >> std::hex >> val;
sum += val;
}
@@ -150,25 +154,28 @@ bool checksum(std::string *record) {
* \param data output data
* \return true if record is sucessfully read, false on error
*/
-bool parse_record(std::string *record, boost::uint16_t &len, \
+bool parse_record(const std::string& record, boost::uint16_t &len, \
boost::uint16_t &addr, boost::uint16_t &type, unsigned char* data) {
unsigned int i;
std::string _data;
unsigned int val;
- if (record->substr(0, 1) != ":")
+ 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;
+ 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;
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;
+ std::istringstream(record.substr(9 + 2 * i, 2)) >> std::hex >> val;
data[i] = (unsigned char) val;
}
@@ -183,19 +190,16 @@ class b200_iface_impl : public b200_iface{
public:
b200_iface_impl(usb_control::sptr usb_ctrl):
- _usb_ctrl(usb_ctrl)
- {
+ _usb_ctrl(usb_ctrl) {
//NOP
}
-
int fx3_control_write(boost::uint8_t request,
boost::uint16_t value,
boost::uint16_t index,
unsigned char *buff,
boost::uint16_t length,
- boost::int32_t timeout = 0)
- {
+ boost::int32_t timeout = 0) {
return _usb_ctrl->submit(VRT_VENDOR_OUT, // bmReqeustType
request, // bRequest
value, // wValue
@@ -205,14 +209,12 @@ public:
timeout); // timeout
}
-
int fx3_control_read(boost::uint8_t request,
boost::uint16_t value,
boost::uint16_t index,
unsigned char *buff,
boost::uint16_t length,
- boost::int32_t timeout = 0)
- {
+ boost::int32_t timeout = 0) {
return _usb_ctrl->submit(VRT_VENDOR_IN, // bmReqeustType
request, // bRequest
value, // wValue
@@ -222,7 +224,6 @@ public:
timeout); // timeout
}
-
void write_i2c(UHD_UNUSED(boost::uint16_t addr), UHD_UNUSED(const byte_vector_t &bytes))
{
throw uhd::not_implemented_error("b200 write i2c");
@@ -235,26 +236,33 @@ public:
}
void write_eeprom(boost::uint16_t addr, boost::uint16_t offset,
- const byte_vector_t &bytes)
- {
- fx3_control_write(B200_VREQ_EEPROM_WRITE,
+ const byte_vector_t &bytes) {
+ int ret = fx3_control_write(B200_VREQ_EEPROM_WRITE,
0, offset | (boost::uint16_t(addr) << 8),
(unsigned char *) &bytes[0],
bytes.size());
+
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to write EEPROM (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if ((size_t)ret != bytes.size())
+ throw uhd::io_error((boost::format("Short write on write EEPROM (expecting: %d, returned: %d)") % bytes.size() % ret).str());
}
byte_vector_t read_eeprom(
boost::uint16_t addr,
boost::uint16_t offset,
- size_t num_bytes
- ){
+ size_t num_bytes) {
byte_vector_t recv_bytes(num_bytes);
int bytes_read = fx3_control_read(B200_VREQ_EEPROM_READ,
0, offset | (boost::uint16_t(addr) << 8),
(unsigned char*) &recv_bytes[0],
num_bytes);
- if (bytes_read != num_bytes)
- throw uhd::io_error("Failed to read data from EEPROM.");
+
+ if (bytes_read < 0)
+ throw uhd::io_error((boost::format("Failed to read EEPROM (%d: %s)") % bytes_read % libusb_error_name(bytes_read)).str());
+ else if ((size_t)bytes_read != num_bytes)
+ throw uhd::io_error((boost::format("Short read on read EEPROM (expecting: %d, returned: %d)") % num_bytes % bytes_read).str());
+
return recv_bytes;
}
@@ -262,8 +270,7 @@ public:
unsigned char *tx_data,
size_t num_tx_bits,
unsigned char *rx_data,
- size_t num_rx_bits
- ){
+ size_t num_rx_bits) {
int ret = 0;
boost::uint16_t tx_length = num_tx_bits / 8;
@@ -275,9 +282,10 @@ public:
0x00, tx_data, tx_length);
}
- if(ret < 0) {
- throw uhd::io_error("transact_spi: fx3_control_write failed!");
- }
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to write SPI (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != tx_length)
+ throw uhd::io_error((boost::format("Short write on write SPI (expecting: %d, returned: %d)") % tx_length % ret).str());
if(num_rx_bits) {
@@ -286,23 +294,36 @@ public:
ret = fx3_control_read(B200_VREQ_LOOP, 0x00, \
0x00, rx_data, total_length);
- if(ret < 0) {
- throw uhd::io_error("transact_spi: readback failed!");
- }
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to readback (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != total_length)
+ throw uhd::io_error((boost::format("Short read on readback (expecting: %d, returned: %d)") % total_length % ret).str());
}
}
void ad9361_transact(const unsigned char in_buff[64], unsigned char out_buff[64]) {
- fx3_control_write(B200_VREQ_AD9361_CTRL_WRITE, 0x00, 0x00, (unsigned char *)in_buff, 64);
- int ret = 0;
- for (size_t i = 0; i < 30; i++)
+ const int bytes_to_write = 64;
+ const int bytes_to_read = 64;
+ const size_t read_retries = 30;
+
+ int ret = fx3_control_write(B200_VREQ_AD9361_CTRL_WRITE, 0x00, 0x00, (unsigned char *)in_buff, bytes_to_write);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to write AD9361 (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_write)
+ throw uhd::io_error((boost::format("Short write on write AD9361 (expecting: %d, returned: %d)") % bytes_to_write % ret).str());
+
+ for (size_t i = 0; i < read_retries; i++)
{
- ret = fx3_control_read(B200_VREQ_AD9361_CTRL_READ, 0x00, 0x00, out_buff, 64, 1000);
- if (ret == 64) return;
+ ret = fx3_control_read(B200_VREQ_AD9361_CTRL_READ, 0x00, 0x00, out_buff, bytes_to_read, 1000);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to read AD9361 (%d: %s)") % ret % libusb_error_name(ret)).str());
+
+ if (ret == bytes_to_read)
+ return;
}
- throw uhd::io_error(str(boost::format("ad9361_transact failed with usb error: %d") % ret));
- }
+ throw uhd::io_error(str(boost::format("Failed to read complete AD9361 (expecting: %d, last read: %d)") % bytes_to_read % ret));
+ }
void load_firmware(const std::string filestring, UHD_UNUSED(bool force) = false)
{
@@ -338,7 +359,7 @@ public:
continue;
/* Check for valid Intel HEX record. */
- if (!checksum(&record) || !parse_record(&record, len, \
+ if (!checksum(record) || !parse_record(record, len, \
lower_address_bits, type, data)) {
throw uhd::io_error("fx3_load_firmware: bad intel hex record checksum");
}
@@ -411,48 +432,74 @@ public:
throw uhd::io_error("fx3_load_firmware: No EOF record found.");
}
-
void reset_fx3(void) {
unsigned char data[4];
memset(data, 0x00, sizeof(data));
+ const int bytes_to_send = sizeof(data);
- fx3_control_write(B200_VREQ_FX3_RESET, 0x00, 0x00, data, 4);
+ int ret = fx3_control_write(B200_VREQ_FX3_RESET, 0x00, 0x00, data, bytes_to_send);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to reset FX3 (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_send)
+ throw uhd::io_error((boost::format("Short write on reset FX3 (expecting: %d, returned: %d)") % bytes_to_send % ret).str());
}
void reset_gpif(void) {
unsigned char data[4];
memset(data, 0x00, sizeof(data));
+ const int bytes_to_send = sizeof(data);
- fx3_control_write(B200_VREQ_GPIF_RESET, 0x00, 0x00, data, 4);
+ int ret = fx3_control_write(B200_VREQ_GPIF_RESET, 0x00, 0x00, data, bytes_to_send);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to reset GPIF (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_send)
+ throw uhd::io_error((boost::format("Short write on reset GPIF (expecting: %d, returned: %d)") % bytes_to_send % ret).str());
}
- void set_fpga_reset_pin(const bool reset)
- {
+ void set_fpga_reset_pin(const bool reset) {
unsigned char data[4];
memset(data, (reset)? 0xFF : 0x00, sizeof(data));
+ const int bytes_to_send = sizeof(data);
UHD_THROW_INVALID_CODE_PATH();
// Below is dead code as long as UHD_THROW_INVALID_CODE_PATH(); is declared above.
// It is preserved here in a comment in case it is needed later:
- // fx3_control_write(B200_VREQ_FPGA_RESET, 0x00, 0x00, data, 4);
+ /*
+ int ret = fx3_control_write(B200_VREQ_FPGA_RESET, 0x00, 0x00, data, bytes_to_send);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to reset FPGA (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_send)
+ throw uhd::io_error((boost::format("Short write on reset FPGA (expecting: %d, returned: %d)") % bytes_to_send % ret).str());
+ */
}
boost::uint8_t get_usb_speed(void) {
unsigned char rx_data[1];
+ memset(rx_data, 0x00, sizeof(rx_data));
+ const int bytes_to_recv = sizeof(rx_data);
- fx3_control_read(B200_VREQ_GET_USB, 0x00, 0x00, rx_data, 1);
+ int ret = fx3_control_read(B200_VREQ_GET_USB, 0x00, 0x00, rx_data, bytes_to_recv);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to get USB speed (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_recv)
+ throw uhd::io_error((boost::format("Short read on get USB speed (expecting: %d, returned: %d)") % bytes_to_recv % ret).str());
return boost::lexical_cast<boost::uint8_t>(rx_data[0]);
}
-
boost::uint8_t get_fx3_status(void) {
unsigned char rx_data[1];
+ memset(rx_data, 0x00, sizeof(rx_data));
+ const int bytes_to_recv = sizeof(rx_data);
- fx3_control_read(B200_VREQ_GET_STATUS, 0x00, 0x00, &rx_data[0], 1);
+ int ret = fx3_control_read(B200_VREQ_GET_STATUS, 0x00, 0x00, rx_data, bytes_to_recv);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to get FX3 status (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_recv)
+ throw uhd::io_error((boost::format("Short read on get FX3 status (expecting: %d, returned: %d)") % bytes_to_recv % ret).str());
return boost::lexical_cast<boost::uint8_t>(rx_data[0]);
}
@@ -460,47 +507,79 @@ public:
boost::uint16_t get_compat_num(void) {
unsigned char rx_data[2];
+ memset(rx_data, 0x00, sizeof(rx_data));
+ const int bytes_to_recv = sizeof(rx_data);
- fx3_control_read(B200_VREQ_GET_COMPAT , 0x00, 0x00, rx_data, 2);
-
- boost::uint16_t compat = 0x0000;
- compat |= (((uint16_t) rx_data[0]) << 8);
- compat |= (rx_data[1] & 0x00FF);
+ int ret = fx3_control_read(B200_VREQ_GET_COMPAT , 0x00, 0x00, rx_data, bytes_to_recv);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to get compat num (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_recv)
+ throw uhd::io_error((boost::format("Short read on get compat num (expecting: %d, returned: %d)") % bytes_to_recv % ret).str());
- return compat;
+ return (((uint16_t)rx_data[0]) << 8) | rx_data[1];
}
void usrp_get_firmware_hash(hash_type &hash) {
- fx3_control_read(B200_VREQ_GET_FW_HASH, 0x00, 0x00,
- (unsigned char*) &hash, 4, 500);
+ const int bytes_to_recv = 4;
+ if (sizeof(hash_type) != bytes_to_recv)
+ throw uhd::type_error((boost::format("hash_type is %d bytes but transfer length is %d bytes") % sizeof(hash_type) % bytes_to_recv).str());
+
+ int ret = fx3_control_read(B200_VREQ_GET_FW_HASH, 0x00, 0x00, (unsigned char*) &hash, bytes_to_recv, 500);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to get firmware hash (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_recv)
+ throw uhd::io_error((boost::format("Short read on get firmware hash (expecting: %d, returned: %d)") % bytes_to_recv % ret).str());
}
void usrp_set_firmware_hash(hash_type hash) {
- fx3_control_write(B200_VREQ_SET_FW_HASH, 0x00, 0x00,
- (unsigned char*) &hash, 4);
+ const int bytes_to_send = 4;
+ if (sizeof(hash_type) != bytes_to_send)
+ throw uhd::type_error((boost::format("hash_type is %d bytes but transfer length is %d bytes") % sizeof(hash_type) % bytes_to_send).str());
+
+ int ret = fx3_control_write(B200_VREQ_SET_FW_HASH, 0x00, 0x00, (unsigned char*) &hash, bytes_to_send);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to set firmware hash (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_send)
+ throw uhd::io_error((boost::format("Short write on set firmware hash (expecting: %d, returned: %d)") % bytes_to_send % ret).str());
}
void usrp_get_fpga_hash(hash_type &hash) {
- fx3_control_read(B200_VREQ_GET_FPGA_HASH, 0x00, 0x00,
- (unsigned char*) &hash, 4, 500);
+ const int bytes_to_recv = 4;
+ if (sizeof(hash_type) != bytes_to_recv)
+ throw uhd::type_error((boost::format("hash_type is %d bytes but transfer length is %d bytes") % sizeof(hash_type) % bytes_to_recv).str());
+
+ int ret = fx3_control_read(B200_VREQ_GET_FPGA_HASH, 0x00, 0x00, (unsigned char*) &hash, bytes_to_recv, 500);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to get FPGA hash (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_recv)
+ throw uhd::io_error((boost::format("Short read on get FPGA hash (expecting: %d, returned: %d)") % bytes_to_recv % ret).str());
}
void usrp_set_fpga_hash(hash_type hash) {
- fx3_control_write(B200_VREQ_SET_FPGA_HASH, 0x00, 0x00,
- (unsigned char*) &hash, 4);
+ const int bytes_to_send = 4;
+ if (sizeof(hash_type) != bytes_to_send)
+ throw uhd::type_error((boost::format("hash_type is %d bytes but transfer length is %d bytes") % sizeof(hash_type) % bytes_to_send).str());
+
+ int ret = fx3_control_write(B200_VREQ_SET_FPGA_HASH, 0x00, 0x00, (unsigned char*) &hash, bytes_to_send);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to set FPGA hash (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_send)
+ throw uhd::io_error((boost::format("Short write on set FPGA hash (expecting: %d, returned: %d)") % bytes_to_send % ret).str());
}
boost::uint32_t load_fpga(const std::string filestring) {
boost::uint8_t fx3_state = 0;
boost::uint32_t wait_count;
+ int ret = 0;
+ int bytes_to_xfer = 0;
const char *filename = filestring.c_str();
hash_type hash = generate_hash(filename);
hash_type loaded_hash; usrp_get_fpga_hash(loaded_hash);
if (hash == loaded_hash) return 0;
-
+
// Establish default largest possible control request transfer size based on operating USB speed
int transfer_size = VREQ_DEFAULT_SIZE;
int current_usb_speed = get_usb_speed();
@@ -508,15 +587,19 @@ public:
transfer_size = VREQ_MAX_SIZE_USB3;
else if (current_usb_speed != 2)
throw uhd::io_error("load_fpga: get_usb_speed returned invalid USB speed (not 2 or 3).");
-
+
UHD_ASSERT_THROW(transfer_size <= VREQ_MAX_SIZE);
-
+
unsigned char out_buff[VREQ_MAX_SIZE];
-
+
// Request loopback read, which will indicate the firmware's current control request buffer size
- int nread = fx3_control_read(B200_VREQ_LOOP, 0, 0, out_buff, sizeof(out_buff), 1000);
- if (nread <= 0)
- throw uhd::io_error("load_fpga: unable to complete firmware loopback request.");
+ // Make sure that if operating as USB2, requested length is within spec
+ int ntoread = std::min(transfer_size, (int)sizeof(out_buff));
+ int nread = fx3_control_read(B200_VREQ_LOOP, 0, 0, out_buff, ntoread, 1000);
+ if (nread < 0)
+ throw uhd::io_error((boost::format("load_fpga: unable to complete firmware loopback request (%d: %s)") % nread % libusb_error_name(nread)).str());
+ else if (nread != ntoread)
+ throw uhd::io_error((boost::format("load_fpga: short read on firmware loopback request (expecting: %d, returned: %d)") % ntoread % nread).str());
transfer_size = std::min(transfer_size, nread); // Select the smaller value
size_t file_size = 0;
@@ -528,18 +611,26 @@ public:
std::ifstream file;
file.open(filename, std::ios::in | std::ios::binary);
- if(!file.good()) {
+ if (!file.good()) {
throw uhd::io_error("load_fpga: cannot open FPGA input file.");
}
+ // Zero the hash, in case we abort programming another image and revert to the previously programmed image
+ usrp_set_fpga_hash(0);
+
memset(out_buff, 0x00, sizeof(out_buff));
- fx3_control_write(B200_VREQ_FPGA_CONFIG, 0, 0, out_buff, 1, 1000);
+ bytes_to_xfer = 1;
+ ret = fx3_control_write(B200_VREQ_FPGA_CONFIG, 0, 0, out_buff, bytes_to_xfer, 1000);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to start FPGA config (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_xfer)
+ throw uhd::io_error((boost::format("Short write on start FPGA config (expecting: %d, returned: %d)") % bytes_to_xfer % ret).str());
wait_count = 0;
do {
fx3_state = get_fx3_status();
- if((wait_count >= 500) || (fx3_state == FX3_STATE_ERROR)) {
+ if((wait_count >= 500) || (fx3_state == FX3_STATE_ERROR) || (fx3_state == FX3_STATE_UNDEFINED)) {
return fx3_state;
}
@@ -551,13 +642,18 @@ public:
if (load_img_msg) UHD_MSG(status) << "Loading FPGA image: " \
<< filestring << "..." << std::flush;
- fx3_control_write(B200_VREQ_FPGA_START, 0, 0, out_buff, 1, 1000);
+ bytes_to_xfer = 1;
+ ret = fx3_control_write(B200_VREQ_FPGA_START, 0, 0, out_buff, bytes_to_xfer, 1000);
+ if (ret < 0)
+ throw uhd::io_error((boost::format("Failed to start FPGA bitstream (%d: %s)") % ret % libusb_error_name(ret)).str());
+ else if (ret != bytes_to_xfer)
+ throw uhd::io_error((boost::format("Short write on start FPGA bitstream (expecting: %d, returned: %d)") % bytes_to_xfer % ret).str());
wait_count = 0;
do {
fx3_state = get_fx3_status();
- if((wait_count >= 1000) || (fx3_state == FX3_STATE_ERROR)) {
+ if((wait_count >= 1000) || (fx3_state == FX3_STATE_ERROR) || (fx3_state == FX3_STATE_UNDEFINED)) {
return fx3_state;
}
@@ -567,19 +663,20 @@ public:
} while(fx3_state != FX3_STATE_CONFIGURING_FPGA);
size_t bytes_sent = 0;
- while(!file.eof()) {
+ while (!file.eof()) {
file.read((char *) out_buff, transfer_size);
const std::streamsize n = file.gcount();
- if(n == 0) continue;
+ if(n == 0)
+ continue;
boost::uint16_t transfer_count = boost::uint16_t(n);
/* Send the data to the device. */
int nwritten = fx3_control_write(B200_VREQ_FPGA_DATA, 0, 0, out_buff, transfer_count, 5000);
- if (nwritten <= 0)
- throw uhd::io_error("load_fpga: cannot write bitstream to FX3.");
+ if (nwritten < 0)
+ throw uhd::io_error((boost::format("load_fpga: cannot write bitstream to FX3 (%d: %s)") % nwritten % libusb_error_name(nwritten)).str());
else if (nwritten != transfer_count)
- throw uhd::io_error("load_fpga: short write while transferring bitstream to FX3.");
+ throw uhd::io_error((boost::format("load_fpga: short write while transferring bitstream to FX3 (expecting: %d, returned: %d)") % transfer_count % nwritten).str());
if (load_img_msg)
{
@@ -600,7 +697,7 @@ public:
do {
fx3_state = get_fx3_status();
- if((wait_count >= 500) || (fx3_state == FX3_STATE_ERROR)) {
+ if((wait_count >= 500) || (fx3_state == FX3_STATE_ERROR) || (fx3_state == FX3_STATE_UNDEFINED)) {
return fx3_state;
}
@@ -611,7 +708,8 @@ public:
usrp_set_fpga_hash(hash);
- if (load_img_msg) UHD_MSG(status) << "\b\b\b\b done" << std::endl;
+ if (load_img_msg)
+ UHD_MSG(status) << "\b\b\b\b done" << std::endl;
return 0;
}
diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp
index 362c45347..bee42679b 100644
--- a/host/lib/usrp/b200/b200_impl.hpp
+++ b/host/lib/usrp/b200/b200_impl.hpp
@@ -44,9 +44,9 @@
#include <uhd/transport/bounded_buffer.hpp>
#include <boost/weak_ptr.hpp>
#include "recv_packet_demuxer_3000.hpp"
-static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 0x03;
+static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 0x04;
static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0x00;
-static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x02;
+static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x03;
static const double B200_LINK_RATE_BPS = (5e9)/8; //practical link rate (5 Gbps)
static const double B200_BUS_CLOCK_RATE = 100e6;
static const double B200_DEFAULT_TICK_RATE = 32e6;
diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp
index 4fe90bd4a..4768aa37b 100644
--- a/host/lib/usrp/b200/b200_io_impl.cpp
+++ b/host/lib/usrp/b200/b200_io_impl.cpp
@@ -249,14 +249,14 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_)
//calculate packet size
static const size_t hdr_size = 0
+ vrt::max_if_hdr_words32*sizeof(boost::uint32_t)
- //+ sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer
+ //+ sizeof(vrt::if_packet_info_t().tlr) //no longer using trailer
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
- sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;
const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size;
const size_t bpi = convert::get_bytes_per_item(args.otw_format);
size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi));
- spp = std::min<size_t>(2000, spp); //magic maximum for framing at full rate
+ spp = std::min<size_t>(4092, spp); //FPGA FIFO maximum for framing at full rate
//make the new streamer given the samples per packet
if (not my_streamer) my_streamer = boost::make_shared<sph::recv_packet_streamer>(spp);
diff --git a/host/lib/usrp/cores/radio_ctrl_core_3000.cpp b/host/lib/usrp/cores/radio_ctrl_core_3000.cpp
index 0d6e1c665..27fac3471 100644
--- a/host/lib/usrp/cores/radio_ctrl_core_3000.cpp
+++ b/host/lib/usrp/cores/radio_ctrl_core_3000.cpp
@@ -189,6 +189,7 @@ private:
//parse the packet
vrt::if_packet_info_t packet_info;
resp_buff_type resp_buff;
+ memset(&resp_buff, 0x00, sizeof(resp_buff));
boost::uint32_t const *pkt = NULL;
managed_recv_buffer::sptr buff;
@@ -221,9 +222,9 @@ private:
*/
double accum_timeout = 0.0;
const double short_timeout = 0.005; // == 5ms
- while(not (_resp_queue.pop_with_haste(resp_buff)
- || check_dump_queue(resp_buff)
- || _resp_queue.pop_with_timed_wait(resp_buff, short_timeout)
+ while(not ((_resp_queue.pop_with_haste(resp_buff))
+ || (check_dump_queue(resp_buff))
+ || (_resp_queue.pop_with_timed_wait(resp_buff, short_timeout))
)){
/*
* If a message couldn't be received within a given timeout
@@ -247,7 +248,12 @@ private:
catch(const std::exception &ex)
{
UHD_MSG(error) << "Radio ctrl bad VITA packet: " << ex.what() << std::endl;
- UHD_VAR(buff->size());
+ if (buff){
+ UHD_VAR(buff->size());
+ }
+ else{
+ UHD_MSG(status) << "buff is NULL" << std::endl;
+ }
UHD_MSG(status) << std::hex << pkt[0] << std::dec << std::endl;
UHD_MSG(status) << std::hex << pkt[1] << std::dec << std::endl;
UHD_MSG(status) << std::hex << pkt[2] << std::dec << std::endl;
@@ -288,16 +294,17 @@ private:
* With check_dump_queue we can check if a message we are waiting for got stranded there.
* If a message got stuck we get it here and push it onto our own message_queue.
*/
- bool check_dump_queue(resp_buff_type b) {
+ bool check_dump_queue(resp_buff_type& b) {
+ const size_t min_buff_size = 8; // Same value as in b200_io_impl->handle_async_task
boost::uint32_t recv_sid = (((_sid)<<16)|((_sid)>>16));
uhd::msg_task::msg_payload_t msg;
do{
msg = _async_task->get_msg_from_dump_queue(recv_sid);
}
- while(msg.size() < 8 && msg.size() != 0);
+ while(msg.size() < min_buff_size && msg.size() != 0);
- if(msg.size() >= 8) {
- memcpy(b.data, &msg.front(), 8);
+ if(msg.size() >= min_buff_size) {
+ memcpy(b.data, &msg.front(), std::min(msg.size(), sizeof(b.data)));
return true;
}
return false;
diff --git a/host/utils/uhd_images_downloader.py.in b/host/utils/uhd_images_downloader.py.in
index bb082190c..697bd4e16 100644
--- a/host/utils/uhd_images_downloader.py.in
+++ b/host/utils/uhd_images_downloader.py.in
@@ -16,144 +16,341 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import atexit
-import hashlib
+import sys, os, string, tempfile, math
+import traceback
+import shutil, hashlib, urllib2, zipfile
+
from optparse import OptionParser
-import os
-import os.path
-import shutil
-import string
-import sys
-import tempfile
-import urllib2
-import zipfile
+
+_DEFAULT_BUFFER_SIZE = 8192
+_BASE_DIR_STRUCTURE_PARTS = ["share", "uhd", "images"]
+_BASE_DIR_STRUCTURE = os.path.join(_BASE_DIR_STRUCTURE_PARTS)
+_DEFAULT_INSTALL_PATH = os.path.join("@CMAKE_INSTALL_PREFIX@", *_BASE_DIR_STRUCTURE)
+_AUTOGEN_IMAGES_SOURCE = "@UHD_IMAGES_DOWNLOAD_SRC@"
+_AUTOGEN_IMAGES_CHECKSUM = "@UHD_IMAGES_MD5SUM@"
+_IMAGES_CHECKSUM_TYPE = "md5"
+_CONTACT = "support@ettus.com"
def md5Checksum(filePath):
- with open(filePath, 'rb') as fh:
- m = hashlib.md5()
- while True:
- data = fh.read(8192)
- if not data:
- break
- m.update(data)
- return m.hexdigest()
+ try:
+ with open(filePath, 'rb') as fh:
+ m = hashlib.md5()
+ while True:
+ data = fh.read(_DEFAULT_BUFFER_SIZE)
+ if not data:
+ break
+ m.update(data)
+ return m.hexdigest()
+ except Exception, e:
+ print "Failed to calculated MD5 sum of: %s (%s)" % (filePath, e)
+ raise e
-class temp_dir():
+_checksum_fns = {
+ 'md5': md5Checksum
+}
+class temporary_directory():
def __enter__(self):
- self.name = tempfile.mkdtemp()
- return self.name
+ try:
+ self.name = tempfile.mkdtemp()
+ return self.name
+ except Exception, e:
+ print "Failed to create a temporary directory (%s)" % (e)
+ raise e
+
+ # Can return 'True' to suppress incoming exception
def __exit__(self, type, value, traceback):
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"
+ except Exception, e:
+ print "Could not delete temporary directory: %s (%s)" % (self.name, e)
- #Command line options
- parser = OptionParser()
- 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()
+class uhd_images_downloader():
+ def __init__(self):
+ pass
- #Configuring image download info
- images_src = "@UHD_IMAGES_DOWNLOAD_SRC@"
- 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)
-
- if os.path.isabs(options.install_location):
- #Custom absolute path given
- images_dir = options.install_location
- else:
- #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)
-
+ def download(self, images_url, filename, buffer_size=_DEFAULT_BUFFER_SIZE, print_progress=False):
opener = urllib2.build_opener()
opener.add_headers = [('User-Agent', 'UHD Images Downloader')]
- u = opener.open(images_src)
- f = open(filename, "wb")
+ u = opener.open(images_url)
meta = u.info()
filesize = float(meta.getheaders("Content-Length")[0])
- print "Downloading images from: %s" % images_src
+ filesize_dl = 0
- filesize_dl = 0.0
-
- #Downloading file
- while True:
- buffer = u.read(options.buffer_size)
- if not buffer:
- break
-
- filesize_dl -= len(buffer)
- f.write(buffer)
+ with open(filename, "wb") as f:
+ while True:
+ buffer = u.read(buffer_size)
+ if not buffer:
+ break
+
+ f.write(buffer)
- status = r"%2.2f MB/%2.2f MB (%3.2f" % (-filesize_dl/1e6, filesize/1e6, (-filesize_dl*100.)/filesize) + r"%)"
- status += chr(8)*(len(status)+1)
- print status,
+ filesize_dl += len(buffer)
+
+ if print_progress:
+ status = r"%05d kB / %05d kB (%03d%%)" % (int(math.ceil(filesize_dl/1000.)), int(math.ceil(filesize/1000.)), int(math.ceil(filesize_dl*100.)/filesize))
+ status += chr(8)*(len(status)+1)
+ print status,
- f.close()
-
- #Checking md5sum of zip file
- downloaded_zip_md5sum = md5Checksum(filename)
- 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)
+ if print_progress:
+ print
+
+ return (filesize, filesize_dl)
+
+ def check_directories(self, dirs, print_progress=False):
+ if dirs is None or dirs == "":
+ dirs = "."
+ dirs = os.path.abspath(dirs)
+
+ def _check_part(head, tail=None):
+ if print_progress:
+ print "Checking: %s" % (head)
+ if tail is not None and tail == "":
+ return True
+ if not os.path.exists(head):
+ if print_progress:
+ print "Does not exist: %s" % (head)
+ return _check_part(*os.path.split(head))
+ if not os.path.isdir(head):
+ if print_progress:
+ print "Is not a directory: %s" % (head)
+ return (False, head)
+ if not os.access(head, os.W_OK):
+ if print_progress:
+ print "Write permission denied on: %s" % (head)
+ return (False, head)
+ if print_progress:
+ print "Write permission granted on: %s" % (head)
+ return (True, head)
+
+ return _check_part(dirs)
+
+ def validate_checksum(self, checksum_fn, file_path, expecting, print_progress=False):
+ if checksum_fn is None:
+ return (True, "")
+
+ calculated_checksum = checksum_fn(file_path)
+
+ if (expecting is not None) and (expecting != "") and calculated_checksum != expecting:
+ return (False, calculated_checksum)
+
+ return (True, calculated_checksum)
+
+ def extract_images_archive(self, archive_path, destination=None, print_progress=False):
+ if not os.path.exists(archive_path):
+ if print_progress:
+ print "Path does not exist: %s" % (archive_path)
+ raise Exception("path does not exist: %s" % (archive_path))
+
+ if print_progress:
+ print "Archive path: %s" % (archive_path)
+
+ (head, tail) = os.path.split(archive_path)
+
+ if not os.access(head, os.W_OK):
+ if print_progress:
+ print "Write access denied on: %s" % (head)
+ raise Exception("write access denied on: %s" % (head))
+
+ (root, ext) = os.path.splitext(tail)
+ temp_dir = os.path.join(head, root)
+
+ if print_progress:
+ print "Temporary extraction location: %s" % (temp_dir)
+
+ if os.path.exists(temp_dir):
+ if print_progress:
+ print "Deleting existing location: %s" % (temp_dir)
+ shutil.rmtree(temp_dir)
+
+ if print_progress:
+ print "Creating directory: %s" % (temp_dir)
+ os.mkdir(temp_dir)
+
+ if print_progress:
+ print "Extracting archive %s to %s" % (archive_path, temp_dir)
+
+ images_zip = zipfile.ZipFile(archive_path)
+ images_zip.extractall(temp_dir)
+ images_zip.close()
+
+ return temp_dir
+
+ def install_images(self, source, dest, keep=False, print_progress=False):
+ if not os.path.exists(source):
+ if print_progress:
+ print "Source path does not exist: %s" % (source)
+ return
+
+ if keep:
+ if print_progress:
+ print "Not wiping directory tree (existing files will be overwritten): %s" % (dest)
+ elif os.path.exists(dest):
+ if print_progress:
+ print "Deleting directory tree: %s" % (dest)
+ shutil.rmtree(dest)
+
+ (head, tail) = os.path.split(source)
+
+ if print_progress:
+ print "Source install path: %s" % (source)
+
+ uhd_source = os.path.join(source, tail, *_BASE_DIR_STRUCTURE_PARTS)
+
+ if print_progress:
+ print "Copying files from: %s" % (uhd_source)
+ print "Copying files to: %s" % (dest)
+
+ if keep:
+ # mgrant @ http://stackoverflow.com/questions/12683834/how-to-copy-directory-recursively-in-python-and-overwrite-all
+ def _recursive_overwrite(src, dest, ignore=None):
+ if os.path.isdir(src):
+ if not os.path.isdir(dest):
+ os.makedirs(dest)
+ files = os.listdir(src)
+ if ignore is not None:
+ ignored = ignore(src, files)
+ else:
+ ignored = set()
+ for f in files:
+ if f not in ignored:
+ _recursive_overwrite(os.path.join(src, f), os.path.join(dest, f), ignore)
+ else:
+ shutil.copyfile(src, dest)
+
+ _recursive_overwrite(uhd_source, dest)
else:
- temp_path = "tempdir"
-
- #Extracting contents of zip file
- if os.path.exists(temp_path):
- shutil.rmtree(temp_path)
- os.mkdir(temp_path)
-
- images_zip = zipfile.ZipFile(filename)
- images_zip.extractall(temp_path)
+ shutil.copytree(uhd_source, dest)
- #Removing images currently in images_dir
- if os.path.exists(images_dir):
- try:
- shutil.rmtree(images_dir)
- 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(os.path.join(temp_path, os.path.splitext(filename)[0], 'share', 'uhd', 'images'), images_dir)
-
- #Removing tempdir and zip file
- shutil.rmtree(temp_path)
- images_zip.close()
- os.remove(filename)
+def main():
+ 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 = _DEFAULT_INSTALL_PATH
+
+ parser = OptionParser()
+ parser.add_option("-i", "--install-location", type="string", default=default_images_dir,
+ help="Set custom install location for images [default=%default]")
+ parser.add_option("--buffer-size", type="int", default=_DEFAULT_BUFFER_SIZE,
+ help="Set download buffer size [default=%default]")
+ parser.add_option("-u", "--url", type="string", default=_AUTOGEN_IMAGES_SOURCE,
+ help="Set images download location [default=%default]")
+ parser.add_option("-c", "--checksum", type="string", default=_AUTOGEN_IMAGES_CHECKSUM,
+ help="Validate images archive against this checksum (blank to skip) [default=%default]")
+ parser.add_option("-t", "--checksum-type", type="string", default=_IMAGES_CHECKSUM_TYPE,
+ help=("Select checksum hash function (options: %s) [default=%%default]" % (",".join(_checksum_fns.keys()))))
+ parser.add_option("-k", "--keep", action="store_true", default=False,
+ help="Do not clear images directory before extracting new files [default=%default]")
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="Enable verbose output [default=%default]")
+
+ (options, args) = parser.parse_args()
+
+ if options.buffer_size <= 0:
+ print "Invalid buffer size: %s" % (options.buffer_size)
+ return 1
+
+ checksum_fn = None
+ if options.checksum != "":
+ options.checksum_type = options.checksum_type.lower()
+ if not _checksum_fns.has_key(options.checksum_type):
+ print "Not a supported checksum function: %s" % (options.checksum_type)
+ return 1
+ checksum_fn = _checksum_fns[options.checksum_type]
+
+ url_parts = options.url.split("/")
+ if len(url_parts) <= 1 or url_parts[-1] == "":
+ print "Not a valid URL: %s" % (options.url)
+ return 1
+ images_filename = url_parts[-1]
+
+ images_dir = os.path.abspath(options.install_location) # This will use the current working directory if it's not absolute
+
+ if options.verbose:
+ print "Requested install location: %s" % (options.install_location)
+ print "Images source: %s" % (options.url)
+ print "Images filename: %s" % (images_filename)
+ print "Images checksum: %s (%s)" % (options.checksum, _IMAGES_CHECKSUM_TYPE)
+ print "Final install location: %s" % (images_dir)
+ else:
+ print "Images destination: %s" % (images_dir)
+
+ downloader = uhd_images_downloader()
+
+ try:
+ (access, last_path) = downloader.check_directories(images_dir, print_progress=options.verbose)
+ if access:
+ with temporary_directory() as temp_dir:
+ if options.verbose:
+ print "Using temporary directory: %s" % (temp_dir)
+
+ print "Downloading images from: %s" % options.url
+
+ temp_images_dest = os.path.join(temp_dir, images_filename)
+
+ print "Downloading images to: %s" % (temp_images_dest)
+
+ (reported_size, downloaded_size) = downloader.download(images_url=options.url, filename=temp_images_dest, buffer_size=options.buffer_size, print_progress=True)
+
+ if options.verbose:
+ print "Downloaded %d of %d bytes" % (downloaded_size, reported_size)
+
+ (checksum_match, calculated_checksum) = downloader.validate_checksum(checksum_fn, temp_images_dest, options.checksum, print_progress=options.verbose)
+
+ if options.verbose:
+ print "Calculated checksum: %s" % (calculated_checksum)
+
+ if checksum_match:
+ if options.verbose:
+ if options.checksum == "":
+ print "Ignoring checksum"
+ else:
+ print "Checksum OK"
+
+ try:
+ extract_path = downloader.extract_images_archive(temp_images_dest, print_progress=options.verbose)
+
+ if options.verbose:
+ print "Image archive extracted to: %s" % (extract_path)
+
+ downloader.install_images(extract_path, images_dir, options.keep, print_progress=options.verbose)
+
+ print
+ print "Images successfully installed to: %s" % (images_dir)
+ except Exception, e:
+ print "Failed to install image archive: %s" % (e)
+ print "This is usually a permissions problem."
+ print "Please check your file system access rights and try again."
+
+ if options.verbose:
+ traceback.print_exc()
+ else:
+ print "You can run this again with the '--verbose' flag to see more information"
+ print "If the problem persists, please email the output to: %s" % (_CONTACT)
+ else:
+ print "Checksum of downloaded file is not correct (not installing - see options to override)"
+ print "Expected: %s" % (options.checksum)
+ print "Calculated: %s" % (calculated_checksum)
+ print "Please try downloading again."
+ print "If the problem persists, please email the output to: %s" % (_CONTACT)
+ else:
+ print "You do not have sufficient permissions to write to: %s" % (last_path)
+ print "Are you root?"
+ except KeyboardInterrupt:
+ print
+ print "Cancelled at user request"
+ except Exception, e:
+ print "Downloader raised an unhandled exception: %s" % (e)
+ if options.verbose:
+ traceback.print_exc()
+ else:
+ print "You can run this again with the '--verbose' flag to see more information"
+ print "If the problem persists, please email the output to: %s" % (_CONTACT)
+ return 1
+
+ return 0
- os.chdir(images_dir)
- print "\n\nImages successfully installed!"
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/host/utils/usrp_n2xx_simple_net_burner.cpp b/host/utils/usrp_n2xx_simple_net_burner.cpp
index c3ccba173..1898ee9ae 100644
--- a/host/utils/usrp_n2xx_simple_net_burner.cpp
+++ b/host/utils/usrp_n2xx_simple_net_burner.cpp
@@ -468,13 +468,21 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << "Searching for specified images." << std::endl << std::endl;
if(burn_fpga){
if(!use_custom_fpga) fpga_path = find_image_path(default_fpga_filename);
- else validate_custom_fpga_file(filename_map[hw_rev], fpga_path);
+ else{
+ //Replace ~ with home directory
+ if(fpga_path.find("~/") == 0) fpga_path.replace(0,1,getenv("HOME"));
+ validate_custom_fpga_file(filename_map[hw_rev], fpga_path);
+ }
grab_fpga_image(fpga_path);
}
if(burn_fw){
if(!use_custom_fw) fw_path = find_image_path(default_fw_filename);
- else validate_custom_fw_file(filename_map[hw_rev], fw_path);
+ else{
+ //Replace ~ with home directory
+ if(fw_path.find("~/") == 0) fw_path.replace(0,1,getenv("HOME"));
+ validate_custom_fw_file(filename_map[hw_rev], fw_path);
+ }
grab_fw_image(fw_path);
}