From 5ddbb6b87266d0f8d7dffc03c86c2e80b3735d2c Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 30 Jun 2016 19:27:25 +0300 Subject: 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 Reviewed-by: Denis Shienkov --- src/serialport/qserialport.cpp | 9 -- src/serialport/qserialport_unix.cpp | 221 +++++++++++++++++++++--------------- src/serialport/qserialport_win.cpp | 172 +++++++++++++++++----------- 3 files changed, 233 insertions(+), 169 deletions(-) (limited to 'src') 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; -- cgit v1.2.1