summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2014-11-29 16:23:33 +0000
committerDenis Shienkov <denis.shienkov@gmail.com>2014-12-03 11:54:19 +0100
commit52e0a7c73dc5ac3352e4cec8ac7c9295b94eef97 (patch)
treebb46ecd21681bf937111971cb63f768981b5a363
parent8975c4ad32a8244a0eadc2d0c6bb49ea489ac57a (diff)
downloadqtserialport-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.h1
-rw-r--r--src/serialport/qserialportinfo_unix.cpp36
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());