radio_tool 0.2.1
Loading...
Searching...
No Matches
serial_radio_factory.cpp
1
18#include <radio_tool/radio/serial_radio_factory.hpp>
19#include <radio_tool/radio/radio.hpp>
20#include <radio_tool/radio/ailunce_radio.hpp>
21#include <radio_tool/util.hpp>
22
23#include <functional>
24#include <string>
25#include <iostream>
26
27#ifdef _WIN32
28#define WIN32_LEAN_AND_MEAN 1
29#include <Windows.h>
30#else
31#include <filesystem>
32namespace fs = std::filesystem;
33#endif
34
35using namespace radio_tool::radio;
36
38{
39 std::function<bool(const std::string&)> SupportsDevice;
40 std::function<RadioOperations* (const std::string&)> CreateOperations;
41};
42
43const std::vector<DeviceMapper> Drivers = {
44 {AilunceRadio::SupportsDevice, AilunceRadio::Create} };
45
46auto SerialRadioFactory::ListDevices(const uint16_t& idx_offset) const -> const std::vector<RadioInfo*>
47{
48 auto ret = std::vector<RadioInfo*>();
49
50 OpDeviceList(
51 [&ret, idx_offset](const std::string& port, const uint16_t& idx)
52 {
53 for (auto& driver : Drivers)
54 {
55 auto fnOpen = [&driver, port]()
56 {
57 return driver.CreateOperations(port);
58 };
59
60 if (driver.SupportsDevice(port))
61 {
62 ret.push_back(new SerialRadioInfo(fnOpen, port, idx_offset + idx));
63 }
64 }
65 });
66 return ret;
67}
68
69#ifdef _WIN32
70auto SerialRadioFactory::OpDeviceList(std::function<void(const std::string&, const uint16_t&)> fn) const -> void
71{
72 HKEY comKey = nullptr;
73 auto openResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE, (LPSTR)"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_READ | KEY_WOW64_64KEY, &comKey);
74 if (openResult != ERROR_SUCCESS)
75 {
76 throw std::runtime_error("Failed to enumerate serial ports");
77 }
78
79 constexpr auto BufferSize = 1024L;
80 auto idx = 0UL;
81 char name[BufferSize] = {}, value[BufferSize] = {};
82 while (1)
83 {
84 auto nameSize = BufferSize;
85 auto valueSize = BufferSize;
86 memset(name, 0, BufferSize);
87 memset(value, 0, BufferSize);
88
89 auto readResult = RegEnumValueA(comKey, idx, name, (LPDWORD)&nameSize, NULL, NULL, (LPBYTE)value, (LPDWORD)&valueSize);
90 if (readResult == ERROR_SUCCESS)
91 {
92 fn(std::string(value), (uint16_t)idx);
93 }
94 else if (readResult == ERROR_NO_MORE_ITEMS)
95 {
96 break;
97 }
98 else
99 {
100 throw std::runtime_error("Error reading registory key values");
101 }
102 idx++;
103 }
104
105 RegCloseKey(comKey);
106}
107
108#else
109auto SerialRadioFactory::OpDeviceList(std::function<void(const std::string&, const uint16_t&)> op) const -> void
110{
111#ifdef __APPLE__
112 auto p = fs::path("/dev");
113 auto idx = 0;
114 for (const auto& de : fs::directory_iterator(p))
115 {
116 auto stem = de.path().stem().string();
117 if (stem == "tty" || stem == "cu")
118 {
119 op(de.path().string(), idx++);
120 }
121 }
122#else
123 //https://stackoverflow.com/a/65764414
124 auto p = fs::path("/dev/serial/by-id");
125 if (!fs::exists(p))
126 {
127 return;
128 }
129
130 auto idx = 0;
131 for (auto& de : fs::directory_iterator(p))
132 {
133 if (fs::is_symlink(de.symlink_status()))
134 {
135 auto canonical_path = fs::canonical(de);
136 op(canonical_path.string(), idx++);
137 }
138 }
139#endif
140}
141#endif