From 4c2806f966b8d8c3ef4d4c4fa44df1d07b94225b Mon Sep 17 00:00:00 2001 From: LordGrey <48840279+Lord-Grey@users.noreply.github.com> Date: Sun, 23 May 2021 19:11:05 +0200 Subject: [PATCH] Serial-Devices - Add udev support (#1246) --- assets/webconfig/js/content_leds.js | 41 +++++++------ libsrc/leddevice/dev_serial/ProviderRs232.cpp | 59 +++++++++++++++++-- libsrc/leddevice/dev_serial/ProviderRs232.h | 2 + 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/assets/webconfig/js/content_leds.js b/assets/webconfig/js/content_leds.js index a8718284..982c6a00 100755 --- a/assets/webconfig/js/content_leds.js +++ b/assets/webconfig/js/content_leds.js @@ -46,7 +46,7 @@ function createLedPreview(leds, origin) { canvas_width = $('#leds_preview').innerWidth(); imageCanvasNodeCtx = document.getElementById("image_preview").getContext("2d"); - $('#image_preview').css({"width":canvas_width, "height":canvas_height}); + $('#image_preview').css({ "width": canvas_width, "height": canvas_height }); var leds_html = ""; for (var idx = 0; idx < leds.length; idx++) { @@ -421,8 +421,8 @@ $(document).ready(function () { // translate performTranslation(); - // update instance listing - updateHyperionInstanceListing(); + // update instance listing + updateHyperionInstanceListing(); //add intros if (window.showOptHelp) { @@ -561,30 +561,28 @@ $(document).ready(function () { toggleClass('#leds_prev_toggle_num', "btn-danger", "btn-success"); }); - // toggle live video - $('#leds_prev_toggle_live_video').off().on("click", function() { - setClassByBool('#leds_prev_toggle_live_video', window.imageStreamActive, "btn-success", "btn-danger"); - if (window.imageStreamActive) - { - requestLedImageStop(); + // toggle live video + $('#leds_prev_toggle_live_video').off().on("click", function () { + setClassByBool('#leds_prev_toggle_live_video', window.imageStreamActive, "btn-success", "btn-danger"); + if (window.imageStreamActive) { + requestLedImageStop(); imageCanvasNodeCtx.clear(); - } - else - { - requestLedImageStart(); - } - }); + } + else { + requestLedImageStart(); + } + }); - $(window.hyperion).on("cmd-ledcolors-imagestream-update",function(event){ + $(window.hyperion).on("cmd-ledcolors-imagestream-update", function (event) { setClassByBool('#leds_prev_toggle_live_video', window.imageStreamActive, "btn-danger", "btn-success"); var imageData = (event.response.result.image); var image = new Image(); - image.onload = function() { + image.onload = function () { imageCanvasNodeCtx.drawImage(image, 0, 0, imageCanvasNodeCtx.canvas.width, imageCanvasNodeCtx.canvas.height); }; image.src = imageData; - }); + }); // open checklist $('#leds_prev_checklist').off().on("click", function () { @@ -1366,7 +1364,11 @@ var updateSelectList = function (ledType, discoveryInfo) { case "sedu": case "tpm2": for (const device of discoveryInfo.devices) { - enumVals.push(device.portName); + if (device.udev) { + enumVals.push(device.systemLocation); + } else { + enumVals.push(device.portName); + } enumTitelVals.push(device.portName + " (" + device.vendorIdentifier + "|" + device.productIdentifier + ") - " + device.manufacturer); } @@ -1557,3 +1559,4 @@ function showAllDeviceInputOptions(showForKey, state) { showInputOptionsForKey(conf_editor, "generalOptions", showForKey, state); showInputOptionsForKey(conf_editor, "specificOptions", showForKey, state); } + diff --git a/libsrc/leddevice/dev_serial/ProviderRs232.cpp b/libsrc/leddevice/dev_serial/ProviderRs232.cpp index 8c5d6eaa..2a487cc7 100644 --- a/libsrc/leddevice/dev_serial/ProviderRs232.cpp +++ b/libsrc/leddevice/dev_serial/ProviderRs232.cpp @@ -7,6 +7,7 @@ // qt includes #include #include +#include #include @@ -20,6 +21,10 @@ namespace { const int NUM_POWEROFF_WRITE_BLACK = 2; // Number of write "BLACK" during powering off constexpr std::chrono::milliseconds DEFAULT_IDENTIFY_TIME{ 500 }; + + // tty discovery service + const char DISCOVERY_DIRECTORY[] = "/dev/"; + const char DISCOVERY_FILEPATTERN[] = "tty*"; } //End of constants ProviderRs232::ProviderRs232(const QJsonObject &deviceConfig) @@ -47,18 +52,26 @@ bool ProviderRs232::init(const QJsonObject &deviceConfig) Debug(_log, "LatchTime : %d", this->getLatchTime()); _deviceName = deviceConfig["output"].toString("auto"); + _isAutoDeviceName = _deviceName.toLower() == "auto"; // If device name was given as unix /dev/ system-location, get port name if ( _deviceName.startsWith(QLatin1String("/dev/")) ) { + _location = _deviceName; + //Handle udev devices + QFileInfo file_info(_deviceName); + if (file_info.isSymLink()) + { + _deviceName = file_info.symLinkTarget(); + } _deviceName = _deviceName.mid(5); } - _isAutoDeviceName = _deviceName.toLower() == "auto"; _baudRate_Hz = deviceConfig["rate"].toInt(); _delayAfterConnect_ms = deviceConfig["delayAfterConnect"].toInt(1500); - Debug(_log, "deviceName : %s", QSTRING_CSTR(_deviceName)); + Debug(_log, "DeviceName : %s", QSTRING_CSTR(_deviceName)); + DebugIf(!_location.isEmpty(), _log, "Location : %s", QSTRING_CSTR(_location)); Debug(_log, "AutoDevice : %d", _isAutoDeviceName); Debug(_log, "baudRate_Hz : %d", _baudRate_Hz); Debug(_log, "delayAfCon ms: %d", _delayAfterConnect_ms); @@ -141,7 +154,14 @@ bool ProviderRs232::tryOpen(int delayAfterConnect_ms) if (!_rs232Port.isOpen()) { - Info(_log, "Opening UART: %s", QSTRING_CSTR(_deviceName)); + if (!_location.isEmpty()) + { + Info(_log, "Opening UART: %s (%s)", QSTRING_CSTR(_deviceName), QSTRING_CSTR(_location)); + } + else + { + Info(_log, "Opening UART: %s", QSTRING_CSTR(_deviceName)); + } _frameDropCounter = 0; @@ -168,7 +188,7 @@ bool ProviderRs232::tryOpen(int delayAfterConnect_ms) } else { - QString errortext = QString("Invalid serial device name: [%1]!").arg(_deviceName); + QString errortext = QString("Invalid serial device name: %1 %2!").arg(_deviceName, _location); this->setInError( errortext ); // List available device @@ -300,6 +320,37 @@ QJsonObject ProviderRs232::discover(const QJsonObject& /*params*/) } } +#ifndef _WIN32 + //Check all /dev/tty* files, if they are udev-serial devices + QDir deviceDirectory (DISCOVERY_DIRECTORY); + QStringList deviceFilter(DISCOVERY_FILEPATTERN); + deviceDirectory.setNameFilters(deviceFilter); + deviceDirectory.setSorting(QDir::Name); + QFileInfoList deviceFiles = deviceDirectory.entryInfoList(QDir::AllEntries); + + QFileInfoList::const_iterator deviceFileIterator; + for (deviceFileIterator = deviceFiles.constBegin(); deviceFileIterator != deviceFiles.constEnd(); ++deviceFileIterator) + { + if ((*deviceFileIterator).isSymLink()) + { + QSerialPortInfo port = QSerialPortInfo(QSerialPort((*deviceFileIterator).symLinkTarget())); + + QJsonObject portInfo; + portInfo.insert("portName", (*deviceFileIterator).fileName()); + portInfo.insert("systemLocation", (*deviceFileIterator).absoluteFilePath()); + portInfo.insert("udev", true); + + portInfo.insert("description", port.description()); + portInfo.insert("manufacturer", port.manufacturer()); + portInfo.insert("productIdentifier", QString("0x%1").arg(port.productIdentifier(), 0, 16)); + portInfo.insert("serialNumber", port.serialNumber()); + portInfo.insert("vendorIdentifier", QString("0x%1").arg(port.vendorIdentifier(), 0, 16)); + + deviceList.append(portInfo); + } + } +#endif + devicesDiscovered.insert("devices", deviceList); DebugIf(verbose,_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); diff --git a/libsrc/leddevice/dev_serial/ProviderRs232.h b/libsrc/leddevice/dev_serial/ProviderRs232.h index 2ca95982..108ea1b3 100644 --- a/libsrc/leddevice/dev_serial/ProviderRs232.h +++ b/libsrc/leddevice/dev_serial/ProviderRs232.h @@ -97,6 +97,8 @@ protected: /// The name of the output device QString _deviceName; + /// The system location of the output device + QString _location; /// The RS232 serial-device QSerialPort _rs232Port; /// The used baud-rate of the output device