diff options
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | src/serialport/doc/qtserialport.qdocconf | 3 | ||||
-rw-r--r-- | src/serialport/doc/src/qtserialport-module.qdoc | 2 | ||||
-rw-r--r-- | src/serialport/qserialport.cpp | 14 | ||||
-rw-r--r-- | src/serialport/qserialport.h | 11 | ||||
-rw-r--r-- | src/serialport/qserialport_symbian.cpp | 5 | ||||
-rw-r--r-- | src/serialport/qserialport_unix.cpp | 9 | ||||
-rw-r--r-- | src/serialport/qserialport_win.cpp | 9 | ||||
-rw-r--r-- | src/serialport/qserialport_wince.cpp | 6 | ||||
-rw-r--r-- | src/serialport/qserialportinfo_unix.cpp | 165 |
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 |