diff options
| author | Martin Braun <martin.braun@ettus.com> | 2015-01-28 22:10:10 +0100 | 
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2015-01-28 22:10:10 +0100 | 
| commit | db3fac73beb30ceaaf6a275d9668a38af3b839f5 (patch) | |
| tree | d0713571a7a4d14d38c4d6c59337e6fbfca1f4a1 | |
| parent | 156c21206e8bccf4b5680a62c28a7dc7544aa9be (diff) | |
| parent | 75d519706b9b0956307a6a4bdc53c36376f19f03 (diff) | |
| download | uhd-db3fac73beb30ceaaf6a275d9668a38af3b839f5.tar.gz uhd-db3fac73beb30ceaaf6a275d9668a38af3b839f5.tar.bz2 uhd-db3fac73beb30ceaaf6a275d9668a38af3b839f5.zip | |
Merge paths-fix branch into maint.
29 files changed, 416 insertions, 312 deletions
| diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index c90c5de14..4a6c171f5 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -60,6 +60,26 @@ SET(PKG_DOC_DIR share/doc/uhd)  SET(PKG_MAN_DIR share/man/man1)  ######################################################################## +# UHD Image Directories +######################################################################## +IF(NOT DEFINED UHD_IMAGES_DIR) +    IF(DEFINED FPGA_IMAGES_DIR) +        SET(UHD_IMAGES_DIR ${FPGA_IMAGES_DIR}) +    ELSE(DEFINED FPGA_IMAGES_DIR) +        FILE(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/share/uhd/images using_images_dir) +        SET(UHD_IMAGES_DIR ${using_images_dir}) +    ENDIF(DEFINED FPGA_IMAGES_DIR) +ENDIF(NOT DEFINED UHD_IMAGES_DIR) + +OPTION(UHD_IMAGES_DIR "Path to installed UHD image binaries.") +MESSAGE( STATUS "Using UHD Images Directory: ${UHD_IMAGES_DIR}" ) +ADD_DEFINITIONS(-DUHD_IMAGES_DIR=${UHD_IMAGES_DIR}) + +IF(DEFINED USE_NIUSRP_WINREG_KEY) +    ADD_DEFINITIONS(-DUSE_NIUSRP_WINREG_KEY) +ENDIF(DEFINED USE_NIUSRP_WINREG_KEY) + +########################################################################  # Local Include Dir  ########################################################################  INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include) @@ -362,7 +382,7 @@ UHD_INSTALL(  )  ######################################################################## -# Handle pre-built images +# Handle pre-built UHD Images meant for installation  ########################################################################  IF(DEFINED UHD_IMAGES_DIR AND EXISTS "${UHD_IMAGES_DIR}")      FILE(GLOB_RECURSE _image_files "${UHD_IMAGES_DIR}/*") diff --git a/host/docs/images.dox b/host/docs/images.dox index e00f599b5..bd2ffacf6 100644 --- a/host/docs/images.dox +++ b/host/docs/images.dox @@ -65,9 +65,9 @@ configure-time.  <b>Option 2:</b> -Unpack the archive anywhere and set the `UHD_IMAGES_PATH` -environment variable. `UHD_IMAGES_PATH` may contain a list of -directories to search for image files. +Unpack the archive anywhere and set the `UHD_IMAGES_DIR` environment variable. +The `UHD_IMAGES_DIR` environment variable may contain a list of paths. They +should be ordered by preference.  \section images_building Building Images diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index 619bd0787..7ecc4924a 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -92,4 +92,16 @@ typedef ptrdiff_t ssize_t;      #define UHD_PLATFORM_BSD  #endif +// Define 'stringize' preprocessor macros. The stringize macro, XSTR, takes +// variable arguments so that it can deal with strings that contain commas. +// There are two different versions because MSVC handles this syntax a bit +// differently than other compilers. +#if defined(BOOST_MSVC) +    #define XSTR(x,...) #x +#else +    #define XSTR(x...) #x +#endif + +#define STR(x) XSTR(x) +  #endif /* INCLUDED_UHD_CONFIG_HPP */ diff --git a/host/include/uhd/transport/nirio/nifpga_lvbitx.h b/host/include/uhd/transport/nirio/nifpga_lvbitx.h index 598f7fcbe..f037ffd47 100644 --- a/host/include/uhd/transport/nirio/nifpga_lvbitx.h +++ b/host/include/uhd/transport/nirio/nifpga_lvbitx.h @@ -51,8 +51,8 @@ public:  protected:      std::string _get_bitstream_checksum(const std::string& file_path); -    std::string _get_fpga_images_dir(const std::string search_paths);  }; +  }}  #endif /* INCLUDED_UHD_TRANSPORT_NIRIO_NIFPGA_LVBITX_H */ diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index c308c9cde..05f6892d2 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -25,7 +25,6 @@ UHD_INSTALL(FILES      cast.hpp      csv.hpp      gain_group.hpp -    images.hpp      log.hpp      math.hpp      msg.hpp diff --git a/host/include/uhd/utils/images.hpp b/host/include/uhd/utils/images.hpp deleted file mode 100644 index a0934fb08..000000000 --- a/host/include/uhd/utils/images.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright 2010,2012 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#ifndef INCLUDED_UHD_UTILS_IMAGES_HPP -#define INCLUDED_UHD_UTILS_IMAGES_HPP - -#include <uhd/config.hpp> -#include <string> - -namespace uhd{ - -    /*! -     * Search for an image in the system image paths: -     * Search compiled-in paths and environment variable paths -     * for a specific image file with the provided file name. -     * \param image_name the name of the file -     * \return the full system path to the file -     * \throw exception if the image was not found -     */ -    UHD_API std::string find_image_path(const std::string &image_name); - -    /*! -     * Search for the location of the UHD Images Downloader script. -     * \return the full system path to uhd_images_downloader.py -     */ - -    UHD_API std::string find_images_downloader(void); - -    /*! -     * Return the error string for recommending using the UHD Images Downloader. -     * String depends on OS. -     * \return the message suggesting the use of uhd_images_downloader.py -     */ - -    UHD_API std::string print_images_error(void); - -} //namespace uhd - -#endif /* INCLUDED_UHD_UTILS_IMAGES_HPP */ diff --git a/host/include/uhd/utils/paths.hpp b/host/include/uhd/utils/paths.hpp index e0f455e92..8edb87546 100644 --- a/host/include/uhd/utils/paths.hpp +++ b/host/include/uhd/utils/paths.hpp @@ -19,9 +19,15 @@  #define INCLUDED_UHD_UTILS_PATHS_HPP  #include <uhd/config.hpp> + +#include <boost/filesystem.hpp> +  #include <string> +#include <vector> -namespace uhd{ +namespace fs = boost::filesystem; + +namespace uhd {      //! Get a string representing the system's temporary directory      UHD_API std::string get_tmp_path(void); @@ -32,6 +38,56 @@ namespace uhd{      //! Get a string representing the system's pkg directory      UHD_API std::string get_pkg_path(void); +    //! Get UHD library paths +    std::vector<fs::path> get_module_paths(void); + +    /*! Return the UHD images directory path. +    * +    * This function returns the UHD images installation path on this system. The +    * returned directory path is guaranteed to exist (assuming a valid path is +    * found). This function will look for a directory that exists using this +    * order of precedence: +    * +    *   1) `UHD_IMAGES_DIR` environment variable +    *   2) Any paths passed to this function via `search_paths' +    *   3) UHD package path / share / uhd / images +    * +    * The `search_paths` parameter may contain Windows registry keys.  If no +    * directory is found, an empty string is returned. +    * +    * \param search_paths A comma-separated list of hints for paths to include. +    * \returns A path string if one is found, or an empty string on failure. +    */ +    UHD_API std::string get_images_dir(const std::string search_paths); + +    /*! Return the full path to particular UHD binary image. +     * +     * This function searches for the passed image name, and returns an absolute +     * path to it. The returned path is guaranteed to exist. The caller can also +     * provide a full path to the image in the argument, and this function will +     * validate it and convert it to an absolute system path. +     * +     * \param image_name The name of the file to search for, or the full path. +     * \param search_paths Hints / paths to use when calling `get_images_dir` +     * \return the full system path to the file +     * \throw exception uhd::io_error if the file was not found. +     */ +    UHD_API std::string find_image_path(const std::string &image_name, const std::string search_paths = ""); + +    /*! +     * Search for the location of a particular UHD utility. +     * The utility must be installed in the `uhd/utils` directory. +     * \param the name of the utility to search for +     * \return the full system path to @param +     */ +    UHD_API std::string find_utility(std::string name); + +    /*! +     * Return an error string recommending the user run the utility. +     * The error string will include the full path to the utility to run. +     * \return the message suggesting the use of the named utility. +     */ +    UHD_API std::string print_utility_error(std::string name);  } //namespace uhd  #endif /* INCLUDED_UHD_UTILS_PATHS_HPP */ diff --git a/host/lib/transport/nirio/lvbitx/CMakeLists.txt b/host/lib/transport/nirio/lvbitx/CMakeLists.txt index 35cfaa456..b9a2a9f15 100644 --- a/host/lib/transport/nirio/lvbitx/CMakeLists.txt +++ b/host/lib/transport/nirio/lvbitx/CMakeLists.txt @@ -27,7 +27,7 @@ MACRO(LIBUHD_LVBITX_GEN_SOURCE_AND_BITSTREAM lvbitx binfile)      ENDIF( ${binfile} STREQUAL "OFF" )      SET(OUTPUT_PATH_OPT --output-src-path=${CMAKE_CURRENT_BINARY_DIR}) -    SET(IMAGES_PATH_OPT --uhd-images-path=${FPGA_IMAGES_DIR}) +    SET(IMAGES_PATH_OPT --uhd-images-path=${UHD_IMAGES_DIR})      ADD_CUSTOM_COMMAND(          OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${lvbitxprefix}_lvbitx.hpp  @@ -53,11 +53,6 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})  MESSAGE(STATUS "")  MESSAGE(STATUS "Processing NI-RIO FPGA LVBITX Bitstreams...") -FILE(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/share/uhd/images default_images_dir) -SET( FPGA_IMAGES_DIR ${default_images_dir} CACHE STRING "Path to installed FPGA image files." ) -OPTION( FPGA_IMAGES_DIR "Path to installed FPGA image files." "" ) -MESSAGE( STATUS "  LVBITX install directory: ${FPGA_IMAGES_DIR}" ) -  # X300 Stuff  LIBUHD_LVBITX_GEN_SOURCE_AND_BITSTREAM(x300.lvbitx_base OFF) diff --git a/host/lib/transport/nirio/lvbitx/template_lvbitx.cpp b/host/lib/transport/nirio/lvbitx/template_lvbitx.cpp index a1899c771..8f1fb6b36 100644 --- a/host/lib/transport/nirio/lvbitx/template_lvbitx.cpp +++ b/host/lib/transport/nirio/lvbitx/template_lvbitx.cpp @@ -8,6 +8,7 @@  #include <boost/filesystem/path.hpp>  #include <boost/algorithm/string.hpp>  #include <boost/regex.hpp> +#include <uhd/utils/paths.hpp>  namespace uhd {{ namespace niusrprio {{ @@ -27,8 +28,9 @@ const char* {lvbitx_classname}_lvbitx::INPUT_FIFOS[] = {{{in_fifo_list}  {lvbitx_classname}_lvbitx::{lvbitx_classname}_lvbitx(const std::string& option)  {{ -    boost::filesystem::path fpga_path(_get_fpga_images_dir(SEARCH_PATHS)); -    fpga_path /= "usrp_{lvbitx_classname}_fpga_" + option + ".lvbitx"; +    std::string fpga_file = "usrp_{lvbitx_classname}_fpga_" + option + ".lvbitx"; +    boost::filesystem::path fpga_path(uhd::find_image_path(fpga_file, SEARCH_PATHS)); +      _fpga_file_name = fpga_path.string();      _bitstream_checksum = _get_bitstream_checksum(_fpga_file_name);  }} diff --git a/host/lib/transport/nirio/nifpga_lvbitx.cpp b/host/lib/transport/nirio/nifpga_lvbitx.cpp index b87d87a8d..8135a4d01 100644 --- a/host/lib/transport/nirio/nifpga_lvbitx.cpp +++ b/host/lib/transport/nirio/nifpga_lvbitx.cpp @@ -18,12 +18,8 @@  #include <uhd/transport/nirio/nifpga_lvbitx.h>  #include <cstdlib>  #include <string> -#include <iostream>  #include <fstream>  #include <streambuf> -#include <boost/foreach.hpp> -#include <boost/format.hpp> -#include <boost/filesystem.hpp>  #include <boost/algorithm/string.hpp>  #include <boost/regex.hpp> @@ -52,103 +48,4 @@ std::string nifpga_lvbitx::_get_bitstream_checksum(const std::string& file_path)      return checksum;  } -#ifdef UHD_PLATFORM_WIN32 -#include <windows.h> - -std::string _get_path_from_registry(const std::string& registry_key_path) -{ -    boost::smatch reg_key_match; -    //If a substring in the search path is enclosed in [] (square brackets) then it is interpreted as a registry path -    if (not boost::regex_search(registry_key_path, reg_key_match, boost::regex("\\[(.+)\\](.*)", boost::regex::icase))) -        return std::string(); -    std::string reg_key_path = std::string(reg_key_match[1].first, reg_key_match[1].second); -    std::string path_suffix = std::string(reg_key_match[2].first, reg_key_match[2].second); - -    //Split the registry path into parent, key-path and value. -    boost::smatch reg_parent_match; -    if (not boost::regex_search(reg_key_path, reg_parent_match, boost::regex("^(.+?)\\\\(.+)\\\\(.+)$", boost::regex::icase))) -        return std::string(); -    std::string reg_parent = std::string(reg_parent_match[1].first, reg_parent_match[1].second); -    std::string reg_path = std::string(reg_parent_match[2].first, reg_parent_match[2].second); -    std::string reg_val_name = std::string(reg_parent_match[3].first, reg_parent_match[3].second); - -    HKEY hkey_parent = HKEY_LOCAL_MACHINE; -    if      (reg_parent == "HKEY_LOCAL_MACHINE")    hkey_parent = HKEY_LOCAL_MACHINE; -    else if (reg_parent == "HKEY_CURRENT_USER")     hkey_parent = HKEY_CURRENT_USER; -    else if (reg_parent == "HKEY_CLASSES_ROOT")     hkey_parent = HKEY_CLASSES_ROOT; -    else if (reg_parent == "HKEY_CURRENT_CONFIG")   hkey_parent = HKEY_CURRENT_CONFIG; -    else if (reg_parent == "HKEY_USERS")            hkey_parent = HKEY_CURRENT_USER; - -    TCHAR value_buff[1024]; -    DWORD value_buff_size = 1024*sizeof(TCHAR); - -    //Get a handle to the key location -    HKEY hkey_location; -    if (RegOpenKeyExA(hkey_parent, reg_path.c_str(), NULL, KEY_QUERY_VALUE, &hkey_location) != ERROR_SUCCESS) -        return std::string(); - -    //Query key value -    DWORD dw_type = REG_SZ; -    if(RegQueryValueExA(hkey_location, reg_val_name.c_str(), NULL, &dw_type, (LPBYTE)value_buff, &value_buff_size) == ERROR_SUCCESS) { -        RegCloseKey(hkey_location); -        if (value_buff_size >= 1024*sizeof(TCHAR)) { -            return std::string(); -        } else { -            std::string return_value(value_buff, value_buff_size-1); //value_buff_size includes the null terminator -            return_value += path_suffix; -            return return_value; -        } -    } else { -        return std::string(); -    } -} - -#endif  /*UHD_PLATFORM_WIN32*/ - -std::string nifpga_lvbitx::_get_fpga_images_dir(const std::string search_paths) -{ -    std::vector<std::string> search_path_vtr; -    boost::split(search_path_vtr, search_paths, boost::is_any_of(",")); - -    // -    // Add the value of the UHD_IMAGES_DIR environment variable to the list of -    // directories searched for a LVBITX image. -    // -    char* uhd_images_dir; -#ifdef UHD_PLATFORM_WIN32 -    size_t len; -    errno_t err = _dupenv_s(&uhd_images_dir, &len, "UHD_IMAGES_DIR"); -    if(not err and uhd_images_dir != NULL) search_path_vtr.push_back(std::string(uhd_images_dir)); -    free(uhd_images_dir); -#else -    uhd_images_dir = getenv("UHD_IMAGES_DIR"); -    if(uhd_images_dir != NULL) search_path_vtr.push_back(std::string(uhd_images_dir)); -#endif - -    std::string lvbitx_dir; -    //Traverse through the list of search paths. Priority: lexical -    BOOST_FOREACH(std::string& search_path, search_path_vtr) { -        boost::algorithm::trim(search_path); -        if (search_path.empty()) continue; - -#ifdef UHD_PLATFORM_WIN32 -        lvbitx_dir = _get_path_from_registry(search_path); -        if (lvbitx_dir.empty()) { -            //Could not read from the registry due to missing key, invalid values, etc -            //Just use the search path. The is_directory check will fail if this is a -            //registry path and we will move on to the next item in the list. -            lvbitx_dir = search_path; -        } -#else -        lvbitx_dir = search_path; -#endif - -        //If the current directory exists then stop traversing the search path list. -        if (boost::filesystem::is_directory(lvbitx_dir)) break; -    } - -    return lvbitx_dir; -} - -  }} diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 24a87a3c8..c4279913c 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -23,7 +23,7 @@  #include <uhd/utils/cast.hpp>  #include <uhd/exception.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_call.hpp>  #include <boost/format.hpp>  #include <boost/assign/list_of.hpp> @@ -82,7 +82,7 @@ static device_addrs_t b100_find(const device_addr_t &hint)              b100_fw_image = find_image_path(hint.get("fw", B100_FW_FILE_NAME));          }          catch(...){ -            UHD_MSG(warning) << boost::format("Could not locate B100 firmware. %s\n") % print_images_error(); +            UHD_MSG(warning) << boost::format("Could not locate B100 firmware. %s\n") % print_utility_error("uhd_images_downloader.py");              return b100_addrs;          }          UHD_LOG << "the firmware image: " << b100_fw_image << std::endl; @@ -532,10 +532,10 @@ void b100_impl::check_fw_compat(void){      );      if (fw_compat_num != B100_FW_COMPAT_NUM){          throw uhd::runtime_error(str(boost::format( -            "Expected firmware compatibility number 0x%x, but got 0x%x:\n" +            "Expected firmware compatibility number %d, but got %d:\n"              "The firmware build is not compatible with the host code build.\n"              "%s" -        ) % B100_FW_COMPAT_NUM % fw_compat_num % print_images_error())); +        ) % int(B100_FW_COMPAT_NUM) % fw_compat_num % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>("/mboards/0/fw_version").set(str(boost::format("%u.0") % fw_compat_num));  } @@ -552,7 +552,7 @@ void b100_impl::check_fpga_compat(void){              "Expected FPGA compatibility number %d, but got %d:\n"              "The FPGA build is not compatible with the host code build."              "%s" -        ) % int(B100_FPGA_COMPAT_NUM) % fpga_major % print_images_error())); +        ) % int(B100_FPGA_COMPAT_NUM) % fpga_major % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor));  } diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 59ea2202e..dbca543be 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -46,7 +46,7 @@  static const double          B100_LINK_RATE_BPS = 256e6/5; //pratical link rate (< 480 Mbps)  static const std::string     B100_FW_FILE_NAME = "usrp_b100_fw.ihx";  static const std::string     B100_FPGA_FILE_NAME = "usrp_b100_fpga.bin"; -static const boost::uint16_t B100_FW_COMPAT_NUM = 0x04; +static const boost::uint16_t B100_FW_COMPAT_NUM = 4;  static const boost::uint16_t B100_FPGA_COMPAT_NUM = 11;  static const boost::uint32_t B100_RX_SID_BASE = 30;  static const boost::uint32_t B100_TX_ASYNC_SID = 10; diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 13bdc09b4..355d12d12 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -17,12 +17,13 @@  #include "b200_impl.hpp"  #include "b200_regs.hpp" +#include <uhd/config.hpp>  #include <uhd/transport/usb_control.hpp>  #include <uhd/utils/msg.hpp>  #include <uhd/utils/cast.hpp>  #include <uhd/exception.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_call.hpp>  #include <uhd/usrp/dboard_eeprom.hpp>  #include <boost/format.hpp> @@ -109,13 +110,11 @@ static device_addrs_t b200_find(const device_addr_t &hint)          //extract the firmware path for the b200          std::string b200_fw_image;          try{ -            b200_fw_image = find_image_path(hint.get("fw", B200_FW_FILE_NAME)); +            b200_fw_image = hint.get("fw", B200_FW_FILE_NAME); +            b200_fw_image = uhd::find_image_path(b200_fw_image, STR(UHD_IMAGES_DIR)); // FIXME          } -        catch(...){ -            UHD_MSG(warning) << boost::format( -                "Could not locate B200 firmware.\n" -                "Please install the images package. %s\n" -            ) % print_images_error(); +        catch(uhd::exception &e){ +            UHD_MSG(warning) << e.what();              return b200_addrs;          }          UHD_LOG << "the firmware image: " << b200_fw_image << std::endl; @@ -783,11 +782,11 @@ void b200_impl::check_fw_compat(void)      if (compat_major != B200_FW_COMPAT_NUM_MAJOR){          throw uhd::runtime_error(str(boost::format( -            "Expected firmware compatibility number 0x%x, but got 0x%x.%x:\n" +            "Expected firmware compatibility number %d.%d, but got %d.%d:\n"              "The firmware build is not compatible with the host code build.\n"              "%s" -        ) % int(B200_FW_COMPAT_NUM_MAJOR) % compat_major % compat_minor -          % print_images_error())); +        )   % int(B200_FW_COMPAT_NUM_MAJOR) % int(B200_FW_COMPAT_NUM_MINOR) +            % compat_major % compat_minor % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>("/mboards/0/fw_version").set(str(boost::format("%u.%u")                  % compat_major % compat_minor)); @@ -804,11 +803,10 @@ void b200_impl::check_fpga_compat(void)      if (compat_major != B200_FPGA_COMPAT_NUM){          throw uhd::runtime_error(str(boost::format( -            "Expected FPGA compatibility number 0x%x, but got 0x%x.%x:\n" +            "Expected FPGA compatibility number %d, but got %d:\n"              "The FPGA build is not compatible with the host code build.\n"              "%s" -        ) % int(B200_FPGA_COMPAT_NUM) % compat_major % compat_minor -          % print_images_error())); +        ) % int(B200_FPGA_COMPAT_NUM) % compat_major % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>("/mboards/0/fpga_version").set(str(boost::format("%u.%u")                  % compat_major % compat_minor)); diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index ab95ebce1..396819f9a 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -45,9 +45,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 = 0x07; -static const boost::uint8_t  B200_FW_COMPAT_NUM_MINOR = 0x00; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x04; +static const boost::uint8_t  B200_FW_COMPAT_NUM_MAJOR = 7; +static const boost::uint8_t  B200_FW_COMPAT_NUM_MINOR = 0; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 4;  static const double          B200_BUS_CLOCK_RATE = 100e6;  static const double          B200_DEFAULT_TICK_RATE = 32e6;  static const double          B200_DEFAULT_FREQ = 100e6; // Hz diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 8b4f2316c..ac419e0e0 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -21,7 +21,7 @@  #include <uhd/utils/msg.hpp>  #include <uhd/exception.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <boost/bind.hpp>  #include <boost/format.hpp>  #include <boost/filesystem.hpp> @@ -132,7 +132,7 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){          e100_fpga_image = find_image_path(device_addr.get("fpga", default_fpga_file_name));      }      catch(...){ -        UHD_MSG(error) << boost::format("Could not find FPGA image. %s\n") % print_images_error(); +        UHD_MSG(error) << boost::format("Could not find FPGA image. %s\n") % print_utility_error("uhd_images_downloader.py");          throw;      }      e100_load_fpga(e100_fpga_image); diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index 0c112fdb1..ac6294d5a 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -28,7 +28,7 @@  #include <uhd/utils/msg.hpp>  #include <uhd/utils/log.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/usrp/dboard_eeprom.hpp>  #include <uhd/transport/if_addrs.hpp>  #include <uhd/transport/udp_zero_copy.hpp> @@ -397,7 +397,7 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)              "%s"          ) % fpga::COMPAT_MAJOR            % _get_version(FPGA_MAJOR) % _get_version(FPGA_MINOR) -          % print_images_error())); +          % print_utility_error("uhd_images_downloader.py")));      }      //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 2c37f2ff1..bb904773b 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -33,7 +33,7 @@  #include <uhd/utils/msg.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <boost/asio.hpp>  #include <boost/thread.hpp> diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 709092e42..dbd5408e8 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -23,7 +23,7 @@  #include <uhd/utils/cast.hpp>  #include <uhd/exception.hpp>  #include <uhd/utils/static.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <boost/format.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/filesystem.hpp> @@ -85,7 +85,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)              usrp1_fw_image = find_image_path(hint.get("fw", "usrp1_fw.ihx"));          }          catch(...){ -            UHD_MSG(warning) << boost::format("Could not locate USRP1 firmware. %s") % print_images_error(); +            UHD_MSG(warning) << boost::format("Could not locate USRP1 firmware. %s") % print_utility_error("uhd_images_downloader.py");          }          UHD_LOG << "USRP1 firmware image: " << usrp1_fw_image << std::endl; diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index b2085807f..65cf90a17 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -23,7 +23,7 @@  #include <uhd/utils/msg.hpp>  #include <uhd/utils/paths.hpp>  #include <uhd/utils/tasks.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_call.hpp>  #include <uhd/types/dict.hpp>  #include <boost/thread.hpp> @@ -375,7 +375,7 @@ public:              fpga_image_path = uhd::find_image_path(fpga_image);          }          catch(const std::exception &){ -            return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_images_error()); +            return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_utility_error("uhd_images_downloader.py"));          }          //escape char for multi-line cmd + newline + indent? @@ -389,13 +389,13 @@ public:          if (this->get_rev() == USRP2_REV3 or this->get_rev() == USRP2_REV4){              const std::string card_burner = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp2_card_burner.py").string();              const std::string card_burner_cmd = str(boost::format("\"%s%s\" %s--fpga=\"%s\" %s--fw=\"%s\"") % sudo % card_burner % ml % fpga_image_path % ml % fw_image_path); -            return str(boost::format("%s\n%s") % print_images_error() % card_burner_cmd); +            return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % card_burner_cmd);          }          else{              const std::string addr = _ctrl_transport->get_recv_addr();              const std::string net_burner_path = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp_n2xx_simple_net_burner").string();              const std::string net_burner_cmd = str(boost::format("\"%s\" %s--addr=\"%s\"") % net_burner_path % ml % addr); -            return str(boost::format("%s\n%s") % print_images_error() % net_burner_cmd); +            return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % net_burner_cmd);          }      } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index eab5cfef2..e35f73eab 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -24,7 +24,7 @@  #include "apply_corrections.hpp"  #include <uhd/utils/static.hpp>  #include <uhd/utils/msg.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_call.hpp>  #include <uhd/usrp/subdev_spec.hpp>  #include <uhd/transport/if_addrs.hpp> @@ -171,7 +171,7 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu              default:                  continue;          } -         +          niriok_proxy::sptr kernel_proxy = niriok_proxy::make_and_open(dev_info.interface_path);          //Attempt to read the name from the EEPROM and perform filtering. @@ -1668,11 +1668,11 @@ void x300_impl::check_fw_compat(const fs_path &mb_path, wb_iface::sptr iface)      if (compat_major != X300_FW_COMPAT_MAJOR)      {          throw uhd::runtime_error(str(boost::format( -            "Expected firmware compatibility number 0x%x, but got 0x%x.%x:\n" +            "Expected firmware compatibility number %d.%d, but got %d.%d:\n"              "The firmware build is not compatible with the host code build.\n"              "%s" -        ) % int(X300_FW_COMPAT_MAJOR) % compat_major % compat_minor -          % print_images_error())); +        )   % int(X300_FW_COMPAT_MAJOR) % int(X300_FW_COMPAT_MINOR) +            % compat_major % compat_minor % print_utility_error("uhd_images_downloader.py")));      }      _tree->create<std::string>(mb_path / "fw_version").set(str(boost::format("%u.%u")                  % compat_major % compat_minor)); @@ -1692,11 +1692,11 @@ void x300_impl::check_fpga_compat(const fs_path &mb_path, wb_iface::sptr iface)              "Download the appropriate FPGA images for this version of UHD.\n"              "%s\n\n"              "Then burn a new image to the on-board flash storage of your\n" -            "USRP X3xx device using the burner utility. \n\n" +            "USRP X3xx device using the burner utility. %s\n\n"              "For more information, refer to the UHD manual:\n\n"              " http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_flash"          )   % int(X300_FPGA_COMPAT_MAJOR) % compat_major -            % print_images_error())); +            % print_utility_error("uhd_images_downloader.py") % print_utility_error("usrp_x3xx_fpga_burner")));      }      _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u")                  % compat_major % compat_minor)); diff --git a/host/lib/usrp_clock/octoclock/octoclock_impl.cpp b/host/lib/usrp_clock/octoclock/octoclock_impl.cpp index 8c207dd9f..d55fab10e 100644 --- a/host/lib/usrp_clock/octoclock/octoclock_impl.cpp +++ b/host/lib/usrp_clock/octoclock/octoclock_impl.cpp @@ -33,7 +33,7 @@  #include <uhd/usrp/gps_ctrl.hpp>  #include <uhd/usrp_clock/octoclock_eeprom.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/msg.hpp>  #include <uhd/utils/paths.hpp>  #include <uhd/utils/static.hpp> @@ -420,7 +420,7 @@ std::string octoclock_impl::_get_images_help_message(const std::string &addr){      catch(const std::exception &e){          return str(boost::format("Could not find %s in your images path.\n%s")                     % image_name -                   % uhd::print_images_error()); +                   % uhd::print_utility_error("uhd_images_downloader.py"));      }      //Get escape character @@ -433,5 +433,5 @@ std::string octoclock_impl::_get_images_help_message(const std::string &addr){      //Get burner command      const std::string burner_path = (fs::path(uhd::get_pkg_path()) / "bin" / "octoclock_firmware_burner").string();      const std::string burner_cmd = str(boost::format("%s %s--addr=\"%s\"") % burner_path % ml % addr); -    return str(boost::format("%s\n%s") % uhd::print_images_error() % burner_cmd); +    return str(boost::format("%s\n%s") % uhd::print_utility_error("uhd_images_downloader.py") % burner_cmd);  } diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index 106e2b650..369920ac1 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -132,7 +132,6 @@ SET_SOURCE_FILES_PROPERTIES(  LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/csv.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/gain_group.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/images.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/msg.cpp diff --git a/host/lib/utils/images.cpp b/host/lib/utils/images.cpp deleted file mode 100644 index 1ba2f81e6..000000000 --- a/host/lib/utils/images.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2010-2012 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#include <uhd/utils/images.hpp> -#include <uhd/exception.hpp> -#include <uhd/utils/paths.hpp> -#include <boost/foreach.hpp> -#include <boost/filesystem.hpp> -#include <vector> -#include <iostream> - -namespace fs = boost::filesystem; - -std::vector<fs::path> get_image_paths(void); //defined in paths.cpp - -/*********************************************************************** - * Find an image in the image paths - **********************************************************************/ -std::string uhd::find_image_path(const std::string &image_name){ -    if (fs::exists(image_name)){ -        return fs::system_complete(image_name).string(); -    } -    BOOST_FOREACH(const fs::path &path, get_image_paths()){ -        fs::path image_path = path / image_name; -        if (fs::exists(image_path)) return image_path.string(); -    } -    throw uhd::io_error("Could not find path for image: " + image_name + "\n\n" + uhd::print_images_error()); -} - -std::string uhd::find_images_downloader(void){ -    return fs::path(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "uhd_images_downloader.py").string(); -} - -std::string uhd::print_images_error(void){ -    #ifdef UHD_PLATFORM_WIN32 -    return "As an Administrator, please run:\n\n\"" + find_images_downloader() + "\""; -    #else -    return "Please run:\n\nsudo \"" + find_images_downloader() + "\""; -    #endif -} diff --git a/host/lib/utils/load_modules.cpp b/host/lib/utils/load_modules.cpp index bee0d5304..aba3adeed 100644 --- a/host/lib/utils/load_modules.cpp +++ b/host/lib/utils/load_modules.cpp @@ -15,6 +15,7 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +#include <uhd/utils/paths.hpp>  #include <uhd/utils/static.hpp>  #include <uhd/exception.hpp>  #include <boost/format.hpp> @@ -97,13 +98,11 @@ static void load_module_path(const fs::path &path){      }  } -std::vector<fs::path> get_module_paths(void); //defined in paths.cpp -  /*!   * Load all the modules given in the module paths.   */  UHD_STATIC_BLOCK(load_modules){ -    BOOST_FOREACH(const fs::path &path, get_module_paths()){ +    BOOST_FOREACH(const fs::path &path, uhd::get_module_paths()){          load_module_path(path);      }  } diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index 3e2bea1c6..e304555bd 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -16,37 +16,77 @@  //  #include <uhd/config.hpp> +#include <uhd/exception.hpp> +#include <uhd/transport/nirio/nifpga_lvbitx.h>  #include <uhd/utils/paths.hpp> -#include <boost/tokenizer.hpp> + +#include <boost/algorithm/string.hpp> +#include <boost/bind.hpp>  #include <boost/filesystem.hpp>  #include <boost/foreach.hpp> -#include <boost/bind.hpp> +#include <boost/format.hpp> +#include <boost/regex.hpp> +#include <boost/tokenizer.hpp> + +#include <cstdio>  #include <cstdlib> +#include <fstream> +#include <iostream> +#include <streambuf>  #include <string>  #include <vector> -#include <cstdlib> //getenv -#include <cstdio>  //P_tmpdir +  #ifdef BOOST_MSVC  #define USE_GET_TEMP_PATH  #include <windows.h> //GetTempPath  #endif +#ifdef USE_NIUSRP_WINREG_KEY +#define NIUSRP_WINREG_KEY "[HKLM\\Software\\National Instruments\\NI-USRP\\DriverBitfilesDir]" +#endif +  namespace fs = boost::filesystem; -/*********************************************************************** - * Get a list of paths for an environment variable - **********************************************************************/ -static std::string get_env_var(const std::string &var_name, const std::string &def_val = ""){ -    const char *var_value_ptr = std::getenv(var_name.c_str()); -    return (var_value_ptr == NULL)? def_val : var_value_ptr; -} +/*! Get the value of an environment variable. + * + * The returned std::string is the full environment variable string, and thus + * may actually contain multiple fields in the string with delimiters. + * + * \param var_name The name of the variable to search for. + * \param default_val A default string value to use if the path isn't found. + * \returns The string value of the environment variable. + */ +static std::string get_env_var(const std::string &var_name, +        const std::string &default_val = "") { -static std::vector<fs::path> get_env_paths(const std::string &var_name){ +    std::string env_result = default_val; +    char *env_var_str = NULL; -/*********************************************************************** - * Determine the paths separator - **********************************************************************/ +    /* Some versions of MinGW don't expose `_dupenv_s` */ +#if defined(UHD_PLATFORM_WIN32) && !defined(__MINGW32__) +    size_t len; +    errno_t err = _dupenv_s(&env_var_str, &len, var_name.c_str()); +    if((not err) and (env_var_str != NULL)) +        env_result = std::string(env_var_str); +    free(env_var_str); +#else +    env_var_str = std::getenv(var_name.c_str()); +    if(env_var_str != NULL) +        env_result = std::string(env_var_str); +#endif +    return env_result; +} + +/*! Get a vector of paths from an environment variable. + * + * Reads an environment variable, which should contain a list of paths, and + * returns a vector of those paths in the form of strings. + * + * \param var_name The environment variable name to read. + * \returns The vector of paths from the environment variable. + */ +static std::vector<std::string> get_env_paths(const std::string &var_name){  #ifdef UHD_PLATFORM_WIN32      static const std::string env_path_sep = ";";  #else @@ -59,40 +99,45 @@ static std::vector<fs::path> get_env_paths(const std::string &var_name){      std::string var_value = get_env_var(var_name); -    //convert to filesystem path, filter blank paths -    std::vector<fs::path> paths; -    if (var_value.empty()) return paths; //FIXME boost tokenizer throws w/ blank strings on some platforms +    std::vector<std::string> paths; + +    //convert to full filesystem path, filter blank paths +    if (var_value.empty()) return paths;      BOOST_FOREACH(const std::string &path_string, path_tokenizer(var_value)){          if (path_string.empty()) continue; -        paths.push_back(fs::system_complete(path_string)); +        paths.push_back(fs::system_complete(path_string).string());      } +      return paths;  } -/*********************************************************************** - * Get a list of special purpose paths - **********************************************************************/ -std::string uhd::get_pkg_path(void) -{ -    return get_env_var("UHD_PKG_PATH", UHD_PKG_PATH); -} +/*! Expand a tilde character to the $HOME path. + * + * The path passed to this function must start with the tilde character in order + * for this function to work properly. If it does not, it will simply return the + * original path. The $HOME environment variable must exist. + * + * \param path The path starting with the tilde character + * \returns The same path with the tilde expanded to contents of $HOME. + */ +static std::string expand_home_directory(std::string path) { +    boost::trim(path); -std::vector<fs::path> get_image_paths(void){ -    std::vector<fs::path> paths = get_env_paths("UHD_IMAGE_PATH"); -    paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "images"); -    return paths; -} +    if(path.empty() || (path[0] != '~')) { +        return path; +    } -std::vector<fs::path> get_module_paths(void){ -    std::vector<fs::path> paths = get_env_paths("UHD_MODULE_PATH"); -    paths.push_back(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "modules"); -    paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "modules"); -    return paths; +    std::string user_home_path = get_env_var("HOME"); +    path.replace(0, 1, user_home_path); + +    return path;  }  /***********************************************************************   * Implement the functions in paths.hpp   **********************************************************************/ + +  std::string uhd::get_tmp_path(void){      const char *tmp_path = NULL; @@ -136,3 +181,192 @@ std::string uhd::get_app_path(void){      return uhd::get_tmp_path();  } + +std::string uhd::get_pkg_path(void) { +    return get_env_var("UHD_PKG_PATH", UHD_PKG_PATH); +} + +std::vector<fs::path> uhd::get_module_paths(void){ +    std::vector<fs::path> paths; + +    std::vector<std::string> env_paths = get_env_paths("UHD_MODULE_PATH"); +    BOOST_FOREACH(std::string &str_path, env_paths) { +        paths.push_back(str_path); +    } + +    paths.push_back(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "modules"); +    paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "modules"); + +    return paths; +} + +#ifdef UHD_PLATFORM_WIN32 +#include <windows.h> +/*! + * On Windows, query the system registry for the UHD images install path. + * If the key isn't found in the registry, an empty string is returned. + * \param registry_key_path The registry key to look for. + * \return The images path, formatted for windows. + */ +std::string _get_images_path_from_registry(const std::string& registry_key_path) { +    boost::smatch reg_key_match; +    //If a substring in the search path is enclosed in [] (square brackets) then it is interpreted as a registry path +    if (not boost::regex_search(registry_key_path, reg_key_match, boost::regex("\\[(.+)\\](.*)", boost::regex::icase))) +        return std::string(); +    std::string reg_key_path = std::string(reg_key_match[1].first, reg_key_match[1].second); +    std::string path_suffix = std::string(reg_key_match[2].first, reg_key_match[2].second); + +    //Split the registry path into parent, key-path and value. +    boost::smatch reg_parent_match; +    if (not boost::regex_search(reg_key_path, reg_parent_match, boost::regex("^(.+?)\\\\(.+)\\\\(.+)$", boost::regex::icase))) +        return std::string(); +    std::string reg_parent = std::string(reg_parent_match[1].first, reg_parent_match[1].second); +    std::string reg_path = std::string(reg_parent_match[2].first, reg_parent_match[2].second); +    std::string reg_val_name = std::string(reg_parent_match[3].first, reg_parent_match[3].second); + +    HKEY hkey_parent = HKEY_LOCAL_MACHINE; +    if      (reg_parent == "HKEY_LOCAL_MACHINE")    hkey_parent = HKEY_LOCAL_MACHINE; +    else if (reg_parent == "HKEY_CURRENT_USER")     hkey_parent = HKEY_CURRENT_USER; +    else if (reg_parent == "HKEY_CLASSES_ROOT")     hkey_parent = HKEY_CLASSES_ROOT; +    else if (reg_parent == "HKEY_CURRENT_CONFIG")   hkey_parent = HKEY_CURRENT_CONFIG; +    else if (reg_parent == "HKEY_USERS")            hkey_parent = HKEY_CURRENT_USER; + +    TCHAR value_buff[1024]; +    DWORD value_buff_size = 1024*sizeof(TCHAR); + +    //Get a handle to the key location +    HKEY hkey_location; +    if (RegOpenKeyExA(hkey_parent, reg_path.c_str(), NULL, KEY_QUERY_VALUE, &hkey_location) != ERROR_SUCCESS) +        return std::string(); + +    //Query key value +    DWORD dw_type = REG_SZ; +    if(RegQueryValueExA(hkey_location, reg_val_name.c_str(), NULL, &dw_type, (LPBYTE)value_buff, &value_buff_size) == ERROR_SUCCESS) { +        RegCloseKey(hkey_location); +        if (value_buff_size >= 1024*sizeof(TCHAR)) { +            return std::string(); +        } else { +            std::string return_value(value_buff, value_buff_size-1); //value_buff_size includes the null terminator +            return_value += path_suffix; +            return return_value; +        } +    } else { +        return std::string(); +    } +} +#endif  /*UHD_PLATFORM_WIN32*/ + +std::string uhd::get_images_dir(const std::string search_paths) { + +    /*   This function will check for the existence of directories in this +     *   order: +     * +     *   1) `UHD_IMAGES_DIR` environment variable +     *   2) Any paths passed to this function via `search_paths' (may contain +     *      Windows registry keys) +     *   3) `UHD package path` / share / uhd / images +     */ + +    std::string possible_dir; + +    /* We will start by looking for a path indicated by the `UHD_IMAGES_DIR` +     * environment variable. */ +    std::vector<std::string> env_paths = get_env_paths("UHD_IMAGES_DIR"); +    BOOST_FOREACH(possible_dir, env_paths) { +        if (fs::is_directory(fs::path(possible_dir))) { +                return possible_dir; +        } +    } + +    /* On Windows systems, we may need to modify the `search_paths` parameter +     * (see below). Making a local copy for const correctness. */ +    std::string _search_paths = search_paths; + +#ifdef USE_NIUSRP_WINREG_KEY +    _search_paths = std::string(NIUSRP_WINREG_KEY) + "," + search_paths; +#endif + +    /* Now we will parse and attempt to qualify the paths in the `search_paths` +     * parameter. If this is Windows, we will check the system registry for +     * these strings. */ +    if (!_search_paths.empty()) { +        std::vector<std::string> search_paths_vector; + +        boost::split(search_paths_vector, _search_paths, boost::is_any_of(",;")); +        BOOST_FOREACH(std::string& search_path, search_paths_vector) { + +            boost::algorithm::trim(search_path); +            if (search_path.empty()) continue; + +#ifdef UHD_PLATFORM_WIN32 +            possible_dir = _get_images_path_from_registry(search_path); +            if (possible_dir.empty()) { +                //Could not read from the registry due to missing key, invalid +                //values, etc Just use the search path. The is_directory check +                //will fail if this is a registry path and we will move on to +                //the next item in the list. +                possible_dir = search_path; +            } +#else +            possible_dir = expand_home_directory(search_path); +#endif + +            if (fs::is_directory(fs::path(possible_dir))) { +                return possible_dir; +            } +        } +    } + +    /* Finally, check for the default UHD images installation path. */ +    fs::path pkg_path = fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "images"; +    if (fs::is_directory(pkg_path)) { +        return pkg_path.string(); +    } else { +        /* No luck. Return an empty string. */ +        return std::string(""); +    } +} + +std::string uhd::find_image_path(const std::string &image_name, const std::string search_paths){ +    /* If a path was provided on the command-line or as a hint from the caller, +     * we default to that. */ +    if (fs::exists(image_name)){ +        return fs::system_complete(image_name).string(); +    } + +    /* Otherwise, look for the image in the images directory. */ +    std::string images_dir = get_images_dir(search_paths); +    if (!images_dir.empty()) { +        fs::path image_path = fs::path(images_dir) / image_name; +        if (fs::exists(image_path)) { +            return image_path.string(); +        } else { +            throw uhd::io_error( +                "Could not find the image '" + image_name + "' in the image directory " + images_dir +                + "\nFor more information regarding image paths, please refer to the UHD manual."); +        } +    } + +    /* If we made it this far, then we didn't find anything. */ +    throw uhd::io_error("Could not find path for image: " + image_name +            + "\n\n" +            + "Using images directory: " + images_dir +            + "\n\n" +            + "Set the environment variable 'UHD_IMAGES_DIR' appropriately or" +            + " follow the below instructions to download the images package." +            + "\n\n" +            + uhd::print_utility_error("uhd_images_downloader.py")); +} + +std::string uhd::find_utility(std::string name) { +    return fs::path(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / name) +        .string(); +} + +std::string uhd::print_utility_error(std::string name){ +    #ifdef UHD_PLATFORM_WIN32 +    return "As an Administrator, please run:\n\n\"" + find_utility(name) + "\""; +    #else +    return "Please run:\n\n \"" + find_utility(name) + "\""; +    #endif +} diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp index 0cab6618d..8b64be63e 100644 --- a/host/utils/b2xx_fx3_utils.cpp +++ b/host/utils/b2xx_fx3_utils.cpp @@ -39,7 +39,7 @@  #include <uhd/transport/usb_control.hpp>  #include <uhd/transport/usb_device_handle.hpp>  #include <uhd/exception.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  namespace po = boost::program_options;  namespace fs = boost::filesystem; diff --git a/host/utils/octoclock_firmware_burner.cpp b/host/utils/octoclock_firmware_burner.cpp index 9551ddd20..0a48caabd 100644 --- a/host/utils/octoclock_firmware_burner.cpp +++ b/host/utils/octoclock_firmware_burner.cpp @@ -37,7 +37,7 @@  #include <uhd/types/device_addr.hpp>  #include <uhd/types/time_spec.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_main.hpp> diff --git a/host/utils/usrp_n2xx_simple_net_burner.cpp b/host/utils/usrp_n2xx_simple_net_burner.cpp index dc83b6fdf..b06e67bb2 100644 --- a/host/utils/usrp_n2xx_simple_net_burner.cpp +++ b/host/utils/usrp_n2xx_simple_net_burner.cpp @@ -38,7 +38,7 @@  #include <uhd/transport/udp_simple.hpp>  #include <uhd/types/dict.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_main.hpp>  #include <uhd/utils/safe_call.hpp> diff --git a/host/utils/usrp_x3xx_fpga_burner.cpp b/host/utils/usrp_x3xx_fpga_burner.cpp index b849cfb92..abd5815e8 100644 --- a/host/utils/usrp_x3xx_fpga_burner.cpp +++ b/host/utils/usrp_x3xx_fpga_burner.cpp @@ -45,7 +45,7 @@  #include <uhd/device.hpp>  #include <uhd/types/device_addr.hpp>  #include <uhd/utils/byteswap.hpp> -#include <uhd/utils/images.hpp> +#include <uhd/utils/paths.hpp>  #include <uhd/utils/safe_main.hpp>  #include <uhd/utils/safe_call.hpp> | 
