From d4e939fd0414f92dfebcfdeee234117a31adbb38 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 21 May 2018 17:22:27 +0200 Subject: [PATCH] Serial port fix, get description for serial ports on OSX. --- xs/src/slic3r/Utils/Serial.cpp | 84 +++++++++++++++++++++++++++------- xs/src/slic3r/Utils/Serial.hpp | 2 +- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/xs/src/slic3r/Utils/Serial.cpp b/xs/src/slic3r/Utils/Serial.cpp index 57e52318d..fa0d52454 100644 --- a/xs/src/slic3r/Utils/Serial.cpp +++ b/xs/src/slic3r/Utils/Serial.cpp @@ -7,21 +7,27 @@ #include #if _WIN32 -#include -#include -#include -#include -// Undefine min/max macros incompatible with the standard library -// For example, std::numeric_limits::max() -// produces some weird errors -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif -#include "boost/nowide/convert.hpp" -#pragma comment(lib, "user32.lib") + #include + #include + #include + #include + // Undefine min/max macros incompatible with the standard library + // For example, std::numeric_limits::max() + // produces some weird errors + #ifdef min + #undef min + #endif + #ifdef max + #undef max + #endif + #include "boost/nowide/convert.hpp" + #pragma comment(lib, "user32.lib") +#elif __APPLE__ + #include + #include + #include + #include + #include #endif namespace Slic3r { @@ -44,7 +50,7 @@ std::vector scan_serial_ports_extended() if (hDeviceInfo != INVALID_HANDLE_VALUE) { // Iterate over all the devices in the tree. for (int nDevice = 0; SetupDiEnumDeviceInfo(hDeviceInfo, nDevice, &devInfoData); ++ nDevice) { - SerialPortInfo port_info = {}; + SerialPortInfo port_info; // Get the registry key which stores the ports settings. HKEY hDeviceKey = SetupDiOpenDevRegKey(hDeviceInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (hDeviceKey) { @@ -82,8 +88,52 @@ std::vector scan_serial_ports_extended() output.emplace_back(std::move(port_info)); } } +#elif __APPLE__ + // inspired by https://sigrok.org/wiki/Libserialport + CFMutableDictionaryRef classes = IOServiceMatching(kIOSerialBSDServiceValue); + if (classes != 0) { + io_iterator_t iter; + if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes, &iter) == KERN_SUCCESS) { + io_object_t port; + while ((port = IOIteratorNext(iter)) != 0) { + CFTypeRef cf_property = IORegistryEntryCreateCFProperty(port, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0); + if (cf_property) { + char path[PATH_MAX]; + Boolean result = CFStringGetCString(cf_property, path, sizeof(path), kCFStringEncodingUTF8); + CFRelease(cf_property); + if (result) { + SerialPortInfo port_info; + port_info.port = path; + if ((cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane, + CFSTR("USB Interface Name"), kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents)) || + (cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane, + CFSTR("USB Product Name"), kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents)) || + (cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane, + CFSTR("Product Name"), kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents)) || + (cf_property = IORegistryEntryCreateCFProperty(port, + CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) { + // Description limited to 127 char, anything longer would not be user friendly anyway. + char description[128]; + if (CFStringGetCString(cf_property, description, sizeof(description), kCFStringEncodingUTF8)) { + port_info.friendly_name = std::string(description) + " (" + port_info.path + ")"; + port_info.is_printer = looks_like_printer(port_info.friendly_name); + } + CFRelease(cf_property); + } + if (port_info.friendly_name.empty()) + port_info.friendly_name = port_info.path; + output.emplace_back(std::move(port_info)); + } + } + IOObjectRelease(port); + } + } + } #else - // UNIX and OS X + // UNIX / Linux std::initializer_list prefixes { "ttyUSB" , "ttyACM", "tty.", "cu.", "rfcomm" }; for (auto &dir_entry : boost::filesystem::directory_iterator(boost::filesystem::path("/dev"))) { std::string name = dir_entry.path().filename().string(); diff --git a/xs/src/slic3r/Utils/Serial.hpp b/xs/src/slic3r/Utils/Serial.hpp index 583661ae5..1b023afc8 100644 --- a/xs/src/slic3r/Utils/Serial.hpp +++ b/xs/src/slic3r/Utils/Serial.hpp @@ -11,7 +11,7 @@ struct SerialPortInfo { std::string port; std::string hardware_id; std::string friendly_name; - bool is_printer; + bool is_printer = false; }; inline bool operator==(const SerialPortInfo &sp1, const SerialPortInfo &sp2)