diff options
Diffstat (limited to 'host/utils')
-rw-r--r-- | host/utils/CMakeLists.txt | 2 | ||||
-rw-r--r-- | host/utils/b2xx_fx3_utils.cpp | 268 | ||||
-rw-r--r-- | host/utils/uhd_images_downloader.py.in | 435 | ||||
-rw-r--r-- | host/utils/usrp_n2xx_simple_net_burner.cpp | 12 |
4 files changed, 503 insertions, 214 deletions
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index f73690475..abf2a546b 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -47,7 +47,7 @@ SET(util_share_sources IF(ENABLE_USB) LIST(APPEND util_share_sources fx2_init_eeprom.cpp - b2xx_fx3_utils + b2xx_fx3_utils.cpp ) INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS}) # Additional include directories for b2xx_fx3_utils diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp index c182548b7..96cd1f3e7 100644 --- a/host/utils/b2xx_fx3_utils.cpp +++ b/host/utils/b2xx_fx3_utils.cpp @@ -44,6 +44,27 @@ namespace po = boost::program_options; namespace fs = boost::filesystem; +struct vid_pid_t { + boost::uint16_t vid; + boost::uint16_t pid; +}; +const static vid_pid_t known_vid_pids[] = { + {FX3_VID, FX3_DEFAULT_PID}, + {FX3_VID, FX3_REENUM_PID}, + {B200_VENDOR_ID, B200_PRODUCT_ID} + }; +const static std::vector<vid_pid_t> known_vid_pid_vector(known_vid_pids, known_vid_pids + (sizeof(known_vid_pids) / sizeof(known_vid_pids[0]))); +const static boost::uint8_t eeprom_init_values[] = { + 0x43, + 0x59, + 0x14, + 0xB2, + (B200_PRODUCT_ID & 0xff), + (B200_PRODUCT_ID >> 8), + (B200_VENDOR_ID & 0xff), + (B200_VENDOR_ID >> 8) + }; +const static uhd::byte_vector_t eeprom_init_value_vector(eeprom_init_values, eeprom_init_values + (sizeof(eeprom_init_values) / sizeof(eeprom_init_values[0]))); //!used with lexical cast to parse a hex string template <class T> struct to_hex{ @@ -96,6 +117,9 @@ int reset_usb() std::string file = fs::path((*it).filename()).string(); + if (file.length() < 5) + continue; + if(file.compare(0, 5, "0000:") == 0) { /* Un-bind the device. */ std::fstream unbind((devpath.string() + "unbind").c_str(), @@ -118,22 +142,30 @@ int reset_usb() return 0; } -uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, const boost::uint16_t pid) +uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, const boost::uint16_t pid, const bool user_supplied = false) { std::vector<uhd::transport::usb_device_handle::sptr> handles; uhd::transport::usb_device_handle::sptr handle; + vid_pid_t vp = {vid, pid}; 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 + // try caller's VID/PID first + handles = uhd::transport::usb_device_handle::get_device_list(vp.vid,vp.pid); + if (user_supplied && handles.size() == 0) + std::cerr << (boost::format("Failed to open device with VID 0x%04x and PID 0x%04x - trying other known VID/PIDs") % vid % pid).str() << std::endl; + + // try known VID/PIDs next + for (size_t i = 0; handles.size() == 0 && i < known_vid_pid_vector.size(); i++) + { + vp = known_vid_pid_vector[i]; + handles = uhd::transport::usb_device_handle::get_device_list(vp.vid,vp.pid); + } if (handles.size() > 0) + { handle = handles[0]; + std::cout << (boost::format("Device opened (VID=0x%04x,PID=0x%04x)") % vp.vid % vp.pid).str() << std::endl; + } if (!handle) std::cerr << "Cannot open device" << std::endl; @@ -141,7 +173,7 @@ uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, c 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; + std::cerr << "The necessary drivers are not installed. Read the UHD Transport Application Notes for details:\nhttp://files.ettus.com/uhd_docs/manual/html/transport.html" << std::endl; #endif /* UHD_PLATFORM_WIN32 */ handle.reset(); } @@ -163,7 +195,7 @@ b200_iface::sptr make_b200_iface(const uhd::transport::usb_device_handle::sptr & 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; + std::cerr << "The necessary drivers are not installed. Read the UHD Transport Application Notes for details:\nhttp://files.ettus.com/uhd_docs/manual/html/transport.html" << std::endl; #endif /* UHD_PLATFORM_WIN32 */ b200.reset(); } @@ -171,9 +203,83 @@ b200_iface::sptr make_b200_iface(const uhd::transport::usb_device_handle::sptr & return b200; } +int read_eeprom(b200_iface::sptr& b200, 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; + } + + return 0; +} + +int write_eeprom(b200_iface::sptr& b200, const uhd::byte_vector_t& data) +{ + try { + b200->write_eeprom(0x0, 0x0, data); + } catch (std::exception &e) { + std::cerr << "Exception while writing EEPROM: " << e.what() << std::endl; + return -1; + } + + return 0; +} + +int verify_eeprom(b200_iface::sptr& b200, const uhd::byte_vector_t& data) +{ + bool verified = true; + uhd::byte_vector_t read_bytes; + if (read_eeprom(b200, read_bytes)) + return -1; + + if (data.size() != read_bytes.size()) + { + std::cerr << "ERROR: Only able to verify first " << std::min(data.size(), read_bytes.size()) << " bytes." << std::endl; + verified = false; + } + + for (size_t i = 0; i < std::min(data.size(), read_bytes.size()); i++) { + if (data[i] != read_bytes[i]) { + verified = false; + std::cerr << "Byte " << i << " Expected: " << data[i] << ", Got: " << read_bytes[i] << std::endl; + } + } + + if (!verified) { + std::cerr << "Verification failed" << std::endl; + return -1; + } + + return 0; +} + +int write_and_verify_eeprom(b200_iface::sptr& b200, const uhd::byte_vector_t& data) +{ + if (write_eeprom(b200, data)) + return -1; + if (verify_eeprom(b200, data)) + return -1; + + return 0; +} + +int erase_eeprom(b200_iface::sptr& b200) +{ + uhd::byte_vector_t bytes(8); + + memset(&bytes[0], 0xFF, 8); + if (write_and_verify_eeprom(b200, bytes)) + return -1; + + return 0; +} + boost::int32_t main(boost::int32_t argc, char *argv[]) { boost::uint16_t vid, pid; std::string pid_str, vid_str, fw_file, fpga_file; + bool user_supplied_vid_pid = false; po::options_description visible("Allowed options"); visible.add_options() @@ -205,13 +311,24 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { desc.add(hidden); po::variables_map vm; - po::store(po::parse_command_line(argc, argv, desc), vm); - po::notify(vm); - if (vm.count("help")){ + try { + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + } catch (std::exception &e) { + std::cerr << "Exception while parsing arguments: " << e.what() << std::endl; std::cout << boost::format("B2xx Utility Program %s") % visible << std::endl; return ~0; - } else if (vm.count("reset-usb")) { + } + + if (vm.count("help")){ + try { + std::cout << boost::format("B2xx Utility Program %s") % visible << std::endl; + } catch(...) {} + return ~0; + } + + if (vm.count("reset-usb")) { return reset_usb(); } @@ -220,13 +337,20 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { vid = B200_VENDOR_ID; // Default pid = B200_PRODUCT_ID; // Default - if (vm.count("vid")) - vid = atoh(vid_str); - if (vm.count("pid")) - pid = atoh(pid_str); + if (vm.count("vid") && vm.count("pid")) + { + try { + vid = atoh(vid_str); + pid = atoh(pid_str); + } catch (std::exception &e) { + std::cerr << "Exception while parsing VID and PID: " << e.what() << std:: endl; + return ~0; + } + user_supplied_vid_pid = true; + } // open the device - handle = open_device(vid, pid); + handle = open_device(vid, pid, user_supplied_vid_pid); if (!handle) return -1; std::cout << "B2xx detected..." << std::flush; @@ -242,8 +366,19 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { { std::cout << "Overwriting existing firmware" << std::endl; + // before we reset, make sure we have a good firmware file + if(!(fs::exists(fw_file))) + { + std::cerr << "Invalid firmware filepath: " << fw_file << std::endl; + return -1; + } + // reset the device - b200->reset_fx3(); + try { + b200->reset_fx3(); + } catch (std::exception &e) { + std::cerr << "Exception while reseting FX3: " << e.what() << std::endl; + } // re-open device b200.reset(); @@ -264,19 +399,24 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { 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 - b200->load_firmware(fw_file); + 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(); @@ -287,6 +427,8 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { b200 = make_b200_iface(handle); if (!b200) return -1; + + std::cout << "Firmware loaded" << std::endl; } // Added for testing purposes - not exposed @@ -294,12 +436,9 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { { 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; + if (read_eeprom(b200, data)) return -1; - } + for (int i = 0; i < 8; i++) std::cout << i << ": " << boost::format("0x%X") % (int)data[i] << std::endl; @@ -309,34 +448,8 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { // 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; - } - - // 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; + if (erase_eeprom(b200)) 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; - } - } - if (!verified) { - std::cerr << "Verification failed" << std::endl; - return -1; - } std::cout << "Erase Successful!" << std::endl; @@ -346,16 +459,8 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { // 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; - } + // erase EEPROM + erase_eeprom(b200); std::cout << "EEPROM uninitialized, resetting device..." << std::endl << std::endl; @@ -379,22 +484,8 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { if (vm.count("init-device")) { /* Now, initialize the device. */ - uhd::byte_vector_t bytes(8); - bytes[0] = 0x43; - bytes[1] = 0x59; - bytes[2] = 0x14; - bytes[3] = 0xB2; - 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; + if (write_and_verify_eeprom(b200, eeprom_init_value_vector)) return -1; - } std::cout << "EEPROM initialized, resetting device..." << std::endl << std::endl; @@ -403,7 +494,7 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { try { b200->reset_fx3(); } catch (const std::exception &e) { - std::cerr << "Exceptions while resetting device: " << e.what() << std::endl; + std::cerr << "Exception while resetting device: " << e.what() << std::endl; return -1; } @@ -423,8 +514,9 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { return -1; } std::cout << "Currently operating at USB " << (int) speed << std::endl; + } - } else if (vm.count("reset-device")) { + if (vm.count("reset-device")) { try {b200->reset_fx3();} catch (uhd::exception &e) { std::cerr << "Exception while resetting FX3: " << e.what() << std::endl; @@ -438,10 +530,6 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { return -1; } - } else if (vm.count("load-fw")) { - std::cout << "Firmware load complete, releasing USB interface..." - << std::endl; - } else if (vm.count("load-fpga")) { std::cout << "Loading FPGA image (" << fpga_file << ")" << std::endl; uint32_t fx3_state; @@ -452,17 +540,13 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { } if (fx3_state != 0) { - std::cerr << std::flush << "Error loading FPGA. FX3 state: " - << fx3_state << std::endl; + std::cerr << std::flush << "Error loading FPGA. FX3 state (" + << fx3_state << "): " << b200_iface::fx3_state_string(fx3_state) << std::endl; return ~0; } std::cout << "FPGA load complete, releasing USB interface..." << std::endl; - - } else { - std::cout << boost::format("B2xx Utility Program %s") % visible << std::endl; - return ~0; } std::cout << "Operation complete! I did it! I did it!" << std::endl; 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); } |