summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2016-06-30 19:27:25 +0300
committerDenis Shienkov <denis.shienkov@gmail.com>2016-07-07 17:12:54 +0000
commit5ddbb6b87266d0f8d7dffc03c86c2e80b3735d2c (patch)
treeb1765f3ca80875dbeb0899340ef2ad571dded79e
parenta713565d119c39bd31ec25926ded881d1f0b78b7 (diff)
downloadqtserialport-5ddbb6b87266d0f8d7dffc03c86c2e80b3735d2c.tar.gz
Minimize number of system calls at opening
Currently, the method QSP::open() several times calls the system functions to get/set of DCB/termios structures for each parameter. It is not rational and should be minimized as possible, in ideally to once executed. Change-Id: If1f308176a82f3c8896fc648bf656f089e099f3f Reviewed-by: Sergey Belyashov <Sergey.Belyashov@gmail.com> Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
-rw-r--r--src/serialport/qserialport.cpp9
-rw-r--r--src/serialport/qserialport_unix.cpp221
-rw-r--r--src/serialport/qserialport_win.cpp172
3 files changed, 233 insertions, 169 deletions
diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp
index 45f56c8..d4e9a4f 100644
--- a/src/serialport/qserialport.cpp
+++ b/src/serialport/qserialport.cpp
@@ -568,15 +568,6 @@ bool QSerialPort::open(OpenMode mode)
if (!d->open(mode))
return false;
- if (!d->setBaudRate()
- || !d->setDataBits(d->dataBits)
- || !d->setParity(d->parity)
- || !d->setStopBits(d->stopBits)
- || !d->setFlowControl(d->flowControl)) {
- d->close();
- return false;
- }
-
QIODevice::open(mode);
return true;
}
diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp
index acc53c8..acd76b5 100644
--- a/src/serialport/qserialport_unix.cpp
+++ b/src/serialport/qserialport_unix.cpp
@@ -193,6 +193,120 @@ private:
QSerialPortPrivate *dptr;
};
+static inline void qt_set_common_props(termios *tio, QIODevice::OpenMode m)
+{
+#ifdef Q_OS_SOLARIS
+ tio->c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ tio->c_oflag &= ~OPOST;
+ tio->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ tio->c_cflag &= ~(CSIZE|PARENB);
+ tio->c_cflag |= CS8;
+#else
+ ::cfmakeraw(tio);
+#endif
+
+ tio->c_cflag |= CLOCAL;
+ tio->c_cc[VTIME] = 0;
+ tio->c_cc[VMIN] = 0;
+
+ if (m & QIODevice::ReadOnly)
+ tio->c_cflag |= CREAD;
+}
+
+static inline void qt_set_databits(termios *tio, QSerialPort::DataBits databits)
+{
+ tio->c_cflag &= ~CSIZE;
+ switch (databits) {
+ case QSerialPort::Data5:
+ tio->c_cflag |= CS5;
+ break;
+ case QSerialPort::Data6:
+ tio->c_cflag |= CS6;
+ break;
+ case QSerialPort::Data7:
+ tio->c_cflag |= CS7;
+ break;
+ case QSerialPort::Data8:
+ tio->c_cflag |= CS8;
+ break;
+ default:
+ tio->c_cflag |= CS8;
+ break;
+ }
+}
+
+static inline void qt_set_parity(termios *tio, QSerialPort::Parity parity)
+{
+ tio->c_iflag &= ~(PARMRK | INPCK);
+ tio->c_iflag |= IGNPAR;
+
+ switch (parity) {
+
+#ifdef CMSPAR
+ // Here Installation parity only for GNU/Linux where the macro CMSPAR.
+ case QSerialPort::SpaceParity:
+ tio->c_cflag &= ~PARODD;
+ tio->c_cflag |= PARENB | CMSPAR;
+ break;
+ case QSerialPort::MarkParity:
+ tio->c_cflag |= PARENB | CMSPAR | PARODD;
+ break;
+#endif
+ case QSerialPort::NoParity:
+ tio->c_cflag &= ~PARENB;
+ break;
+ case QSerialPort::EvenParity:
+ tio->c_cflag &= ~PARODD;
+ tio->c_cflag |= PARENB;
+ break;
+ case QSerialPort::OddParity:
+ tio->c_cflag |= PARENB | PARODD;
+ break;
+ default:
+ tio->c_cflag |= PARENB;
+ tio->c_iflag |= PARMRK | INPCK;
+ tio->c_iflag &= ~IGNPAR;
+ break;
+ }
+}
+
+static inline void qt_set_stopbits(termios *tio, QSerialPort::StopBits stopbits)
+{
+ switch (stopbits) {
+ case QSerialPort::OneStop:
+ tio->c_cflag &= ~CSTOPB;
+ break;
+ case QSerialPort::TwoStop:
+ tio->c_cflag |= CSTOPB;
+ break;
+ default:
+ tio->c_cflag &= ~CSTOPB;
+ break;
+ }
+}
+
+static inline void qt_set_flowcontrol(termios *tio, QSerialPort::FlowControl flowcontrol)
+{
+ switch (flowcontrol) {
+ case QSerialPort::NoFlowControl:
+ tio->c_cflag &= ~CRTSCTS;
+ tio->c_iflag &= ~(IXON | IXOFF | IXANY);
+ break;
+ case QSerialPort::HardwareControl:
+ tio->c_cflag |= CRTSCTS;
+ tio->c_iflag &= ~(IXON | IXOFF | IXANY);
+ break;
+ case QSerialPort::SoftwareControl:
+ tio->c_cflag &= ~CRTSCTS;
+ tio->c_iflag |= IXON | IXOFF | IXANY;
+ break;
+ default:
+ tio->c_cflag &= ~CRTSCTS;
+ tio->c_iflag &= ~(IXON | IXOFF | IXANY);
+ break;
+ }
+}
+
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
QString lockFilePath = serialPortLockFilePath(QSerialPortInfoPrivate::portNameFromSystemLocation(systemLocation));
@@ -605,24 +719,8 @@ bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits)
if (!getTermios(&tio))
return false;
- tio.c_cflag &= ~CSIZE;
- switch (dataBits) {
- case QSerialPort::Data5:
- tio.c_cflag |= CS5;
- break;
- case QSerialPort::Data6:
- tio.c_cflag |= CS6;
- break;
- case QSerialPort::Data7:
- tio.c_cflag |= CS7;
- break;
- case QSerialPort::Data8:
- tio.c_cflag |= CS8;
- break;
- default:
- tio.c_cflag |= CS8;
- break;
- }
+ qt_set_databits(&tio, dataBits);
+
return setTermios(&tio);
}
@@ -632,37 +730,7 @@ bool QSerialPortPrivate::setParity(QSerialPort::Parity parity)
if (!getTermios(&tio))
return false;
- tio.c_iflag &= ~(PARMRK | INPCK);
- tio.c_iflag |= IGNPAR;
-
- switch (parity) {
-
-#ifdef CMSPAR
- // Here Installation parity only for GNU/Linux where the macro CMSPAR.
- case QSerialPort::SpaceParity:
- tio.c_cflag &= ~PARODD;
- tio.c_cflag |= PARENB | CMSPAR;
- break;
- case QSerialPort::MarkParity:
- tio.c_cflag |= PARENB | CMSPAR | PARODD;
- break;
-#endif
- case QSerialPort::NoParity:
- tio.c_cflag &= ~PARENB;
- break;
- case QSerialPort::EvenParity:
- tio.c_cflag &= ~PARODD;
- tio.c_cflag |= PARENB;
- break;
- case QSerialPort::OddParity:
- tio.c_cflag |= PARENB | PARODD;
- break;
- default:
- tio.c_cflag |= PARENB;
- tio.c_iflag |= PARMRK | INPCK;
- tio.c_iflag &= ~IGNPAR;
- break;
- }
+ qt_set_parity(&tio, parity);
return setTermios(&tio);
}
@@ -673,17 +741,8 @@ bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits)
if (!getTermios(&tio))
return false;
- switch (stopBits) {
- case QSerialPort::OneStop:
- tio.c_cflag &= ~CSTOPB;
- break;
- case QSerialPort::TwoStop:
- tio.c_cflag |= CSTOPB;
- break;
- default:
- tio.c_cflag &= ~CSTOPB;
- break;
- }
+ qt_set_stopbits(&tio, stopBits);
+
return setTermios(&tio);
}
@@ -693,24 +752,8 @@ bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl)
if (!getTermios(&tio))
return false;
- switch (flowControl) {
- case QSerialPort::NoFlowControl:
- tio.c_cflag &= ~CRTSCTS;
- tio.c_iflag &= ~(IXON | IXOFF | IXANY);
- break;
- case QSerialPort::HardwareControl:
- tio.c_cflag |= CRTSCTS;
- tio.c_iflag &= ~(IXON | IXOFF | IXANY);
- break;
- case QSerialPort::SoftwareControl:
- tio.c_cflag &= ~CRTSCTS;
- tio.c_iflag |= IXON | IXOFF | IXANY;
- break;
- default:
- tio.c_cflag &= ~CRTSCTS;
- tio.c_iflag &= ~(IXON | IXOFF | IXANY);
- break;
- }
+ qt_set_flowcontrol(&tio, flowControl);
+
return setTermios(&tio);
}
@@ -825,25 +868,19 @@ inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode)
return false;
restoredTermios = tio;
-#ifdef Q_OS_SOLARIS
- tio.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
- tio.c_oflag &= ~OPOST;
- tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
- tio.c_cflag &= ~(CSIZE|PARENB);
- tio.c_cflag |= CS8;
-#else
- ::cfmakeraw(&tio);
-#endif
- tio.c_cflag |= CLOCAL;
- tio.c_cc[VTIME] = 0;
- tio.c_cc[VMIN] = 0;
- if (mode & QIODevice::ReadOnly)
- tio.c_cflag |= CREAD;
+ qt_set_common_props(&tio, mode);
+ qt_set_databits(&tio, dataBits);
+ qt_set_parity(&tio, parity);
+ qt_set_stopbits(&tio, stopBits);
+ qt_set_flowcontrol(&tio, flowControl);
if (!setTermios(&tio))
return false;
+ if (!setBaudRate())
+ return false;
+
if (mode & QIODevice::ReadOnly)
setReadNotificationEnabled(true);
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 7cbb81d..f4f8317 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -81,6 +81,94 @@
QT_BEGIN_NAMESPACE
+static inline void qt_set_common_props(DCB *dcb)
+{
+ dcb->fBinary = TRUE;
+ dcb->fAbortOnError = FALSE;
+ dcb->fNull = FALSE;
+ dcb->fErrorChar = FALSE;
+
+ if (dcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
+ dcb->fDtrControl = DTR_CONTROL_DISABLE;
+}
+
+static inline void qt_set_baudrate(DCB *dcb, qint32 baudrate)
+{
+ dcb->BaudRate = baudrate;
+}
+
+static inline void qt_set_databits(DCB *dcb, QSerialPort::DataBits databits)
+{
+ dcb->ByteSize = databits;
+}
+
+static inline void qt_set_parity(DCB *dcb, QSerialPort::Parity parity)
+{
+ dcb->fParity = TRUE;
+ switch (parity) {
+ case QSerialPort::NoParity:
+ dcb->Parity = NOPARITY;
+ dcb->fParity = FALSE;
+ break;
+ case QSerialPort::OddParity:
+ dcb->Parity = ODDPARITY;
+ break;
+ case QSerialPort::EvenParity:
+ dcb->Parity = EVENPARITY;
+ break;
+ case QSerialPort::MarkParity:
+ dcb->Parity = MARKPARITY;
+ break;
+ case QSerialPort::SpaceParity:
+ dcb->Parity = SPACEPARITY;
+ break;
+ default:
+ dcb->Parity = NOPARITY;
+ dcb->fParity = FALSE;
+ break;
+ }
+}
+
+static inline void qt_set_stopbits(DCB *dcb, QSerialPort::StopBits stopbits)
+{
+ switch (stopbits) {
+ case QSerialPort::OneStop:
+ dcb->StopBits = ONESTOPBIT;
+ break;
+ case QSerialPort::OneAndHalfStop:
+ dcb->StopBits = ONE5STOPBITS;
+ break;
+ case QSerialPort::TwoStop:
+ dcb->StopBits = TWOSTOPBITS;
+ break;
+ default:
+ dcb->StopBits = ONESTOPBIT;
+ break;
+ }
+}
+
+static inline void qt_set_flowcontrol(DCB *dcb, QSerialPort::FlowControl flowcontrol)
+{
+ dcb->fInX = FALSE;
+ dcb->fOutX = FALSE;
+ dcb->fOutxCtsFlow = FALSE;
+ dcb->fRtsControl = RTS_CONTROL_DISABLE;
+ switch (flowcontrol) {
+ case QSerialPort::NoFlowControl:
+ break;
+ case QSerialPort::SoftwareControl:
+ dcb->fInX = TRUE;
+ dcb->fOutX = TRUE;
+ break;
+ case QSerialPort::HardwareControl:
+ dcb->fOutxCtsFlow = TRUE;
+ dcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
+ break;
+ default:
+ break;
+ }
+}
+
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
DWORD desiredAccess = 0;
@@ -319,7 +407,8 @@ bool QSerialPortPrivate::setBaudRate(qint32 baudRate, QSerialPort::Directions di
if (!getDcb(&dcb))
return false;
- dcb.BaudRate = baudRate;
+ qt_set_baudrate(&dcb, baudRate);
+
return setDcb(&dcb);
}
@@ -329,7 +418,8 @@ bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits)
if (!getDcb(&dcb))
return false;
- dcb.ByteSize = dataBits;
+ qt_set_databits(&dcb, dataBits);
+
return setDcb(&dcb);
}
@@ -339,29 +429,8 @@ bool QSerialPortPrivate::setParity(QSerialPort::Parity parity)
if (!getDcb(&dcb))
return false;
- dcb.fParity = TRUE;
- switch (parity) {
- case QSerialPort::NoParity:
- dcb.Parity = NOPARITY;
- dcb.fParity = FALSE;
- break;
- case QSerialPort::OddParity:
- dcb.Parity = ODDPARITY;
- break;
- case QSerialPort::EvenParity:
- dcb.Parity = EVENPARITY;
- break;
- case QSerialPort::MarkParity:
- dcb.Parity = MARKPARITY;
- break;
- case QSerialPort::SpaceParity:
- dcb.Parity = SPACEPARITY;
- break;
- default:
- dcb.Parity = NOPARITY;
- dcb.fParity = FALSE;
- break;
- }
+ qt_set_parity(&dcb, parity);
+
return setDcb(&dcb);
}
@@ -371,20 +440,8 @@ bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits)
if (!getDcb(&dcb))
return false;
- switch (stopBits) {
- case QSerialPort::OneStop:
- dcb.StopBits = ONESTOPBIT;
- break;
- case QSerialPort::OneAndHalfStop:
- dcb.StopBits = ONE5STOPBITS;
- break;
- case QSerialPort::TwoStop:
- dcb.StopBits = TWOSTOPBITS;
- break;
- default:
- dcb.StopBits = ONESTOPBIT;
- break;
- }
+ qt_set_stopbits(&dcb, stopBits);
+
return setDcb(&dcb);
}
@@ -394,24 +451,8 @@ bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl)
if (!getDcb(&dcb))
return false;
- dcb.fInX = FALSE;
- dcb.fOutX = FALSE;
- dcb.fOutxCtsFlow = FALSE;
- dcb.fRtsControl = RTS_CONTROL_DISABLE;
- switch (flowControl) {
- case QSerialPort::NoFlowControl:
- break;
- case QSerialPort::SoftwareControl:
- dcb.fInX = TRUE;
- dcb.fOutX = TRUE;
- break;
- case QSerialPort::HardwareControl:
- dcb.fOutxCtsFlow = TRUE;
- dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
- break;
- default:
- break;
- }
+ qt_set_flowcontrol(&dcb, flowControl);
+
return setDcb(&dcb);
}
@@ -623,17 +664,12 @@ inline bool QSerialPortPrivate::initialize()
restoredDcb = dcb;
- dcb.fBinary = TRUE;
- dcb.fInX = FALSE;
- dcb.fOutX = FALSE;
- dcb.fAbortOnError = FALSE;
- dcb.fNull = FALSE;
- dcb.fErrorChar = FALSE;
-
- if (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
- dcb.fDtrControl = DTR_CONTROL_DISABLE;
-
- dcb.BaudRate = inputBaudRate;
+ qt_set_common_props(&dcb);
+ qt_set_baudrate(&dcb, inputBaudRate);
+ qt_set_databits(&dcb, dataBits);
+ qt_set_parity(&dcb, parity);
+ qt_set_stopbits(&dcb, stopBits);
+ qt_set_flowcontrol(&dcb, flowControl);
if (!setDcb(&dcb))
return false;