summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Henrie <alexhenrie24@gmail.com>2013-07-01 23:51:18 -0600
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-07-03 01:46:13 +0200
commit4c67500e5d14e561e37b4bdc056f059d3eefdfa4 (patch)
tree26d6532dc08bf3d75dea1764d08046fff13010a6
parent4464dfccc8480146744ec1b02aedb41d0fb3ec1b (diff)
downloadqtserialport-4c67500e5d14e561e37b4bdc056f059d3eefdfa4.tar.gz
Add property to set exclusivity
Disabling the serial port driver's exclusive mode is necessary for pseudo serial ports and some USB/serial adapters to work correctly. Change-Id: I74d45feed619817b61e265b00aec8b0ebfae7a33 Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com> Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
-rw-r--r--src/serialport/qserialport.cpp44
-rw-r--r--src/serialport/qserialport.h15
-rw-r--r--src/serialport/qserialport_p.h1
-rw-r--r--src/serialport/qserialport_symbian.cpp6
-rw-r--r--src/serialport/qserialport_symbian_p.h1
-rw-r--r--src/serialport/qserialport_unix.cpp76
-rw-r--r--src/serialport/qserialport_unix_p.h3
-rw-r--r--src/serialport/qserialport_win.cpp6
-rw-r--r--src/serialport/qserialport_win_p.h1
9 files changed, 129 insertions, 24 deletions
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp
index 96f06d4..d90b48d 100644
--- a/src/serialport/qserialport.cpp
+++ b/src/serialport/qserialport.cpp
@@ -73,6 +73,7 @@ QSerialPortPrivateData::QSerialPortPrivateData(QSerialPort *q)
, stopBits(QSerialPort::UnknownStopBits)
, flow(QSerialPort::UnknownFlowControl)
, policy(QSerialPort::IgnorePolicy)
+ , exclusiveMode(QSerialPort::FullyExclusive)
, settingsRestoredOnClose(true)
, q_ptr(q)
{
@@ -320,6 +321,27 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed)
\sa QSerialPort::error
*/
+/*!
+ \enum QSerialPort::ExclusiveModeFlag
+
+ This enum describes the level of exclusivity to set on the serial port.
+
+ \value NotExclusive The serial port may be opened elsewhere even if it
+ is open here. This flag only has effect on Unix.
+ \value LockFileExclusive A lock file prevents the serial port from being
+ opened elsewhere while it is open here. This flag
+ only has effect on Unix.
+ \value DriverExclusive The serial port driver prevents the serial port
+ from being opened elsewhere while it is open here.
+ This flag only has effect on Unix if the ioctl
+ request TIOCEXCL is available.
+ \value FullyExclusive Both the serial port driver and, if on Unix, a
+ lock file prevent the serial port from being opened
+ elsewhere while it is open here.
+
+ \sa QSerialPort::exclusiveMode
+*/
+
/*!
@@ -489,6 +511,28 @@ void QSerialPort::close()
}
/*!
+ \property QSerialPort::exclusiveMode
+ \brief the exclusivity of this object's claim on the serial port
+
+ If the setting is successful, returns true; otherwise returns false. Serial
+ ports are set to QSerialPort::FullyExclusive by default.
+
+ This flag is always QSerialPort::FullyExclusive on Windows and Symbian and
+ cannot be changed.
+*/
+bool QSerialPort::setExclusiveMode(ExclusiveMode exclusiveMode)
+{
+ Q_D(QSerialPort);
+ return d->setExclusiveMode(exclusiveMode);
+}
+
+QSerialPort::ExclusiveMode QSerialPort::exclusiveMode() const
+{
+ Q_D(const QSerialPort);
+ return d->exclusiveMode;
+}
+
+/*!
\property QSerialPort::settingsRestoredOnClose
\brief the flag which allows to restore the previous settings while closing
the serial port.
diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h
index c193bcd..6ec8e25 100644
--- a/src/serialport/qserialport.h
+++ b/src/serialport/qserialport.h
@@ -65,10 +65,11 @@ class Q_SERIALPORT_EXPORT QSerialPort : public QIODevice
Q_PROPERTY(bool dataTerminalReady READ isDataTerminalReady WRITE setDataTerminalReady NOTIFY dataTerminalReadyChanged)
Q_PROPERTY(bool requestToSend READ isRequestToSend WRITE setRequestToSend NOTIFY requestToSendChanged)
Q_PROPERTY(SerialPortError error READ error RESET clearError NOTIFY error)
+ Q_PROPERTY(ExclusiveMode exclusiveMode READ exclusiveMode WRITE setExclusiveMode)
Q_PROPERTY(bool settingsRestoredOnClose READ settingsRestoredOnClose WRITE setSettingsRestoredOnClose NOTIFY settingsRestoredOnCloseChanged)
Q_ENUMS(BaudRate DataBits Parity StopBits FlowControl DataErrorPolicy SerialPortError)
- Q_FLAGS(Directions PinoutSignals)
+ Q_FLAGS(Directions PinoutSignals ExclusiveMode)
public:
@@ -160,6 +161,14 @@ public:
UnknownError
};
+ enum ExclusiveModeFlag {
+ NotExclusive = 0,
+ LockFileExclusive = 1,
+ DriverExclusive = 2,
+ FullyExclusive = LockFileExclusive | DriverExclusive
+ };
+ Q_DECLARE_FLAGS(ExclusiveMode, ExclusiveModeFlag)
+
explicit QSerialPort(QObject *parent = 0);
explicit QSerialPort(const QString &name, QObject *parent = 0);
explicit QSerialPort(const QSerialPortInfo &info, QObject *parent = 0);
@@ -173,6 +182,9 @@ public:
bool open(OpenMode mode) Q_DECL_OVERRIDE;
void close() Q_DECL_OVERRIDE;
+ bool setExclusiveMode(ExclusiveMode exclusiveMode);
+ ExclusiveMode exclusiveMode() const;
+
void setSettingsRestoredOnClose(bool restore);
bool settingsRestoredOnClose() const;
@@ -252,6 +264,7 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::Directions)
Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::PinoutSignals)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::ExclusiveMode)
QT_END_NAMESPACE
diff --git a/src/serialport/qserialport_p.h b/src/serialport/qserialport_p.h
index abd9cb6..b74cda6 100644
--- a/src/serialport/qserialport_p.h
+++ b/src/serialport/qserialport_p.h
@@ -80,6 +80,7 @@ public:
QSerialPort::DataErrorPolicy policy;
bool dataTerminalReady;
bool requestToSend;
+ QSerialPort::ExclusiveMode exclusiveMode;
bool settingsRestoredOnClose;
QSerialPort * const q_ptr;
};
diff --git a/src/serialport/qserialport_symbian.cpp b/src/serialport/qserialport_symbian.cpp
index 2bba5a4..3e904ab 100644
--- a/src/serialport/qserialport_symbian.cpp
+++ b/src/serialport/qserialport_symbian.cpp
@@ -158,6 +158,12 @@ void QSerialPortPrivate::close()
descriptor.Close();
}
+bool QSerialPortPrivate::setExclusiveMode(QSerialPort::ExclusiveMode exclusiveMode)
+{
+ Q_UNUSED(exclusiveMode);
+ return false;
+}
+
QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() const
{
QSerialPort::PinoutSignals ret = QSerialPort::NoSignal;
diff --git a/src/serialport/qserialport_symbian_p.h b/src/serialport/qserialport_symbian_p.h
index 7f9eadd..1b235f5 100644
--- a/src/serialport/qserialport_symbian_p.h
+++ b/src/serialport/qserialport_symbian_p.h
@@ -84,6 +84,7 @@ public:
bool setStopBits(QSerialPort::StopBits stopBits);
bool setFlowControl(QSerialPort::FlowControl flowControl);
bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
+ bool setExclusiveMode(QSerialPort::ExclusiveMode exclusiveMode);
bool notifyRead();
bool notifyWrite();
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index 2f6c8cc..0e19d05 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -139,11 +139,7 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
- QByteArray portName = portNameFromSystemLocation(systemLocation).toLocal8Bit();
- const char *ptr = portName.constData();
-
- bool byCurrPid = false;
- if (QTtyLocker::isLocked(ptr, &byCurrPid)) {
+ if (isLockedByFile()) {
q_ptr->setError(QSerialPort::PermissionError);
return false;
}
@@ -169,17 +165,13 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
return false;
}
- ::fcntl(descriptor, F_SETFL, FNDELAY);
-
- QTtyLocker::lock(ptr);
- if (!QTtyLocker::isLocked(ptr, &byCurrPid)) {
+ if (!changeExclusiveMode(exclusiveMode)) {
+ ::close(descriptor);
q_ptr->setError(QSerialPort::PermissionError);
return false;
}
-#ifdef TIOCEXCL
- ::ioctl(descriptor, TIOCEXCL);
-#endif
+ ::fcntl(descriptor, F_SETFL, FNDELAY);
if (::tcgetattr(descriptor, &restoredTermios) == -1) {
q_ptr->setError(decodeSystemError());
@@ -217,10 +209,6 @@ void QSerialPortPrivate::close()
#endif
}
-#ifdef TIOCNXCL
- ::ioctl(descriptor, TIOCNXCL);
-#endif
-
if (readNotifier) {
readNotifier->setEnabled(false);
readNotifier->deleteLater();
@@ -239,19 +227,24 @@ void QSerialPortPrivate::close()
exceptionNotifier = 0;
}
- ::close(descriptor);
-
- QByteArray portName = portNameFromSystemLocation(systemLocation).toLocal8Bit();
- const char *ptr = portName.constData();
+ changeExclusiveMode(QSerialPort::NotExclusive);
- bool byCurrPid = false;
- if (QTtyLocker::isLocked(ptr, &byCurrPid) && byCurrPid)
- QTtyLocker::unlock(ptr);
+ ::close(descriptor);
descriptor = -1;
isCustomBaudRateSupported = false;
}
+bool QSerialPortPrivate::setExclusiveMode(QSerialPort::ExclusiveMode exclusiveMode)
+{
+ if (descriptor != -1 && !changeExclusiveMode(exclusiveMode)) {
+ q_ptr->setError(QSerialPort::PermissionError);
+ return false;
+ }
+ this->exclusiveMode = exclusiveMode;
+ return true;
+}
+
QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() const
{
int arg = 0;
@@ -1340,4 +1333,41 @@ QList<qint32> QSerialPortPrivate::standardBaudRates()
return standardBaudRateMap().keys();
}
+bool QSerialPortPrivate::isLockedByFile()
+{
+ QByteArray portName = portNameFromSystemLocation(systemLocation).toLocal8Bit();
+ const char *ptr = portName.constData();
+ bool byCurrPid;
+
+ return QTtyLocker::isLocked(ptr, &byCurrPid);
+}
+
+bool QSerialPortPrivate::changeExclusiveMode(QSerialPort::ExclusiveMode exclusiveMode)
+{
+ QByteArray portName = portNameFromSystemLocation(systemLocation).toLocal8Bit();
+ const char *ptr = portName.constData();
+ bool byCurrPid;
+
+ if (exclusiveMode & QSerialPort::LockFileExclusive) {
+ QTtyLocker::lock(ptr);
+ if (!QTtyLocker::isLocked(ptr, &byCurrPid))
+ return false;
+ } else {
+ if (QTtyLocker::isLocked(ptr, &byCurrPid) && byCurrPid)
+ QTtyLocker::unlock(ptr);
+ }
+
+#ifdef TIOCEXCL
+ if (exclusiveMode & QSerialPort::DriverExclusive) {
+ if (::ioctl(descriptor, TIOCEXCL) < 0) {
+ QTtyLocker::unlock(ptr);
+ return false;
+ }
+ } else
+ ::ioctl(descriptor, TIOCNXCL);
+#endif
+
+ return true;
+}
+
QT_END_NAMESPACE
diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h
index ce70c24..3d96ecb 100644
--- a/src/serialport/qserialport_unix_p.h
+++ b/src/serialport/qserialport_unix_p.h
@@ -91,6 +91,7 @@ public:
bool setStopBits(QSerialPort::StopBits stopBits);
bool setFlowControl(QSerialPort::FlowControl flow);
bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
+ bool setExclusiveMode(QSerialPort::ExclusiveMode exclusiveMode);
bool readNotification();
bool writeNotification(int maxSize = INT_MAX);
@@ -149,6 +150,8 @@ private:
#endif
qint64 readPerChar(char *data, qint64 maxSize);
+ bool isLockedByFile();
+ bool changeExclusiveMode(QSerialPort::ExclusiveMode exclusiveMode);
};
QT_END_NAMESPACE
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index e8d4d62..4da1d1d 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -310,6 +310,12 @@ void QSerialPortPrivate::close()
#endif // #ifndef Q_OS_WINCE
+bool QSerialPortPrivate::setExclusiveMode(QSerialPort::ExclusiveMode exclusiveMode)
+{
+ Q_UNUSED(exclusiveMode);
+ return false;
+}
+
QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() const
{
DWORD modemStat = 0;
diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h
index a59ea9a..02810c0 100644
--- a/src/serialport/qserialport_win_p.h
+++ b/src/serialport/qserialport_win_p.h
@@ -97,6 +97,7 @@ public:
bool setStopBits(QSerialPort::StopBits stopBits);
bool setFlowControl(QSerialPort::FlowControl flowControl);
bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
+ bool setExclusiveMode(QSerialPort::ExclusiveMode exclusiveMode);
bool processIoErrors(bool error);
#ifndef Q_OS_WINCE