aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Corgan <nick.corgan@ettus.com>2015-08-05 08:46:28 -0700
committerMartin Braun <martin.braun@ettus.com>2015-08-05 13:04:04 -0700
commitbb62ab84fdad6f7cf18ea55d395dfbd7f11ed79d (patch)
treeab9bb3a78f10661e12b832c9c341d027463739ba
parentc3c9513b9b5f67afe4233659222fdfc5bbb2511c (diff)
downloaduhd-bb62ab84fdad6f7cf18ea55d395dfbd7f11ed79d.tar.gz
uhd-bb62ab84fdad6f7cf18ea55d395dfbd7f11ed79d.tar.bz2
uhd-bb62ab84fdad6f7cf18ea55d395dfbd7f11ed79d.zip
image_loader: force user to specify device
* On utility level, force user to use --args=type=foo * In each loader, throw an error if args are ambiguous
-rw-r--r--host/include/uhd/image_loader.hpp3
-rw-r--r--host/lib/usrp/b200/b200_image_loader.cpp33
-rw-r--r--host/lib/usrp/usrp2/n200_image_loader.cpp80
-rw-r--r--host/lib/usrp/x300/x300_image_loader.cpp32
-rw-r--r--host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp48
-rw-r--r--host/utils/uhd_image_loader.cpp5
6 files changed, 148 insertions, 53 deletions
diff --git a/host/include/uhd/image_loader.hpp b/host/include/uhd/image_loader.hpp
index 8124e7dea..5963c862f 100644
--- a/host/include/uhd/image_loader.hpp
+++ b/host/include/uhd/image_loader.hpp
@@ -46,8 +46,9 @@ public:
*
* This function must return true upon the end of a successful image load
* or false if no applicable device was found. It may only throw a runtime
- * error under one of two conditions:
+ * error under one of three conditions:
*
+ * * The function finds multiple devices that fit the user's arguments.
* * The function has already engaged with a specific device and
* something goes wrong.
* * The user gives arguments that unambiguously lead to a specific
diff --git a/host/lib/usrp/b200/b200_image_loader.cpp b/host/lib/usrp/b200/b200_image_loader.cpp
index 87010244c..9eaeeff63 100644
--- a/host/lib/usrp/b200/b200_image_loader.cpp
+++ b/host/lib/usrp/b200/b200_image_loader.cpp
@@ -40,27 +40,50 @@ static b200_iface::sptr get_b200_iface(const image_loader::image_loader_args_t &
bool user_specified){
std::vector<usb_device_handle::sptr> dev_handles = get_b200_device_handles(image_loader_args.args);
+ std::vector<usb_device_handle::sptr> applicable_dev_handles;
b200_iface::sptr iface;
+ mboard_eeprom_t eeprom; // Internal use
if(dev_handles.size() > 0){
BOOST_FOREACH(usb_device_handle::sptr dev_handle, dev_handles){
if(dev_handle->firmware_loaded()){
iface = b200_iface::make(usb_control::make(dev_handle,0));
- mb_eeprom = mboard_eeprom_t(*iface, "B200");
+ eeprom = mboard_eeprom_t(*iface, "B200");
if(user_specified){
if(image_loader_args.args.has_key("serial") and
- mb_eeprom.get("serial") != image_loader_args.args.get("serial")){
+ eeprom.get("serial") != image_loader_args.args.get("serial")){
continue;
}
if(image_loader_args.args.has_key("name") and
- mb_eeprom.get("name") != image_loader_args.args.get("name")){
+ eeprom.get("name") != image_loader_args.args.get("name")){
continue;
}
- return iface;
+ applicable_dev_handles.push_back(dev_handle);
}
- else return iface; // Just return first found
+ else applicable_dev_handles.push_back(dev_handle);
}
}
+
+ // At this point, we should have a single B2XX
+ if(applicable_dev_handles.size() == 1){
+ mb_eeprom = eeprom;
+ return iface;
+ }
+ else if(applicable_dev_handles.size() > 1){
+ std::string err_msg = "Could not resolve given args to a single B2XX device.\n"
+ "Applicable devices:\n";
+
+ BOOST_FOREACH(usb_device_handle::sptr dev_handle, applicable_dev_handles){
+ eeprom = mboard_eeprom_t(*b200_iface::make(usb_control::make(dev_handle,0)), "B200");
+ err_msg += str(boost::format(" * %s (serial=%s)\n")
+ % B2X0_STR_NAMES.get(get_b200_type(mb_eeprom), "B2XX")
+ % mb_eeprom.get("serial"));
+ }
+
+ err_msg += "\nSpecify one of these devices with the given args to load an image onto it.";
+
+ throw uhd::runtime_error(err_msg);
+ }
}
// No applicable devices found, return empty sptr so we can exit
diff --git a/host/lib/usrp/usrp2/n200_image_loader.cpp b/host/lib/usrp/usrp2/n200_image_loader.cpp
index ce956c22c..29bec8b4a 100644
--- a/host/lib/usrp/usrp2/n200_image_loader.cpp
+++ b/host/lib/usrp/usrp2/n200_image_loader.cpp
@@ -210,36 +210,62 @@ static uhd::device_addr_t n200_find(const image_loader::image_loader_args_t &ima
image_loader_args.args.has_key("name");
uhd::device_addrs_t found = usrp2_find(image_loader_args.args);
- if(found.size() > 0){
- uhd::device_addr_t ret = found[0];
-
- /*
- * Make sure the device found is an N-Series and not a USRP2. A USRP2
- * will not respond to this query. If the user supplied specific
- * arguments that led to a USRP2, throw an error.
- */
- udp_simple::sptr rev_xport = udp_simple::make_connected(
- ret["addr"],
- BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT)
- );
+ if(found.size() > 0){
+ uhd::device_addrs_t n200_found;
+ udp_simple::sptr rev_xport;
n200_fw_update_data_t pkt_out;
boost::uint8_t data_in[udp_simple::mtu];
const n200_fw_update_data_t *pkt_in = reinterpret_cast<const n200_fw_update_data_t*>(data_in);
+ size_t len = 0;
- size_t len = n200_send_and_recv(rev_xport, GET_HW_REV_CMD, &pkt_out, data_in);
- if(n200_response_matches(pkt_in, GET_HW_REV_ACK, len)){
- boost::uint32_t rev = ntohl(pkt_in->data.hw_rev);
- ret["hw_rev"] = n200_filename_map.get(rev, "n2xx");
- return ret;
+ /*
+ * Filter out any USRP2 devices by sending a query over the
+ * UDP update port. Only N-Series devices will respond to
+ * this query. If the user supplied specific arguments that
+ * led to a USRP2, throw an error.
+ */
+ BOOST_FOREACH(const uhd::device_addr_t &dev, found){
+ rev_xport = udp_simple::make_connected(
+ dev.get("addr"),
+ BOOST_STRINGIZE(N200_UDP_FW_UPDATE_PORT)
+ );
+
+ len = n200_send_and_recv(rev_xport, GET_HW_REV_CMD, &pkt_out, data_in);
+ if(n200_response_matches(pkt_in, GET_HW_REV_ACK, len)){
+ boost::uint32_t rev = ntohl(pkt_in->data.hw_rev);
+ std::string hw_rev = n200_filename_map.get(rev, "n2xx");
+
+ n200_found.push_back(dev);
+ n200_found[n200_found.size()-1]["hw_rev"] = hw_rev;
+ }
+ else if(len > offsetof(n200_fw_update_data_t, data) and ntohl(pkt_in->id) != GET_HW_REV_ACK){
+ throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.")
+ % ntohl(pkt_in->id)));
+ }
+ else if(user_specified){
+ // At this point, we haven't received any response, so assume it's a USRP2
+ print_usrp2_error(image_loader_args);
+ }
}
- else if(len > offsetof(n200_fw_update_data_t, data) and ntohl(pkt_in->id) != GET_HW_REV_ACK){
- throw uhd::runtime_error(str(boost::format("Received invalid reply %d from device.")
- % ntohl(pkt_in->id)));
+
+ // At this point, we should have a single N-Series device
+ if(n200_found.size() == 1){
+ return n200_found[0];
}
- else if(user_specified){
- // At this point, we haven't received any response, so assume it's a USRP2
- print_usrp2_error(image_loader_args);
+ else if(n200_found.size() > 1){
+ std::string err_msg = "Could not resolve given args to a single N-Series device.\n"
+ "Applicable devices:\n";
+
+ BOOST_FOREACH(const uhd::device_addr_t &dev, n200_found){
+ err_msg += str(boost::format("* %s (addr=%s)\n")
+ % dev.get("hw_rev")
+ % dev.get("addr"));
+ }
+
+ err_msg += "\nSpecify one of these devices with the given args to load an image onto it.";
+
+ throw uhd::runtime_error(err_msg);
}
}
@@ -259,7 +285,7 @@ static void n200_validate_firmware_image(n200_session_t &session){
session.max_size = N200_FW_MAX_SIZE_BYTES;
if(session.size > session.max_size){
- throw uhd::runtime_error(str(boost::format("The specified FPGA image is too large: %d vs. %d")
+ throw uhd::runtime_error(str(boost::format("The specified firmware image is too large: %d vs. %d")
% session.size % session.max_size));
}
@@ -559,11 +585,15 @@ static std::string nice_name(const std::string &fw_rev){
}
static bool n200_image_loader(const image_loader::image_loader_args_t &image_loader_args){
+ if(!image_loader_args.load_firmware and !image_loader_args.load_fpga){
+ return false;
+ }
+
// See if any N2x0 with the given args is found
// This will throw if specific args lead to a USRP2
n200_session_t session;
session.dev_addr = n200_find(image_loader_args);
- if(session.dev_addr.size() == 0 or (!image_loader_args.load_firmware and !image_loader_args.load_fpga)){
+ if(session.dev_addr.size() == 0){
return false;
}
diff --git a/host/lib/usrp/x300/x300_image_loader.cpp b/host/lib/usrp/x300/x300_image_loader.cpp
index 321309868..9ec8a2e13 100644
--- a/host/lib/usrp/x300/x300_image_loader.cpp
+++ b/host/lib/usrp/x300/x300_image_loader.cpp
@@ -158,17 +158,31 @@ static void x300_validate_image(x300_session_t &session){
static void x300_setup_session(x300_session_t &session,
const device_addr_t &args,
const std::string &filepath){
- device_addr_t find_args;
- find_args["type"] = "x300";
- if(args.has_key("name")) find_args["name"] = args["name"];
- if(args.has_key("serial")) find_args["serial"] = args["serial"];
- if(args.has_key("ip-addr")) find_args["addr"] = args["ip-addr"];
- else if(args.has_key("resource")) find_args["resource"] = args["resource"];
-
device_addrs_t devs = x300_find(args);
- session.found = (devs.size() > 0);
- if(!session.found) return;
+ if(devs.size() == 0){
+ session.found = false;
+ return;
+ }
+ else if(devs.size() > 1){
+ std::string err_msg = "Could not resolve given args to a single X-Series device.\n"
+ "Applicable devices:\n";
+
+ BOOST_FOREACH(const uhd::device_addr_t &dev, devs){
+ std::string identifier = dev.has_key("addr") ? "addr"
+ : "resource";
+
+ err_msg += str(boost::format(" * %s (%s=%s)\n")
+ % dev.get("product", "X3XX")
+ % identifier
+ % dev.get(identifier));
+ }
+
+ err_msg += "\nSpecify one of these devices with the given args to load an image onto it.";
+
+ throw uhd::runtime_error(err_msg);
+ }
+ session.found = true;
session.dev_addr = devs[0];
session.ethernet = session.dev_addr.has_key("addr");
if(session.ethernet){
diff --git a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
index c88177f0f..e8c50e029 100644
--- a/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
+++ b/host/lib/usrp_clock/octoclock/octoclock_image_loader.cpp
@@ -51,7 +51,7 @@ using namespace uhd::transport;
* OctoClock burn session
*/
typedef struct {
- bool valid;
+ bool found;
uhd::device_addr_t dev_addr;
std::string given_filepath;
std::string actual_filepath; // If using a .hex, this is the converted .bin
@@ -113,18 +113,43 @@ static void octoclock_validate_firmware_image(octoclock_session_t &session){
: (session.size / OCTOCLOCK_BLOCK_SIZE);
octoclock_calculate_crc(session);
- session.valid = true;
}
static void octoclock_setup_session(octoclock_session_t &session,
+ const uhd::device_addr_t &args,
const std::string &filepath){
+ // See if we can find an OctoClock with the given args
+ device_addrs_t devs = octoclock_find(args);
+ if(devs.size() == 0){
+ session.found = false;
+ return;
+ }
+ else if(devs.size() > 1){
+ std::string err_msg = "Could not resolve given args to a single OctoClock device.\n"
+ "Applicable devices:\n";
+
+ BOOST_FOREACH(const uhd::device_addr_t &dev, devs){
+ std::string name = (dev["type"] == "octoclock") ? str(boost::format("OctoClock r%d")
+ % dev.get("revision","4"))
+ : "OctoClock Bootloader";
+ err_msg += str(boost::format(" * %s (addr=%s)\n")
+ % name
+ % dev.get("addr"));
+ }
+
+ err_msg += "\nSpecify one of these devices with the given args to load an image onto it.";
+
+ throw uhd::runtime_error(err_msg);
+ }
+
+ session.dev_addr = devs[0];
+
// If no filepath is given, use the default
if(filepath == ""){
- session.given_filepath = find_image_path(str(boost::format("octoclock_r%d_fw.hex")
- % boost::lexical_cast<std::string>(
- session.dev_addr.get("revision","4")
- )));
+ session.given_filepath = find_image_path(str(boost::format("octoclock_r%s_fw.hex")
+ % session.dev_addr.get("revision","4")
+ ));
}
else session.given_filepath = filepath;
@@ -287,7 +312,7 @@ static void octoclock_verify(octoclock_session_t &session){
}
static void octoclock_finalize(octoclock_session_t &session){
-
+
octoclock_packet_t pkt_out;
pkt_out.sequence = htonx<boost::uint32_t>(std::rand());
const octoclock_packet_t* pkt_in = reinterpret_cast<const octoclock_packet_t*>(session.data_in);
@@ -305,15 +330,12 @@ static void octoclock_finalize(octoclock_session_t &session){
}
bool octoclock_image_loader(const image_loader::image_loader_args_t &image_loader_args){
- // See if we can find an OctoClock with the given args
- device_addrs_t devs = octoclock_find(image_loader_args.args);
- if(devs.size() == 0 or !image_loader_args.load_firmware) return false;
-
octoclock_session_t session;
- session.dev_addr = devs[0];
octoclock_setup_session(session,
+ image_loader_args.args,
image_loader_args.firmware_path
);
+ if(!session.found or !image_loader_args.load_firmware) return false;
std::cout << boost::format("Unit: OctoClock (%s)")
% session.dev_addr["addr"]
@@ -329,7 +351,7 @@ bool octoclock_image_loader(const image_loader::image_loader_args_t &image_loade
UHD_STATIC_BLOCK(register_octoclock_image_loader){
std::string recovery_instructions = "Aborting. Your OctoClock firmware is now corrupt. The bootloader\n"
- "is functional, but the device will not have functional clock distribution."
+ "is functional, but the device will not have functional clock distribution.\n"
"Run this utility again to restore functionality or refer to:\n\n"
"http://files.ettus.com/manual/page_octoclock.html\n\n"
"for alternative setups.";
diff --git a/host/utils/uhd_image_loader.cpp b/host/utils/uhd_image_loader.cpp
index 39efc8f1e..5ea789ee2 100644
--- a/host/utils/uhd_image_loader.cpp
+++ b/host/utils/uhd_image_loader.cpp
@@ -91,6 +91,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
image_loader_args.firmware_path = vm["fw-path"].as<std::string>();
image_loader_args.fpga_path = vm["fpga-path"].as<std::string>();
+ // Force user to specify a device
+ if(not image_loader_args.args.has_key("type")){
+ throw uhd::runtime_error("You must specify a device type.");
+ }
+
// Clean up paths, if given
if(image_loader_args.firmware_path != ""){
#ifndef UHD_PLATFORM_WIN32