2018-01-24 02:27:11 +00:00
|
|
|
//
|
|
|
|
|
// Copyright 2018 Ettus Research, a National Instruments Company
|
|
|
|
|
//
|
2018-02-19 23:30:32 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
2018-01-24 02:27:11 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// property tree initialization code
|
|
|
|
|
|
|
|
|
|
#include "mpmd_impl.hpp"
|
|
|
|
|
#include <uhd/property_tree.hpp>
|
|
|
|
|
#include <uhd/types/component_file.hpp>
|
|
|
|
|
#include <uhd/types/eeprom.hpp>
|
2019-01-14 18:35:25 +00:00
|
|
|
#include <uhd/types/sensors.hpp>
|
2018-01-24 02:27:11 +00:00
|
|
|
#include <uhd/usrp/mboard_eeprom.hpp>
|
|
|
|
|
|
|
|
|
|
using namespace uhd;
|
|
|
|
|
using namespace uhd::mpmd;
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2019-01-14 18:35:25 +00:00
|
|
|
/*! Update a component using all required files. For example, when updating the FPGA image
|
|
|
|
|
* (.bit or .bin), users can provide a new overlay image (DTS) to apply in addition.
|
|
|
|
|
*
|
|
|
|
|
* \param comps Vector of component files to be updated
|
|
|
|
|
* \param mb Reference to the actual device
|
|
|
|
|
*/
|
|
|
|
|
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;
|
2018-01-24 02:27:11 +00:00
|
|
|
|
2019-01-14 18:35:25 +00:00
|
|
|
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];
|
2018-01-24 02:27:11 +00:00
|
|
|
}
|
2019-01-14 18:35:25 +00:00
|
|
|
// 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);
|
2018-01-24 02:27:11 +00:00
|
|
|
}
|
|
|
|
|
|
2019-01-14 18:35:25 +00:00
|
|
|
// Now call update component
|
|
|
|
|
mb->rpc->notify_with_token(
|
2019-01-29 18:46:57 +00:00
|
|
|
MPMD_DEFAULT_INIT_TIMEOUT, "update_component", all_metadata, all_data);
|
2019-01-14 18:35:25 +00:00
|
|
|
return all_comps_copy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Query the device to get the metadata for desired component
|
|
|
|
|
*
|
|
|
|
|
* \param comp_name String component name
|
|
|
|
|
* \param mb Reference to the actual device
|
|
|
|
|
* \return component files containing the component metadata
|
|
|
|
|
*/
|
|
|
|
|
uhd::usrp::component_files_t _get_component_info(
|
|
|
|
|
const std::string& comp_name, mpmd_mboard_impl* mb)
|
|
|
|
|
{
|
|
|
|
|
UHD_LOG_TRACE("MPMD", "Getting component info for " << comp_name);
|
|
|
|
|
const auto component_metadata = mb->rpc->request<std::map<std::string, std::string>>(
|
|
|
|
|
"get_component_info", comp_name);
|
|
|
|
|
// Copy the contents of the component metadata into a object we can return
|
|
|
|
|
uhd::usrp::component_file_t return_component;
|
|
|
|
|
auto& return_metadata = return_component.metadata;
|
|
|
|
|
for (auto item : component_metadata) {
|
|
|
|
|
return_metadata[item.first] = item.second;
|
2018-02-02 19:48:35 +00:00
|
|
|
}
|
2019-01-14 18:35:25 +00:00
|
|
|
return uhd::usrp::component_files_t{return_component};
|
2018-01-24 02:27:11 +00:00
|
|
|
}
|
2019-01-14 18:35:25 +00:00
|
|
|
} // namespace
|
2018-01-24 02:27:11 +00:00
|
|
|
|
|
|
|
|
void mpmd_impl::init_property_tree(
|
2019-01-14 18:35:25 +00:00
|
|
|
uhd::property_tree::sptr tree, fs_path mb_path, mpmd_mboard_impl* mb)
|
|
|
|
|
{
|
2018-01-24 02:27:11 +00:00
|
|
|
/*** Device info ****************************************************/
|
|
|
|
|
if (not tree->exists("/name")) {
|
2019-01-14 18:35:25 +00:00
|
|
|
tree->create<std::string>("/name").set(
|
|
|
|
|
mb->device_info.get("description", "Unknown MPM device"));
|
2018-01-24 02:27:11 +00:00
|
|
|
}
|
|
|
|
|
tree->create<std::string>(mb_path / "name")
|
2018-03-01 19:59:52 +00:00
|
|
|
.set(mb->device_info.get("name", "UNKNOWN"));
|
2018-01-24 02:27:11 +00:00
|
|
|
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);
|
2018-03-01 19:59:52 +00:00
|
|
|
tree->create<std::string>(mb_path / "mpm_version")
|
|
|
|
|
.set(mb->device_info.get("mpm_version", "UNKNOWN"));
|
|
|
|
|
tree->create<std::string>(mb_path / "fpga_version")
|
|
|
|
|
.set(mb->device_info.get("fpga_version", "UNKNOWN"));
|
2018-11-16 19:02:15 +00:00
|
|
|
tree->create<std::string>(mb_path / "fpga_version_hash")
|
|
|
|
|
.set(mb->device_info.get("fpga_version_hash", "UNKNOWN"));
|
2018-01-24 02:27:11 +00:00
|
|
|
|
|
|
|
|
/*** Clocking *******************************************************/
|
|
|
|
|
tree->create<std::string>(mb_path / "clock_source/value")
|
2019-01-14 18:35:25 +00:00
|
|
|
.add_coerced_subscriber([mb](const std::string& clock_source) {
|
|
|
|
|
mb->rpc->notify_with_token(
|
|
|
|
|
MPMD_DEFAULT_INIT_TIMEOUT, "set_clock_source", clock_source);
|
2018-01-24 02:27:11 +00:00
|
|
|
})
|
2019-01-14 18:35:25 +00:00
|
|
|
.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]() {
|
2018-01-24 02:27:11 +00:00
|
|
|
return mb->rpc->request_with_token<std::vector<std::string>>(
|
2019-01-14 18:35:25 +00:00
|
|
|
"get_clock_sources");
|
|
|
|
|
});
|
2018-01-24 02:27:11 +00:00
|
|
|
tree->create<std::string>(mb_path / "time_source/value")
|
2019-01-14 18:35:25 +00:00
|
|
|
.add_coerced_subscriber([mb](const std::string& time_source) {
|
|
|
|
|
mb->rpc->notify_with_token(
|
|
|
|
|
MPMD_DEFAULT_INIT_TIMEOUT, "set_time_source", time_source);
|
2018-01-24 02:27:11 +00:00
|
|
|
})
|
2019-01-14 18:35:25 +00:00
|
|
|
.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]() {
|
2018-01-24 02:27:11 +00:00
|
|
|
return mb->rpc->request_with_token<std::vector<std::string>>(
|
2019-01-14 18:35:25 +00:00
|
|
|
"get_time_sources");
|
|
|
|
|
});
|
2018-01-24 02:27:11 +00:00
|
|
|
|
|
|
|
|
/*** Sensors ********************************************************/
|
|
|
|
|
auto sensor_list =
|
2019-01-14 18:35:25 +00:00
|
|
|
mb->rpc->request_with_token<std::vector<std::string>>("get_mb_sensors");
|
|
|
|
|
UHD_LOG_DEBUG("MPMD", "Found " << sensor_list.size() << " motherboard sensors.");
|
2018-01-24 02:27:11 +00:00
|
|
|
for (const auto& sensor_name : sensor_list) {
|
2019-01-14 18:35:25 +00:00
|
|
|
UHD_LOG_TRACE("MPMD", "Adding motherboard sensor `" << sensor_name << "'");
|
|
|
|
|
tree->create<sensor_value_t>(mb_path / "sensors" / sensor_name)
|
|
|
|
|
.set_publisher([mb, sensor_name]() {
|
2018-11-12 01:52:16 +00:00
|
|
|
auto sensor_val = sensor_value_t(
|
2018-01-24 02:27:11 +00:00
|
|
|
mb->rpc->request_with_token<sensor_value_t::sensor_map_t>(
|
2019-01-14 18:35:25 +00:00
|
|
|
MPMD_DEFAULT_INIT_TIMEOUT, "get_mb_sensor", sensor_name));
|
2018-11-12 01:52:16 +00:00
|
|
|
return sensor_val;
|
2018-01-24 02:27:11 +00:00
|
|
|
})
|
2019-01-14 18:35:25 +00:00
|
|
|
.set_coercer([](const sensor_value_t&) {
|
|
|
|
|
throw uhd::runtime_error("Trying to write read-only sensor value!");
|
2018-01-24 02:27:11 +00:00
|
|
|
return sensor_value_t("", "", "");
|
2019-01-14 18:35:25 +00:00
|
|
|
});
|
2018-01-24 02:27:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** EEPROM *********************************************************/
|
|
|
|
|
tree->create<uhd::usrp::mboard_eeprom_t>(mb_path / "eeprom")
|
2019-01-14 18:35:25 +00:00
|
|
|
.add_coerced_subscriber([mb](const uhd::usrp::mboard_eeprom_t& mb_eeprom) {
|
2018-01-24 02:27:11 +00:00
|
|
|
eeprom_map_t eeprom_map;
|
|
|
|
|
for (const auto& key : mb_eeprom.keys()) {
|
2019-01-14 18:35:25 +00:00
|
|
|
eeprom_map[key] =
|
|
|
|
|
std::vector<uint8_t>(mb_eeprom[key].cbegin(), mb_eeprom[key].cend());
|
2018-01-24 02:27:11 +00:00
|
|
|
}
|
2019-01-14 18:35:25 +00:00
|
|
|
mb->rpc->notify_with_token(
|
|
|
|
|
MPMD_DEFAULT_INIT_TIMEOUT, "set_mb_eeprom", eeprom_map);
|
2018-01-24 02:27:11 +00:00
|
|
|
})
|
2019-01-14 18:35:25 +00:00
|
|
|
.set_publisher([mb]() {
|
2018-01-24 02:27:11 +00:00
|
|
|
auto mb_eeprom =
|
|
|
|
|
mb->rpc->request_with_token<std::map<std::string, std::string>>(
|
2019-01-14 18:35:25 +00:00
|
|
|
"get_mb_eeprom");
|
2018-01-24 02:27:11 +00:00
|
|
|
uhd::usrp::mboard_eeprom_t mb_eeprom_dict(
|
2019-01-14 18:35:25 +00:00
|
|
|
mb_eeprom.cbegin(), mb_eeprom.cend());
|
2018-01-24 02:27:11 +00:00
|
|
|
return mb_eeprom_dict;
|
2019-01-14 18:35:25 +00:00
|
|
|
});
|
2018-01-24 02:27:11 +00:00
|
|
|
|
|
|
|
|
/*** Updateable Components ******************************************/
|
|
|
|
|
std::vector<std::string> updateable_components =
|
2019-01-14 18:35:25 +00:00
|
|
|
mb->rpc->request<std::vector<std::string>>("list_updateable_components");
|
2018-01-24 02:27:11 +00:00
|
|
|
// TODO: Check the 'id' against the registered property
|
|
|
|
|
UHD_LOG_DEBUG("MPMD",
|
2019-01-14 18:35:25 +00:00
|
|
|
"Found " << updateable_components.size()
|
|
|
|
|
<< " updateable motherboard components.");
|
2018-01-24 02:27:11 +00:00
|
|
|
for (const auto& comp_name : updateable_components) {
|
2019-01-14 18:35:25 +00:00
|
|
|
UHD_LOG_TRACE("MPMD", "Adding motherboard component: " << comp_name);
|
2018-01-24 02:27:11 +00:00
|
|
|
tree->create<uhd::usrp::component_files_t>(mb_path / "components" / comp_name)
|
2019-01-14 18:35:25 +00:00
|
|
|
.set_coercer([mb](const uhd::usrp::component_files_t& comp_files) {
|
|
|
|
|
return _update_component(comp_files, mb);
|
2018-02-02 19:48:35 +00:00
|
|
|
})
|
2019-01-14 18:35:25 +00:00
|
|
|
.set_publisher([mb, comp_name]() {
|
|
|
|
|
return _get_component_info(comp_name, mb);
|
|
|
|
|
}); // Done adding component to property tree
|
2018-01-24 02:27:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*** MTUs ***********************************************************/
|
|
|
|
|
tree->create<size_t>(mb_path / "mtu/recv")
|
2019-01-14 18:35:25 +00:00
|
|
|
.add_coerced_subscriber([](const size_t) {
|
|
|
|
|
throw uhd::runtime_error("Attempting to write read-only value (MTU)!");
|
2018-01-24 02:27:11 +00:00
|
|
|
})
|
2019-01-14 18:35:25 +00:00
|
|
|
.set_publisher([mb]() { return mb->get_mtu(uhd::RX_DIRECTION); });
|
2018-01-24 02:27:11 +00:00
|
|
|
tree->create<size_t>(mb_path / "mtu/send")
|
2019-01-14 18:35:25 +00:00
|
|
|
.add_coerced_subscriber([](const size_t) {
|
|
|
|
|
throw uhd::runtime_error("Attempting to write read-only value (MTU)!");
|
2018-01-24 02:27:11 +00:00
|
|
|
})
|
2019-01-14 18:35:25 +00:00
|
|
|
.set_publisher([mb]() { return mb->get_mtu(uhd::TX_DIRECTION); });
|
2018-01-24 02:27:11 +00:00
|
|
|
}
|