1 //
2 // Copyright 2011 Ettus Research LLC
3 // Copyright 2018 Ettus Research, a National Instruments Company
4 //
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 
8 #include <uhd/exception.hpp>
9 #include <uhd/utils/assert_has.hpp>
10 #include <uhdlib/usrp/common/validate_subdev_spec.hpp>
11 #include <boost/format.hpp>
12 
13 using namespace uhd;
14 using namespace uhd::usrp;
15 
16 namespace uhd { namespace usrp {
17 
operator <<(std::ostream & out,const subdev_spec_pair_t & pair)18 static std::ostream& operator<<(std::ostream& out, const subdev_spec_pair_t& pair)
19 {
20     out << pair.db_name << ":" << pair.sd_name;
21     return out;
22 }
23 
24 }} // namespace uhd::usrp
25 
validate_subdev_spec(property_tree::sptr tree,const subdev_spec_t & spec,const std::string & type,const std::string & mb)26 void uhd::usrp::validate_subdev_spec(property_tree::sptr tree,
27     const subdev_spec_t& spec,
28     const std::string& type,
29     const std::string& mb)
30 {
31     const size_t num_dsps =
32         tree->list(str(boost::format("/mboards/%s/%s_dsps") % mb % type)).size();
33 
34     // sanity checking on the length
35     if (spec.size() == 0)
36         throw uhd::value_error(
37             str(boost::format("Empty %s subdevice specification is not supported.\n")
38                 % type));
39     if (spec.size() > num_dsps)
40         throw uhd::value_error(
41             str(boost::format("The subdevice specification \"%s\" is too long.\n"
42                               "The user specified %u channels, but there are only %u %s "
43                               "dsps on mboard %s.\n")
44                 % spec.to_string() % spec.size() % num_dsps % type % mb));
45 
46     // make a list of all possible specs
47     subdev_spec_t all_specs;
48     for (const std::string& db :
49         tree->list(str(boost::format("/mboards/%s/dboards") % mb))) {
50         for (const std::string& sd :
51             tree->list(str(
52                 boost::format("/mboards/%s/dboards/%s/%s_frontends") % mb % db % type))) {
53             all_specs.push_back(subdev_spec_pair_t(db, sd));
54         }
55     }
56 
57     // validate that the spec is possible
58     for (const subdev_spec_pair_t& pair : spec) {
59         uhd::assert_has(all_specs,
60             pair,
61             str(boost::format("%s subdevice specification on mboard %s") % type % mb));
62     }
63 
64     // enable selected frontends, disable others
65     for (const subdev_spec_pair_t& pair : all_specs) {
66         const bool enb = uhd::has(spec, pair);
67         tree->access<bool>(
68                 str(boost::format("/mboards/%s/dboards/%s/%s_frontends/%s/enabled") % mb
69                     % pair.db_name % type % pair.sd_name))
70             .set(enb);
71     }
72 }
73