|
1 | 1 | #include "Arduino.h" |
| 2 | +#include "Utils.h" |
2 | 3 |
|
3 | 4 | Arduino::~Arduino() |
4 | 5 | { |
@@ -71,115 +72,204 @@ Arduino::Arduino(LPCSTR name) : handle(INVALID_HANDLE_VALUE) |
71 | 72 | cout << "Successfully connected!" << endl; |
72 | 73 | } |
73 | 74 |
|
74 | | -bool Arduino::IsAvailable() const |
75 | | -{ |
76 | | - DWORD errors; |
77 | | - COMSTAT status; |
78 | | - |
79 | | - if (!ClearCommError(handle, &errors, &status)) |
80 | | - { |
81 | | - LOG("Error checking available data: " + to_string(GetLastError())); |
82 | | - return false; |
83 | | - } |
84 | | - |
85 | | - return status.cbInQue > 0; |
86 | | -} |
87 | | - |
88 | 75 | bool Arduino::GetDevice(LPCSTR name, LPSTR port) |
89 | 76 | { |
90 | | - bool status = false; |
91 | 77 | HDEVINFO device_info = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, NULL, NULL, DIGCF_PRESENT); |
92 | 78 |
|
93 | 79 | if (device_info == INVALID_HANDLE_VALUE) |
94 | 80 | { |
95 | | - LOG("Failed to get device information."); |
| 81 | + LOG("Failed to get device information (SetupDiGetClassDevs returned INVALID_HANDLE_VALUE)."); |
96 | 82 | return false; |
97 | 83 | } |
98 | 84 |
|
99 | | - DWORD count = 0; |
100 | | - SP_DEVINFO_DATA dev_info_data = {}; |
101 | | - dev_info_data.cbSize = sizeof(dev_info_data); |
102 | | - LOG("Searching for device: " + string(name)); |
103 | | - |
104 | | - struct DeviceInfo |
| 85 | + vector<DeviceInfo> devices; |
| 86 | + vector<regex> patterns = |
105 | 87 | { |
106 | | - string port; |
107 | | - string hardware_id; |
108 | | - string friendly_name; |
| 88 | + regex("VID_2341&PID_.*"), |
| 89 | + regex("VID_2A03&PID_.*"), |
| 90 | + regex("VID_1A86&PID_.*") |
109 | 91 | }; |
110 | 92 |
|
111 | | - vector<DeviceInfo> devices; |
112 | | - vector<regex> patterns = { regex("VID_2341&PID_.*"), regex("VID_1A86&PID_.*"), regex("VID_10C4&PID_.*") }; |
| 93 | + // Load configuration |
| 94 | + DeviceInfo config_device; |
| 95 | + bool found_device = false; |
| 96 | + bool config_loaded = Arduino::LoadConfiguration("device_config.cfg", config_device); |
| 97 | + |
| 98 | + // Collect system devices |
| 99 | + LOG("Enumerating connected devices..."); |
| 100 | + DWORD count = 0; |
| 101 | + SP_DEVINFO_DATA dev_info_data = {}; |
| 102 | + dev_info_data.cbSize = sizeof(dev_info_data); |
113 | 103 |
|
114 | | - // Step 1: Collecting all devices |
115 | 104 | while (SetupDiEnumDeviceInfo(device_info, count++, &dev_info_data)) |
116 | 105 | { |
117 | | - DeviceInfo info; |
118 | | - BYTE buffer[256]; |
| 106 | + DeviceInfo system_device; |
119 | 107 |
|
120 | | - // Reading FRIENDLYNAME |
121 | | - if (SetupDiGetDeviceRegistryProperty(device_info, &dev_info_data, SPDRP_FRIENDLYNAME, NULL, buffer, sizeof(buffer), NULL)) |
| 108 | + if (Arduino::ExtractProperties(device_info, dev_info_data, system_device)) |
122 | 109 | { |
123 | | - info.friendly_name = string((LPCSTR)buffer); |
124 | | - LOG("Device detected with FRIENDLYNAME: " + info.friendly_name); |
| 110 | + devices.push_back(system_device); |
| 111 | + LOG("Detected device: FRIENDLYNAME = " + system_device.friendly_name + ", HARDWAREID = " + system_device.hardware_id + ", PORT = " + system_device.port); |
| 112 | + |
| 113 | + // Check against configuration file |
| 114 | + if (config_loaded && system_device.friendly_name == config_device.friendly_name && system_device.hardware_id == config_device.hardware_id) |
| 115 | + { |
| 116 | + strncpy_s(port, 100, system_device.port.c_str(), system_device.port.size()); |
| 117 | + LOG("Using saved device: FRIENDLYNAME = " + system_device.friendly_name + ", HARDWAREID = " + system_device.hardware_id + ", PORT = " + system_device.port); |
| 118 | + found_device = true; |
| 119 | + break; |
| 120 | + } |
125 | 121 |
|
126 | | - // Reading PORT |
127 | | - LPCSTR start = strchr((LPCSTR)buffer, '('); |
128 | | - LPCSTR end = strchr((LPCSTR)buffer, ')'); |
| 122 | + // Check against VID/PID patterns or name |
| 123 | + if (!found_device && name && system_device.friendly_name.find(name) != string::npos) |
| 124 | + { |
| 125 | + strncpy_s(port, 100, system_device.port.c_str(), system_device.port.size()); |
| 126 | + LOG("Device matched by FRIENDLYNAME: " + system_device.friendly_name); |
| 127 | + found_device = true; |
| 128 | + break; |
| 129 | + } |
129 | 130 |
|
130 | | - if (start && end && end > start) |
| 131 | + for (const auto& pattern : patterns) |
131 | 132 | { |
132 | | - info.port = string(start + 1, end - start - 1); |
| 133 | + if (regex_search(system_device.hardware_id, pattern)) |
| 134 | + { |
| 135 | + strncpy_s(port, 100, system_device.port.c_str(), system_device.port.size()); |
| 136 | + LOG("Device matched by VID/PID: " + system_device.hardware_id); |
| 137 | + found_device = true; |
| 138 | + break; |
| 139 | + } |
133 | 140 | } |
134 | 141 | } |
135 | 142 |
|
136 | | - // Reading HARDWAREID |
137 | | - if (SetupDiGetDeviceRegistryProperty(device_info, &dev_info_data, SPDRP_HARDWAREID, NULL, buffer, sizeof(buffer), NULL)) |
| 143 | + if (found_device) |
| 144 | + break; |
| 145 | + } |
| 146 | + |
| 147 | + SetupDiDestroyDeviceInfoList(device_info); |
| 148 | + |
| 149 | + // Handle case where no device was found |
| 150 | + if (!found_device) |
| 151 | + { |
| 152 | + if (config_loaded) |
| 153 | + { |
| 154 | + LOG("Saved device not found in the system. Deleting configuration file."); |
| 155 | + remove("device_config.cfg"); |
| 156 | + } |
| 157 | + |
| 158 | + if (devices.empty()) |
138 | 159 | { |
139 | | - info.hardware_id = string((LPCSTR)buffer); |
140 | | - LOG("Device detected with HARDWAREID: " + info.hardware_id); |
| 160 | + LOG("No devices found in the system."); |
| 161 | + return false; |
141 | 162 | } |
142 | 163 |
|
143 | | - devices.push_back(info); |
| 164 | + LOG("Prompting user to select a device..."); |
| 165 | + return Arduino::SelectDevice(devices, port); |
144 | 166 | } |
145 | 167 |
|
146 | | - SetupDiDestroyDeviceInfoList(device_info); |
| 168 | + return true; |
| 169 | +} |
147 | 170 |
|
148 | | - // Step 2: Checking and selecting the device |
149 | | - for (const auto& device : devices) |
| 171 | +bool Arduino::LoadConfiguration(const string& file_name, DeviceInfo& config_device) |
| 172 | +{ |
| 173 | + string line; |
| 174 | + ifstream config(file_name); |
| 175 | + |
| 176 | + if (!config) |
150 | 177 | { |
151 | | - LOG("Evaluating device: FRIENDLYNAME = " + device.friendly_name + ", HARDWAREID = " + device.hardware_id); |
| 178 | + LOG("Configuration file not found."); |
| 179 | + return false; |
| 180 | + } |
152 | 181 |
|
153 | | - // If the name is specified, check it |
154 | | - if (name && !device.friendly_name.empty() && device.friendly_name.find(name) != string::npos) |
| 182 | + while (getline(config, line)) |
| 183 | + { |
| 184 | + if (line.find("FRIENDLYNAME=") == 0) |
155 | 185 | { |
156 | | - strncpy_s(port, 100, device.port.c_str(), device.port.size()); |
157 | | - LOG("Device matched by FRIENDLYNAME: " + device.friendly_name); |
158 | | - status = true; |
159 | | - break; |
| 186 | + config_device.friendly_name = line.substr(13); |
| 187 | + } |
| 188 | + else if (line.find("HARDWAREID=") == 0) |
| 189 | + { |
| 190 | + config_device.hardware_id = line.substr(11); |
160 | 191 | } |
| 192 | + else if (line.find("PORT=") == 0) |
| 193 | + { |
| 194 | + config_device.port = line.substr(5); |
| 195 | + } |
| 196 | + } |
| 197 | + |
| 198 | + if (!config_device.friendly_name.empty() && !config_device.hardware_id.empty()) |
| 199 | + { |
| 200 | + LOG("Loaded device from configuration: FRIENDLYNAME = " + config_device.friendly_name + ", HARDWAREID = " + config_device.hardware_id + ", PORT = " + config_device.port); |
| 201 | + return true; |
| 202 | + } |
| 203 | + |
| 204 | + LOG("Configuration file is incomplete or corrupted."); |
| 205 | + return false; |
| 206 | +} |
| 207 | + |
| 208 | +bool Arduino::ExtractProperties(HDEVINFO device_info, SP_DEVINFO_DATA& dev_info_data, DeviceInfo& device) |
| 209 | +{ |
| 210 | + BYTE buffer[256]; |
161 | 211 |
|
162 | | - // If the name does not match, check the VID/PID |
163 | | - for (const auto& pattern : patterns) |
| 212 | + if (SetupDiGetDeviceRegistryProperty(device_info, &dev_info_data, SPDRP_FRIENDLYNAME, NULL, buffer, sizeof(buffer), NULL)) |
| 213 | + { |
| 214 | + device.friendly_name = string((LPCSTR)buffer); |
| 215 | + |
| 216 | + LPCSTR start = strchr((LPCSTR)buffer, '('); |
| 217 | + LPCSTR end = strchr((LPCSTR)buffer, ')'); |
| 218 | + |
| 219 | + if (start && end && end > start) |
164 | 220 | { |
165 | | - if (!device.hardware_id.empty() && regex_search(device.hardware_id, pattern)) |
166 | | - { |
167 | | - strncpy_s(port, 100, device.port.c_str(), device.port.size()); |
168 | | - LOG("Device matched by VID/PID: " + device.hardware_id); |
169 | | - status = true; |
170 | | - break; |
171 | | - } |
| 221 | + device.port = string(start + 1, end - start - 1); |
172 | 222 | } |
| 223 | + } |
173 | 224 |
|
174 | | - if (status) break; |
| 225 | + if (SetupDiGetDeviceRegistryProperty(device_info, &dev_info_data, SPDRP_HARDWAREID, NULL, buffer, sizeof(buffer), NULL)) |
| 226 | + { |
| 227 | + device.hardware_id = string((LPCSTR)buffer); |
175 | 228 | } |
176 | 229 |
|
177 | | - if (!status) |
| 230 | + return !device.friendly_name.empty() && !device.hardware_id.empty(); |
| 231 | +} |
| 232 | + |
| 233 | +bool Arduino::SelectDevice(const vector<DeviceInfo>& devices, LPSTR port) |
| 234 | +{ |
| 235 | + Utils utils; |
| 236 | + utils.PrintCenteredText("The following devices were detected:"); |
| 237 | + |
| 238 | + for (size_t i = 0; i < devices.size(); ++i) |
178 | 239 | { |
179 | | - LOG("No matching device found."); |
| 240 | + string device_info = "[" + to_string(i + 1) + "] FRIENDLYNAME: " + devices[i].friendly_name + ", HARDWAREID: " + devices[i].hardware_id + ", PORT: " + devices[i].port; |
| 241 | + utils.PrintCenteredText(device_info); |
180 | 242 | } |
181 | 243 |
|
182 | | - return status; |
| 244 | + utils.PrintCenteredText("Please select the device you want to use by entering its number (0 to cancel): ", false); |
| 245 | + |
| 246 | + int choice; |
| 247 | + cin >> choice; |
| 248 | + |
| 249 | + if (choice > 0 && choice <= static_cast<int>(devices.size())) |
| 250 | + { |
| 251 | + const auto& selected_device = devices[choice - 1]; |
| 252 | + strncpy_s(port, 100, selected_device.port.c_str(), selected_device.port.size()); |
| 253 | + LOG("User selected device: " + selected_device.friendly_name); |
| 254 | + |
| 255 | + ofstream config("device_config.cfg"); |
| 256 | + |
| 257 | + if (config) |
| 258 | + { |
| 259 | + config << "FRIENDLYNAME=" << selected_device.friendly_name << endl; |
| 260 | + config << "HARDWAREID=" << selected_device.hardware_id << endl; |
| 261 | + config << "PORT=" << selected_device.port << endl; |
| 262 | + |
| 263 | + LOG("Device selection saved to configuration."); |
| 264 | + } |
| 265 | + |
| 266 | + return true; |
| 267 | + } |
| 268 | + |
| 269 | + utils.PrintCenteredText("No device selected by the user."); |
| 270 | + LOG("No device selected by the user."); |
| 271 | + |
| 272 | + return false; |
183 | 273 | } |
184 | 274 |
|
185 | 275 | bool Arduino::WriteMessage(const string& message) const |
|
0 commit comments