summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--src/serialport/doc/qtserialport.qdocconf3
-rw-r--r--src/serialport/doc/src/qtserialport-module.qdoc2
-rw-r--r--src/serialport/qserialport.cpp14
-rw-r--r--src/serialport/qserialport.h11
-rw-r--r--src/serialport/qserialport_symbian.cpp5
-rw-r--r--src/serialport/qserialport_unix.cpp9
-rw-r--r--src/serialport/qserialport_win.cpp9
-rw-r--r--src/serialport/qserialport_wince.cpp6
-rw-r--r--src/serialport/qserialportinfo_unix.cpp165
10 files changed, 185 insertions, 41 deletions
diff --git a/.qmake.conf b/.qmake.conf
index bf1b71f1..2f09a2ba 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,3 +1,3 @@
load(qt_build_config)
-MODULE_VERSION = 5.1.2
+MODULE_VERSION = 5.2.0
diff --git a/src/serialport/doc/qtserialport.qdocconf b/src/serialport/doc/qtserialport.qdocconf
index f095c2f1..a1c9ad55 100644
--- a/src/serialport/doc/qtserialport.qdocconf
+++ b/src/serialport/doc/qtserialport.qdocconf
@@ -35,3 +35,6 @@ exampledirs += ../../../examples/serialport
imagedirs += images
depends += qtcore qtdoc
+
+navigation.landingpage = "Qt Serial Port"
+navigation.cppclassespage = "Qt Serial Port C++ Classes"
diff --git a/src/serialport/doc/src/qtserialport-module.qdoc b/src/serialport/doc/src/qtserialport-module.qdoc
index b0fc506e..9a2b89a8 100644
--- a/src/serialport/doc/src/qtserialport-module.qdoc
+++ b/src/serialport/doc/src/qtserialport-module.qdoc
@@ -28,6 +28,8 @@
/*!
\module QtSerialPort
\title Qt Serial Port C++ Classes
+ \ingroup modules
+ \qtvariable serialport
\brief List of C++ classes that enable access to a serial port.
To use these classes in your application, use the following include
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp
index fb5615fc..531dc39c 100644
--- a/src/serialport/qserialport.cpp
+++ b/src/serialport/qserialport.cpp
@@ -315,8 +315,8 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
e.g. when the device is unexpectedly removed from the system.
\value UnsupportedOperationError The requested device operation is
not supported or prohibited by the running operating system.
+ \value TimeoutError A timeout error occurred. This value was introduced in QtSerialPort 5.2.
\value UnknownError An unidentified error occurred.
-
\sa QSerialPort::error
*/
@@ -1081,6 +1081,18 @@ bool QSerialPort::waitForReadyRead(int msecs)
}
/*!
+ \fn QSerialPort::Handle QSerialPort::handle()
+ \since 5.2
+
+ Returns the native serial port descriptor of the object. If the serial port
+ is not open or the platform is not supported, handle() returns -1.
+
+ \warning This function is for expert use only; use it at your own risk.
+ Furthermore, this function carries no compatibility promise between minor
+ Qt releases.
+*/
+
+/*!
\reimp
*/
bool QSerialPort::waitForBytesWritten(int msecs)
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h
index eb2baa38..781a98b1 100644
--- a/src/serialport/qserialport.h
+++ b/src/serialport/qserialport.h
@@ -71,6 +71,12 @@ class Q_SERIALPORT_EXPORT QSerialPort : public QIODevice
Q_ENUMS(BaudRate DataBits Parity StopBits FlowControl DataErrorPolicy SerialPortError)
Q_FLAGS(Directions PinoutSignals)
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ typedef void* Handle;
+#else
+ typedef int Handle;
+#endif
+
public:
enum Direction {
@@ -158,7 +164,8 @@ public:
ReadError,
ResourceError,
UnsupportedOperationError,
- UnknownError
+ UnknownError,
+ TimeoutError
};
explicit QSerialPort(QObject *parent = 0);
@@ -225,6 +232,8 @@ public:
bool sendBreak(int duration = 0);
bool setBreakEnabled(bool set = true);
+ Handle handle() const;
+
Q_SIGNALS:
void baudRateChanged(qint32 baudRate, QSerialPort::Directions directions);
void dataBitsChanged(QSerialPort::DataBits dataBits);
diff --git a/src/serialport/qserialport_symbian.cpp b/src/serialport/qserialport_symbian.cpp
index 50359de0..d905db1a 100644
--- a/src/serialport/qserialport_symbian.cpp
+++ b/src/serialport/qserialport_symbian.cpp
@@ -648,4 +648,9 @@ QList<qint32> QSerialPortPrivate::standardBaudRates()
return standardBaudRateMap().keys();
}
+QSerialPort::Handle QSerialPort::handle() const
+{
+ return -1;
+}
+
QT_END_NAMESPACE
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index 6a5a5c2c..f72322f4 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -993,6 +993,8 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
bool checkRead, bool checkWrite,
int msecs, bool *timedOut)
{
+ Q_Q(QSerialPort);
+
Q_ASSERT(selectForRead);
Q_ASSERT(selectForWrite);
Q_ASSERT(timedOut);
@@ -1016,6 +1018,7 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
return false;
if (ret == 0) {
*timedOut = true;
+ q->setError(QSerialPort::TimeoutError);
return false;
}
@@ -1391,4 +1394,10 @@ QList<qint32> QSerialPortPrivate::standardBaudRates()
return standardBaudRateMap().keys();
}
+QSerialPort::Handle QSerialPort::handle() const
+{
+ Q_D(const QSerialPort);
+ return d->descriptor;
+}
+
QT_END_NAMESPACE
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 1ab18a99..3d9e98aa 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -979,6 +979,8 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut,
AbstractOverlappedEventNotifier **triggeredNotifier)
{
+ Q_Q(QSerialPort);
+
Q_ASSERT(timedOut);
QVector<HANDLE> handles = notifiers.keys().toVector();
@@ -988,6 +990,7 @@ bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut,
msecs == -1 ? INFINITE : msecs);
if (waitResult == WAIT_TIMEOUT) {
*timedOut = true;
+ q->setError(QSerialPort::TimeoutError);
return false;
}
@@ -1119,4 +1122,10 @@ QList<qint32> QSerialPortPrivate::standardBaudRates()
return ret;
}
+QSerialPort::Handle QSerialPort::handle() const
+{
+ Q_D(const QSerialPort);
+ return d->descriptor;
+}
+
QT_END_NAMESPACE
diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp
index e99c6aa7..bc4c5269 100644
--- a/src/serialport/qserialport_wince.cpp
+++ b/src/serialport/qserialport_wince.cpp
@@ -435,6 +435,8 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
bool checkRead, bool checkWrite,
int msecs, bool *timedOut)
{
+ Q_Q(QSerialPort);
+
DWORD eventMask = 0;
// FIXME: Here the situation is not properly handled with zero timeout:
// breaker can work out before you call a method WaitCommEvent()
@@ -443,8 +445,10 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
::WaitCommEvent(descriptor, &eventMask, NULL);
breaker.stop();
- if (breaker.isWorked())
+ if (breaker.isWorked()) {
*timedOut = true;
+ q->setError(QSerialPort::TimeoutError);
+ }
if (!breaker.isWorked()) {
if (checkRead) {
diff --git a/src/serialport/qserialportinfo_unix.cpp b/src/serialport/qserialportinfo_unix.cpp
index 70188802..ea5a1b38 100644
--- a/src/serialport/qserialportinfo_unix.cpp
+++ b/src/serialport/qserialportinfo_unix.cpp
@@ -49,7 +49,7 @@
#ifndef Q_OS_MAC
-#if defined (Q_OS_LINUX) && defined (HAVE_LIBUDEV)
+#ifdef HAVE_LIBUDEV
extern "C"
{
#include <libudev.h>
@@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
#ifndef Q_OS_MAC
-#if !(defined (Q_OS_LINUX) && defined (HAVE_LIBUDEV))
+#ifndef HAVE_LIBUDEV
static inline const QStringList& filtersOfDevices()
{
@@ -90,13 +90,135 @@ static inline const QStringList& filtersOfDevices()
return deviceFileNameFilterList;
}
-#endif
+static QStringList filteredDeviceFilePaths()
+{
+ QStringList result;
+
+ QDir deviceDir(QLatin1String("/dev"));
+ if (deviceDir.exists()) {
+ deviceDir.setNameFilters(filtersOfDevices());
+ deviceDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks);
+ QStringList deviceFilePaths;
+ foreach (const QFileInfo &deviceFileInfo, deviceDir.entryInfoList()) {
+ const QString deviceAbsoluteFilePath = deviceFileInfo.absoluteFilePath();
+ if (!deviceFilePaths.contains(deviceAbsoluteFilePath)) {
+ deviceFilePaths.append(deviceAbsoluteFilePath);
+ result.append(deviceAbsoluteFilePath);
+ }
+ }
+ }
+
+ return result;
+}
QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
{
QList<QSerialPortInfo> serialPortInfoList;
-#if defined (Q_OS_LINUX) && defined (HAVE_LIBUDEV)
+ bool sysfsEnabled = false;
+
+#ifdef Q_OS_LINUX
+
+ QDir ttySysClassDir(QLatin1String("/sys/class/tty"));
+ sysfsEnabled = ttySysClassDir.exists() && ttySysClassDir.isReadable();
+
+ if (sysfsEnabled) {
+ ttySysClassDir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach (const QFileInfo &fileInfo, ttySysClassDir.entryInfoList()) {
+ if (!fileInfo.isSymLink())
+ continue;
+
+ const QString targetPath = fileInfo.symLinkTarget();
+ const int lastIndexOfSlash = targetPath.lastIndexOf(QLatin1Char('/'));
+ if (lastIndexOfSlash == -1)
+ continue;
+
+ bool canAppendToList = true;
+ QSerialPortInfo serialPortInfo;
+
+ if (targetPath.contains(QLatin1String("pnp"))) {
+ // TODO: Implement me.
+ } else if (targetPath.contains(QLatin1String("platform"))) {
+ // Platform 'pseudo' bus for legacy device.
+ // Skip this devices because this type of subsystem does
+ // not include a real physical serial device.
+ canAppendToList = false;
+ } else if (targetPath.contains(QLatin1String("usb"))) {
+
+ QDir targetDir(targetPath);
+ targetDir.setFilter(QDir::Files | QDir::Readable);
+ targetDir.setNameFilters(QStringList(QLatin1String("uevent")));
+
+ do {
+ const QFileInfoList entryInfoList = targetDir.entryInfoList();
+ if (entryInfoList.isEmpty())
+ continue;
+
+ QFile uevent(entryInfoList.first().absoluteFilePath());
+ if (!uevent.open(QIODevice::ReadOnly | QIODevice::Text))
+ continue;
+
+ const QString ueventContent = QString::fromLatin1(uevent.readAll());
+
+ if (ueventContent.contains(QLatin1String("DEVTYPE=usb_device"))
+ && ueventContent.contains(QLatin1String("DRIVER=usb"))) {
+
+ QFile description(QFileInfo(targetDir, QLatin1String("product")).absoluteFilePath());
+ if (description.open(QIODevice::ReadOnly | QIODevice::Text))
+ serialPortInfo.d_ptr->description = QString::fromLatin1(description.readAll()).simplified();
+
+ QFile manufacturer(QFileInfo(targetDir, QLatin1String("manufacturer")).absoluteFilePath());
+ if (manufacturer.open(QIODevice::ReadOnly | QIODevice::Text))
+ serialPortInfo.d_ptr->manufacturer = QString::fromLatin1(manufacturer.readAll()).simplified();
+
+ QFile vendorIdentifier(QFileInfo(targetDir, QLatin1String("idVendor")).absoluteFilePath());
+ if (vendorIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ serialPortInfo.d_ptr->vendorIdentifier = QString::fromLatin1(vendorIdentifier.readAll())
+ .toInt(&serialPortInfo.d_ptr->hasVendorIdentifier, 16);
+ }
+
+ QFile productIdentifier(QFileInfo(targetDir, QLatin1String("idProduct")).absoluteFilePath());
+ if (productIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ serialPortInfo.d_ptr->productIdentifier = QString::fromLatin1(productIdentifier.readAll())
+ .toInt(&serialPortInfo.d_ptr->hasProductIdentifier, 16);
+ }
+
+ break;
+ }
+ } while (targetDir.cdUp());
+
+ } else {
+ // unknown types of devices
+ canAppendToList = false;
+ }
+
+ if (canAppendToList) {
+ serialPortInfo.d_ptr->portName = targetPath.mid(lastIndexOfSlash + 1);
+ serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(serialPortInfo.d_ptr->portName);
+ serialPortInfoList.append(serialPortInfo);
+ }
+ }
+ }
+
+#endif
+
+ if (!sysfsEnabled) {
+ foreach (const QString &deviceFilePath, filteredDeviceFilePaths()) {
+ QSerialPortInfo serialPortInfo;
+ serialPortInfo.d_ptr->device = deviceFilePath;
+ serialPortInfo.d_ptr->portName = QSerialPortPrivate::portNameFromSystemLocation(deviceFilePath);
+ serialPortInfoList.append(serialPortInfo);
+ }
+ }
+
+ return serialPortInfoList;
+}
+
+#else
+
+QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
+{
+ QList<QSerialPortInfo> serialPortInfoList;
// White list for devices without a parent
static const QString rfcommDeviceName(QLatin1String("rfcomm"));
@@ -202,42 +324,11 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
::udev_unref(udev);
}
-#elif defined (Q_OS_FREEBSD) && defined (HAVE_LIBUSB)
- // TODO: Implement me.
-#else
-
- QDir devDir(QLatin1String("/dev"));
- if (devDir.exists()) {
-
- devDir.setNameFilters(filtersOfDevices());
- devDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks);
-
- QStringList foundDevices; // Found devices list.
-
- foreach (const QFileInfo &deviceFileInfo, devDir.entryInfoList()) {
- QString deviceFilePath = deviceFileInfo.absoluteFilePath();
- if (!foundDevices.contains(deviceFilePath)) {
- foundDevices.append(deviceFilePath);
-
- QSerialPortInfo serialPortInfo;
-
- serialPortInfo.d_ptr->device = deviceFilePath;
- serialPortInfo.d_ptr->portName = QSerialPortPrivate::portNameFromSystemLocation(deviceFilePath);
-
- // Get description, manufacturer, vendor identifier, product
- // identifier are not supported.
-
- serialPortInfoList.append(serialPortInfo);
-
- }
- }
- }
-
-#endif
-
return serialPortInfoList;
}
+#endif
+
#endif // Q_OS_MAC
// common part