summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2014-11-29 00:14:37 +0000
committerDenis Shienkov <denis.shienkov@gmail.com>2014-12-03 10:12:54 +0100
commit8975c4ad32a8244a0eadc2d0c6bb49ea489ac57a (patch)
tree2cf6c957f0b812fe08cadea7ead19a4e3ae0dc8f
parent1013d61f492f168e90d7266dcec59a79a869d69a (diff)
downloadqtserialport-8975c4ad32a8244a0eadc2d0c6bb49ea489ac57a.tar.gz
Improve QSPI sysfs algorithm
Earlier, the algorithm used check for magic keywords (like "usb", "platform" and so on) in the target path for decision-making what of device can be skipped or accepted. But this is a wrong approach, because on different platforms can be different key-words and we can not know it. So, it is more reasonable to use a different approach where we make decision by a driver name (by analogy with current udev implementation). In this case we skip those devices which has an empty driver name or when a name is equal to "serial8250". * When a driver name is empty, then we can be sure that it is other than serial port device (e.g. as pseudo-terminal, console and so on). Thus, it is similar to udev devices without a parent, which we ignore. * When a driver name is "serial8250", it is equal to "platform" devices, which we too ignore for current implementation. Though in a future this can be solved (i.e. we can try to detect a valid devices based on "serial8250" driver). Tested on Linux with on-board and USB serial ports using Qt5. Change-Id: I884ad8f3fddff9487ad4a67c4904b57f62164e00 Reviewed-by: Rainer Keller <rainer.keller@theqtcompany.com> Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com>
-rw-r--r--src/serialport/qserialportinfo_unix.cpp188
1 files changed, 107 insertions, 81 deletions
diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp
index b2f2a1c..6a27d41 100644
--- a/src/serialport/qserialportinfo_unix.cpp
+++ b/src/serialport/qserialportinfo_unix.cpp
@@ -108,6 +108,80 @@ QList<QSerialPortInfo> availablePortsByFiltersOfDevices(bool &ok)
return serialPortInfoList;
}
+static bool isSerial8250Driver(const QString &driverName)
+{
+ return (driverName == QStringLiteral("serial8250"));
+}
+
+static QString ueventProperty(const QDir &targetDir, const QByteArray &pattern)
+{
+ QFile f(QFileInfo(targetDir, QStringLiteral("uevent")).absoluteFilePath());
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ return QString();
+
+ const QByteArray content = f.readAll();
+
+ const int firstbound = content.indexOf(pattern);
+ if (firstbound == -1)
+ return QString();
+
+ const int lastbound = content.indexOf('\n', firstbound);
+ return QString::fromLatin1(
+ content.mid(firstbound + pattern.size(),
+ lastbound - firstbound - pattern.size()))
+ .simplified();
+}
+
+static QString deviceName(const QDir &targetDir)
+{
+ return ueventProperty(targetDir, "DEVNAME=");
+}
+
+static QString deviceDriver(const QDir &targetDir)
+{
+ const QDir deviceDir(targetDir.absolutePath() + "/device");
+ return ueventProperty(deviceDir, "DRIVER=");
+}
+
+static QString deviceProperty(const QString &targetFilePath)
+{
+ QFile f(targetFilePath);
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ return QString();
+ return QString::fromLatin1(f.readAll()).simplified();
+}
+
+static QString deviceDescription(const QDir &targetDir)
+{
+ return deviceProperty(QFileInfo(targetDir, QStringLiteral("product")).absoluteFilePath());
+}
+
+static QString deviceManufacturer(const QDir &targetDir)
+{
+ return deviceProperty(QFileInfo(targetDir, QStringLiteral("manufacturer")).absoluteFilePath());
+}
+
+static quint16 deviceProductIdentifier(const QDir &targetDir, bool &hasIdentifier)
+{
+ QString result = deviceProperty(QFileInfo(targetDir, QStringLiteral("idProduct")).absoluteFilePath());
+ if (result.isEmpty())
+ result = deviceProperty(QFileInfo(targetDir, QStringLiteral("device")).absoluteFilePath());
+ return result.toInt(&hasIdentifier, 16);
+}
+
+static quint16 deviceVendorIdentifier(const QDir &targetDir, bool &hasIdentifier)
+{
+ QString result = deviceProperty(QFileInfo(targetDir, QStringLiteral("idVendor")).absoluteFilePath());
+ if (result.isEmpty())
+ result = deviceProperty(QFileInfo(targetDir, QStringLiteral("vendor")).absoluteFilePath());
+ return result.toInt(&hasIdentifier, 16);
+}
+
+static QString deviceSerialNumber(const QDir &targetDir)
+{
+ return deviceProperty(QFileInfo(targetDir, QStringLiteral("serial")).absoluteFilePath());
+}
+
QList<QSerialPortInfo> availablePortsBySysfs(bool &ok)
{
QDir ttySysClassDir(QStringLiteral("/sys/class/tty"));
@@ -123,89 +197,46 @@ QList<QSerialPortInfo> availablePortsBySysfs(bool &ok)
if (!fileInfo.isSymLink())
continue;
- const QString targetPath = fileInfo.symLinkTarget();
- const int lastIndexOfSlash = targetPath.lastIndexOf(QLatin1Char('/'));
- if (lastIndexOfSlash == -1)
+ QDir targetDir(fileInfo.symLinkTarget());
+
+ const QString driverName = deviceDriver(targetDir);
+ if (driverName.isEmpty() || isSerial8250Driver(driverName))
continue;
- QSerialPortInfoPrivate priv;
- if (targetPath.contains(QStringLiteral("pnp"))) {
- // TODO: Obtain more information
-#ifndef Q_OS_ANDROID
- } else if (targetPath.contains(QStringLiteral("platform"))) {
-#else
- } else if (targetPath.contains(QStringLiteral("platform")) && !targetPath.contains(QStringLiteral("ttyUSB")) ) {
-#endif
+ const QString portName = deviceName(targetDir);
+ if (portName.isEmpty())
continue;
- } else if (targetPath.contains(QStringLiteral("usb"))) {
- QDir targetDir(targetPath);
- targetDir.setFilter(QDir::Files | QDir::Readable);
- targetDir.setNameFilters(QStringList(QStringLiteral("uevent")));
-
- do {
- const QFileInfoList entryInfoList = targetDir.entryInfoList();
- if (entryInfoList.isEmpty())
- continue;
- QFile uevent(entryInfoList.first().absoluteFilePath());
- if (!uevent.open(QIODevice::ReadOnly | QIODevice::Text))
- continue;
+ QSerialPortInfoPrivate priv;
- const QString ueventContent = QString::fromLatin1(uevent.readAll());
-
- if (ueventContent.contains(QStringLiteral("DEVTYPE=usb_device"))
- && ueventContent.contains(QStringLiteral("DRIVER=usb"))) {
-
- QFile description(QFileInfo(targetDir, QStringLiteral("product")).absoluteFilePath());
- if (description.open(QIODevice::ReadOnly | QIODevice::Text))
- priv.description = QString::fromLatin1(description.readAll()).simplified();
-
- QFile manufacturer(QFileInfo(targetDir, QStringLiteral("manufacturer")).absoluteFilePath());
- if (manufacturer.open(QIODevice::ReadOnly | QIODevice::Text))
- priv.manufacturer = QString::fromLatin1(manufacturer.readAll()).simplified();
-
- QFile serialNumber(QFileInfo(targetDir, QStringLiteral("serial")).absoluteFilePath());
- if (serialNumber.open(QIODevice::ReadOnly | QIODevice::Text))
- priv.serialNumber = QString::fromLatin1(serialNumber.readAll()).simplified();
-
- QFile vendorIdentifier(QFileInfo(targetDir, QStringLiteral("idVendor")).absoluteFilePath());
- if (vendorIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
- priv.vendorIdentifier = QString::fromLatin1(vendorIdentifier.readAll())
- .toInt(&priv.hasVendorIdentifier, 16);
- }
-
- QFile productIdentifier(QFileInfo(targetDir, QStringLiteral("idProduct")).absoluteFilePath());
- if (productIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
- priv.productIdentifier = QString::fromLatin1(productIdentifier.readAll())
- .toInt(&priv.hasProductIdentifier, 16);
- }
-
- break;
- }
- } while (targetDir.cdUp());
-
- } else if (targetPath.contains(QStringLiteral("pci"))) {
- QDir targetDir(targetPath + QStringLiteral("/device"));
- QFile vendorIdentifier(QFileInfo(targetDir, QStringLiteral("vendor")).absoluteFilePath());
- if (vendorIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
- priv.vendorIdentifier = QString::fromLatin1(vendorIdentifier.readAll())
- .toInt(&priv.hasVendorIdentifier, 16);
- }
- QFile productIdentifier(QFileInfo(targetDir, QStringLiteral("device")).absoluteFilePath());
- if (productIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
- priv.productIdentifier = QString::fromLatin1(productIdentifier.readAll())
- .toInt(&priv.hasProductIdentifier, 16);
+ priv.portName = portName;
+ priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(portName);
+
+ do {
+ if (priv.description.isEmpty())
+ priv.description = deviceDescription(targetDir);
+
+ if (priv.manufacturer.isEmpty())
+ priv.manufacturer = deviceManufacturer(targetDir);
+
+ if (priv.serialNumber.isEmpty())
+ priv.serialNumber = deviceSerialNumber(targetDir);
+
+ if (!priv.hasVendorIdentifier)
+ priv.vendorIdentifier = deviceVendorIdentifier(targetDir, priv.hasVendorIdentifier);
+
+ if (!priv.hasProductIdentifier)
+ priv.productIdentifier = deviceProductIdentifier(targetDir, priv.hasProductIdentifier);
+
+ if (!priv.description.isEmpty()
+ || !priv.manufacturer.isEmpty()
+ || !priv.serialNumber.isEmpty()
+ || priv.hasVendorIdentifier
+ || priv.hasProductIdentifier) {
+ break;
}
- // TODO: Obtain more information about the device
- } else if (targetPath.contains(QStringLiteral(".serial/tty/tty"))) {
- // This condition matches onboard serial port on embedded devices.
- // Keep those devices in the list
- } else {
- continue;
- }
+ } while (targetDir.cdUp());
- priv.portName = targetPath.mid(lastIndexOfSlash + 1);
- priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(priv.portName);
serialPortInfoList.append(priv);
}
@@ -241,11 +272,6 @@ struct ScopedPointerUdevDeviceDeleter
Q_GLOBAL_STATIC(QLibrary, udevLibrary)
#endif
-static bool isSerial8250Driver(const QString &driverName)
-{
- return (driverName == QStringLiteral("serial8250"));
-}
-
static QString deviceProperty(struct ::udev_device *dev, const char *name)
{
return QString::fromLatin1(::udev_device_get_property_value(dev, name));