From 1295df8cbba76c088a36f9d546a68c1d00e7a1a8 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Mon, 29 Mar 2010 12:58:06 -0700
Subject: Added utility methods to device addr and mac addr to make them more
 usable.

---
 host/include/uhd/types/device_addr.hpp | 37 ++++++++++++++++----
 host/include/uhd/types/dict.hpp        |  7 ++--
 host/include/uhd/types/mac_addr.hpp    | 35 +++++++++++++++++--
 host/lib/device.cpp                    |  8 ++---
 host/lib/simple_device.cpp             | 26 +-------------
 host/lib/types.cpp                     | 63 ++++++++++++++++++++++++++++------
 host/lib/usrp/dboard_manager.cpp       |  6 ++--
 host/lib/usrp/usrp2/mboard_impl.cpp    |  6 ++--
 host/test/addr_test.cpp                |  2 +-
 host/utils/usrp2_burner.cpp            | 17 +++++----
 10 files changed, 143 insertions(+), 64 deletions(-)

(limited to 'host')

diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp
index d32dfa77e..1162884fb 100644
--- a/host/include/uhd/types/device_addr.hpp
+++ b/host/include/uhd/types/device_addr.hpp
@@ -26,15 +26,40 @@
 namespace uhd{
 
     /*!
-     * The device address args are just a mapping of key/value string pairs.
-     * When left empty, the discovery routine will try to find all usrps.
-     * The discovery can be narrowed down by specifying the transport type arguments.
+     * Mapping of key/value pairs for locating devices on the system.
+     * When left empty, the device discovery routines will search
+     * all available transports on the system (ethernet, usb...).
      *
-     * For example, to access a specific usrp2 one would specify the transport type
-     * ("type", "udp") and the transport args ("addr", "<resolvable_hostname_or_addr>").
+     * To narrow down the discovery process to a particular device,
+     * specify a transport key/value pair specific to your device.
+     * Ex, to find a usrp2: my_dev_addr["addr"] = <resolvable_hostname_or_ip>
+     *
+     * The device address can also be used to pass arguments into
+     * the transport layer control to set (for example) buffer sizes.
      */
     class UHD_API device_addr_t : public dict<std::string, std::string>{
-        public: std::string to_string(void) const;
+    public:
+
+        /*!
+         * Convert a device address into a printable string.
+         * \return string good for use with std::cout <<
+         */
+        std::string to_string(void) const;
+
+        /*!
+         * Convert the device address into an args string.
+         * The args string contains delimiter symbols.
+         * \return a string with delimiter markup
+         */
+        std::string to_args_str(void) const;
+
+        /*!
+         * Make a device address from an args string.
+         * The args string contains delimiter symbols.
+         * \param args_str the arguments string
+         * \return the new device address
+         */
+        static device_addr_t from_args_str(const std::string &args_str);
     };
 
     //handy typedef for a vector of device addresses
diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp
index 5b9883704..7fb712e76 100644
--- a/host/include/uhd/types/dict.hpp
+++ b/host/include/uhd/types/dict.hpp
@@ -18,10 +18,11 @@
 #ifndef INCLUDED_UHD_TYPES_DICT_HPP
 #define INCLUDED_UHD_TYPES_DICT_HPP
 
-#include <list>
-#include <vector>
-#include <stdexcept>
+#include <uhd/config.hpp>
 #include <boost/foreach.hpp>
+#include <stdexcept>
+#include <vector>
+#include <list>
 
 namespace uhd{
 
diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp
index 2cac7d343..3cd1fe86b 100644
--- a/host/include/uhd/types/mac_addr.hpp
+++ b/host/include/uhd/types/mac_addr.hpp
@@ -28,10 +28,39 @@ namespace uhd{
     * Wrapper for an ethernet mac address.
     * Provides conversion between string and binary formats.
     */
-    struct UHD_API mac_addr_t{
-        boost::uint8_t mac_addr[6];
-        mac_addr_t(const std::string &mac_addr_str = "00:00:00:00:00:00");
+    class UHD_API mac_addr_t{
+    public:
+        static const size_t hlen = 6;
+
+        /*!
+         * Create a mac address a byte array.
+         * \param bytes a pointer for the byte array
+         * \return a new mac address
+         */
+        static mac_addr_t from_bytes(const boost::uint8_t *bytes);
+
+        /*!
+         * Create a mac address from a string.
+         * \param mac_addr_str the string with delimiters
+         * \return a new mac address
+         */
+        static mac_addr_t from_string(const std::string &mac_addr_str);
+
+        /*!
+         * Get the byte representation of the mac address.
+         * \return a pointer to the internal byte array
+         */
+        const boost::uint8_t *to_bytes(void) const;
+
+        /*!
+         * Get the string representation of this mac address.
+         * \return a string with delimiters
+         */
         std::string to_string(void) const;
+
+    private:
+        mac_addr_t(const boost::uint8_t *bytes); //private constructor
+        boost::uint8_t _bytes[hlen]; //internal representation
     };
 
 } //namespace uhd
diff --git a/host/lib/device.cpp b/host/lib/device.cpp
index 833e7a0da..ca45d0795 100644
--- a/host/lib/device.cpp
+++ b/host/lib/device.cpp
@@ -47,7 +47,7 @@ static size_t hash_device_addr(
 
     //combine the hashes of sorted keys/value pairs
     size_t hash = 0;
-    BOOST_FOREACH(std::string key, keys){
+    BOOST_FOREACH(const std::string &key, keys){
         boost::hash_combine(hash, key);
         boost::hash_combine(hash, dev_addr[key]);
     }
@@ -76,7 +76,7 @@ void device::register_device(
 device_addrs_t device::discover(const device_addr_t &hint){
     device_addrs_t device_addrs;
 
-    BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){
+    BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){
         device_addrs_t discovered_addrs = fcn.get<0>()(hint);
         device_addrs.insert(
             device_addrs.begin(),
@@ -95,11 +95,11 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
     typedef boost::tuple<device_addr_t, make_t> dev_addr_make_t;
     std::vector<dev_addr_make_t> dev_addr_makers;
 
-    BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){
+    BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){
         BOOST_FOREACH(device_addr_t dev_addr, fcn.get<0>()(hint)){
             //copy keys that were in hint but not in dev_addr
             //this way, we can pass additional transport arguments
-            BOOST_FOREACH(std::string key, hint.get_keys()){
+            BOOST_FOREACH(const std::string &key, hint.get_keys()){
                 if (not dev_addr.has_key(key)) dev_addr[key] = hint[key];
             }
             //append the discovered address and its factory function
diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp
index 2e6bffc9c..25beb45a9 100644
--- a/host/lib/simple_device.cpp
+++ b/host/lib/simple_device.cpp
@@ -19,7 +19,6 @@
 #include <uhd/utils/tune_helper.hpp>
 #include <uhd/utils/assert.hpp>
 #include <uhd/props.hpp>
-#include <boost/algorithm/string.hpp>
 #include <boost/foreach.hpp>
 #include <boost/format.hpp>
 #include <stdexcept>
@@ -29,29 +28,6 @@ using namespace uhd;
 /***********************************************************************
  * Helper Functions
  **********************************************************************/
-static std::string trim(const std::string &in){
-    return boost::algorithm::trim_copy(in);
-}
-
-device_addr_t args_to_device_addr(const std::string &args){
-    device_addr_t addr;
-
-    //split the args at the semi-colons
-    std::vector<std::string> pairs;
-    boost::split(pairs, args, boost::is_any_of(";"));
-    BOOST_FOREACH(std::string pair, pairs){
-        if (trim(pair) == "") continue;
-
-        //split the key value pairs at the equals
-        std::vector<std::string> key_val;
-        boost::split(key_val, pair, boost::is_any_of("="));
-        if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args);
-        addr[trim(key_val[0])] = trim(key_val[1]);
-    }
-
-    return addr;
-}
-
 static std::vector<double> get_xx_rates(wax::obj decerps, wax::obj rate){
     std::vector<double> rates;
     BOOST_FOREACH(size_t decerp, decerps.as<std::vector<size_t> >()){
@@ -223,5 +199,5 @@ private:
  * The Make Function
  **********************************************************************/
 simple_device::sptr simple_device::make(const std::string &args){
-    return sptr(new simple_device_impl(args_to_device_addr(args)));
+    return sptr(new simple_device_impl(device_addr_t::from_args_str(args)));
 }
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index bd5dc8e26..3fde40596 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -123,14 +123,55 @@ std::string device_addr_t::to_string(void) const{
     return ss.str();
 }
 
+static const std::string arg_delim = ";";
+static const std::string pair_delim = "=";
+
+static std::string trim(const std::string &in){
+    return boost::algorithm::trim_copy(in);
+}
+
+std::string device_addr_t::to_args_str(void) const{
+    std::string args_str;
+    const device_addr_t &device_addr = *this;
+    BOOST_FOREACH(const std::string &key, device_addr.get_keys()){
+        args_str += key + pair_delim + device_addr[key] + arg_delim;
+    }
+    return args_str;
+}
+
+device_addr_t device_addr_t::from_args_str(const std::string &args_str){
+    device_addr_t addr;
+
+    //split the args at the semi-colons
+    std::vector<std::string> pairs;
+    boost::split(pairs, args_str, boost::is_any_of(arg_delim));
+    BOOST_FOREACH(const std::string &pair, pairs){
+        if (trim(pair) == "") continue;
+
+        //split the key value pairs at the equals
+        std::vector<std::string> key_val;
+        boost::split(key_val, pair, boost::is_any_of(pair_delim));
+        if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args_str);
+        addr[trim(key_val[0])] = trim(key_val[1]);
+    }
+
+    return addr;
+}
+
 /***********************************************************************
  * mac addr
  **********************************************************************/
-uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){
-    std::string mac_addr_str = (mac_addr_str_ == "")? "ff:ff:ff:ff:ff:ff" : mac_addr_str_;
+mac_addr_t::mac_addr_t(const boost::uint8_t *bytes){
+    std::copy(bytes, bytes+hlen, _bytes);
+}
 
-    //ether_aton_r(str.c_str(), &mac_addr);
-    boost::uint8_t p[6] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB
+mac_addr_t mac_addr_t::from_bytes(const boost::uint8_t *bytes){
+    return mac_addr_t(bytes);
+}
+
+mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
+
+    boost::uint8_t p[hlen] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB
 
     try{
         //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx
@@ -155,15 +196,17 @@ uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){
         ));
     }
 
-    memcpy(&mac_addr, p, sizeof(mac_addr));
+    return from_bytes(p);
+}
+
+const boost::uint8_t *mac_addr_t::to_bytes(void) const{
+    return _bytes;
 }
 
-std::string uhd::mac_addr_t::to_string(void) const{
-    //ether_ntoa_r(&mac_addr, addr_buf);
-    const boost::uint8_t *p = reinterpret_cast<const boost::uint8_t *>(&mac_addr);
+std::string mac_addr_t::to_string(void) const{
     return str(
         boost::format("%02x:%02x:%02x:%02x:%02x:%02x")
-        % int(p[0]) % int(p[1]) % int(p[2])
-        % int(p[3]) % int(p[4]) % int(p[5])
+        % int(to_bytes()[0]) % int(to_bytes()[1]) % int(to_bytes()[2])
+        % int(to_bytes()[3]) % int(to_bytes()[4]) % int(to_bytes()[5])
     );
 }
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index f86545696..424626023 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -204,7 +204,7 @@ dboard_manager_impl::dboard_manager_impl(
     //make xcvr subdevs (make one subdev for both rx and tx dboards)
     if (rx_dboard_ctor == tx_dboard_ctor){
         ASSERT_THROW(rx_subdevs == tx_subdevs);
-        BOOST_FOREACH(std::string subdev, rx_subdevs){
+        BOOST_FOREACH(const std::string &subdev, rx_subdevs){
             dboard_base::sptr xcvr_dboard = rx_dboard_ctor(
                 dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, tx_dboard_id)
             );
@@ -222,7 +222,7 @@ dboard_manager_impl::dboard_manager_impl(
     //make tx and rx subdevs (separate subdevs for rx and tx dboards)
     else{
         //make the rx subdevs
-        BOOST_FOREACH(std::string subdev, rx_subdevs){
+        BOOST_FOREACH(const std::string &subdev, rx_subdevs){
             dboard_base::sptr rx_dboard = rx_dboard_ctor(
                 dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, dboard_id::NONE)
             );
@@ -232,7 +232,7 @@ dboard_manager_impl::dboard_manager_impl(
             );
         }
         //make the tx subdevs
-        BOOST_FOREACH(std::string subdev, tx_subdevs){
+        BOOST_FOREACH(const std::string &subdev, tx_subdevs){
             dboard_base::sptr tx_dboard = tx_dboard_ctor(
                 dboard_base::ctor_args_t(subdev, interface, dboard_id::NONE, tx_dboard_id)
             );
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index b6919a738..35dfd6287 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -116,7 +116,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
             ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE);
 
             //extract the address
-            val = reinterpret_cast<mac_addr_t*>(in_data.data.mac_addr)->to_string();
+            val = mac_addr_t::from_bytes(in_data.data.mac_addr).to_string();
             return;
         }
 
@@ -211,8 +211,8 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
             //setup the out data
             usrp2_ctrl_data_t out_data;
             out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO);
-            mac_addr_t mac_addr(val.as<std::string>());
-            std::memcpy(out_data.data.mac_addr, &mac_addr, sizeof(mac_addr_t));
+            mac_addr_t mac_addr = mac_addr_t::from_string(val.as<std::string>());
+            std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr);
 
             //send and recv
             usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
diff --git a/host/test/addr_test.cpp b/host/test/addr_test.cpp
index 0c8f63b0a..a75804949 100644
--- a/host/test/addr_test.cpp
+++ b/host/test/addr_test.cpp
@@ -22,7 +22,7 @@
 BOOST_AUTO_TEST_CASE(test_mac_addr){
     std::cout << "Testing mac addr..." << std::endl;
     const std::string mac_addr_str("00:01:23:45:67:89");
-    uhd::mac_addr_t mac_addr(mac_addr_str);
+    uhd::mac_addr_t mac_addr = uhd::mac_addr_t::from_string(mac_addr_str);
     std::cout << "Input: " << mac_addr_str << std::endl;
     std::cout << "Output: " << mac_addr.to_string() << std::endl;
     BOOST_CHECK_EQUAL(mac_addr_str, mac_addr.to_string());
diff --git a/host/utils/usrp2_burner.cpp b/host/utils/usrp2_burner.cpp
index ff6d4426f..b24425316 100644
--- a/host/utils/usrp2_burner.cpp
+++ b/host/utils/usrp2_burner.cpp
@@ -57,27 +57,32 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
     uhd::device::sptr u2_dev = uhd::usrp::usrp2::make(device_addr);
     //FIXME usees the default mboard for now (until the mimo link is supported)
     wax::obj u2_mb = (*u2_dev)[uhd::DEVICE_PROP_MBOARD];
+    std::cout << std::endl;
+
+    //fetch and print current settings
+    std::cout << "Fetching current settings from usrp2 eeprom:" << std::endl;
+    std::string curr_ip = u2_mb[std::string("ip-addr")].as<std::string>();
+    std::cout << boost::format("  Current IP Address: %s") % curr_ip << std::endl;
+    std::string curr_mac = u2_mb[std::string("mac-addr")].as<std::string>();
+    std::cout << boost::format("  Current MAC Address: %s") % curr_mac << std::endl;
+    std::cout << "  Done" << std::endl << std::endl;
 
     //try to set the new ip (if provided)
     if (vm.count("new-ip")){
         std::cout << "Burning a new ip address into the usrp2 eeprom:" << std::endl;
-        std::string old_ip = u2_mb[std::string("ip-addr")].as<std::string>();
-        std::cout << boost::format("  Old IP Address: %s") % old_ip << std::endl;
         std::string new_ip = vm["new-ip"].as<std::string>();
         std::cout << boost::format("  New IP Address: %s") % new_ip << std::endl;
         u2_mb[std::string("ip-addr")] = new_ip;
-        std::cout << "  Done" << std::endl;
+        std::cout << "  Done" << std::endl << std::endl;
     }
 
     //try to set the new mac (if provided)
     if (vm.count("new-mac")){
         std::cout << "Burning a new mac address into the usrp2 eeprom:" << std::endl;
-        std::string old_mac = u2_mb[std::string("mac-addr")].as<std::string>();
-        std::cout << boost::format("  Old MAC Address: %s") % old_mac << std::endl;
         std::string new_mac = vm["new-mac"].as<std::string>();
         std::cout << boost::format("  New MAC Address: %s") % new_mac << std::endl;
         u2_mb[std::string("mac-addr")] = new_mac;
-        std::cout << "  Done" << std::endl;
+        std::cout << "  Done" << std::endl << std::endl;
     }
 
     std::cout << "Power-cycle the usrp2 for the changes to take effect." << std::endl;
-- 
cgit v1.2.3