120{
121 std::vector<SerialPortInfo> output;
122
123#ifdef _WIN32
124 SP_DEVINFO_DATA devInfoData = { 0 };
125 devInfoData.cbSize = sizeof(devInfoData);
126
127 HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0, nullptr, DIGCF_PRESENT);
128 if (hDeviceInfo != INVALID_HANDLE_VALUE) {
129
130 for (int nDevice = 0; SetupDiEnumDeviceInfo(hDeviceInfo, nDevice, &devInfoData); ++ nDevice) {
131 SerialPortInfo port_info;
132
133 HKEY hDeviceKey = SetupDiOpenDevRegKey(hDeviceInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
134 if (hDeviceKey) {
135
136 wchar_t pszPortName[4096];
137 DWORD dwSize = sizeof(pszPortName);
138 DWORD dwType = 0;
139 if (RegQueryValueEx(hDeviceKey,
L"PortName",
NULL, &dwType, (LPBYTE)pszPortName, &dwSize) == ERROR_SUCCESS)
140 port_info.port = boost::nowide::narrow(pszPortName);
141 RegCloseKey(hDeviceKey);
142 if (port_info.port.empty())
143 continue;
144 }
145
146
147 DWORD regDataType;
148 DWORD reqSize = 0;
149 SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, nullptr, nullptr, 0, &reqSize);
150 std::vector<wchar_t> hardware_id(reqSize > 1 ? reqSize : 1);
151
152 if (! SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, ®DataType, (BYTE*)hardware_id.data(), reqSize, nullptr))
153 continue;
154 parse_hardware_id(boost::nowide::narrow(hardware_id.data()), port_info);
155
156
157 reqSize = 0;
158 SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize);
159 std::vector<wchar_t> friendly_name;
160 friendly_name.reserve(reqSize > 1 ? reqSize : 1);
161
162 if (! SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, (BYTE*)friendly_name.data(), reqSize, nullptr)) {
163 port_info.friendly_name = port_info.port;
164 } else {
165 port_info.friendly_name = boost::nowide::narrow(friendly_name.data());
167 }
168 output.emplace_back(std::move(port_info));
169 }
170 }
171#elif __APPLE__
172
173 CFMutableDictionaryRef classes = IOServiceMatching(kIOSerialBSDServiceValue);
174 if (classes != 0) {
175 io_iterator_t iter;
176 if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes, &iter) == KERN_SUCCESS) {
177 io_object_t port;
178 while ((port = IOIteratorNext(iter)) != 0) {
179 CFTypeRef cf_property = IORegistryEntryCreateCFProperty(port, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
180 if (cf_property) {
181 char path[PATH_MAX];
182 Boolean result = CFStringGetCString((CFStringRef)cf_property, path,
sizeof(path), kCFStringEncodingUTF8);
183 CFRelease(cf_property);
184 if (result) {
186 port_info.
port = path;
187
188
189 if ((cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane,
190 CFSTR("USB Interface Name"), kCFAllocatorDefault,
191 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
192 (cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane,
193 CFSTR("USB Product Name"), kCFAllocatorDefault,
194 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
195 (cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane,
196 CFSTR("Product Name"), kCFAllocatorDefault,
197 kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
198 (cf_property = IORegistryEntryCreateCFProperty(port,
199 CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) {
200
201 char description[128];
202 if (CFStringGetCString((CFStringRef)cf_property, description, sizeof(description), kCFStringEncodingUTF8)) {
203 port_info.friendly_name = std::string(description) + " (" + port_info.port + ")";
205 }
206 CFRelease(cf_property);
207 }
208 if (port_info.friendly_name.empty())
209 port_info.friendly_name = port_info.port;
210
211
212 int vid, pid;
213 auto cf_vendor = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idVendor"),
214 kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
215 auto cf_product = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idProduct"),
216 kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
217 if (cf_vendor && cf_product) {
218 if (CFNumberGetValue((CFNumberRef)cf_vendor, kCFNumberIntType, &vid) &&
219 CFNumberGetValue((CFNumberRef)cf_product, kCFNumberIntType, &pid)) {
220 port_info.id_vendor = vid;
221 port_info.id_product = pid;
222 }
223 }
224 if (cf_vendor) { CFRelease(cf_vendor); }
225 if (cf_product) { CFRelease(cf_product); }
226
227 output.emplace_back(std::move(port_info));
228 }
229 }
230 IOObjectRelease(port);
231 }
232 }
233 }
234#else
235
236 std::initializer_list<const char*> prefixes { "ttyUSB" , "ttyACM", "tty.", "cu.", "rfcomm" };
237 for (auto &dir_entry : boost::filesystem::directory_iterator(boost::filesystem::path("/dev"))) {
238 std::string name = dir_entry.path().filename().string();
239 for (const char *prefix : prefixes) {
240 if (boost::starts_with(name, prefix)) {
241 const auto path = dir_entry.path().string();
244#ifdef __linux__
245 auto friendly_name = sysfs_tty_prop(name, "product");
246 if (friendly_name) {
248 spi.friendly_name = (boost::format("%1% (%2%)") % *friendly_name % path).str();
249 } else {
250 spi.friendly_name = path;
251 }
252 auto vid = sysfs_tty_prop_hex(name, "idVendor");
253 auto pid = sysfs_tty_prop_hex(name, "idProduct");
254 if (vid && pid) {
255 spi.id_vendor = *vid;
256 spi.id_product = *pid;
257 }
258#else
259 spi.friendly_name = path;
260#endif
261 output.emplace_back(std::move(spi));
262 break;
263 }
264 }
265 }
266#endif
267
268 output.erase(std::remove_if(output.begin(), output.end(),
270 return boost::starts_with(info.port, "Bluetooth") || boost::starts_with(info.port, "FireFly");
271 }),
272 output.end());
273 return output;
274}
#define L(s)
Definition ExtrusionEntity.cpp:25
static bool looks_like_printer(const std::string &friendly_name)
Definition Serial.cpp:77
@ Boolean
Definition CadDocument.hpp:26