initial commit
This commit is contained in:
93
src/device_discovery.cpp
Normal file
93
src/device_discovery.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "adc_sweep/device_discovery.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace adc_sweep {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace {
|
||||
|
||||
std::string trim(std::string s) {
|
||||
while (!s.empty() && (s.back() == '\n' || s.back() == '\r' || s.back() == ' ' || s.back() == '\t')) {
|
||||
s.pop_back();
|
||||
}
|
||||
size_t i = 0;
|
||||
while (i < s.size() && (s[i] == ' ' || s[i] == '\t')) {
|
||||
++i;
|
||||
}
|
||||
return s.substr(i);
|
||||
}
|
||||
|
||||
std::string read_file_trim(const fs::path& p) {
|
||||
std::ifstream f(p);
|
||||
if (!f.is_open()) {
|
||||
return {};
|
||||
}
|
||||
std::ostringstream ss;
|
||||
ss << f.rdbuf();
|
||||
return trim(ss.str());
|
||||
}
|
||||
|
||||
std::string hex4(uint16_t v) {
|
||||
constexpr char kHex[] = "0123456789abcdef";
|
||||
std::string out(4, '0');
|
||||
out[0] = kHex[(v >> 12U) & 0xFU];
|
||||
out[1] = kHex[(v >> 8U) & 0xFU];
|
||||
out[2] = kHex[(v >> 4U) & 0xFU];
|
||||
out[3] = kHex[v & 0xFU];
|
||||
return out;
|
||||
}
|
||||
|
||||
bool tty_name_ok(const std::string& name) {
|
||||
return (name.rfind("ttyACM", 0) == 0) || (name.rfind("ttyUSB", 0) == 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::optional<std::string> find_tty_by_vid_pid(uint16_t vid, uint16_t pid) {
|
||||
const fs::path usb_root("/sys/bus/usb/devices");
|
||||
if (!fs::exists(usb_root)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const std::string vid_s = hex4(vid);
|
||||
const std::string pid_s = hex4(pid);
|
||||
std::vector<std::string> candidates;
|
||||
|
||||
for (const auto& entry : fs::directory_iterator(usb_root)) {
|
||||
if (!entry.is_directory()) {
|
||||
continue;
|
||||
}
|
||||
const fs::path devdir = entry.path();
|
||||
const std::string v = read_file_trim(devdir / "idVendor");
|
||||
const std::string p = read_file_trim(devdir / "idProduct");
|
||||
if (v != vid_s || p != pid_s) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& sub : fs::recursive_directory_iterator(devdir, fs::directory_options::skip_permission_denied)) {
|
||||
const std::string name = sub.path().filename().string();
|
||||
if (!tty_name_ok(name)) {
|
||||
continue;
|
||||
}
|
||||
const std::string devnode = "/dev/" + name;
|
||||
if (fs::exists(devnode)) {
|
||||
candidates.push_back(devnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (candidates.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::sort(candidates.begin(), candidates.end());
|
||||
candidates.erase(std::unique(candidates.begin(), candidates.end()), candidates.end());
|
||||
return candidates.front();
|
||||
}
|
||||
|
||||
} // namespace adc_sweep
|
||||
Reference in New Issue
Block a user