mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
host: refactor find and centralize device filtering
- centralize device filtering: instead of filtering the discovered devices in each device specific finds, move this filtering logic to device::find. Also merge all the filtering conditions here. - remove type=mpm filtering ability this feature of finding device using hint type=mpm is not used as much and is not documented. Removing this helps to keep filtering logic cleaner and centralized. - refactor find to return [device,make] pairs moving device specific find filtering into device::find method breaks device::make which was calling its own device finds and was relying on the device specific find filtering. To solve this, we create a device addr and make fcn pairs in the device::find which is now called into device::make. Based on filtered discovered devices, the rest of the make method is executed. 2 more internal functions are created supporting device::find that helps to make the code readable.
This commit is contained in:
parent
a2ee0402f4
commit
8f6c7e5f0e
@ -12,6 +12,7 @@
|
||||
#include <uhd/utils/log.hpp>
|
||||
#include <uhd/utils/static.hpp>
|
||||
#include <uhdlib/utils/prefs.hpp>
|
||||
#include <uhdlib/utils/serial_number.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
@ -80,40 +81,99 @@ device::~device(void)
|
||||
/***********************************************************************
|
||||
* Discover
|
||||
**********************************************************************/
|
||||
device_addrs_t device::find(const device_addr_t& hint, device_filter_t filter)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_device_mutex);
|
||||
|
||||
device_addrs_t device_addrs;
|
||||
std::vector<std::future<device_addrs_t>> find_tasks;
|
||||
// Internal function that discovers devices and returns them with their make functions
|
||||
static std::vector<std::tuple<device_addr_t, device::make_t>>
|
||||
discover_devices_with_makers(const device_addr_t& hint, device::device_filter_t filter)
|
||||
{
|
||||
std::vector<std::tuple<device_addr_t, device::make_t>> device_maker_pairs;
|
||||
|
||||
// Launch async find tasks with their corresponding make functions
|
||||
std::vector<std::pair<std::future<device_addrs_t>, device::make_t>> tasks;
|
||||
for (const auto& fcn : get_dev_fcn_regs()) {
|
||||
if (filter == ANY or std::get<2>(fcn) == filter) {
|
||||
find_tasks.emplace_back(std::async(
|
||||
std::launch::async, [fcn, hint]() { return std::get<0>(fcn)(hint); }));
|
||||
if (filter == device::ANY or std::get<2>(fcn) == filter) {
|
||||
tasks.emplace_back(std::async(std::launch::async,
|
||||
[fcn, hint]() { return std::get<0>(fcn)(hint); }),
|
||||
std::get<1>(fcn));
|
||||
}
|
||||
}
|
||||
for (auto& find_task : find_tasks) {
|
||||
|
||||
// Collect results from async tasks
|
||||
for (auto& [task, maker] : tasks) {
|
||||
try {
|
||||
device_addrs_t discovered_addrs = find_task.get();
|
||||
device_addrs.insert(
|
||||
device_addrs.begin(), discovered_addrs.begin(), discovered_addrs.end());
|
||||
device_addrs_t discovered_addrs = task.get();
|
||||
for (const auto& addr : discovered_addrs) {
|
||||
device_maker_pairs.emplace_back(addr, maker);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
UHD_LOGGER_ERROR("UHD") << "Device discovery error: " << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
return device_maker_pairs;
|
||||
}
|
||||
|
||||
// Internal function that returns filtered device-maker pairs
|
||||
static std::vector<std::tuple<device_addr_t, device::make_t>>
|
||||
find_filtered_devices_with_makers(
|
||||
const device_addr_t& hint, device::device_filter_t filter)
|
||||
{
|
||||
// Get devices with their makers
|
||||
auto device_maker_pairs = discover_devices_with_makers(hint, filter);
|
||||
|
||||
std::vector<std::tuple<device_addr_t, device::make_t>> filtered_pairs;
|
||||
|
||||
// Filter the discovered devices
|
||||
for (const auto& pair : device_maker_pairs) {
|
||||
const device_addr_t& discovered_addr = std::get<0>(pair);
|
||||
|
||||
// Filter with the optional keys name/serial/type/product
|
||||
if ((not hint.has_key("name") or hint["name"] == discovered_addr["name"])
|
||||
and (not hint.has_key("serial")
|
||||
or utils::serial_numbers_match(
|
||||
hint["serial"], discovered_addr["serial"]))
|
||||
and (not hint.has_key("type") or hint["type"] == discovered_addr["type"])
|
||||
and (not hint.has_key("product") or not discovered_addr.has_key("product")
|
||||
or hint["product"] == discovered_addr["product"])) {
|
||||
UHD_LOG_DEBUG("Device FIND",
|
||||
"Found device that matches hints: " << discovered_addr.to_string());
|
||||
filtered_pairs.push_back(pair);
|
||||
} else {
|
||||
UHD_LOG_DEBUG("Device FIND",
|
||||
"Found device, but does not match hint: " << discovered_addr.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// find might return duplicate entries if a device received a broadcast multiple
|
||||
// times. These entries needs to be removed from the result.
|
||||
std::set<size_t> device_hashes;
|
||||
device_addrs.erase(std::remove_if(device_addrs.begin(),
|
||||
device_addrs.end(),
|
||||
[&device_hashes](const device_addr_t& other) {
|
||||
size_t hash = hash_device_addr(other);
|
||||
const bool result = device_hashes.count(hash);
|
||||
device_hashes.insert(hash);
|
||||
return result;
|
||||
}),
|
||||
device_addrs.end());
|
||||
filtered_pairs.erase(
|
||||
std::remove_if(filtered_pairs.begin(),
|
||||
filtered_pairs.end(),
|
||||
[&device_hashes](const std::tuple<device_addr_t, device::make_t>& pair) {
|
||||
size_t hash = hash_device_addr(std::get<0>(pair));
|
||||
const bool result = device_hashes.count(hash);
|
||||
device_hashes.insert(hash);
|
||||
return result;
|
||||
}),
|
||||
filtered_pairs.end());
|
||||
|
||||
return filtered_pairs;
|
||||
}
|
||||
|
||||
device_addrs_t device::find(const device_addr_t& hint, device_filter_t filter)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_device_mutex);
|
||||
|
||||
// Get filtered device-maker pairs
|
||||
auto filtered_pairs = find_filtered_devices_with_makers(hint, filter);
|
||||
|
||||
// Extract just the device addresses
|
||||
device_addrs_t device_addrs;
|
||||
std::transform(filtered_pairs.begin(),
|
||||
filtered_pairs.end(),
|
||||
std::back_inserter(device_addrs),
|
||||
[](const auto& pair) { return std::get<0>(pair); });
|
||||
|
||||
return device_addrs;
|
||||
}
|
||||
@ -125,21 +185,15 @@ device::sptr device::make(const device_addr_t& hint, device_filter_t filter, siz
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_device_mutex);
|
||||
|
||||
// Use the internal function that returns filtered device-maker pairs
|
||||
auto filtered_pairs = find_filtered_devices_with_makers(hint, filter);
|
||||
|
||||
typedef std::tuple<device_addr_t, make_t> dev_addr_make_t;
|
||||
std::vector<dev_addr_make_t> dev_addr_makers;
|
||||
|
||||
for (const dev_fcn_reg_t& fcn : get_dev_fcn_regs()) {
|
||||
try {
|
||||
if (filter == ANY or std::get<2>(fcn) == filter) {
|
||||
for (device_addr_t dev_addr : std::get<0>(fcn)(hint)) {
|
||||
// append the discovered address and its factory function
|
||||
dev_addr_makers.push_back(
|
||||
dev_addr_make_t(dev_addr, std::get<1>(fcn)));
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
UHD_LOGGER_ERROR("UHD") << "Device discovery error: " << e.what();
|
||||
}
|
||||
// Convert to the expected format (no additional filtering needed)
|
||||
for (const auto& pair : filtered_pairs) {
|
||||
dev_addr_makers.push_back(dev_addr_make_t(std::get<0>(pair), std::get<1>(pair)));
|
||||
}
|
||||
|
||||
// check that we found any devices
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include <uhd/transport/usb_control.hpp>
|
||||
#include <uhd/types/metadata.hpp>
|
||||
#include <uhd/usrp/dboard_eeprom.hpp>
|
||||
#include <uhd/utils/algorithm.hpp>
|
||||
#include <uhd/utils/cast.hpp>
|
||||
#include <uhd/utils/log.hpp>
|
||||
#include <uhd/utils/paths.hpp>
|
||||
@ -184,6 +185,13 @@ static device_addrs_t b200_find(const device_addr_t& hint)
|
||||
if (hint.has_key("type") and hint["type"] != "b200")
|
||||
return b200_addrs;
|
||||
|
||||
// return an empty list of addresses when product is set to non-B2XX
|
||||
if (hint.has_key("product")) {
|
||||
if (!uhd::has(B2XX_STR_NAMES.vals(), hint["product"])) {
|
||||
return b200_addrs;
|
||||
}
|
||||
}
|
||||
|
||||
// Return an empty list of addresses when an address or resource is specified,
|
||||
// since an address and resource is intended for a different, non-USB, device.
|
||||
for (device_addr_t hint_i : separate_device_addr(hint)) {
|
||||
@ -252,13 +260,7 @@ static device_addrs_t b200_find(const device_addr_t& hint)
|
||||
// No problem if this fails -- this is just device discovery, after all.
|
||||
new_addr["product"] = "B2??";
|
||||
}
|
||||
|
||||
// this is a found b200 when the hint serial and name match or blank
|
||||
if ((not hint.has_key("name") or hint["name"] == new_addr["name"])
|
||||
and (not hint.has_key("serial")
|
||||
or hint["serial"] == new_addr["serial"])) {
|
||||
b200_addrs.push_back(new_addr);
|
||||
}
|
||||
b200_addrs.push_back(new_addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -112,21 +112,7 @@ device_addrs_t mpmd_find_with_addr(
|
||||
new_addr[value[0]] = value[1];
|
||||
}
|
||||
}
|
||||
// filter the discovered device below by matching optional keys
|
||||
if ((not hint_.has_key("name") or hint_["name"] == new_addr["name"])
|
||||
and (not hint_.has_key("serial")
|
||||
or utils::serial_numbers_match(hint_["serial"], new_addr["serial"]))
|
||||
and (not hint_.has_key("type") or hint_["type"] == new_addr["type"]
|
||||
or hint_["type"] == MPM_CATCHALL_DEVICE_TYPE)
|
||||
and (not hint_.has_key("product")
|
||||
or hint_["product"] == new_addr["product"])) {
|
||||
UHD_LOG_TRACE(
|
||||
"MPMD FIND", "Found device that matches hints: " << new_addr.to_string());
|
||||
addrs.push_back(new_addr);
|
||||
} else {
|
||||
UHD_LOG_DEBUG(
|
||||
"MPMD FIND", "Found device, but does not match hint: " << recv_addr);
|
||||
}
|
||||
addrs.push_back(new_addr);
|
||||
}
|
||||
return addrs;
|
||||
};
|
||||
|
||||
@ -70,6 +70,11 @@ device_addrs_t usrp2_find(const device_addr_t& hint_)
|
||||
if (hint.has_key("resource"))
|
||||
return usrp2_addrs;
|
||||
|
||||
// Return an empty list of addresses when a product is specified,
|
||||
// since a product is intended for a different, non-usrp2, device.
|
||||
if (hint.has_key("product"))
|
||||
return usrp2_addrs;
|
||||
|
||||
// if no address was specified, send a broadcast on each interface
|
||||
if (not hint.has_key("addr")) {
|
||||
for (const if_addrs_t& if_addrs : get_if_addrs()) {
|
||||
@ -161,14 +166,7 @@ device_addrs_t usrp2_find(const device_addr_t& hint_)
|
||||
new_addr["name"] = "";
|
||||
new_addr["serial"] = "";
|
||||
}
|
||||
|
||||
// filter the discovered device below by matching optional keys
|
||||
if ((not hint.has_key("name") or hint["name"] == new_addr["name"])
|
||||
and (not hint.has_key("serial")
|
||||
or hint["serial"] == new_addr["serial"])) {
|
||||
usrp2_addrs.push_back(new_addr);
|
||||
}
|
||||
|
||||
usrp2_addrs.push_back(new_addr);
|
||||
// dont break here, it will exit the while loop
|
||||
// just continue on to the next loop iteration
|
||||
}
|
||||
|
||||
@ -168,12 +168,7 @@ device_addrs_t eth_manager::find(const device_addr_t& hint)
|
||||
new_addr["name"] = "";
|
||||
new_addr["serial"] = "";
|
||||
}
|
||||
// filter the discovered device below by matching optional keys
|
||||
if ((not hint.has_key("name") or hint["name"] == new_addr["name"])
|
||||
and (not hint.has_key("serial") or hint["serial"] == new_addr["serial"])
|
||||
and (not hint.has_key("product") or hint["product"] == new_addr["product"])) {
|
||||
addrs.push_back(new_addr);
|
||||
}
|
||||
addrs.push_back(new_addr);
|
||||
}
|
||||
|
||||
return addrs;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user