diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2014-11-29 16:23:33 +0000 |
---|---|---|
committer | Denis Shienkov <denis.shienkov@gmail.com> | 2014-12-03 11:54:19 +0100 |
commit | 52e0a7c73dc5ac3352e4cec8ac7c9295b94eef97 (patch) | |
tree | bb46ecd21681bf937111971cb63f768981b5a363 | |
parent | 8975c4ad32a8244a0eadc2d0c6bb49ea489ac57a (diff) | |
download | qtserialport-52e0a7c73dc5ac3352e4cec8ac7c9295b94eef97.tar.gz |
Detect a valid of serial8250 ports
Usually, a Linux kernel reserves a places for the non-PnP serial
devices, for example, such as ttyS[0-4/14]. In case the system has not a
HW devices which are attached to this places, then these devices will be
stubs and present as usual serial ports. Thus, we can know about a
validity of these devices only in attempt to open them and to query a
type of.
Note: This patch is theoretical, because are not tested for a valid 8250
devices.
Task-number: QTBUG-32024
Change-Id: I313145caadfeeee4d5fe3c8e16c1bcf4ae79214d
Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com>
-rw-r--r-- | src/serialport/qserialport_unix_p.h | 1 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_unix.cpp | 36 |
2 files changed, 29 insertions, 8 deletions
diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h index 75e6004..5ec6653 100644 --- a/src/serialport/qserialport_unix_p.h +++ b/src/serialport/qserialport_unix_p.h @@ -82,6 +82,7 @@ struct serial_struct { }; #define ASYNC_SPD_CUST 0x0030 #define ASYNC_SPD_MASK 0x1030 +#define PORT_UNKNOWN 0 #endif QT_BEGIN_NAMESPACE diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp index 6a27d41..58eb62b 100644 --- a/src/serialport/qserialportinfo_unix.cpp +++ b/src/serialport/qserialportinfo_unix.cpp @@ -42,6 +42,7 @@ #include <QtCore/qdir.h> #include <QtCore/qscopedpointer.h> +#include <private/qcore_unix_p.h> #include <errno.h> #include <sys/types.h> // kill @@ -113,6 +114,24 @@ static bool isSerial8250Driver(const QString &driverName) return (driverName == QStringLiteral("serial8250")); } +static bool isValidSerial8250(const QString &systemLocation) +{ +#ifdef Q_OS_LINUX + const mode_t flags = O_RDWR | O_NONBLOCK | O_NOCTTY; + const int fd = qt_safe_open(systemLocation.toLocal8Bit().constData(), flags); + if (fd != -1) { + struct serial_struct serinfo; + const int retval = ::ioctl(fd, TIOCGSERIAL, &serinfo); + qt_safe_close(fd); + if (retval != -1 && serinfo.type != PORT_UNKNOWN) + return true; + } +#else + Q_UNUSED(systemLocation); +#endif + return false; +} + static QString ueventProperty(const QDir &targetDir, const QByteArray &pattern) { QFile f(QFileInfo(targetDir, QStringLiteral("uevent")).absoluteFilePath()); @@ -200,17 +219,18 @@ QList<QSerialPortInfo> availablePortsBySysfs(bool &ok) QDir targetDir(fileInfo.symLinkTarget()); const QString driverName = deviceDriver(targetDir); - if (driverName.isEmpty() || isSerial8250Driver(driverName)) - continue; - - const QString portName = deviceName(targetDir); - if (portName.isEmpty()) + if (driverName.isEmpty()) continue; QSerialPortInfoPrivate priv; - priv.portName = portName; - priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(portName); + priv.portName = deviceName(targetDir); + if (priv.portName.isEmpty()) + continue; + + priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(priv.portName); + if (isSerial8250Driver(driverName) && !isValidSerial8250(priv.device)) + continue; do { if (priv.description.isEmpty()) @@ -366,7 +386,7 @@ QList<QSerialPortInfo> availablePortsByUdev(bool &ok) if (parentdev) { const QString driverName = deviceDriver(parentdev); - if (isSerial8250Driver(driverName)) + if (isSerial8250Driver(driverName) && !isValidSerial8250(priv.portName)) continue; priv.description = deviceDescription(dev.data()); priv.manufacturer = deviceManufacturer(dev.data()); |