From d46011218d25483ee4fae74e69869b6881b1ae53 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 8 Feb 2016 14:56:28 +0100 Subject: Bump version Change-Id: I479d9a1c08d0291a21d05bd0cdd5763ca8e76cd4 --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 66a0241e..b6425273 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.6.0 +MODULE_VERSION = 5.6.1 -- cgit v1.2.3 From 6ba354a0ec3bd3064d072cf170fe9f60f9ae3389 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Wed, 13 Jan 2016 12:47:44 +0300 Subject: Add changelog for 5.6.0 version Change-Id: I5557b7651f96bd83a9665eee1b792d6e2b9d2409 Reviewed-by: Sergey Belyashov Reviewed-by: Frederik Gladhorn --- dist/changes-5.6.0 | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 dist/changes-5.6.0 diff --git a/dist/changes-5.6.0 b/dist/changes-5.6.0 new file mode 100644 index 00000000..815ae54a --- /dev/null +++ b/dist/changes-5.6.0 @@ -0,0 +1,53 @@ +QtSerialPort 5.6 introduces a few new features and improvements as well as +bugfixes over the 5.5.x series. For more details, refer to the online +documentation included in this distribution. The documentation is also available +online: + + http://doc.qt.io/qt-5/index.html + +The QtSerialPort version 5.6 series is binary compatible with the 5.5.x series. +Applications compiled for 5.5 will continue to run with 5.6. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + + - Improved the documentation: + * [QTBUG-45391] Fixed the examples link. + * [QTBUG-43810] Improved the references to the readyRead() signal for + some examples. + * [QTBUG-48736] Fixed the examplesinstallpath variable in .qdocconf file. + * [QTBUG-44994] Fixed warning about supported directions on Windows(CE). + + - QSerialPortInfo: + * Added enumeration of virtual tty0tty devices, which are provided by the + http://sourceforge.net/p/tty0tty/wiki/Home/ driver. + * Fixed detection of 8250 serial port types with the udev backend. + * [QTBUG-50223] Now it enumerates the ttyTHSx devices, which are provided + by the 'Tegra Jetson TK1' board, when no udev or sysfs backends are + available. + + - QSerialPort: + * Added handling of the ERROR_PATH_NOT_FOUND error code on Windows, which + now is interpreted as QSP::DeviceNotFoundError. + * Fixed the QSP::clear() method that caused "The parameter is incorrect" + error on Windows. + * [QTBUG-48094] Added support of the termios v2 feature to configure a + custom baud rate on Linux. + * Custom speed configuration for one direction is not allowed on Linux. + Trying to do this will lead to QSP::UnsupportedOperationError. + * Now any attempt to change the policy to anything else than QSP::IgnorePolicy + will fail with QSerialPoirt::UnsupportedOperationError. + * Fixed stalling of reading with the limited buffer size on *nix. + * Improved the console warning message when a suitable custom baud rate + divisor is not found. + * [QTBUG-50052] Fixed recursion issue that is caused because of an error + in QSP::close(). -- cgit v1.2.3 From 02e4a66a8bd9ce4d2f7f8c89cd1bddf4b6385b5f Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Wed, 10 Feb 2016 16:24:41 +0000 Subject: Move the FreeBSD code to own implementation file ... that simplified a code and its maintenance. Change-Id: Ic4a7aa14a461bd99c745665c56300c13ab84691d Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialportinfo.h | 3 - src/serialport/qserialportinfo_freebsd.cpp | 363 +++++++++++++++++++++++++++++ src/serialport/qserialportinfo_unix.cpp | 288 ----------------------- src/serialport/serialport-lib.pri | 11 +- 4 files changed, 370 insertions(+), 295 deletions(-) create mode 100644 src/serialport/qserialportinfo_freebsd.cpp diff --git a/src/serialport/qserialportinfo.h b/src/serialport/qserialportinfo.h index 2b757f9c..9f0352b7 100644 --- a/src/serialport/qserialportinfo.h +++ b/src/serialport/qserialportinfo.h @@ -84,9 +84,6 @@ private: QSerialPortInfo(const QSerialPortInfoPrivate &dd); friend QList availablePortsByUdev(bool &ok); friend QList availablePortsBySysfs(bool &ok); -#ifdef Q_OS_FREEBSD - friend QList availablePortsBySysctl(bool &ok); -#endif friend QList availablePortsByFiltersOfDevices(bool &ok); QScopedPointer d_ptr; }; diff --git a/src/serialport/qserialportinfo_freebsd.cpp b/src/serialport/qserialportinfo_freebsd.cpp new file mode 100644 index 00000000..e65f09c4 --- /dev/null +++ b/src/serialport/qserialportinfo_freebsd.cpp @@ -0,0 +1,363 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Denis Shienkov +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtSerialPort module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qserialportinfo.h" +#include "qserialportinfo_p.h" +#include "qserialport_p.h" + +#include +#include +#include + +#include +#include // kill +#include // kill + +#include // sysctl, sysctlnametomib + +QT_BEGIN_NAMESPACE + +static QString deviceProperty(const QString &pnpinfo, const QByteArray &pattern) +{ + const int firstbound = pnpinfo.indexOf(QLatin1String(pattern)); + if (firstbound == -1) + return QString(); + const int lastbound = pnpinfo.indexOf(QLatin1Char(' '), firstbound); + return pnpinfo.mid(firstbound + pattern.size(), lastbound - firstbound - pattern.size()); +} + +static QString deviceName(const QString &pnpinfo) +{ + return deviceProperty(pnpinfo, "ttyname="); +} + +static QString deviceCount(const QString &pnpinfo) +{ + return deviceProperty(pnpinfo, "ttyports="); +} + +static quint16 deviceProductIdentifier(const QString &pnpinfo, bool &hasIdentifier) +{ + QString result = deviceProperty(pnpinfo, "product="); + return result.toInt(&hasIdentifier, 16); +} + +static quint16 deviceVendorIdentifier(const QString &pnpinfo, bool &hasIdentifier) +{ + QString result = deviceProperty(pnpinfo, "vendor="); + return result.toInt(&hasIdentifier, 16); +} + +static QString deviceSerialNumber(const QString &pnpinfo) +{ + QString serialNumber = deviceProperty(pnpinfo, "sernum="); + serialNumber.remove(QLatin1Char('"')); + return serialNumber; +} + +// A 'desc' string contains the both description and manufacturer +// properties, which are not possible to extract from the source +// string. Besides, this string can contains an other information, +// which should be excluded from the result. +static QString deviceDescriptionAndManufacturer(const QString &desc) +{ + const int classindex = desc.indexOf(QLatin1String(", class ")); + if (classindex == -1) + return desc; + return desc.mid(0, classindex); +} + +struct NodeInfo +{ + QString name; + QString value; +}; + +static QVector mibFromName(const QString &name) +{ + size_t mibsize = 0; + if (::sysctlnametomib(name.toLocal8Bit().constData(), Q_NULLPTR, &mibsize) < 0 + || mibsize == 0) { + return QVector(); + } + QVector mib(mibsize); + if (::sysctlnametomib(name.toLocal8Bit().constData(), &mib[0], &mibsize) < 0) + return QVector(); + + return mib; +} + +static QVector nextOid(const QVector &previousOid) +{ + QVector mib; + mib.append(0); // Magic undocumented code (CTL_UNSPEC ?) + mib.append(2); // Magic undocumented code + foreach (int code, previousOid) + mib.append(code); + + size_t requiredLength = 0; + if (::sysctl(&mib[0], mib.count(), Q_NULLPTR, &requiredLength, Q_NULLPTR, 0) < 0) + return QVector(); + const size_t oidLength = requiredLength / sizeof(int); + QVector oid(oidLength, 0); + if (::sysctl(&mib[0], mib.count(), &oid[0], &requiredLength, Q_NULLPTR, 0) < 0) + return QVector(); + + if (previousOid.first() != oid.first()) + return QVector(); + + return oid; +} + +static NodeInfo nodeForOid(const QVector &oid) +{ + QVector mib; + mib.append(0); // Magic undocumented code (CTL_UNSPEC ?) + mib.append(1); // Magic undocumented code + foreach (int code, oid) + mib.append(code); + + // query node name + size_t requiredLength = 0; + if (::sysctl(&mib[0], mib.count(), Q_NULLPTR, &requiredLength, Q_NULLPTR, 0) < 0) + return NodeInfo(); + QByteArray name(requiredLength, 0); + if (::sysctl(&mib[0], mib.count(), name.data(), &requiredLength, Q_NULLPTR, 0) < 0) + return NodeInfo(); + + // query node value + requiredLength = 0; + if (::sysctl(&oid[0], oid.count(), Q_NULLPTR, &requiredLength, Q_NULLPTR, 0) < 0) + return NodeInfo(); + QByteArray value(requiredLength, 0); + if (::sysctl(&oid[0], oid.count(), value.data(), &requiredLength, Q_NULLPTR, 0) < 0) + return NodeInfo(); + + // query value format + mib[1] = 4; // Magic undocumented code + requiredLength = 0; + if (::sysctl(&mib[0], mib.count(), Q_NULLPTR, &requiredLength, Q_NULLPTR, 0) < 0) + return NodeInfo(); + QByteArray buf(requiredLength, 0); + if (::sysctl(&mib[0], mib.count(), buf.data(), &requiredLength, Q_NULLPTR, 0) < 0) + return NodeInfo(); + + QDataStream in(buf); + in.setByteOrder(QDataStream::LittleEndian); + quint32 kind = 0; + qint8 format = 0; + in >> kind >> format; + + NodeInfo result; + + // we need only the string-type value + if (format == 'A') { + result.name = QString::fromLocal8Bit(name.constData()); + result.value = QString::fromLocal8Bit(value.constData()); + } + + return result; +} + +static QList enumerateDesiredNodes(const QVector &mib) +{ + QList nodes; + + QVector oid = mib; + + forever { + const QVector nextoid = nextOid(oid); + if (nextoid.isEmpty()) + break; + + const NodeInfo node = nodeForOid(nextoid); + if (!node.name.isEmpty()) { + if (node.name.endsWith("\%desc") + || node.name.endsWith("\%pnpinfo")) { + nodes.append(node); + } + } + + oid = nextoid; + } + + return nodes; +} + +QList QSerialPortInfo::availablePorts() +{ + const QVector mib = mibFromName(QLatin1String("dev")); + if (mib.isEmpty()) + return QList(); + + const QList nodes = enumerateDesiredNodes(mib); + if (nodes.isEmpty()) + return QList(); + + QDir deviceDir(QLatin1String("/dev")); + if (!(deviceDir.exists() && deviceDir.isReadable())) + return QList(); + + deviceDir.setNameFilters(QStringList() << QLatin1String("cua*")); + deviceDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks); + + QList serialPortInfoList; + + foreach (const QString &portName, deviceDir.entryList()) { + if (portName.endsWith(QLatin1String(".init")) + || portName.endsWith(QLatin1String(".lock"))) { + continue; + } + + QSerialPortInfoPrivate priv; + priv.portName = portName; + priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(portName); + + foreach (const NodeInfo &node, nodes) { + const int pnpinfoindex = node.name.indexOf(QLatin1String("\%pnpinfo")); + if (pnpinfoindex == -1) + continue; + + if (node.value.isEmpty()) + continue; + + QString ttyname = deviceName(node.value); + if (ttyname.isEmpty()) + continue; + + const QString ttyportscount = deviceCount(node.value); + if (ttyportscount.isEmpty()) + continue; + + const int count = ttyportscount.toInt(); + if (count == 0) + continue; + if (count > 1) { + bool matched = false; + for (int i = 0; i < count; ++i) { + const QString ends = QString(QLatin1String("%1.%2")).arg(ttyname).arg(i); + if (portName.endsWith(ends)) { + matched = true; + break; + } + } + + if (!matched) + continue; + } else { + if (!portName.endsWith(ttyname)) + continue; + } + + priv.serialNumber = deviceSerialNumber(node.value); + priv.vendorIdentifier = deviceVendorIdentifier(node.value, priv.hasVendorIdentifier); + priv.productIdentifier = deviceProductIdentifier(node.value, priv.hasProductIdentifier); + + const QString nodebase = node.name.mid(0, pnpinfoindex); + const QString descnode = QString(QLatin1String("%1\%desc")).arg(nodebase); + + // search for description and manufacturer properties + foreach (const NodeInfo &node, nodes) { + if (node.name != descnode) + continue; + + if (node.value.isEmpty()) + continue; + + // We can not separate the description and the manufacturer + // properties from the node value, so lets just duplicate it. + priv.description = deviceDescriptionAndManufacturer(node.value); + priv.manufacturer = priv.description; + break; + } + + break; + } + + serialPortInfoList.append(priv); + } + + return serialPortInfoList; +} + +QList QSerialPortInfo::standardBaudRates() +{ + return QSerialPortPrivate::standardBaudRates(); +} + +bool QSerialPortInfo::isBusy() const +{ + QString lockFilePath = serialPortLockFilePath(portName()); + if (lockFilePath.isEmpty()) + return false; + + QFile reader(lockFilePath); + if (!reader.open(QIODevice::ReadOnly)) + return false; + + QByteArray pidLine = reader.readLine(); + pidLine.chop(1); + if (pidLine.isEmpty()) + return false; + + qint64 pid = pidLine.toLongLong(); + + if (pid && (::kill(pid, 0) == -1) && (errno == ESRCH)) + return false; // PID doesn't exist anymore + + return true; +} + +#if QT_DEPRECATED_SINCE(5, 2) +bool QSerialPortInfo::isValid() const +{ + QFile f(systemLocation()); + return f.exists(); +} +#endif // QT_DEPRECATED_SINCE(5, 2) + +QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source) +{ + return (source.startsWith(QLatin1Char('/')) + || source.startsWith(QLatin1String("./")) + || source.startsWith(QLatin1String("../"))) + ? source : (QLatin1String("/dev/") + source); +} + +QString QSerialPortInfoPrivate::portNameFromSystemLocation(const QString &source) +{ + return source.startsWith(QLatin1String("/dev/")) + ? source.mid(5) : source; +} + +QT_END_NAMESPACE diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp index f5bbfc61..2a66635d 100644 --- a/src/serialport/qserialportinfo_unix.cpp +++ b/src/serialport/qserialportinfo_unix.cpp @@ -42,21 +42,12 @@ #include #include -#ifdef Q_OS_FREEBSD -#include -#include -#endif - #include #include #include // kill #include // kill -#ifdef Q_OS_FREEBSD -#include // sysctl, sysctlnametomib -#endif - #include "qtudev_p.h" QT_BEGIN_NAMESPACE @@ -152,280 +143,6 @@ static bool isValidSerial8250(const QString &systemLocation) return false; } -#ifdef Q_OS_FREEBSD - -static QString deviceProperty(const QString &pnpinfo, const QByteArray &pattern) -{ - const int firstbound = pnpinfo.indexOf(QLatin1String(pattern)); - if (firstbound == -1) - return QString(); - const int lastbound = pnpinfo.indexOf(QLatin1Char(' '), firstbound); - return pnpinfo.mid(firstbound + pattern.size(), lastbound - firstbound - pattern.size()); -} - -static QString deviceName(const QString &pnpinfo) -{ - return deviceProperty(pnpinfo, "ttyname="); -} - -static QString deviceCount(const QString &pnpinfo) -{ - return deviceProperty(pnpinfo, "ttyports="); -} - -static quint16 deviceProductIdentifier(const QString &pnpinfo, bool &hasIdentifier) -{ - QString result = deviceProperty(pnpinfo, "product="); - return result.toInt(&hasIdentifier, 16); -} - -static quint16 deviceVendorIdentifier(const QString &pnpinfo, bool &hasIdentifier) -{ - QString result = deviceProperty(pnpinfo, "vendor="); - return result.toInt(&hasIdentifier, 16); -} - -static QString deviceSerialNumber(const QString &pnpinfo) -{ - QString serialNumber = deviceProperty(pnpinfo, "sernum="); - serialNumber.remove(QLatin1Char('"')); - return serialNumber; -} - -// A 'desc' string contains the both description and manufacturer -// properties, which are not possible to extract from the source -// string. Besides, this string can contains an other information, -// which should be excluded from the result. -static QString deviceDescriptionAndManufacturer(const QString &desc) -{ - const int classindex = desc.indexOf(QLatin1String(", class ")); - if (classindex == -1) - return desc; - return desc.mid(0, classindex); -} - -struct NodeInfo -{ - QString name; - QString value; -}; - -static QVector mibFromName(const QString &name) -{ - size_t mibsize = 0; - if (::sysctlnametomib(name.toLocal8Bit().constData(), Q_NULLPTR, &mibsize) < 0 - || mibsize == 0) { - return QVector(); - } - QVector mib(mibsize); - if (::sysctlnametomib(name.toLocal8Bit().constData(), &mib[0], &mibsize) < 0) - return QVector(); - - return mib; -} - -static QVector nextOid(const QVector &previousOid) -{ - QVector mib; - mib.append(0); // Magic undocumented code (CTL_UNSPEC ?) - mib.append(2); // Magic undocumented code - foreach (int code, previousOid) - mib.append(code); - - size_t requiredLength = 0; - if (::sysctl(&mib[0], mib.count(), Q_NULLPTR, &requiredLength, Q_NULLPTR, 0) < 0) - return QVector(); - const size_t oidLength = requiredLength / sizeof(int); - QVector oid(oidLength, 0); - if (::sysctl(&mib[0], mib.count(), &oid[0], &requiredLength, Q_NULLPTR, 0) < 0) - return QVector(); - - if (previousOid.first() != oid.first()) - return QVector(); - - return oid; -} - -static NodeInfo nodeForOid(const QVector &oid) -{ - QVector mib; - mib.append(0); // Magic undocumented code (CTL_UNSPEC ?) - mib.append(1); // Magic undocumented code - foreach (int code, oid) - mib.append(code); - - // query node name - size_t requiredLength = 0; - if (::sysctl(&mib[0], mib.count(), Q_NULLPTR, &requiredLength, Q_NULLPTR, 0) < 0) - return NodeInfo(); - QByteArray name(requiredLength, 0); - if (::sysctl(&mib[0], mib.count(), name.data(), &requiredLength, Q_NULLPTR, 0) < 0) - return NodeInfo(); - - // query node value - requiredLength = 0; - if (::sysctl(&oid[0], oid.count(), Q_NULLPTR, &requiredLength, Q_NULLPTR, 0) < 0) - return NodeInfo(); - QByteArray value(requiredLength, 0); - if (::sysctl(&oid[0], oid.count(), value.data(), &requiredLength, Q_NULLPTR, 0) < 0) - return NodeInfo(); - - // query value format - mib[1] = 4; // Magic undocumented code - requiredLength = 0; - if (::sysctl(&mib[0], mib.count(), Q_NULLPTR, &requiredLength, Q_NULLPTR, 0) < 0) - return NodeInfo(); - QByteArray buf(requiredLength, 0); - if (::sysctl(&mib[0], mib.count(), buf.data(), &requiredLength, Q_NULLPTR, 0) < 0) - return NodeInfo(); - - QDataStream in(buf); - in.setByteOrder(QDataStream::LittleEndian); - quint32 kind = 0; - qint8 format = 0; - in >> kind >> format; - - NodeInfo result; - - // we need only the string-type value - if (format == 'A') { - result.name = QString::fromLocal8Bit(name.constData()); - result.value = QString::fromLocal8Bit(value.constData()); - } - - return result; -} - -static QList enumerateDesiredNodes(const QVector &mib) -{ - QList nodes; - - QVector oid = mib; - - forever { - const QVector nextoid = nextOid(oid); - if (nextoid.isEmpty()) - break; - - const NodeInfo node = nodeForOid(nextoid); - if (!node.name.isEmpty()) { - if (node.name.endsWith("\%desc") - || node.name.endsWith("\%pnpinfo")) { - nodes.append(node); - } - } - - oid = nextoid; - } - - return nodes; -} - -QList availablePortsBySysctl(bool &ok) -{ - const QVector mib = mibFromName(QLatin1String("dev")); - if (mib.isEmpty()) { - ok = false; - return QList(); - } - - const QList nodes = enumerateDesiredNodes(mib); - if (nodes.isEmpty()) { - ok = false; - return QList(); - } - - QDir deviceDir(QLatin1String("/dev")); - if (!(deviceDir.exists() && deviceDir.isReadable())) { - ok = false; - return QList(); - } - - deviceDir.setNameFilters(QStringList() << QLatin1String("cua*")); - deviceDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks); - - QList serialPortInfoList; - - foreach (const QString &portName, deviceDir.entryList()) { - if (portName.endsWith(QLatin1String(".init")) - || portName.endsWith(QLatin1String(".lock"))) { - continue; - } - - QSerialPortInfoPrivate priv; - priv.portName = portName; - priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(portName); - - foreach (const NodeInfo &node, nodes) { - const int pnpinfoindex = node.name.indexOf(QLatin1String("\%pnpinfo")); - if (pnpinfoindex == -1) - continue; - - if (node.value.isEmpty()) - continue; - - QString ttyname = deviceName(node.value); - if (ttyname.isEmpty()) - continue; - - const QString ttyportscount = deviceCount(node.value); - if (ttyportscount.isEmpty()) - continue; - - const int count = ttyportscount.toInt(); - if (count == 0) - continue; - if (count > 1) { - bool matched = false; - for (int i = 0; i < count; ++i) { - const QString ends = QString(QLatin1String("%1.%2")).arg(ttyname).arg(i); - if (portName.endsWith(ends)) { - matched = true; - break; - } - } - - if (!matched) - continue; - } else { - if (!portName.endsWith(ttyname)) - continue; - } - - priv.serialNumber = deviceSerialNumber(node.value); - priv.vendorIdentifier = deviceVendorIdentifier(node.value, priv.hasVendorIdentifier); - priv.productIdentifier = deviceProductIdentifier(node.value, priv.hasProductIdentifier); - - const QString nodebase = node.name.mid(0, pnpinfoindex); - const QString descnode = QString(QLatin1String("%1\%desc")).arg(nodebase); - - // search for description and manufacturer properties - foreach (const NodeInfo &node, nodes) { - if (node.name != descnode) - continue; - - if (node.value.isEmpty()) - continue; - - // We can not separate the description and the manufacturer - // properties from the node value, so lets just duplicate it. - priv.description = deviceDescriptionAndManufacturer(node.value); - priv.manufacturer = priv.description; - break; - } - - break; - } - - serialPortInfoList.append(priv); - } - - ok = true; - return serialPortInfoList; -} - -#endif // Q_OS_FREEBSD - static bool isRfcommDevice(const QString &portName) { if (!portName.startsWith(QLatin1String("rfcomm"))) @@ -736,11 +453,6 @@ QList QSerialPortInfo::availablePorts() serialPortInfoList = availablePortsBySysfs(ok); #endif -#ifdef Q_OS_FREEBSD - if (!ok) - serialPortInfoList = availablePortsBySysctl(ok); -#endif - if (!ok) serialPortInfoList = availablePortsByFiltersOfDevices(ok); diff --git a/src/serialport/serialport-lib.pri b/src/serialport/serialport-lib.pri index c3b00eaf..7179beae 100644 --- a/src/serialport/serialport-lib.pri +++ b/src/serialport/serialport-lib.pri @@ -37,14 +37,17 @@ unix { SOURCES += \ $$PWD/qserialport_unix.cpp - !osx { - SOURCES += \ - $$PWD/qserialportinfo_unix.cpp - } else { + osx { SOURCES += \ $$PWD/qserialportinfo_osx.cpp LIBS_PRIVATE += -framework IOKit -framework CoreFoundation + } else:freebsd { + SOURCES += \ + $$PWD/qserialportinfo_freebsd.cpp + } else { + SOURCES += \ + $$PWD/qserialportinfo_unix.cpp } } -- cgit v1.2.3 From c32a064349ddce1149afd8c524ac43f30cdddc80 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Sun, 14 Feb 2016 17:01:12 +0000 Subject: Enumerate dial-in devices on FreeBSD BSD-like systems divide serial ports into dial-in (tty) and dial-out (cua) devices. QSPI did not return a list of dial-in devices, that now has been fixed in this patch. Change-Id: I593719429e3b6641012eb046851dd08b9dc829fb Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialportinfo_freebsd.cpp | 38 +++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/serialport/qserialportinfo_freebsd.cpp b/src/serialport/qserialportinfo_freebsd.cpp index e65f09c4..49612f15 100644 --- a/src/serialport/qserialportinfo_freebsd.cpp +++ b/src/serialport/qserialportinfo_freebsd.cpp @@ -47,13 +47,13 @@ QT_BEGIN_NAMESPACE -static QString deviceProperty(const QString &pnpinfo, const QByteArray &pattern) +static QString deviceProperty(const QString &source, const QByteArray &pattern) { - const int firstbound = pnpinfo.indexOf(QLatin1String(pattern)); + const int firstbound = source.indexOf(QLatin1String(pattern)); if (firstbound == -1) return QString(); - const int lastbound = pnpinfo.indexOf(QLatin1Char(' '), firstbound); - return pnpinfo.mid(firstbound + pattern.size(), lastbound - firstbound - pattern.size()); + const int lastbound = source.indexOf(QLatin1Char(' '), firstbound); + return source.mid(firstbound + pattern.size(), lastbound - firstbound - pattern.size()); } static QString deviceName(const QString &pnpinfo) @@ -202,8 +202,8 @@ static QList enumerateDesiredNodes(const QVector &mib) const NodeInfo node = nodeForOid(nextoid); if (!node.name.isEmpty()) { - if (node.name.endsWith("\%desc") - || node.name.endsWith("\%pnpinfo")) { + if (node.name.endsWith(QLatin1String("\%desc")) + || node.name.endsWith(QLatin1String("\%pnpinfo"))) { nodes.append(node); } } @@ -228,10 +228,11 @@ QList QSerialPortInfo::availablePorts() if (!(deviceDir.exists() && deviceDir.isReadable())) return QList(); - deviceDir.setNameFilters(QStringList() << QLatin1String("cua*")); + deviceDir.setNameFilters(QStringList() << QLatin1String("cua*") << QLatin1String("tty*")); deviceDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks); - QList serialPortInfoList; + QList cuaCandidates; + QList ttyCandidates; foreach (const QString &portName, deviceDir.entryList()) { if (portName.endsWith(QLatin1String(".init")) @@ -304,7 +305,26 @@ QList QSerialPortInfo::availablePorts() break; } - serialPortInfoList.append(priv); + if (portName.startsWith(QLatin1String("cua"))) + cuaCandidates.append(priv); + else if (portName.startsWith(QLatin1String("tty"))) + ttyCandidates.append(priv); + } + + QList serialPortInfoList; + + foreach (const QSerialPortInfo &cuaCandidate, cuaCandidates) { + const QString cuaPortName = cuaCandidate.portName(); + const QString cuaToken = deviceProperty(cuaPortName, "cua"); + foreach (const QSerialPortInfo &ttyCandidate, ttyCandidates) { + const QString ttyPortName = ttyCandidate.portName(); + const QString ttyToken = deviceProperty(ttyPortName, "tty"); + if (cuaToken != ttyToken) + continue; + + serialPortInfoList.append(cuaCandidate); + serialPortInfoList.append(ttyCandidate); + } } return serialPortInfoList; -- cgit v1.2.3 From 26ea44e3b45de4a33515c826f6f5c9aa501f57fd Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Sun, 14 Feb 2016 17:46:11 +0300 Subject: Enumerate dial-in devices on OS X OS X divide serial ports into dialin (tty) and callout (cu) devices. QSPI did not return a list of dialin devices, that now has been fixed in this patch. Task-number: QTBUG-50895 Change-Id: I9f25b8f042ce1fdef9fd140896fc1d7093ee91a1 Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialportinfo_osx.cpp | 38 ++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/serialport/qserialportinfo_osx.cpp b/src/serialport/qserialportinfo_osx.cpp index 4e73025e..5a0cdd8a 100644 --- a/src/serialport/qserialportinfo_osx.cpp +++ b/src/serialport/qserialportinfo_osx.cpp @@ -83,10 +83,10 @@ static quint16 searchShortIntProperty(io_registry_entry_t ioRegistryEntry, return value; } -static bool isCompleteInfo(const QSerialPortInfoPrivate &priv) +static bool isCompleteInfo(const QSerialPortInfoPrivate &priv, const QString &calloutDevice, const QString &dialinDevice) { - return !priv.portName.isEmpty() - && !priv.device.isEmpty() + return !calloutDevice.isEmpty() + && !dialinDevice.isEmpty() && !priv.manufacturer.isEmpty() && !priv.description.isEmpty() && !priv.serialNumber.isEmpty() @@ -94,11 +94,16 @@ static bool isCompleteInfo(const QSerialPortInfoPrivate &priv) && priv.hasVendorIdentifier; } -static QString deviceSystemLocation(io_registry_entry_t ioRegistryEntry) +static QString calloutDeviceSystemLocation(io_registry_entry_t ioRegistryEntry) { return searchStringProperty(ioRegistryEntry, QCFString(kIOCalloutDeviceKey)); } +static QString dialinDeviceSystemLocation(io_registry_entry_t ioRegistryEntry) +{ + return searchStringProperty(ioRegistryEntry, QCFString(kIODialinDeviceKey)); +} + static QString deviceDescription(io_registry_entry_t ioRegistryEntry) { QString result = searchStringProperty(ioRegistryEntry, QCFString(kIOPropertyProductNameKey)); @@ -162,12 +167,15 @@ QList QSerialPortInfo::availablePorts() QSerialPortInfoPrivate priv; + QString calloutDevice; + QString dialinDevice; + forever { - if (priv.device.isEmpty()) { - priv.device = deviceSystemLocation(serialPortService); - if (!priv.device.isEmpty()) - priv.portName = QSerialPortInfoPrivate::portNameFromSystemLocation(priv.device); - } + if (calloutDevice.isEmpty()) + calloutDevice = calloutDeviceSystemLocation(serialPortService); + + if (dialinDevice.isEmpty()) + dialinDevice = dialinDeviceSystemLocation(serialPortService); if (priv.description.isEmpty()) priv.description = deviceDescription(serialPortService); @@ -190,7 +198,7 @@ QList QSerialPortInfo::availablePorts() priv.hasProductIdentifier); } - if (isCompleteInfo(priv)) { + if (isCompleteInfo(priv, calloutDevice, dialinDevice)) { ::IOObjectRelease(serialPortService); break; } @@ -200,7 +208,15 @@ QList QSerialPortInfo::availablePorts() break; } - serialPortInfoList.append(priv); + QSerialPortInfoPrivate calloutCandidate = priv; + calloutCandidate.device = calloutDevice; + calloutCandidate.portName = QSerialPortInfoPrivate::portNameFromSystemLocation(calloutDevice); + serialPortInfoList.append(calloutCandidate); + + QSerialPortInfoPrivate dialinCandidate = priv; + dialinCandidate.device = dialinDevice; + dialinCandidate.portName = QSerialPortInfoPrivate::portNameFromSystemLocation(dialinDevice); + serialPortInfoList.append(dialinCandidate); } ::IOObjectRelease(serialPortIterator); -- cgit v1.2.3