aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/mpmd/mpmd_prop_tree.cpp
blob: 33ffde401949b7fc1858f8a5beecabe055caf801 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
//
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

// property tree initialization code

#include "mpmd_impl.hpp"
#include <uhd/property_tree.hpp>
#include <uhd/types/component_file.hpp>
#include <uhd/types/sensors.hpp>
#include <uhd/types/eeprom.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>

using namespace uhd;
using namespace uhd::mpmd;

namespace {
    //! Timeout value for the update_component RPC call (ms)
    constexpr size_t MPMD_UPDATE_COMPONENT_TIMEOUT = 20000;

    uhd::usrp::component_files_t _update_component(
        const uhd::usrp::component_files_t& comps,
        mpmd_mboard_impl *mb
    ) {
        // Construct the arguments to update component
        std::vector<std::vector<uint8_t>> all_data;
        std::vector<std::map<std::string, std::string>> all_metadata;
        // Also construct a copy of just the metadata to store in the property tree
        uhd::usrp::component_files_t all_comps_copy;

        for  (const auto& comp : comps) {
            // Make a map for update components args
            std::map<std::string, std::string> metadata;
            // Make a component copy to add to the property tree
            uhd::usrp::component_file_t comp_copy;
            // Copy the metadata
            for (const auto& key : comp.metadata.keys()) {
                metadata[key] = comp.metadata[key];
                comp_copy.metadata[key] = comp.metadata[key];
            }
            // Copy to the update component args
            all_data.push_back(comp.data);
            all_metadata.push_back(metadata);
            // Copy to the property tree
            all_comps_copy.push_back(comp_copy);
        }

        // Now call update component
        const size_t update_component_timeout = MPMD_UPDATE_COMPONENT_TIMEOUT * comps.size();
        mb->rpc->set_timeout(update_component_timeout);
        mb->rpc->notify_with_token("update_component", all_metadata, all_data);
        mb->set_timeout_default();

        return all_comps_copy;
    }

}

void mpmd_impl::init_property_tree(
        uhd::property_tree::sptr tree,
        fs_path mb_path,
        mpmd_mboard_impl *mb
) {
    /*** Device info ****************************************************/
    if (not tree->exists("/name")) {
        tree->create<std::string>("/name")
            .set(mb->device_info.get("name", "Unknown MPM device"))
        ;
    }
    tree->create<std::string>(mb_path / "name")
        .set(mb->device_info.get("type", "UNKNOWN"));
    tree->create<std::string>(mb_path / "serial")
        .set(mb->device_info.get("serial", "n/a"));
    tree->create<std::string>(mb_path / "connection")
        .set(mb->device_info.get("connection", "UNKNOWN"));
    tree->create<size_t>(mb_path / "link_max_rate").set(1e9 / 8);

    /*** Clocking *******************************************************/
    tree->create<std::string>(mb_path / "clock_source/value")
        .add_coerced_subscriber([mb](const std::string &clock_source){
            // FIXME: Undo these changes
            //mb->rpc->notify_with_token("set_clock_source", clock_source);
            auto current_src = mb->rpc->request_with_token<std::string>(
                "get_clock_source"
            );
            if (current_src != clock_source) {
                UHD_LOG_WARNING("MPMD",
                    "Setting clock source at runtime is currently not "
                    "supported. Use clock_source=XXX as a device arg to "
                    "select a clock source. The current source is: "
                    << current_src);
            }
        })
        .set_publisher([mb](){
            return mb->rpc->request_with_token<std::string>(
                "get_clock_source"
            );
        })
    ;
    tree->create<std::vector<std::string>>(
            mb_path / "clock_source/options")
        .set_publisher([mb](){
            return mb->rpc->request_with_token<std::vector<std::string>>(
                "get_clock_sources"
            );
        })
    ;
    tree->create<std::string>(mb_path / "time_source/value")
        .add_coerced_subscriber([mb](const std::string &time_source){
            //mb->rpc->notify_with_token("set_time_source", time_source);
            // FIXME: Undo these changes
            auto current_src = mb->rpc->request_with_token<std::string>(
                "get_time_source"
            );
            if (current_src != time_source) {
                UHD_LOG_WARNING("MPMD",
                    "Setting time source at runtime is currently not "
                    "supported. Use time_source=XXX as a device arg to "
                    "select a time source. The current source is: "
                    << current_src);
            }
        })
        .set_publisher([mb](){
            return mb->rpc->request_with_token<std::string>(
                "get_time_source"
            );
        })
    ;
    tree->create<std::vector<std::string>>(
            mb_path / "time_source/options")
        .set_publisher([mb](){
            return mb->rpc->request_with_token<std::vector<std::string>>(
                "get_time_sources"
            );
        })
    ;

    /*** Sensors ********************************************************/
    auto sensor_list =
        mb->rpc->request_with_token<std::vector<std::string>>(
            "get_mb_sensors"
        );
    UHD_LOG_DEBUG("MPMD",
        "Found " << sensor_list.size() << " motherboard sensors."
    );
    for (const auto& sensor_name : sensor_list) {
        UHD_LOG_TRACE("MPMD",
            "Adding motherboard sensor `" << sensor_name << "'"
        );
        tree->create<sensor_value_t>(
                mb_path / "sensors" / sensor_name)
            .set_publisher([mb, sensor_name](){
                return sensor_value_t(
                    mb->rpc->request_with_token<sensor_value_t::sensor_map_t>(
                        "get_mb_sensor", sensor_name
                    )
                );
            })
            .set_coercer([](const sensor_value_t &){
                throw uhd::runtime_error(
                    "Trying to write read-only sensor value!"
                );
                return sensor_value_t("", "", "");
            })
        ;
    }

    /*** EEPROM *********************************************************/
    tree->create<uhd::usrp::mboard_eeprom_t>(mb_path / "eeprom")
        .add_coerced_subscriber([mb](const uhd::usrp::mboard_eeprom_t& mb_eeprom){
            eeprom_map_t eeprom_map;
            for (const auto& key : mb_eeprom.keys()) {
                eeprom_map[key] = std::vector<uint8_t>(
                        mb_eeprom[key].cbegin(),
                        mb_eeprom[key].cend()
                );
            }
            mb->rpc->notify_with_token("set_mb_eeprom", eeprom_map);
        })
        .set_publisher([mb](){
            auto mb_eeprom =
                mb->rpc->request_with_token<std::map<std::string, std::string>>(
                    "get_mb_eeprom"
                );
            uhd::usrp::mboard_eeprom_t mb_eeprom_dict(
                mb_eeprom.cbegin(), mb_eeprom.cend()
            );
            return mb_eeprom_dict;
        })
    ;

    /*** Updateable Components ******************************************/
    std::vector<std::string> updateable_components =
            mb->rpc->request<std::vector<std::string>>(
                    "list_updateable_components"
            );
    // TODO: Check the 'id' against the registered property
    UHD_LOG_DEBUG("MPMD",
                "Found " << updateable_components.size() << " updateable motherboard components."
            );
    for (const auto& comp_name : updateable_components) {
        UHD_LOG_TRACE("MPMD",
                "Adding motherboard component: " << comp_name);
        tree->create<uhd::usrp::component_files_t>(mb_path / "components" / comp_name)
                    .set_coercer([mb](const uhd::usrp::component_files_t& comp_files) {
                return _update_component(
                        comp_files,
                        mb
                );
        })
        ;
    }

    /*** MTUs ***********************************************************/
    tree->create<size_t>(mb_path / "mtu/recv")
        .add_coerced_subscriber([](const size_t){
            throw uhd::runtime_error(
                "Attempting to write read-only value (MTU)!");
        })
        .set_publisher([mb](){
            return mb->get_mtu(uhd::RX_DIRECTION);
        })
    ;
    tree->create<size_t>(mb_path / "mtu/send")
        .add_coerced_subscriber([](const size_t){
            throw uhd::runtime_error(
                "Attempting to write read-only value (MTU)!");
        })
        .set_publisher([mb](){
            return mb->get_mtu(uhd::TX_DIRECTION);
        })
    ;
}