summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--dist/changes-5.12.1028
-rw-r--r--dist/changes-5.15.225
-rw-r--r--src/plugins/canbus/socketcan/libsocketcan.cpp10
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp2
-rw-r--r--src/serialbus/qcanbusdevice.cpp2
-rw-r--r--src/serialbus/qcanbusdeviceinfo.h2
-rw-r--r--src/serialbus/qmodbusclient.cpp12
-rw-r--r--src/serialbus/qmodbusdevice.cpp7
-rw-r--r--src/serialbus/qmodbuspdu.cpp124
-rw-r--r--src/serialbus/qmodbuspdu.h2
-rw-r--r--src/serialbus/qmodbusreply.cpp10
-rw-r--r--tests/auto/qmodbusreply/tst_qmodbusreply.cpp2
13 files changed, 166 insertions, 62 deletions
diff --git a/.qmake.conf b/.qmake.conf
index d07755f..3edcad8 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
CONFIG += warning_clean
DEFINES += QT_NO_FOREACH
-MODULE_VERSION = 5.15.1
+MODULE_VERSION = 5.15.13
diff --git a/dist/changes-5.12.10 b/dist/changes-5.12.10
new file mode 100644
index 0000000..c9b97b2
--- /dev/null
+++ b/dist/changes-5.12.10
@@ -0,0 +1,28 @@
+Qt 5.12.10 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.9.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+ https://doc.qt.io/qt-5.12/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+ https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Important Behavior Changes *
+****************************************************************************
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+
diff --git a/dist/changes-5.15.2 b/dist/changes-5.15.2
new file mode 100644
index 0000000..dbef3fc
--- /dev/null
+++ b/dist/changes-5.15.2
@@ -0,0 +1,25 @@
+Qt 5.15.2 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.15.1.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+ https://doc.qt.io/qt-5.15/index.html
+
+The Qt version 5.15 series is binary compatible with the 5.14.x series.
+Applications compiled for 5.14 will continue to run with 5.15.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+ https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* SocketCAN *
+****************************************************************************
+
+ - [QTBUG-87328] Fixed that libsocketcan could not be loaded when no
+ symlink libsocketcan.so -> libsocketcan.so.2 was present.
diff --git a/src/plugins/canbus/socketcan/libsocketcan.cpp b/src/plugins/canbus/socketcan/libsocketcan.cpp
index c6144db..acc29c7 100644
--- a/src/plugins/canbus/socketcan/libsocketcan.cpp
+++ b/src/plugins/canbus/socketcan/libsocketcan.cpp
@@ -87,10 +87,14 @@ LibSocketCan::LibSocketCan(QString *errorString)
{
#if QT_CONFIG(library)
auto resolveSymbols = [](QLibrary *library) {
+ const QString libName = QStringLiteral("socketcan");
if (!library->isLoaded()) {
- library->setFileName(QStringLiteral("socketcan"));
- if (!library->load())
- return false;
+ library->setFileName(libName);
+ if (!library->load()) {
+ library->setFileNameAndVersion(libName, 2);
+ if (!library->load())
+ return false;
+ }
}
RESOLVE_SYMBOL(can_do_start);
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index 572fef8..fe22494 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -349,7 +349,7 @@ bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &valu
case QCanBusDevice::BitRateKey:
{
const quint32 bitRate = value.toUInt();
- libSocketCan->setBitrate(canSocketName, bitRate);
+ success = libSocketCan->setBitrate(canSocketName, bitRate);
break;
}
default:
diff --git a/src/serialbus/qcanbusdevice.cpp b/src/serialbus/qcanbusdevice.cpp
index 5b6c343..7cf0c7e 100644
--- a/src/serialbus/qcanbusdevice.cpp
+++ b/src/serialbus/qcanbusdevice.cpp
@@ -606,7 +606,7 @@ void QCanBusDevice::clear(QCanBusDevice::Directions direction)
clearError();
if (direction & Direction::Input) {
- QMutexLocker(&d->incomingFramesGuard);
+ QMutexLocker locker(&d->incomingFramesGuard);
d->incomingFrames.clear();
}
diff --git a/src/serialbus/qcanbusdeviceinfo.h b/src/serialbus/qcanbusdeviceinfo.h
index c46302d..ee8d7ae 100644
--- a/src/serialbus/qcanbusdeviceinfo.h
+++ b/src/serialbus/qcanbusdeviceinfo.h
@@ -54,7 +54,7 @@ public:
void swap(QCanBusDeviceInfo &other) Q_DECL_NOTHROW
{
- qSwap(d_ptr, other.d_ptr);
+ d_ptr.swap(other.d_ptr);
}
QCanBusDeviceInfo &operator=(const QCanBusDeviceInfo &other);
diff --git a/src/serialbus/qmodbusclient.cpp b/src/serialbus/qmodbusclient.cpp
index 56a1ab5..a5e3888 100644
--- a/src/serialbus/qmodbusclient.cpp
+++ b/src/serialbus/qmodbusclient.cpp
@@ -222,8 +222,12 @@ QModbusClient::QModbusClient(QModbusClientPrivate &dd, QObject *parent) :
}
/*!
- Processes a Modbus server \a response and stores the decoded information in \a data. Returns
- true on success; otherwise false.
+ Processes a Modbus server \a response and stores the decoded information in
+ \a data. Returns \c true on success; otherwise \c false.
+
+ \note The default implementation does not support all
+ \l {QModbusPdu::}{FunctionCode}s. Override this method in a custom Modbus
+ client implementations to handle the needed functions.
*/
bool QModbusClient::processResponse(const QModbusResponse &response, QModbusDataUnit *data)
{
@@ -361,13 +365,13 @@ void QModbusClientPrivate::processQueueElement(const QModbusResponse &pdu,
return;
}
- if (element.reply->type() != QModbusReply::Common) {
+ if (element.reply->type() == QModbusReply::Broadcast) {
element.reply->setFinished(true);
return;
}
QModbusDataUnit unit = element.unit;
- if (!processResponse(pdu, &unit)) {
+ if (!q_func()->processResponse(pdu, &unit)) {
element.reply->setError(QModbusDevice::UnknownError,
QModbusClient::tr("An invalid response has been received."));
return;
diff --git a/src/serialbus/qmodbusdevice.cpp b/src/serialbus/qmodbusdevice.cpp
index ab8e126..58bdc6d 100644
--- a/src/serialbus/qmodbusdevice.cpp
+++ b/src/serialbus/qmodbusdevice.cpp
@@ -204,6 +204,13 @@ void QModbusDevice::setConnectionParameter(int parameter, const QVariant &value)
\value ReplyAbortedError The reply was aborted due to a disconnection of
the device.
\value UnknownError An unknown error occurred.
+
+ \note An UnknownError can also indicate that the received
+ \l {QModbusPdu::}{FunctionCode} is not supported in the current
+ implementation. In this case custom Modbus client implementations need to
+ override the \l {QModbusClient::}{processResponse()} and
+ \l {QModbusClient::}{processPrivateResponse()} methods to provide support
+ for needed functions.
*/
/*!
diff --git a/src/serialbus/qmodbuspdu.cpp b/src/serialbus/qmodbuspdu.cpp
index 9ca9027..e23fa7b 100644
--- a/src/serialbus/qmodbuspdu.cpp
+++ b/src/serialbus/qmodbuspdu.cpp
@@ -48,13 +48,23 @@ Q_GLOBAL_STATIC(ReqSizeCalc, requestSizeCalculators);
using ResSizeCalc = QHash<quint8, QModbusResponse::CalcFuncPtr>;
Q_GLOBAL_STATIC(ResSizeCalc, responseSizeCalculators);
-namespace Private {
+struct QModbusPduPrivate
+{
+ QModbusPduPrivate() = delete;
+ Q_DISABLE_COPY_MOVE(QModbusPduPrivate)
enum struct Type {
Request,
Response
};
+/*!
+ \internal
+
+ Returns the minimum data size in bytes for the given \a pdu and the
+ Modbus PDU \a type. If the PDU's function code is invalid, undefined
+ or unknown, the return value will be \c {-1}.
+*/
static int minimumDataSize(const QModbusPdu &pdu, Type type)
{
if (pdu.isException())
@@ -103,44 +113,54 @@ static int minimumDataSize(const QModbusPdu &pdu, Type type)
return -1;
}
-static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type type)
+/*!
+ \internal
+
+ Extracts a Modbus PDU from a \a stream into the given \a pdu based on \a type.
+*/
+static QDataStream &pduFromStream(QDataStream &stream, Type type, QModbusPdu *pdu)
{
- quint8 codeByte = 0;
- if (stream.readRawData(reinterpret_cast<char *>(&codeByte), sizeof(quint8)) != sizeof(quint8))
+ struct RAII {
+ RAII(QModbusPdu *ptr = nullptr)
+ : tmp(ptr) {}
+ QModbusPdu *tmp{ nullptr };
+ ~RAII() { if (tmp) *tmp = {}; }
+ } raii = { pdu };
+
+ QModbusPdu::FunctionCode code = QModbusPdu::FunctionCode::Invalid;
+ stream >> code;
+ if (stream.status() == QDataStream::ReadPastEnd)
return stream;
- QModbusPdu::FunctionCode code = QModbusPdu::FunctionCode(codeByte);
- pdu.setFunctionCode(code);
-
- auto needsAdditionalRead = [](QModbusPdu &pdu, int size) -> bool {
- if (size < 0)
- pdu.setFunctionCode(QModbusResponse::Invalid);
- if (size <= 0)
- return false;
- return true;
- };
+ pdu->setFunctionCode(code);
- const bool isResponse = (type == Type::Response);
- int size = isResponse ? QModbusResponse::minimumDataSize(pdu)
- : QModbusRequest::minimumDataSize(pdu);
- if (!needsAdditionalRead(pdu, size))
+ if (code == QModbusPdu::Invalid) // shortcut
return stream;
- QByteArray data(size, Qt::Uninitialized);
- if (stream.device()->peek(data.data(), data.size()) != size)
- return stream;
+ constexpr const int MaxPduDataSize = 252; // in bytes
- pdu.setData(data);
- size = isResponse ? QModbusResponse::calculateDataSize(pdu)
- : QModbusRequest::calculateDataSize(pdu);
- if (!needsAdditionalRead(pdu, size))
+ // The calculateDataSize(...) function might need some data inside the
+ // given PDU argument to be able to figure out the right data size (e.g.
+ // WriteMultipleCoils contains some kind of "header"). So fake fill the PDU
+ // with the maximum available data but no more than the allowed max PDU
+ // data size.
+ QByteArray data(MaxPduDataSize, Qt::Uninitialized);
+ int read = stream.device()->peek(data.data(), MaxPduDataSize);
+ if (read < 0)
return stream;
+ data.resize(read);
+ pdu->setData(data);
+
+ const bool isResponse = (type == Type::Response);
+ int size = isResponse ? QModbusResponse::calculateDataSize(*pdu)
+ : QModbusRequest::calculateDataSize(*pdu);
+
if (isResponse && (code == QModbusPdu::EncapsulatedInterfaceTransport)) {
quint8 meiType;
- pdu.decodeData(&meiType);
+ pdu->decodeData(&meiType);
if (meiType == EncapsulatedInterfaceTransport::ReadDeviceIdentification) {
int left = size, offset = 0;
- while ((left > 0) && (size <= 252)) { // The maximum PDU data size is 252 bytes.
+ while ((left > 0) && (size <= MaxPduDataSize)) {
data.resize(size);
const int read = stream.readRawData(data.data() + offset, size - offset);
if ((read < 0) || (read != (size - offset))) {
@@ -152,35 +172,31 @@ static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type typ
left = QModbusResponse::calculateDataSize(QModbusResponse(code, data)) - offset;
size += left;
}
- if ((stream.status() == QDataStream::Ok) && (size <= 252)) {
- pdu.setData(data);
+ if ((stream.status() == QDataStream::Ok) && (size <= MaxPduDataSize)) {
+ raii = {};
+ pdu->setData(data);
return stream; // early return to avoid second read
}
} else {
data.resize(int(stream.device()->size() - 1)); // One byte for the function code.
}
- } else if (pdu.functionCode() == QModbusPdu::Diagnostics) {
+ } else if (pdu->functionCode() == QModbusPdu::Diagnostics) {
quint16 subCode;
- pdu.decodeData(&subCode);
+ pdu->decodeData(&subCode);
if (subCode == Diagnostics::ReturnQueryData)
data.resize(int(stream.device()->size() - 1)); // One byte for the function code.
}
- // reset what we have so far, next read might fail as well
- pdu.setData(QByteArray());
- pdu.setFunctionCode(QModbusPdu::Invalid);
-
- if (data.size() <= 252) { // The maximum PDU data size is 252 bytes.
+ if (data.size() <= MaxPduDataSize) {
data.resize(size);
if (stream.readRawData(data.data(), data.size()) == size) {
- pdu.setData(data);
- pdu.setFunctionCode(code);
+ raii = {};
+ pdu->setData(data);
}
}
return stream;
}
-
-} // namespace Private
+};
/*!
\class QModbusPdu
@@ -533,7 +549,7 @@ QDataStream &operator<<(QDataStream &stream, const QModbusPdu &pdu)
*/
int QModbusRequest::minimumDataSize(const QModbusRequest &request)
{
- return Private::minimumDataSize(request, Private::Type::Request);
+ return QModbusPduPrivate::minimumDataSize(request, QModbusPduPrivate::Type::Request);
}
/*!
@@ -555,7 +571,7 @@ int QModbusRequest::calculateDataSize(const QModbusRequest &request)
return 1;
int size = -1;
- int minimum = Private::minimumDataSize(request, Private::Type::Request);
+ int minimum = QModbusPduPrivate::minimumDataSize(request, QModbusPduPrivate::Type::Request);
if (minimum < 0)
return size;
@@ -608,6 +624,22 @@ void QModbusRequest::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr cal
}
/*!
+ \internal
+
+ Reads a FunctionCode from a \a stream.
+ In stream we serialize FunctionCode as one byte, so we use a temporary char
+ variable to make the code work on both little endian and big endian systems.
+ If reading from stream fails, code will retain original value.
+*/
+QDataStream &operator>>(QDataStream &stream, QModbusPdu::FunctionCode &code)
+{
+ char buffer;
+ if (stream.readRawData(&buffer, 1) == 1)
+ code = static_cast<QModbusPdu::FunctionCode>(buffer);
+ return stream;
+}
+
+/*!
\relates QModbusRequest
Reads a \a pdu from the \a stream and returns a reference to the stream.
@@ -620,7 +652,7 @@ void QModbusRequest::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr cal
*/
QDataStream &operator>>(QDataStream &stream, QModbusRequest &pdu)
{
- return Private::pduFromStream(stream, pdu, Private::Type::Request);
+ return QModbusPduPrivate::pduFromStream(stream, QModbusPduPrivate::Type::Request, &pdu);
}
/*!
@@ -689,7 +721,7 @@ QDataStream &operator>>(QDataStream &stream, QModbusRequest &pdu)
*/
int QModbusResponse::minimumDataSize(const QModbusResponse &response)
{
- return Private::minimumDataSize(response, Private::Type::Response);
+ return QModbusPduPrivate::minimumDataSize(response, QModbusPduPrivate::Type::Response);
}
/*!
@@ -711,7 +743,7 @@ int QModbusResponse::calculateDataSize(const QModbusResponse &response)
return 1;
int size = -1;
- int minimum = Private::minimumDataSize(response, Private::Type::Response);
+ int minimum = QModbusPduPrivate::minimumDataSize(response, QModbusPduPrivate::Type::Response);
if (minimum < 0)
return size;
@@ -806,7 +838,7 @@ void QModbusResponse::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr ca
*/
QDataStream &operator>>(QDataStream &stream, QModbusResponse &pdu)
{
- return Private::pduFromStream(stream, pdu, Private::Type::Response);
+ return QModbusPduPrivate::pduFromStream(stream, QModbusPduPrivate::Type::Response, &pdu);
}
/*!
diff --git a/src/serialbus/qmodbuspdu.h b/src/serialbus/qmodbuspdu.h
index e93ec4c..5bca0d3 100644
--- a/src/serialbus/qmodbuspdu.h
+++ b/src/serialbus/qmodbuspdu.h
@@ -183,9 +183,11 @@ private:
FunctionCode m_code = Invalid;
QByteArray m_data;
friend class QModbusSerialAdu;
+ friend struct QModbusPduPrivate;
};
Q_SERIALBUS_EXPORT QDebug operator<<(QDebug debug, const QModbusPdu &pdu);
Q_SERIALBUS_EXPORT QDataStream &operator<<(QDataStream &stream, const QModbusPdu &pdu);
+Q_SERIALBUS_EXPORT QDataStream &operator>>(QDataStream &stream, QModbusPdu::FunctionCode &code);
class QModbusRequest : public QModbusPdu
{
diff --git a/src/serialbus/qmodbusreply.cpp b/src/serialbus/qmodbusreply.cpp
index caa2dd9..374fb81 100644
--- a/src/serialbus/qmodbusreply.cpp
+++ b/src/serialbus/qmodbusreply.cpp
@@ -147,15 +147,17 @@ void QModbusReply::setFinished(bool isFinished)
If the request has not finished, has failed with an error or was a write
request then the returned \l QModbusDataUnit instance is invalid.
- \note If the \l type() of the reply is \l QModbusReply::Raw, the return
- value will always be invalid.
+ \note If the \l type() of the reply is \l QModbusReply::Broadcast, the
+ return value will always be invalid. If the l type() of the reply is
+ \l QModbusReply::Raw, the return value might be invalid depending on the
+ implementation of \l QModbusClient::processPrivateResponse().
- \sa type(), rawResult()
+ \sa type(), rawResult(), QModbusClient::processPrivateResponse()
*/
QModbusDataUnit QModbusReply::result() const
{
Q_D(const QModbusReply);
- if (type() == QModbusReply::Common)
+ if (type() != QModbusReply::Broadcast)
return d->m_unit;
return QModbusDataUnit();
}
diff --git a/tests/auto/qmodbusreply/tst_qmodbusreply.cpp b/tests/auto/qmodbusreply/tst_qmodbusreply.cpp
index 810fbee..3ac0395 100644
--- a/tests/auto/qmodbusreply/tst_qmodbusreply.cpp
+++ b/tests/auto/qmodbusreply/tst_qmodbusreply.cpp
@@ -213,7 +213,7 @@ void tst_QModbusReply::tst_setResult()
replyRawTest.setRawResult(response);
QCOMPARE(finishedSpy.count(), 0);
QCOMPARE(errorSpyRaw.count(), 0);
- QCOMPARE(replyRawTest.result().isValid(), false);
+ QCOMPARE(replyRawTest.result().isValid(), true);
QCOMPARE(replyRawTest.rawResult().isValid(), true);
tmp = replyRawTest.rawResult();