diff options
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | src/serialport/doc/images/blockingmaster-example.png | bin | 4656 -> 3797 bytes | |||
-rw-r--r-- | src/serialport/doc/images/blockingslave-example.png | bin | 4784 -> 3918 bytes | |||
-rw-r--r-- | src/serialport/doc/images/enumerator-example.png | bin | 18510 -> 15557 bytes | |||
-rw-r--r-- | src/serialport/doc/images/terminal-example.png | bin | 10918 -> 8548 bytes | |||
-rw-r--r-- | src/serialport/qserialport.cpp | 5 | ||||
-rw-r--r-- | src/serialport/qserialportinfo.cpp | 9 | ||||
-rw-r--r-- | src/serialport/qserialportinfo.h | 3 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_freebsd.cpp | 378 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_osx.cpp | 43 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_unix.cpp | 293 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_win.cpp | 25 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_wince.cpp | 5 | ||||
-rw-r--r-- | src/serialport/serialport-lib.pri | 11 | ||||
-rw-r--r-- | src/serialport/serialport.pro | 4 |
15 files changed, 440 insertions, 338 deletions
diff --git a/.qmake.conf b/.qmake.conf index 66a0241..b642527 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 diff --git a/src/serialport/doc/images/blockingmaster-example.png b/src/serialport/doc/images/blockingmaster-example.png Binary files differindex 44aa5ec..9b5fc4a 100644 --- a/src/serialport/doc/images/blockingmaster-example.png +++ b/src/serialport/doc/images/blockingmaster-example.png diff --git a/src/serialport/doc/images/blockingslave-example.png b/src/serialport/doc/images/blockingslave-example.png Binary files differindex 44aa393..c02ae85 100644 --- a/src/serialport/doc/images/blockingslave-example.png +++ b/src/serialport/doc/images/blockingslave-example.png diff --git a/src/serialport/doc/images/enumerator-example.png b/src/serialport/doc/images/enumerator-example.png Binary files differindex c4add83..c96d990 100644 --- a/src/serialport/doc/images/enumerator-example.png +++ b/src/serialport/doc/images/enumerator-example.png diff --git a/src/serialport/doc/images/terminal-example.png b/src/serialport/doc/images/terminal-example.png Binary files differindex 28aa366..9affaae 100644 --- a/src/serialport/doc/images/terminal-example.png +++ b/src/serialport/doc/images/terminal-example.png diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 38bd150..481b07e 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -955,6 +955,11 @@ bool QSerialPort::setRequestToSend(bool set) return false; } + if (d->flowControl == QSerialPort::HardwareControl) { + d->setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError)); + return false; + } + const bool requestToSend = isRequestToSend(); const bool retval = d->setRequestToSend(set); if (retval && (requestToSend != set)) diff --git a/src/serialport/qserialportinfo.cpp b/src/serialport/qserialportinfo.cpp index ca81cd0..bfa2b09 100644 --- a/src/serialport/qserialportinfo.cpp +++ b/src/serialport/qserialportinfo.cpp @@ -36,6 +36,7 @@ #include "qserialportinfo.h" #include "qserialportinfo_p.h" #include "qserialport.h" +#include "qserialport_p.h" QT_BEGIN_NAMESPACE @@ -283,9 +284,13 @@ bool QSerialPortInfo::hasProductIdentifier() const /*! \fn QList<qint32> QSerialPortInfo::standardBaudRates() - Returns a list of available standard baud rates supported by - the current serial port. + Returns a list of available standard baud rates supported + by the target platform. */ +QList<qint32> QSerialPortInfo::standardBaudRates() +{ + return QSerialPortPrivate::standardBaudRates(); +} /*! \fn QList<QSerialPortInfo> QSerialPortInfo::availablePorts() diff --git a/src/serialport/qserialportinfo.h b/src/serialport/qserialportinfo.h index 74daedc..fc83461 100644 --- a/src/serialport/qserialportinfo.h +++ b/src/serialport/qserialportinfo.h @@ -86,9 +86,6 @@ private: QSerialPortInfo(const QSerialPortInfoPrivate &dd); friend QList<QSerialPortInfo> availablePortsByUdev(bool &ok); friend QList<QSerialPortInfo> availablePortsBySysfs(bool &ok); -#ifdef Q_OS_FREEBSD - friend QList<QSerialPortInfo> availablePortsBySysctl(bool &ok); -#endif friend QList<QSerialPortInfo> availablePortsByFiltersOfDevices(bool &ok); QScopedPointer<QSerialPortInfoPrivate, QSerialPortInfoPrivateDeleter> d_ptr; }; diff --git a/src/serialport/qserialportinfo_freebsd.cpp b/src/serialport/qserialportinfo_freebsd.cpp new file mode 100644 index 0000000..552db89 --- /dev/null +++ b/src/serialport/qserialportinfo_freebsd.cpp @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com> +** 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 <QtCore/qdatastream.h> +#include <QtCore/qvector.h> +#include <QtCore/qdir.h> + +#include <errno.h> +#include <sys/types.h> // kill +#include <signal.h> // kill + +#include <sys/sysctl.h> // sysctl, sysctlnametomib + +QT_BEGIN_NAMESPACE + +static QString deviceProperty(const QString &source, const QByteArray &pattern) +{ + const int firstbound = source.indexOf(QLatin1String(pattern)); + if (firstbound == -1) + return QString(); + const int lastbound = source.indexOf(QLatin1Char(' '), firstbound); + return source.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<int> mibFromName(const QString &name) +{ + size_t mibsize = 0; + if (::sysctlnametomib(name.toLocal8Bit().constData(), Q_NULLPTR, &mibsize) < 0 + || mibsize == 0) { + return QVector<int>(); + } + QVector<int> mib(mibsize); + if (::sysctlnametomib(name.toLocal8Bit().constData(), &mib[0], &mibsize) < 0) + return QVector<int>(); + + return mib; +} + +static QVector<int> nextOid(const QVector<int> &previousOid) +{ + QVector<int> 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<int>(); + const size_t oidLength = requiredLength / sizeof(int); + QVector<int> oid(oidLength, 0); + if (::sysctl(&mib[0], mib.count(), &oid[0], &requiredLength, Q_NULLPTR, 0) < 0) + return QVector<int>(); + + if (previousOid.first() != oid.first()) + return QVector<int>(); + + return oid; +} + +static NodeInfo nodeForOid(const QVector<int> &oid) +{ + QVector<int> 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<NodeInfo> enumerateDesiredNodes(const QVector<int> &mib) +{ + QList<NodeInfo> nodes; + + QVector<int> oid = mib; + + forever { + const QVector<int> nextoid = nextOid(oid); + if (nextoid.isEmpty()) + break; + + const NodeInfo node = nodeForOid(nextoid); + if (!node.name.isEmpty()) { + if (node.name.endsWith(QLatin1String("\%desc")) + || node.name.endsWith(QLatin1String("\%pnpinfo"))) { + nodes.append(node); + } + } + + oid = nextoid; + } + + return nodes; +} + +QList<QSerialPortInfo> QSerialPortInfo::availablePorts() +{ + const QVector<int> mib = mibFromName(QLatin1String("dev")); + if (mib.isEmpty()) + return QList<QSerialPortInfo>(); + + const QList<NodeInfo> nodes = enumerateDesiredNodes(mib); + if (nodes.isEmpty()) + return QList<QSerialPortInfo>(); + + QDir deviceDir(QLatin1String("/dev")); + if (!(deviceDir.exists() && deviceDir.isReadable())) + return QList<QSerialPortInfo>(); + + deviceDir.setNameFilters(QStringList() << QLatin1String("cua*") << QLatin1String("tty*")); + deviceDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks); + + QList<QSerialPortInfo> cuaCandidates; + QList<QSerialPortInfo> ttyCandidates; + + 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; + } + + if (portName.startsWith(QLatin1String("cua"))) + cuaCandidates.append(priv); + else if (portName.startsWith(QLatin1String("tty"))) + ttyCandidates.append(priv); + } + + QList<QSerialPortInfo> 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; +} + +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_osx.cpp b/src/serialport/qserialportinfo_osx.cpp index 912d880..e2fc980 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> 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> QSerialPortInfo::availablePorts() priv.hasProductIdentifier); } - if (isCompleteInfo(priv)) { + if (isCompleteInfo(priv, calloutDevice, dialinDevice)) { ::IOObjectRelease(serialPortService); break; } @@ -200,7 +208,15 @@ QList<QSerialPortInfo> 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); @@ -208,11 +224,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() return serialPortInfoList; } -QList<qint32> QSerialPortInfo::standardBaudRates() -{ - return QSerialPortPrivate::standardBaudRates(); -} - #if QT_DEPRECATED_SINCE(5, 6) bool QSerialPortInfo::isBusy() const { diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp index f7426fc..475aeb4 100644 --- a/src/serialport/qserialportinfo_unix.cpp +++ b/src/serialport/qserialportinfo_unix.cpp @@ -42,21 +42,12 @@ #include <QtCore/qdir.h> #include <QtCore/qscopedpointer.h> -#ifdef Q_OS_FREEBSD -#include <QtCore/qdatastream.h> -#include <QtCore/qvector.h> -#endif - #include <private/qcore_unix_p.h> #include <errno.h> #include <sys/types.h> // kill #include <signal.h> // kill -#ifdef Q_OS_FREEBSD -#include <sys/sysctl.h> // 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<int> mibFromName(const QString &name) -{ - size_t mibsize = 0; - if (::sysctlnametomib(name.toLocal8Bit().constData(), Q_NULLPTR, &mibsize) < 0 - || mibsize == 0) { - return QVector<int>(); - } - QVector<int> mib(mibsize); - if (::sysctlnametomib(name.toLocal8Bit().constData(), &mib[0], &mibsize) < 0) - return QVector<int>(); - - return mib; -} - -static QVector<int> nextOid(const QVector<int> &previousOid) -{ - QVector<int> 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<int>(); - const size_t oidLength = requiredLength / sizeof(int); - QVector<int> oid(oidLength, 0); - if (::sysctl(&mib[0], mib.count(), &oid[0], &requiredLength, Q_NULLPTR, 0) < 0) - return QVector<int>(); - - if (previousOid.first() != oid.first()) - return QVector<int>(); - - return oid; -} - -static NodeInfo nodeForOid(const QVector<int> &oid) -{ - QVector<int> 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<NodeInfo> enumerateDesiredNodes(const QVector<int> &mib) -{ - QList<NodeInfo> nodes; - - QVector<int> oid = mib; - - forever { - const QVector<int> 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> availablePortsBySysctl(bool &ok) -{ - const QVector<int> mib = mibFromName(QLatin1String("dev")); - if (mib.isEmpty()) { - ok = false; - return QList<QSerialPortInfo>(); - } - - const QList<NodeInfo> nodes = enumerateDesiredNodes(mib); - if (nodes.isEmpty()) { - ok = false; - return QList<QSerialPortInfo>(); - } - - QDir deviceDir(QLatin1String("/dev")); - if (!(deviceDir.exists() && deviceDir.isReadable())) { - ok = false; - return QList<QSerialPortInfo>(); - } - - deviceDir.setNameFilters(QStringList() << QLatin1String("cua*")); - deviceDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks); - - QList<QSerialPortInfo> 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,22 +453,12 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() serialPortInfoList = availablePortsBySysfs(ok); #endif -#ifdef Q_OS_FREEBSD - if (!ok) - serialPortInfoList = availablePortsBySysctl(ok); -#endif - if (!ok) serialPortInfoList = availablePortsByFiltersOfDevices(ok); return serialPortInfoList; } -QList<qint32> QSerialPortInfo::standardBaudRates() -{ - return QSerialPortPrivate::standardBaudRates(); -} - #if QT_DEPRECATED_SINCE(5, 6) bool QSerialPortInfo::isBusy() const { diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 0a9fc64..1d55197 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -264,16 +264,22 @@ static QString parseDeviceSerialNumber(const QString &instanceIdentifier) return instanceIdentifier.mid(firstbound + 1, lastbound - firstbound - 1); } -static QString deviceSerialNumber(const QString &instanceIdentifier, +static QString deviceSerialNumber(QString instanceIdentifier, DEVINST deviceInstanceNumber) { - QString result = parseDeviceSerialNumber(instanceIdentifier); - if (result.isEmpty()) { - const DEVINST parentNumber = parentDeviceInstanceNumber(deviceInstanceNumber); - const QString parentInstanceIdentifier = deviceInstanceIdentifier(parentNumber); - result = parseDeviceSerialNumber(parentInstanceIdentifier); + forever { + const QString result = parseDeviceSerialNumber(instanceIdentifier); + if (!result.isEmpty()) + return result; + deviceInstanceNumber = parentDeviceInstanceNumber(deviceInstanceNumber); + if (deviceInstanceNumber == 0) + break; + instanceIdentifier = deviceInstanceIdentifier(deviceInstanceNumber); + if (instanceIdentifier.isEmpty()) + break; } - return result; + + return QString(); } QList<QSerialPortInfo> QSerialPortInfo::availablePorts() @@ -345,11 +351,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() return serialPortInfoList; } -QList<qint32> QSerialPortInfo::standardBaudRates() -{ - return QSerialPortPrivate::standardBaudRates(); -} - #if QT_DEPRECATED_SINCE(5, 6) bool QSerialPortInfo::isBusy() const { diff --git a/src/serialport/qserialportinfo_wince.cpp b/src/serialport/qserialportinfo_wince.cpp index 3b13244..9755d74 100644 --- a/src/serialport/qserialportinfo_wince.cpp +++ b/src/serialport/qserialportinfo_wince.cpp @@ -120,11 +120,6 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts() return serialPortInfoList; } -QList<qint32> QSerialPortInfo::standardBaudRates() -{ - return QSerialPortPrivate::standardBaudRates(); -} - #if QT_DEPRECATED_SINCE(5, 6) bool QSerialPortInfo::isBusy() const { diff --git a/src/serialport/serialport-lib.pri b/src/serialport/serialport-lib.pri index c3b00ea..7179bea 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 } } diff --git a/src/serialport/serialport.pro b/src/serialport/serialport.pro index 92d0795..194958a 100644 --- a/src/serialport/serialport.pro +++ b/src/serialport/serialport.pro @@ -5,8 +5,8 @@ QMAKE_DOCS = $$PWD/doc/qtserialport.qdocconf config_ntddmodm: DEFINES += QT_NO_REDEFINE_GUID_DEVINTERFACE_MODEM -load(qt_module) - include($$PWD/serialport-lib.pri) +load(qt_module) + PRECOMPILED_HEADER = |