From 0e693a62a89dc705c708cf50a8e5debec382e91f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 9 Dec 2010 13:17:24 -0800 Subject: usrp2: polished the multi-device addressing scheme and updated docs --- host/lib/usrp/usrp2/usrp2_impl.cpp | 96 ++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 20 deletions(-) (limited to 'host/lib/usrp/usrp2/usrp2_impl.cpp') diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 610e2f404..c3bbe4d65 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include //htonl and ntohl #include @@ -43,10 +44,76 @@ template std::string num2str(T num){ return boost::lexical_cast(num); } +//! separate indexed device addresses into a vector of device addresses +device_addrs_t sep_indexed_dev_addrs(const device_addr_t &dev_addr){ + //------------ support old deprecated way and print warning -------- + if (dev_addr.has_key("addr")){ + std::vector addrs = std::split_string(dev_addr["addr"]); + if (addrs.size() > 1){ + device_addr_t fixed_dev_addr = dev_addr; + fixed_dev_addr.pop("addr"); + for (size_t i = 0; i < addrs.size(); i++){ + fixed_dev_addr[str(boost::format("addr%d") % i)] = addrs[i]; + } + uhd::warning::post( + "addr = is deprecated.\n" + "To address a multi-device, use multiple = .\n" + "See the USRP-NXXX application notes. Two device example:\n" + " addr0 = 192.168.10.2\n" + " addr1 = 192.168.10.3\n" + ); + return sep_indexed_dev_addrs(fixed_dev_addr); + } + } + //------------------------------------------------------------------ + device_addrs_t dev_addrs; + BOOST_FOREACH(const std::string &key, dev_addr.keys()){ + boost::cmatch matches; + if (not boost::regex_match(key.c_str(), matches, boost::regex("^(\\D+)(\\d*)$"))){ + throw std::runtime_error("unknown key format: " + key); + } + std::string key_part(matches[1].first, matches[1].second); + std::string num_part(matches[2].first, matches[2].second); + size_t num = (num_part.empty())? 0 : boost::lexical_cast(num_part); + dev_addrs.resize(std::max(num+1, dev_addrs.size())); + dev_addrs[num][key_part] = dev_addr[key]; + } + return dev_addrs; +} + +//! combine a vector in device addresses into an indexed device address +device_addr_t combine_dev_addr_vector(const device_addrs_t &dev_addrs){ + device_addr_t dev_addr; + for (size_t i = 0; i < dev_addrs.size(); i++){ + BOOST_FOREACH(const std::string &key, dev_addrs[i].keys()){ + dev_addr[str(boost::format("%s%d") % key % i)] = dev_addrs[i][key]; + } + } + return dev_addr; +} + /*********************************************************************** * Discovery over the udp transport **********************************************************************/ -static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ +static device_addrs_t usrp2_find(const device_addr_t &hint_){ + //handle the multi-device discovery + device_addrs_t hints = sep_indexed_dev_addrs(hint_); + if (hints.size() > 1){ + device_addrs_t found_devices; + BOOST_FOREACH(const device_addr_t &hint_i, hints){ + device_addrs_t found_devices_i = usrp2_find(hint_i); + if (found_devices_i.size() != 1) throw std::runtime_error(str(boost::format( + "Could not resolve device hint \"%s\" to a single device." + ) % hint_i.to_string())); + found_devices.push_back(found_devices_i[0]); + } + return device_addrs_t(1, combine_dev_addr_vector(found_devices)); + } + + //initialize the hint for a single device case + UHD_ASSERT_THROW(hints.size() <= 1); + hints.resize(1); //in case it was empty + device_addr_t hint = hints[0]; device_addrs_t usrp2_addrs; //return an empty list of addresses when type is set to non-usrp2 @@ -71,16 +138,6 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ return usrp2_addrs; } - //if there are multiple addresses, just return good, dont test - std::vector addrs = std::split_string(hint["addr"]); - if (addrs.size() > 1){ - device_addr_t new_addr; - new_addr["type"] = "usrp2"; - new_addr["addr"] = hint["addr"]; - usrp2_addrs.push_back(new_addr); - return usrp2_addrs; - } - //create a udp transport to communicate std::string ctrl_port = boost::lexical_cast(USRP2_UDP_CTRL_PORT); udp_simple::sptr udp_transport = udp_simple::make_broadcast( @@ -106,9 +163,8 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ new_addr["type"] = "usrp2"; new_addr["addr"] = ip_addr.to_string(); //Attempt to read the name from the EEPROM and perform filtering. - //This operation can throw due to COMPAT mismatch. That is OK. - //We will allow the device to be found and the COMPAT mismatch - //will be thrown as an exception in the factory function. + //This operation can throw due to compatibility mismatch. + //In this case, the discovered device will be ignored. try{ mboard_eeprom_t mb_eeprom = usrp2_iface::make( udp_simple::make_connected(new_addr["addr"], num2str(USRP2_UDP_CTRL_PORT)) @@ -141,17 +197,17 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){ * Make **********************************************************************/ static device::sptr usrp2_make(const device_addr_t &device_addr){ - +sep_indexed_dev_addrs(device_addr); //create a ctrl and data transport for each address std::vector ctrl_transports; std::vector data_transports; - BOOST_FOREACH(const std::string &addr, std::split_string(device_addr["addr"])){ + BOOST_FOREACH(const device_addr_t &dev_addr_i, sep_indexed_dev_addrs(device_addr)){ ctrl_transports.push_back(udp_simple::make_connected( - addr, num2str(USRP2_UDP_CTRL_PORT) + dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT) )); data_transports.push_back(udp_zero_copy::make( - addr, num2str(USRP2_UDP_DATA_PORT), device_addr + dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), device_addr )); } @@ -217,8 +273,8 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ case DEVICE_PROP_NAME: - if (_mboards.size() > 1) val = std::string("USRP-NXXX mimo device"); - else val = std::string("USRP-NXXX device"); + if (_mboards.size() > 1) val = std::string("USRP2/N Series multi-device"); + else val = std::string("USRP2/N Series device"); return; case DEVICE_PROP_MBOARD: -- cgit v1.2.3