radio_tool 0.2.1
Loading...
Searching...
No Matches
ailunce_radio.cpp
1
19#include <radio_tool/radio/ailunce_radio.hpp>
20#include <radio_tool/fw/ailunce_fw.hpp>
21
22#include <thread>
23
24#ifdef _WIN32
25#define B57600 57600
26#include <Windows.h>
27#include <io.h>
28#include <iostream>
29#include <regex>
30
31#ifdef COMPORT_DI_LOOKUP
32#pragma comment(lib, "Setupapi.lib")
33#include <SetupAPI.h>
34#else
35#endif
36
37#else
38#include <unistd.h>
39#include <termios.h>
40#endif
41
42using namespace radio_tool::radio;
43
44auto AilunceRadio::ToString() const -> const std::string
45{
46 return "== Ailunce USB Serial Cable ==";
47}
48
49auto AilunceRadio::WriteFirmware(const std::string &file) -> void
50{
51 auto fw = fw::AilunceFW();
52 fw.Read(file);
53
54 //XOR raw binary data before sending
55 fw.Encrypt();
56
57 device.SetInterfaceAttribs(B57600, 0);
58 auto fd = device.GetFD();
59 // send 1 to start firmware upgrade
60#ifdef _WIN32
61 WriteFile((HANDLE)fd, "1", (DWORD)1, NULL, NULL);
62#else
63 write(fd, "1", 1);
64#endif
65 std::this_thread::sleep_for(std::chrono::milliseconds(100));
66
67 auto r = fw.GetDataSegments()[0];
68 device.Write(r.data);
69}
70
71auto AilunceRadio::SupportsDevice(const std::string &port) -> bool
72{
73 // not possible to detect from serial port?
74 // ideally we could map serial ports to USB devices to validate VID:PID
75 //
76 // ✅ possible windows solution: https://aticleworld.com/get-com-port-of-usb-serial-device/
77 // possible linux solution: https://unix.stackexchange.com/a/81767
78 auto ids = GetComPortUSBIds(port);
79 return (ids.first == VID && ids.second == PID) || true;
80}
81
82auto AilunceRadio::GetComPortUSBIds(const std::string &port) -> std::pair<uint16_t, uint16_t>
83{
84#if defined(_WIN32) && defined(COMPORT_DI_LOOKUP)
85 auto handle = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
86 if (handle == nullptr)
87 {
88 throw std::runtime_error("Failed to open device info");
89 }
90
91 BYTE hwIds[1024];
92 DEVPROPTYPE propType;
93 SP_DEVINFO_DATA deviceInfo = {};
94 deviceInfo.cbSize = sizeof(SP_DEVINFO_DATA);
95
96 DWORD idx = 0, outSize = 0;
97 while (SetupDiEnumDeviceInfo(handle, idx++, &deviceInfo))
98 {
99 if (SetupDiGetDeviceRegistryPropertyA(handle, &deviceInfo, SPDRP_HARDWAREID, &propType, (PBYTE)&hwIds, sizeof(hwIds), &outSize))
100 {
101 std::cerr << hwIds << std::endl;
102
103 HKEY regKey;
104 if ((regKey = SetupDiOpenDevRegKey(handle, &deviceInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ)) == INVALID_HANDLE_VALUE)
105 {
106 std::cerr << "Failed to find reg key for device: " << (char *)hwIds << std::endl;
107 }
108
109 // read com port name
110 constexpr auto BufferLen = 256;
111 DWORD dwType = 0;
112 DWORD portNameSize = BufferLen;
113 BYTE portName[BufferLen];
114 if (RegQueryValueExA(regKey, "PortName", NULL, &dwType, (LPBYTE)&portName, &portNameSize) == ERROR_SUCCESS)
115 {
116 // not working for some reason
117 std::cerr << portName << std::endl;
118 }
119 }
120 }
121
122 SetupDiDestroyDeviceInfoList(handle);
123#elif defined(_WIN32)
124 HKEY comKey = nullptr;
125 auto openResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE, (LPSTR) "SYSTEM\\CurrentControlSet\\Control\\COM Name Arbiter\\Devices", 0, KEY_READ | KEY_WOW64_64KEY, &comKey);
126 if (openResult != ERROR_SUCCESS)
127 {
128 throw std::runtime_error("Failed to get serial port info from registry");
129 }
130
131 constexpr auto BufferSize = 256L;
132 BYTE value[BufferSize];
133 DWORD valueSize = BufferSize;
134
135 auto readResult = RegQueryValueExA(comKey, port.c_str(), NULL, NULL, (LPBYTE)&value, &valueSize);
136 if (readResult == ERROR_SUCCESS)
137 {
138 std::cmatch match;
139 if (std::regex_match((char *)value, match, std::regex("^.*#vid_([\\w+]{4})\\+pid_([\\w+]{4}).*$")))
140 {
141 auto vid = std::stoi(match[1], nullptr, 16);
142 auto pid = std::stoi(match[2], nullptr, 16);
143 return std::make_pair(vid, pid);
144 }
145 }
146 else
147 {
148 throw std::runtime_error("Error reading registory key values");
149 }
150
151 RegCloseKey(comKey);
152#else
153
154#endif
155 return std::make_pair(0, 0);
156}
auto ToString() const -> const std::string override
auto WriteFirmware(const std::string &file) -> void override