summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/serialbus/can/mainwindow.cpp33
-rw-r--r--examples/serialbus/can/mainwindow.h2
-rw-r--r--examples/serialbus/can/mainwindow.ui19
-rw-r--r--examples/serialbus/modbus/adueditor/adueditor.pro16
-rw-r--r--examples/serialbus/modbus/adueditor/mainwindow.cpp47
-rw-r--r--examples/serialbus/modbus/adueditor/modbustcpclient_p.h25
-rw-r--r--examples/serialbus/modbus/adueditor/plaintextedit.h6
-rw-r--r--examples/serialbus/modbus/master/main.cpp5
-rw-r--r--examples/serialbus/modbus/master/mainwindow.cpp74
-rw-r--r--examples/serialbus/modbus/master/mainwindow.h26
-rw-r--r--examples/serialbus/modbus/master/master.pro21
-rw-r--r--examples/serialbus/modbus/master/settingsdialog.h2
-rw-r--r--examples/serialbus/modbus/master/writeregistermodel.cpp6
-rw-r--r--examples/serialbus/modbus/master/writeregistermodel.h4
-rw-r--r--examples/serialbus/modbus/slave/main.cpp5
-rw-r--r--examples/serialbus/modbus/slave/mainwindow.cpp47
-rw-r--r--examples/serialbus/modbus/slave/mainwindow.h10
-rw-r--r--examples/serialbus/modbus/slave/slave.pro15
-rw-r--r--src/plugins/canbus/peakcan/peakcan_symbols_p.h51
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend.cpp99
-rw-r--r--src/plugins/canbus/peakcan/peakcanbackend.h3
-rw-r--r--src/plugins/canbus/socketcan/libsocketcan.cpp238
-rw-r--r--src/plugins/canbus/socketcan/libsocketcan.h76
-rw-r--r--src/plugins/canbus/socketcan/socketcan.pro2
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.cpp57
-rw-r--r--src/plugins/canbus/socketcan/socketcanbackend.h9
-rw-r--r--src/plugins/canbus/systeccan/systeccan_symbols_p.h27
-rw-r--r--src/plugins/canbus/systeccan/systeccanbackend.cpp61
-rw-r--r--src/plugins/canbus/systeccan/systeccanbackend.h3
-rw-r--r--src/plugins/canbus/systeccan/systeccanbackend_p.h2
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend.cpp30
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend.h2
-rw-r--r--src/plugins/canbus/tinycan/tinycanbackend_p.h1
-rw-r--r--src/plugins/canbus/vectorcan/vectorcan_symbols_p.h20
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.cpp56
-rw-r--r--src/plugins/canbus/vectorcan/vectorcanbackend.h2
-rw-r--r--src/serialbus/doc/src/peakcan.qdoc15
-rw-r--r--src/serialbus/doc/src/socketcan.qdoc24
-rw-r--r--src/serialbus/doc/src/systeccan.qdoc8
-rw-r--r--src/serialbus/doc/src/tinycan.qdoc9
-rw-r--r--src/serialbus/doc/src/vectorcan.qdoc7
-rw-r--r--src/serialbus/qcanbusdevice.cpp246
-rw-r--r--src/serialbus/qcanbusdevice.h35
-rw-r--r--src/serialbus/qcanbusdevice_p.h3
-rw-r--r--src/serialbus/qmodbusdevice.cpp22
-rw-r--r--src/serialbus/qmodbusdevice.h4
-rw-r--r--src/serialbus/qmodbusdevice_p.h4
-rw-r--r--src/serialbus/qmodbuspdu.cpp20
-rw-r--r--src/serialbus/qmodbuspdu.h2
-rw-r--r--src/serialbus/qmodbusrtuserialmaster_p.h4
-rw-r--r--src/serialbus/qmodbusrtuserialslave_p.h5
-rw-r--r--src/serialbus/qmodbustcpclient_p.h19
-rw-r--r--src/serialbus/qmodbustcpserver_p.h4
-rw-r--r--src/tools/canbusutil/canbusutil.cpp36
-rw-r--r--src/tools/canbusutil/canbusutil.h2
-rw-r--r--src/tools/canbusutil/main.cpp11
-rw-r--r--src/tools/canbusutil/readtask.cpp20
-rw-r--r--src/tools/canbusutil/readtask.h6
-rw-r--r--src/tools/canbusutil/sigtermhandler.cpp2
-rw-r--r--tests/auto/qcanbusdevice/tst_qcanbusdevice.cpp215
61 files changed, 1490 insertions, 337 deletions
diff --git a/.qmake.conf b/.qmake.conf
index c29327d..a8a7769 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.13.1
+MODULE_VERSION = 5.14.0
diff --git a/examples/serialbus/can/mainwindow.cpp b/examples/serialbus/can/mainwindow.cpp
index 300bbde..29c5f1f 100644
--- a/examples/serialbus/can/mainwindow.cpp
+++ b/examples/serialbus/can/mainwindow.cpp
@@ -60,7 +60,8 @@
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
- m_ui(new Ui::MainWindow)
+ m_ui(new Ui::MainWindow),
+ m_busStatusTimer(new QTimer(this))
{
m_ui->setupUi(this);
@@ -93,6 +94,9 @@ void MainWindow::initActionsConnections()
connect(m_ui->actionConnect, &QAction::triggered, m_connectDialog, &ConnectDialog::show);
connect(m_connectDialog, &QDialog::accepted, this, &MainWindow::connectDevice);
connect(m_ui->actionDisconnect, &QAction::triggered, this, &MainWindow::disconnectDevice);
+ connect(m_ui->actionResetController, &QAction::triggered, this, [this]() {
+ m_canDevice->resetController();
+ });
connect(m_ui->actionQuit, &QAction::triggered, this, &QWidget::close);
connect(m_ui->actionAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt);
connect(m_ui->actionClearLog, &QAction::triggered, m_ui->receivedMessagesEdit, &QTextEdit::clear);
@@ -171,6 +175,31 @@ void MainWindow::connectDevice()
.arg(p.pluginName).arg(p.deviceInterfaceName));
}
}
+
+ connect(m_busStatusTimer, &QTimer::timeout, this, [this]() {
+ switch (m_canDevice->busStatus()) {
+ case QCanBusDevice::CanBusStatus::Good:
+ m_ui->busStatus->setText("CAN bus status: Good.");
+ break;
+ case QCanBusDevice::CanBusStatus::Warning:
+ m_ui->busStatus->setText("CAN bus status: Warning.");
+ break;
+ case QCanBusDevice::CanBusStatus::Error:
+ m_ui->busStatus->setText("CAN bus status: Error.");
+ break;
+ case QCanBusDevice::CanBusStatus::BusOff:
+ m_ui->busStatus->setText("CAN bus status: Bus Off.");
+ break;
+ default:
+ m_ui->busStatus->setText("CAN bus status: Unknown.");
+ break;
+ }
+ });
+
+ if (m_canDevice->hasBusStatus())
+ m_busStatusTimer->start(2000);
+ else
+ m_ui->busStatus->setText(tr("No CAN bus status available."));
}
void MainWindow::disconnectDevice()
@@ -178,6 +207,8 @@ void MainWindow::disconnectDevice()
if (!m_canDevice)
return;
+ m_busStatusTimer->stop();
+
m_canDevice->disconnectDevice();
delete m_canDevice;
m_canDevice = nullptr;
diff --git a/examples/serialbus/can/mainwindow.h b/examples/serialbus/can/mainwindow.h
index 40b2e4a..673e87a 100644
--- a/examples/serialbus/can/mainwindow.h
+++ b/examples/serialbus/can/mainwindow.h
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
class QCanBusFrame;
class QLabel;
+class QTimer;
namespace Ui {
class MainWindow;
@@ -96,6 +97,7 @@ private:
QLabel *m_written = nullptr;
ConnectDialog *m_connectDialog = nullptr;
QCanBusDevice *m_canDevice = nullptr;
+ QTimer *m_busStatusTimer = nullptr;
};
#endif // MAINWINDOW_H
diff --git a/examples/serialbus/can/mainwindow.ui b/examples/serialbus/can/mainwindow.ui
index 1d5a657..f773ffb 100644
--- a/examples/serialbus/can/mainwindow.ui
+++ b/examples/serialbus/can/mainwindow.ui
@@ -66,6 +66,13 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QLabel" name="busStatus">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
@@ -77,7 +84,7 @@
<x>0</x>
<y>0</y>
<width>551</width>
- <height>19</height>
+ <height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuCalls">
@@ -87,6 +94,8 @@
<addaction name="actionConnect"/>
<addaction name="actionDisconnect"/>
<addaction name="separator"/>
+ <addaction name="actionResetController"/>
+ <addaction name="separator"/>
<addaction name="actionClearLog"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
@@ -163,6 +172,14 @@
<string>Open plugin documentation in Webbrowser</string>
</property>
</action>
+ <action name="actionResetController">
+ <property name="text">
+ <string>&amp;Reset CAN Controller</string>
+ </property>
+ <property name="toolTip">
+ <string>Reset CAN Controller</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
diff --git a/examples/serialbus/modbus/adueditor/adueditor.pro b/examples/serialbus/modbus/adueditor/adueditor.pro
index facba76..77a6158 100644
--- a/examples/serialbus/modbus/adueditor/adueditor.pro
+++ b/examples/serialbus/modbus/adueditor/adueditor.pro
@@ -7,9 +7,19 @@ QT += serialbus-private core-private
requires(qtConfig(combobox))
requires(qtConfig(modbus-serialport))
-FORMS += interface.ui
-SOURCES += main.cpp mainwindow.cpp modbustcpclient.cpp
-HEADERS += mainwindow.h plaintextedit.h modbustcpclient.h modbustcpclient_p.h
+SOURCES += \
+ main.cpp \
+ mainwindow.cpp \
+ modbustcpclient.cpp
+
+HEADERS += \
+ mainwindow.h \
+ modbustcpclient.h \
+ modbustcpclient_p.h \
+ plaintextedit.h
+
+FORMS += \
+ interface.ui
target.path = $$[QT_INSTALL_EXAMPLES]/serialbus/modbus/adueditor
INSTALLS += target
diff --git a/examples/serialbus/modbus/adueditor/mainwindow.cpp b/examples/serialbus/modbus/adueditor/mainwindow.cpp
index 862be6a..4a0931e 100644
--- a/examples/serialbus/modbus/adueditor/mainwindow.cpp
+++ b/examples/serialbus/modbus/adueditor/mainwindow.cpp
@@ -52,8 +52,8 @@
#include "modbustcpclient.h"
#include <QLoggingCategory>
-#include <QModbusRtuSerialMaster>
#include <QModbusPdu>
+#include <QModbusRtuSerialMaster>
#include <QSerialPortInfo>
#ifndef QT_STATIC
@@ -84,7 +84,7 @@ MainWindow::MainWindow(QWidget *parent)
for (const QSerialPortInfo &info : ports)
serialPortCombo->addItem(info.portName(), false);
serialPortCombo->insertSeparator(serialPortCombo->count());
- serialPortCombo->addItem(QStringLiteral("Add port..."), true);
+ serialPortCombo->addItem(tr("Add port..."), true);
serialPortCombo->setInsertPolicy(QComboBox::InsertAtTop);
connect(tcpRadio, &QRadioButton::toggled, this, [this](bool toggled) {
@@ -119,14 +119,14 @@ void MainWindow::on_sendButton_clicked()
return;
}
- const quint8 address = (isSerial ? addressSpin : ui1Spin)->value();
+ const quint8 address = quint8((isSerial ? addressSpin : ui1Spin)->value());
if (isCustom) {
qDebug() << "Send: Sending custom PDU.";
reply = m_device->sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode(
pduData[0]), pduData.mid(1)), address);
} else {
qDebug() << "Send: Sending PDU with predefined function code.";
- quint16 fc = (isSerial ? fcSerialDrop : fcTcpDrop)->currentText().left(4).toShort(0, 16);
+ quint16 fc = (isSerial ? fcSerialDrop : fcTcpDrop)->currentText().left(4).toUShort(0, 16);
reply = m_device->sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode(fc), pduData),
address);
}
@@ -136,11 +136,11 @@ void MainWindow::on_sendButton_clicked()
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, [reply, this]() {
sendButton->setEnabled(true);
- qDebug() << "Receive: Asynchronous response PDU: " << reply->rawResult() << endl;
+ qDebug() << "Receive: Asynchronous response PDU: " << reply->rawResult() << Qt::endl;
});
} else {
sendButton->setEnabled(true);
- qDebug() << "Receive: Synchronous response pdu: " << reply->rawResult() << endl;
+ qDebug() << "Receive: Synchronous response pdu: " << reply->rawResult() << Qt::endl;
}
}
}
@@ -149,24 +149,23 @@ void MainWindow::on_connectButton_clicked()
{
if (tcpRadio->isChecked()) {
auto device = new ModbusTcpClient;
- using signature = void (QSpinBox::*)(int);
- connect(ti1Spin, static_cast<signature>(&QSpinBox::valueChanged), device,
- &ModbusTcpClient::valueChanged);
- connect(ti2Spin, static_cast<signature>(&QSpinBox::valueChanged), device,
- &ModbusTcpClient::valueChanged);
-
- connect(pi1Spin, static_cast<signature>(&QSpinBox::valueChanged), device,
- &ModbusTcpClient::valueChanged);
- connect(pi2Spin, static_cast<signature>(&QSpinBox::valueChanged), device,
- &ModbusTcpClient::valueChanged);
-
- connect(l1Spin, static_cast<signature>(&QSpinBox::valueChanged), device,
- &ModbusTcpClient::valueChanged);
- connect(l2Spin, static_cast<signature>(&QSpinBox::valueChanged), device,
- &ModbusTcpClient::valueChanged);
-
- connect(ui1Spin, static_cast<signature>(&QSpinBox::valueChanged), device,
- &ModbusTcpClient::valueChanged);
+ connect(ti1Spin, QOverload<int>::of(&QSpinBox::valueChanged),
+ device, &ModbusTcpClient::valueChanged);
+ connect(ti2Spin, QOverload<int>::of(&QSpinBox::valueChanged),
+ device, &ModbusTcpClient::valueChanged);
+
+ connect(pi1Spin, QOverload<int>::of(&QSpinBox::valueChanged),
+ device, &ModbusTcpClient::valueChanged);
+ connect(pi2Spin, QOverload<int>::of(&QSpinBox::valueChanged),
+ device, &ModbusTcpClient::valueChanged);
+
+ connect(l1Spin, QOverload<int>::of(&QSpinBox::valueChanged),
+ device, &ModbusTcpClient::valueChanged);
+ connect(l2Spin, QOverload<int>::of(&QSpinBox::valueChanged),
+ device, &ModbusTcpClient::valueChanged);
+
+ connect(ui1Spin, QOverload<int>::of(&QSpinBox::valueChanged),
+ device, &ModbusTcpClient::valueChanged);
m_device = device;
device->valueChanged(0); // trigger update
diff --git a/examples/serialbus/modbus/adueditor/modbustcpclient_p.h b/examples/serialbus/modbus/adueditor/modbustcpclient_p.h
index c1b37a8..a9170f9 100644
--- a/examples/serialbus/modbus/adueditor/modbustcpclient_p.h
+++ b/examples/serialbus/modbus/adueditor/modbustcpclient_p.h
@@ -73,7 +73,7 @@ public:
QDataStream output(&buffer, QIODevice::WriteOnly);
output << m_tId << m_pId << m_length << m_uId << request;
- int writtenBytes = m_socket->write(buffer);
+ qint64 writtenBytes = m_socket->write(buffer);
if (writtenBytes == -1 || writtenBytes < buffer.size()) {
Q_Q(ModbusTcpClient);
qDebug() << "Cannot write request to socket.";
@@ -82,7 +82,7 @@ public:
return false;
}
qDebug() << "Sent TCP ADU:" << buffer.toHex();
- qDebug() << "Sent TCP PDU:" << request << "with tId:" << hex << m_tId;
+ qDebug() << "Sent TCP PDU:" << request << "with tId:" << Qt::hex << m_tId;
return true;
};
@@ -91,13 +91,12 @@ public:
Q_Q(ModbusTcpClient);
auto reply = new QModbusReply(type, m_uId, q);
- const auto element = QueueElement{ reply, request, unit, m_numberOfRetries,
- m_responseTimeoutDuration };
+ const auto element = QueueElement{reply, request, unit, m_numberOfRetries,
+ m_responseTimeoutDuration};
m_transactionStore.insert(m_tId, element);
- using TypeId = void (QTimer::*)(int);
q->connect(q, &QModbusClient::timeoutChanged,
- element.timer.data(), static_cast<TypeId>(&QTimer::setInterval));
+ element.timer.data(), QOverload<int>::of(&QTimer::setInterval));
QObject::connect(element.timer.data(), &QTimer::timeout, q, [this, writeToSocket]() {
if (!m_transactionStore.contains(m_tId))
return;
@@ -112,21 +111,21 @@ public:
return;
m_transactionStore.insert(m_tId, elem);
elem.timer->start();
- qDebug() << "Resend request with tId:" << hex << m_tId;
+ qDebug() << "Resend request with tId:" << Qt::hex << m_tId;
} else {
- qDebug() << "Timeout of request with tId:" << hex << m_tId;
+ qDebug() << "Timeout of request with tId:" << Qt::hex << m_tId;
elem.reply->setError(QModbusDevice::TimeoutError,
QModbusClient::tr("Request timeout."));
}
});
element.timer->start();
- return reply;
+ return reply;
}
- quint16 m_tId;
- quint16 m_pId;
- quint16 m_length;
- quint8 m_uId;
+ quint16 m_tId = 0;
+ quint16 m_pId = 0;
+ quint16 m_length = 0;
+ quint8 m_uId = 0;
};
#endif // MODBUSTCPCLIENT_P_H
diff --git a/examples/serialbus/modbus/adueditor/plaintextedit.h b/examples/serialbus/modbus/adueditor/plaintextedit.h
index 3cbbaaf..cbc590c 100644
--- a/examples/serialbus/modbus/adueditor/plaintextedit.h
+++ b/examples/serialbus/modbus/adueditor/plaintextedit.h
@@ -81,12 +81,12 @@ public:
void contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
- menu.addAction(QStringLiteral("Clear"), this, &QPlainTextEdit::clear);
+ menu.addAction(tr("Clear"), this, &QPlainTextEdit::clear);
#ifndef QT_NO_CLIPBOARD
- menu.addAction(QStringLiteral("Copy"), this, &QPlainTextEdit::copy, QKeySequence::Copy);
+ menu.addAction(tr("Copy"), this, &QPlainTextEdit::copy, QKeySequence::Copy);
#endif
menu.addSeparator();
- menu.addAction(QStringLiteral("Select All"), this, &QPlainTextEdit::selectAll,
+ menu.addAction(tr("Select All"), this, &QPlainTextEdit::selectAll,
QKeySequence::SelectAll);
menu.exec(event->globalPos());
}
diff --git a/examples/serialbus/modbus/master/main.cpp b/examples/serialbus/modbus/master/main.cpp
index 4f97a39..19a1d5b 100644
--- a/examples/serialbus/modbus/master/main.cpp
+++ b/examples/serialbus/modbus/master/main.cpp
@@ -55,9 +55,8 @@
int main(int argc, char *argv[])
{
- // TODO uncomment this line before release
- // right now we always need it
- QLoggingCategory::setFilterRules(QStringLiteral("qt.modbus* = true"));
+ // Uncomment the following line to enable logging
+ // QLoggingCategory::setFilterRules(QStringLiteral("qt.modbus* = true"));
QApplication a(argc, argv);
MainWindow w;
w.show();
diff --git a/examples/serialbus/modbus/master/mainwindow.cpp b/examples/serialbus/modbus/master/mainwindow.cpp
index 6600af8..d88393b 100644
--- a/examples/serialbus/modbus/master/mainwindow.cpp
+++ b/examples/serialbus/modbus/master/mainwindow.cpp
@@ -67,8 +67,6 @@ enum ModbusConnection {
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
- , lastRequest(nullptr)
- , modbusDevice(nullptr)
{
ui->setupUi(this);
@@ -82,8 +80,8 @@ MainWindow::MainWindow(QWidget *parent)
ui->writeValueTable->setModel(writeModel);
ui->writeValueTable->hideColumn(2);
- connect(writeModel, &WriteRegisterModel::updateViewport, ui->writeValueTable->viewport(),
- static_cast<void (QWidget::*)()>(&QWidget::update));
+ connect(writeModel, &WriteRegisterModel::updateViewport,
+ ui->writeValueTable->viewport(), QOverload<>::of(&QWidget::update));
ui->writeTable->addItem(tr("Coils"), QModbusDataUnit::Coils);
ui->writeTable->addItem(tr("Discrete Inputs"), QModbusDataUnit::DiscreteInputs);
@@ -92,11 +90,11 @@ MainWindow::MainWindow(QWidget *parent)
#if QT_CONFIG(modbus_serialport)
ui->connectType->setCurrentIndex(0);
- on_connectType_currentIndexChanged(0);
+ onConnectTypeChanged(0);
#else
// lock out the serial port option
ui->connectType->setCurrentIndex(1);
- on_connectType_currentIndexChanged(1);
+ onConnectTypeChanged(1);
ui->connectType->setEnabled(false);
#endif
@@ -105,10 +103,10 @@ MainWindow::MainWindow(QWidget *parent)
model->setItem(i, new QStandardItem(QStringLiteral("%1").arg(i + 1)));
ui->writeSize->setModel(model);
ui->writeSize->setCurrentText("10");
- connect(ui->writeSize,&QComboBox::currentTextChanged, writeModel,
- &WriteRegisterModel::setNumberOfValues);
+ connect(ui->writeSize, &QComboBox::currentTextChanged,
+ writeModel, &WriteRegisterModel::setNumberOfValues);
- auto valueChanged = static_cast<void (QSpinBox::*)(int)> (&QSpinBox::valueChanged);
+ auto valueChanged = QOverload<int>::of(&QSpinBox::valueChanged);
connect(ui->writeAddress, valueChanged, writeModel, &WriteRegisterModel::setStartAddress);
connect(ui->writeAddress, valueChanged, this, [this, model](int i) {
int lastPossibleIndex = 0;
@@ -142,16 +140,28 @@ void MainWindow::initActions()
ui->actionExit->setEnabled(true);
ui->actionOptions->setEnabled(true);
+ connect(ui->connectButton, &QPushButton::clicked,
+ this, &MainWindow::onConnectButtonClicked);
connect(ui->actionConnect, &QAction::triggered,
- this, &MainWindow::on_connectButton_clicked);
+ this, &MainWindow::onConnectButtonClicked);
connect(ui->actionDisconnect, &QAction::triggered,
- this, &MainWindow::on_connectButton_clicked);
+ this, &MainWindow::onConnectButtonClicked);
+ connect(ui->readButton, &QPushButton::clicked,
+ this, &MainWindow::onReadButtonClicked);
+ connect(ui->writeButton, &QPushButton::clicked,
+ this, &MainWindow::onWriteButtonClicked);
+ connect(ui->readWriteButton, &QPushButton::clicked,
+ this, &MainWindow::onReadWriteButtonClicked);
+ connect(ui->connectType, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &MainWindow::onConnectTypeChanged);
+ connect(ui->writeTable, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &MainWindow::onWriteTableChanged);
connect(ui->actionExit, &QAction::triggered, this, &QMainWindow::close);
connect(ui->actionOptions, &QAction::triggered, m_settingsDialog, &QDialog::show);
}
-void MainWindow::on_connectType_currentIndexChanged(int index)
+void MainWindow::onConnectTypeChanged(int index)
{
if (modbusDevice) {
modbusDevice->disconnectDevice();
@@ -159,7 +169,7 @@ void MainWindow::on_connectType_currentIndexChanged(int index)
modbusDevice = nullptr;
}
- auto type = static_cast<ModbusConnection> (index);
+ auto type = static_cast<ModbusConnection>(index);
if (type == Serial) {
#if QT_CONFIG(modbus_serialport)
modbusDevice = new QModbusRtuSerialMaster(this);
@@ -167,7 +177,7 @@ void MainWindow::on_connectType_currentIndexChanged(int index)
} else if (type == Tcp) {
modbusDevice = new QModbusTcpClient(this);
if (ui->portEdit->text().isEmpty())
- ui->portEdit->setText(QLatin1Literal("127.0.0.1:502"));
+ ui->portEdit->setText(QLatin1String("127.0.0.1:502"));
}
connect(modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) {
@@ -182,18 +192,18 @@ void MainWindow::on_connectType_currentIndexChanged(int index)
statusBar()->showMessage(tr("Could not create Modbus client."), 5000);
} else {
connect(modbusDevice, &QModbusClient::stateChanged,
- this, &MainWindow::onStateChanged);
+ this, &MainWindow::onModbusStateChanged);
}
}
-void MainWindow::on_connectButton_clicked()
+void MainWindow::onConnectButtonClicked()
{
if (!modbusDevice)
return;
statusBar()->clearMessage();
if (modbusDevice->state() != QModbusDevice::ConnectedState) {
- if (static_cast<ModbusConnection> (ui->connectType->currentIndex()) == Serial) {
+ if (static_cast<ModbusConnection>(ui->connectType->currentIndex()) == Serial) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
ui->portEdit->text());
#if QT_CONFIG(modbus_serialport)
@@ -226,7 +236,7 @@ void MainWindow::on_connectButton_clicked()
}
}
-void MainWindow::onStateChanged(int state)
+void MainWindow::onModbusStateChanged(int state)
{
bool connected = (state != QModbusDevice::UnconnectedState);
ui->actionConnect->setEnabled(!connected);
@@ -238,7 +248,7 @@ void MainWindow::onStateChanged(int state)
ui->connectButton->setText(tr("Disconnect"));
}
-void MainWindow::on_readButton_clicked()
+void MainWindow::onReadButtonClicked()
{
if (!modbusDevice)
return;
@@ -247,7 +257,7 @@ void MainWindow::on_readButton_clicked()
if (auto *reply = modbusDevice->sendReadRequest(readRequest(), ui->serverEdit->value())) {
if (!reply->isFinished())
- connect(reply, &QModbusReply::finished, this, &MainWindow::readReady);
+ connect(reply, &QModbusReply::finished, this, &MainWindow::onReadReady);
else
delete reply; // broadcast replies return immediately
} else {
@@ -255,7 +265,7 @@ void MainWindow::on_readButton_clicked()
}
}
-void MainWindow::readReady()
+void MainWindow::onReadReady()
{
auto reply = qobject_cast<QModbusReply *>(sender());
if (!reply)
@@ -263,7 +273,7 @@ void MainWindow::readReady()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
- for (uint i = 0; i < unit.valueCount(); i++) {
+ for (int i = 0, total = int(unit.valueCount()); i < total; ++i) {
const QString entry = tr("Address: %1, Value: %2").arg(unit.startAddress() + i)
.arg(QString::number(unit.value(i),
unit.registerType() <= QModbusDataUnit::Coils ? 10 : 16));
@@ -282,7 +292,7 @@ void MainWindow::readReady()
reply->deleteLater();
}
-void MainWindow::on_writeButton_clicked()
+void MainWindow::onWriteButtonClicked()
{
if (!modbusDevice)
return;
@@ -290,7 +300,7 @@ void MainWindow::on_writeButton_clicked()
QModbusDataUnit writeUnit = writeRequest();
QModbusDataUnit::RegisterType table = writeUnit.registerType();
- for (uint i = 0; i < writeUnit.valueCount(); i++) {
+ for (int i = 0, total = int(writeUnit.valueCount()); i < total; ++i) {
if (table == QModbusDataUnit::Coils)
writeUnit.setValue(i, writeModel->m_coils[i + writeUnit.startAddress()]);
else
@@ -319,7 +329,7 @@ void MainWindow::on_writeButton_clicked()
}
}
-void MainWindow::on_readWriteButton_clicked()
+void MainWindow::onReadWriteButtonClicked()
{
if (!modbusDevice)
return;
@@ -328,7 +338,7 @@ void MainWindow::on_readWriteButton_clicked()
QModbusDataUnit writeUnit = writeRequest();
QModbusDataUnit::RegisterType table = writeUnit.registerType();
- for (uint i = 0; i < writeUnit.valueCount(); i++) {
+ for (int i = 0, total = int(writeUnit.valueCount()); i < total; ++i) {
if (table == QModbusDataUnit::Coils)
writeUnit.setValue(i, writeModel->m_coils[i + writeUnit.startAddress()]);
else
@@ -338,7 +348,7 @@ void MainWindow::on_readWriteButton_clicked()
if (auto *reply = modbusDevice->sendReadWriteRequest(readRequest(), writeUnit,
ui->serverEdit->value())) {
if (!reply->isFinished())
- connect(reply, &QModbusReply::finished, this, &MainWindow::readReady);
+ connect(reply, &QModbusReply::finished, this, &MainWindow::onReadReady);
else
delete reply; // broadcast replies return immediately
} else {
@@ -346,7 +356,7 @@ void MainWindow::on_readWriteButton_clicked()
}
}
-void MainWindow::on_writeTable_currentIndexChanged(int index)
+void MainWindow::onWriteTableChanged(int index)
{
const bool coilsOrHolding = index == 0 || index == 3;
if (coilsOrHolding) {
@@ -363,25 +373,25 @@ void MainWindow::on_writeTable_currentIndexChanged(int index)
QModbusDataUnit MainWindow::readRequest() const
{
const auto table =
- static_cast<QModbusDataUnit::RegisterType> (ui->writeTable->currentData().toInt());
+ static_cast<QModbusDataUnit::RegisterType>(ui->writeTable->currentData().toInt());
int startAddress = ui->readAddress->value();
Q_ASSERT(startAddress >= 0 && startAddress < 10);
// do not go beyond 10 entries
- int numberOfEntries = qMin(ui->readSize->currentText().toInt(), 10 - startAddress);
+ quint16 numberOfEntries = qMin(ui->readSize->currentText().toUShort(), quint16(10 - startAddress));
return QModbusDataUnit(table, startAddress, numberOfEntries);
}
QModbusDataUnit MainWindow::writeRequest() const
{
const auto table =
- static_cast<QModbusDataUnit::RegisterType> (ui->writeTable->currentData().toInt());
+ static_cast<QModbusDataUnit::RegisterType>(ui->writeTable->currentData().toInt());
int startAddress = ui->writeAddress->value();
Q_ASSERT(startAddress >= 0 && startAddress < 10);
// do not go beyond 10 entries
- int numberOfEntries = qMin(ui->writeSize->currentText().toInt(), 10 - startAddress);
+ quint16 numberOfEntries = qMin(ui->writeSize->currentText().toUShort(), quint16(10 - startAddress));
return QModbusDataUnit(table, startAddress, numberOfEntries);
}
diff --git a/examples/serialbus/modbus/master/mainwindow.h b/examples/serialbus/modbus/master/mainwindow.h
index d4d5036..186d004 100644
--- a/examples/serialbus/modbus/master/mainwindow.h
+++ b/examples/serialbus/modbus/master/mainwindow.h
@@ -83,24 +83,24 @@ private:
QModbusDataUnit writeRequest() const;
private slots:
- void on_connectButton_clicked();
- void onStateChanged(int state);
+ void onConnectButtonClicked();
+ void onModbusStateChanged(int state);
- void on_readButton_clicked();
- void readReady();
+ void onReadButtonClicked();
+ void onReadReady();
- void on_writeButton_clicked();
- void on_readWriteButton_clicked();
+ void onWriteButtonClicked();
+ void onReadWriteButtonClicked();
- void on_connectType_currentIndexChanged(int);
- void on_writeTable_currentIndexChanged(int);
+ void onConnectTypeChanged(int);
+ void onWriteTableChanged(int);
private:
- Ui::MainWindow *ui;
- QModbusReply *lastRequest;
- QModbusClient *modbusDevice;
- SettingsDialog *m_settingsDialog;
- WriteRegisterModel *writeModel;
+ Ui::MainWindow *ui = nullptr;
+ QModbusReply *lastRequest = nullptr;
+ QModbusClient *modbusDevice = nullptr;
+ SettingsDialog *m_settingsDialog = nullptr;
+ WriteRegisterModel *writeModel = nullptr;
};
#endif // MAINWINDOW_H
diff --git a/examples/serialbus/modbus/master/master.pro b/examples/serialbus/modbus/master/master.pro
index 188fbc1..d7a4885 100644
--- a/examples/serialbus/modbus/master/master.pro
+++ b/examples/serialbus/modbus/master/master.pro
@@ -7,17 +7,20 @@ TARGET = modbusmaster
TEMPLATE = app
CONFIG += c++11
-SOURCES += main.cpp\
- mainwindow.cpp \
- settingsdialog.cpp \
- writeregistermodel.cpp
+SOURCES += \
+ main.cpp\
+ mainwindow.cpp \
+ settingsdialog.cpp \
+ writeregistermodel.cpp
-HEADERS += mainwindow.h \
- settingsdialog.h \
- writeregistermodel.h
+HEADERS += \
+ mainwindow.h \
+ settingsdialog.h \
+ writeregistermodel.h
-FORMS += mainwindow.ui \
- settingsdialog.ui
+FORMS += \
+ mainwindow.ui \
+ settingsdialog.ui
RESOURCES += \
master.qrc
diff --git a/examples/serialbus/modbus/master/settingsdialog.h b/examples/serialbus/modbus/master/settingsdialog.h
index 98ba946..fbeb97a 100644
--- a/examples/serialbus/modbus/master/settingsdialog.h
+++ b/examples/serialbus/modbus/master/settingsdialog.h
@@ -88,7 +88,7 @@ public:
private:
Settings m_settings;
- Ui::SettingsDialog *ui;
+ Ui::SettingsDialog *ui = nullptr;
};
#endif // SETTINGSDIALOG_H
diff --git a/examples/serialbus/modbus/master/writeregistermodel.cpp b/examples/serialbus/modbus/master/writeregistermodel.cpp
index 4b61e99..441f643 100644
--- a/examples/serialbus/modbus/master/writeregistermodel.cpp
+++ b/examples/serialbus/modbus/master/writeregistermodel.cpp
@@ -82,7 +82,7 @@ QVariant WriteRegisterModel::data(const QModelIndex &index, int role) const
if (index.column() == CoilsColumn && role == Qt::CheckStateRole) // coils
return m_coils.at(index.row()) ? Qt::Checked : Qt::Unchecked;
- else if (index.column() == HoldingColumn && role == Qt::DisplayRole) //holding registers
+ if (index.column() == HoldingColumn && role == Qt::DisplayRole) // holding registers
return QString("0x%1").arg(QString::number(m_holdingRegisters.at(index.row()), 16));
return QVariant();
@@ -146,9 +146,9 @@ Qt::ItemFlags WriteRegisterModel::flags(const QModelIndex &index) const
if ((index.row() < m_address) || (index.row() >= (m_address + m_number)))
flags &= ~Qt::ItemIsEnabled;
- if (index.column() == CoilsColumn) //coils
+ if (index.column() == CoilsColumn) // coils
return flags | Qt::ItemIsUserCheckable;
- if (index.column() == HoldingColumn) //holding registers
+ if (index.column() == HoldingColumn) // holding registers
return flags | Qt::ItemIsEditable;
return flags;
diff --git a/examples/serialbus/modbus/master/writeregistermodel.h b/examples/serialbus/modbus/master/writeregistermodel.h
index fe49591..4b0311e 100644
--- a/examples/serialbus/modbus/master/writeregistermodel.h
+++ b/examples/serialbus/modbus/master/writeregistermodel.h
@@ -79,8 +79,8 @@ signals:
void updateViewport();
public:
- int m_number;
- int m_address;
+ int m_number = 0;
+ int m_address = 0;
QBitArray m_coils;
QVector<quint16> m_holdingRegisters;
};
diff --git a/examples/serialbus/modbus/slave/main.cpp b/examples/serialbus/modbus/slave/main.cpp
index 4f97a39..19a1d5b 100644
--- a/examples/serialbus/modbus/slave/main.cpp
+++ b/examples/serialbus/modbus/slave/main.cpp
@@ -55,9 +55,8 @@
int main(int argc, char *argv[])
{
- // TODO uncomment this line before release
- // right now we always need it
- QLoggingCategory::setFilterRules(QStringLiteral("qt.modbus* = true"));
+ // Uncomment the following line to enable logging
+ // QLoggingCategory::setFilterRules(QStringLiteral("qt.modbus* = true"));
QApplication a(argc, argv);
MainWindow w;
w.show();
diff --git a/examples/serialbus/modbus/slave/mainwindow.cpp b/examples/serialbus/modbus/slave/mainwindow.cpp
index 4a4c194..213c034 100644
--- a/examples/serialbus/modbus/slave/mainwindow.cpp
+++ b/examples/serialbus/modbus/slave/mainwindow.cpp
@@ -67,18 +67,17 @@ enum ModbusConnection {
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
- , modbusDevice(nullptr)
{
ui->setupUi(this);
setupWidgetContainers();
#if QT_CONFIG(modbus_serialport)
ui->connectType->setCurrentIndex(0);
- on_connectType_currentIndexChanged(0);
+ onCurrentConnectTypeChanged(0);
#else
// lock out the serial port option
ui->connectType->setCurrentIndex(1);
- on_connectType_currentIndexChanged(1);
+ onCurrentConnectTypeChanged(1);
ui->connectType->setEnabled(false);
#endif
@@ -102,16 +101,20 @@ void MainWindow::initActions()
ui->actionExit->setEnabled(true);
ui->actionOptions->setEnabled(true);
+ connect(ui->connectButton, &QPushButton::clicked,
+ this, &MainWindow::onConnectButtonClicked);
connect(ui->actionConnect, &QAction::triggered,
- this, &MainWindow::on_connectButton_clicked);
+ this, &MainWindow::onConnectButtonClicked);
connect(ui->actionDisconnect, &QAction::triggered,
- this, &MainWindow::on_connectButton_clicked);
+ this, &MainWindow::onConnectButtonClicked);
+ connect(ui->connectType, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &MainWindow::onCurrentConnectTypeChanged);
connect(ui->actionExit, &QAction::triggered, this, &QMainWindow::close);
connect(ui->actionOptions, &QAction::triggered, m_settingsDialog, &QDialog::show);
}
-void MainWindow::on_connectType_currentIndexChanged(int index)
+void MainWindow::onCurrentConnectTypeChanged(int index)
{
if (modbusDevice) {
modbusDevice->disconnect();
@@ -119,7 +122,7 @@ void MainWindow::on_connectType_currentIndexChanged(int index)
modbusDevice = nullptr;
}
- ModbusConnection type = static_cast<ModbusConnection> (index);
+ auto type = static_cast<ModbusConnection>(index);
if (type == Serial) {
#if QT_CONFIG(modbus_serialport)
modbusDevice = new QModbusRtuSerialSlave(this);
@@ -127,7 +130,7 @@ void MainWindow::on_connectType_currentIndexChanged(int index)
} else if (type == Tcp) {
modbusDevice = new QModbusTcpServer(this);
if (ui->portEdit->text().isEmpty())
- ui->portEdit->setText(QLatin1Literal("127.0.0.1:502"));
+ ui->portEdit->setText(QLatin1String("127.0.0.1:502"));
}
ui->listenOnlyBox->setEnabled(type == Serial);
@@ -176,14 +179,14 @@ void MainWindow::handleDeviceError(QModbusDevice::Error newError)
statusBar()->showMessage(modbusDevice->errorString(), 5000);
}
-void MainWindow::on_connectButton_clicked()
+void MainWindow::onConnectButtonClicked()
{
bool intendToConnect = (modbusDevice->state() == QModbusDevice::UnconnectedState);
statusBar()->clearMessage();
if (intendToConnect) {
- if (static_cast<ModbusConnection> (ui->connectType->currentIndex()) == Serial) {
+ if (static_cast<ModbusConnection>(ui->connectType->currentIndex()) == Serial) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
ui->portEdit->text());
#if QT_CONFIG(modbus_serialport)
@@ -244,7 +247,7 @@ void MainWindow::bitChanged(int id, QModbusDataUnit::RegisterType table, bool va
if (!modbusDevice)
return;
- if (!modbusDevice->setData(table, id, value))
+ if (!modbusDevice->setData(table, quint16(id), value))
statusBar()->showMessage(tr("Could not set data: ") + modbusDevice->errorString(), 5000);
}
@@ -256,11 +259,11 @@ void MainWindow::setRegister(const QString &value)
const QString objectName = QObject::sender()->objectName();
if (registers.contains(objectName)) {
bool ok = true;
- const int id = QObject::sender()->property("ID").toInt();
+ const quint16 id = quint16(QObject::sender()->property("ID").toUInt());
if (objectName.startsWith(QStringLiteral("inReg")))
- ok = modbusDevice->setData(QModbusDataUnit::InputRegisters, id, value.toInt(&ok, 16));
+ ok = modbusDevice->setData(QModbusDataUnit::InputRegisters, id, value.toUShort(&ok, 16));
else if (objectName.startsWith(QStringLiteral("holdReg")))
- ok = modbusDevice->setData(QModbusDataUnit::HoldingRegisters, id, value.toInt(&ok, 16));
+ ok = modbusDevice->setData(QModbusDataUnit::HoldingRegisters, id, value.toUShort(&ok, 16));
if (!ok)
statusBar()->showMessage(tr("Could not set register: ") + modbusDevice->errorString(),
@@ -275,11 +278,11 @@ void MainWindow::updateWidgets(QModbusDataUnit::RegisterType table, int address,
QString text;
switch (table) {
case QModbusDataUnit::Coils:
- modbusDevice->data(QModbusDataUnit::Coils, address + i, &value);
+ modbusDevice->data(QModbusDataUnit::Coils, quint16(address + i), &value);
coilButtons.button(address + i)->setChecked(value);
break;
case QModbusDataUnit::HoldingRegisters:
- modbusDevice->data(QModbusDataUnit::HoldingRegisters, address + i, &value);
+ modbusDevice->data(QModbusDataUnit::HoldingRegisters, quint16(address + i), &value);
registers.value(QStringLiteral("holdReg_%1").arg(address + i))->setText(text
.setNum(value, 16));
break;
@@ -296,10 +299,10 @@ void MainWindow::setupDeviceData()
if (!modbusDevice)
return;
- for (int i = 0; i < coilButtons.buttons().count(); ++i)
+ for (quint16 i = 0; i < coilButtons.buttons().count(); ++i)
modbusDevice->setData(QModbusDataUnit::Coils, i, coilButtons.button(i)->isChecked());
- for (int i = 0; i < discreteButtons.buttons().count(); ++i) {
+ for (quint16 i = 0; i < discreteButtons.buttons().count(); ++i) {
modbusDevice->setData(QModbusDataUnit::DiscreteInputs, i,
discreteButtons.button(i)->isChecked());
}
@@ -307,11 +310,11 @@ void MainWindow::setupDeviceData()
bool ok;
for (QLineEdit *widget : qAsConst(registers)) {
if (widget->objectName().startsWith(QStringLiteral("inReg"))) {
- modbusDevice->setData(QModbusDataUnit::InputRegisters, widget->property("ID").toInt(),
- widget->text().toInt(&ok, 16));
+ modbusDevice->setData(QModbusDataUnit::InputRegisters, quint16(widget->property("ID").toUInt()),
+ widget->text().toUShort(&ok, 16));
} else if (widget->objectName().startsWith(QStringLiteral("holdReg"))) {
- modbusDevice->setData(QModbusDataUnit::HoldingRegisters, widget->property("ID").toInt(),
- widget->text().toInt(&ok, 16));
+ modbusDevice->setData(QModbusDataUnit::HoldingRegisters, quint16(widget->property("ID").toUInt()),
+ widget->text().toUShort(&ok, 16));
}
}
}
diff --git a/examples/serialbus/modbus/slave/mainwindow.h b/examples/serialbus/modbus/slave/mainwindow.h
index aec1e9d..e824649 100644
--- a/examples/serialbus/modbus/slave/mainwindow.h
+++ b/examples/serialbus/modbus/slave/mainwindow.h
@@ -77,7 +77,7 @@ public:
~MainWindow();
private Q_SLOTS:
- void on_connectButton_clicked();
+ void onConnectButtonClicked();
void onStateChanged(int state);
void coilChanged(int id);
@@ -87,7 +87,7 @@ private Q_SLOTS:
void setRegister(const QString &value);
void updateWidgets(QModbusDataUnit::RegisterType table, int address, int size);
- void on_connectType_currentIndexChanged(int);
+ void onCurrentConnectTypeChanged(int);
void handleDeviceError(QModbusDevice::Error newError);
@@ -96,13 +96,13 @@ private:
void setupDeviceData();
void setupWidgetContainers();
- Ui::MainWindow *ui;
- QModbusServer *modbusDevice;
+ Ui::MainWindow *ui = nullptr;
+ QModbusServer *modbusDevice = nullptr;
QButtonGroup coilButtons;
QButtonGroup discreteButtons;
QHash<QString, QLineEdit *> registers;
- SettingsDialog *m_settingsDialog;
+ SettingsDialog *m_settingsDialog = nullptr;
};
#endif // MAINWINDOW_H
diff --git a/examples/serialbus/modbus/slave/slave.pro b/examples/serialbus/modbus/slave/slave.pro
index aadef07..2e128c2 100644
--- a/examples/serialbus/modbus/slave/slave.pro
+++ b/examples/serialbus/modbus/slave/slave.pro
@@ -7,13 +7,18 @@ TARGET = modbusslave
TEMPLATE = app
CONFIG += c++11
-SOURCES += main.cpp\
- mainwindow.cpp \
- settingsdialog.cpp
+SOURCES += \
+ main.cpp \
+ mainwindow.cpp \
+ settingsdialog.cpp
-HEADERS += mainwindow.h settingsdialog.h
+HEADERS += \
+ mainwindow.h \
+ settingsdialog.h
-FORMS += mainwindow.ui settingsdialog.ui
+FORMS += \
+ mainwindow.ui \
+ settingsdialog.ui
RESOURCES += slave.qrc
diff --git a/src/plugins/canbus/peakcan/peakcan_symbols_p.h b/src/plugins/canbus/peakcan/peakcan_symbols_p.h
index 9ab2e67..3470df2 100644
--- a/src/plugins/canbus/peakcan/peakcan_symbols_p.h
+++ b/src/plugins/canbus/peakcan/peakcan_symbols_p.h
@@ -267,21 +267,28 @@
#define PCAN_TYPE_DNG_SJA_EPP 0x06U // PCAN-Dongle EPP SJA1000
// Type definitions
-#define TPCANHandle quint16 // Represents a PCAN hardware channel handle
-#define TPCANStatus quint32 // Represents a PCAN status/error code
-#define TPCANParameter quint8 // Represents a PCAN parameter to be read or set
-#define TPCANDevice quint8 // Represents a PCAN device
-#define TPCANMessageType quint8 // Represents the type of a PCAN message
-#define TPCANType quint8 // Represents the type of PCAN hardware to be initialized
-#define TPCANMode quint8 // Represents a PCAN filter mode
-#define TPCANBaudrate quint16 // Represents a PCAN Baud rate register value
-#define TPCANBitrateFD char * // Represents a PCAN-FD bit rate string
-#define TPCANTimestampFD quint64 // Represents a timestamp of a received PCAN FD message
+#ifdef Q_OS_MACOS
+#define TPCANLong quint64
+#define TPCANLongToFrameID(a) static_cast<quint32>(a)
+#else
+#define TPCANLong quint32
+#define TPCANLongToFrameID(a) a
+#endif
+#define TPCANHandle quint16 // Represents a PCAN hardware channel handle
+#define TPCANStatus TPCANLong // Represents a PCAN status/error code
+#define TPCANParameter quint8 // Represents a PCAN parameter to be read or set
+#define TPCANDevice quint8 // Represents a PCAN device
+#define TPCANMessageType quint8 // Represents the type of a PCAN message
+#define TPCANType quint8 // Represents the type of PCAN hardware to be initialized
+#define TPCANMode quint8 // Represents a PCAN filter mode
+#define TPCANBaudrate quint16 // Represents a PCAN Baud rate register value
+#define TPCANBitrateFD char * // Represents a PCAN-FD bit rate string
+#define TPCANTimestampFD quint64 // Represents a timestamp of a received PCAN FD message
// Represents a PCAN message
typedef struct tagTPCANMsg
{
- quint32 ID; // 11/29-bit message identifier
+ TPCANLong ID; // 11/29-bit message identifier
TPCANMessageType MSGTYPE; // Type of the message
quint8 LEN; // Data Length Code of the message (0..8)
quint8 DATA[8]; // Data of the message (DATA[0]..DATA[7])
@@ -291,15 +298,15 @@ typedef struct tagTPCANMsg
// Total Microseconds = micros + 1000 * millis + 0xFFFFFFFF * 1000 * millis_overflow
typedef struct tagTPCANTimestamp
{
- quint32 millis; // Base-value: milliseconds: 0.. 2^32-1
- quint16 millis_overflow; // Roll-arounds of millis
- quint16 micros; // Microseconds: 0..999
+ TPCANLong millis; // Base-value: milliseconds: 0.. 2^32-1
+ quint16 millis_overflow; // Roll-arounds of millis
+ quint16 micros; // Microseconds: 0..999
} TPCANTimestamp;
// Represents a PCAN message from a FD capable hardware
typedef struct tagTPCANMsgFD
{
- quint32 ID; // 11/29-bit message identifier
+ TPCANLong ID; // 11/29-bit message identifier
TPCANMessageType MSGTYPE; // Type of the message
quint8 DLC; // Data Length Code of the message (0..15)
quint8 DATA[64]; // Data of the message (DATA[0]..DATA[63])
@@ -314,7 +321,7 @@ typedef struct tagTPCANMsgFD
if (!symbolName) \
return false;
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Initialize, TPCANHandle, TPCANBaudrate, TPCANType, quint32, quint16)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Initialize, TPCANHandle, TPCANBaudrate, TPCANType, TPCANLong, quint16)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_InitializeFD, TPCANHandle, TPCANBitrateFD)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Uninitialize, TPCANHandle)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Reset, TPCANHandle)
@@ -323,15 +330,19 @@ GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Read, TPCANHandle, TPCANMsg *, TPCANTi
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_ReadFD, TPCANHandle, TPCANMsgFD *, TPCANTimestampFD *)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_Write, TPCANHandle, TPCANMsg *)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_WriteFD, TPCANHandle, TPCANMsgFD *)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_FilterMessages, TPCANHandle, quint32, quint32, TPCANMode)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetValue, TPCANHandle, TPCANParameter, void *, quint32)
-GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_SetValue, TPCANHandle, TPCANParameter, void *, quint32)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_FilterMessages, TPCANHandle, TPCANLong, TPCANLong, TPCANMode)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetValue, TPCANHandle, TPCANParameter, void *, TPCANLong)
+GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_SetValue, TPCANHandle, TPCANParameter, void *, TPCANLong)
GENERATE_SYMBOL_VARIABLE(TPCANStatus, CAN_GetErrorText, TPCANStatus, quint16, char *)
inline bool resolveSymbols(QLibrary *pcanLibrary)
{
if (!pcanLibrary->isLoaded()) {
- pcanLibrary->setFileName(QStringLiteral("pcanbasic"));
+ #ifdef Q_OS_MACOS
+ pcanLibrary->setFileName(QStringLiteral("PCBUSB"));
+ #else
+ pcanLibrary->setFileName(QStringLiteral("pcanbasic"));
+ #endif
if (!pcanLibrary->load())
return false;
}
diff --git a/src/plugins/canbus/peakcan/peakcanbackend.cpp b/src/plugins/canbus/peakcan/peakcanbackend.cpp
index f8932e9..b1a991d 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend.cpp
+++ b/src/plugins/canbus/peakcan/peakcanbackend.cpp
@@ -68,6 +68,8 @@ bool PeakCanBackend::canCreate(QString *errorReason)
#else
static bool symbolsResolved = resolveSymbols(pcanLibrary());
if (Q_UNLIKELY(!symbolsResolved)) {
+ qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot load library: %ls",
+ qUtf16Printable(pcanLibrary()->errorString()));
*errorReason = pcanLibrary()->errorString();
return false;
}
@@ -331,15 +333,21 @@ bool PeakCanBackendPrivate::open()
}
if (Q_UNLIKELY(st != PCAN_ERROR_OK)) {
- q->setError(systemErrorString(st), QCanBusDevice::ConnectionError);
+ const QString errorString = systemErrorString(st);
+ qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot initialize hardware: %ls",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::ConnectionError);
return false;
}
#if defined(Q_OS_WIN32)
if (readHandle == INVALID_HANDLE_VALUE) {
readHandle = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
- if (!readHandle) {
- q->setError(qt_error_string(::GetLastError()), QCanBusDevice::ConnectionError);
+ if (Q_UNLIKELY(!readHandle)) {
+ const QString errorString = qt_error_string(::GetLastError());
+ qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot create receive event handler: %ls",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::ConnectionError);
return false;
}
}
@@ -353,7 +361,10 @@ bool PeakCanBackendPrivate::open()
#else
const TPCANStatus err = ::CAN_GetValue(channelIndex, PCAN_RECEIVE_EVENT, &readHandle, sizeof(readHandle));
if (Q_UNLIKELY(err != PCAN_ERROR_OK)) {
- q->setError(systemErrorString(err), QCanBusDevice::ConnectionError);
+ const QString errorString = systemErrorString(err);
+ qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot create receive event handler: %ls",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::ConnectionError);
return false;
}
#endif
@@ -380,8 +391,12 @@ void PeakCanBackendPrivate::close()
quint32 value = 0;
const TPCANStatus err = ::CAN_SetValue(channelIndex, PCAN_RECEIVE_EVENT, &value, sizeof(value));
- if (Q_UNLIKELY(err != PCAN_ERROR_OK))
- q->setError(systemErrorString(err), QCanBusDevice::ConnectionError);
+ if (Q_UNLIKELY(err != PCAN_ERROR_OK)) {
+ const QString errorString = systemErrorString(err);
+ qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot unregister receive event handler: %ls",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::ConnectionError);
+ }
const TPCANStatus st = ::CAN_Uninitialize(channelIndex);
if (Q_UNLIKELY(st != PCAN_ERROR_OK))
@@ -389,8 +404,12 @@ void PeakCanBackendPrivate::close()
#if defined(Q_OS_WIN32)
if (readHandle && (readHandle != INVALID_HANDLE_VALUE)) {
- if (Q_UNLIKELY(!::CloseHandle(readHandle)))
- q->setError(qt_error_string(::GetLastError()), QCanBusDevice::ConnectionError);
+ const QString errorString = qt_error_string(::GetLastError());
+ if (Q_UNLIKELY(!::CloseHandle(readHandle))) {
+ qCCritical(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot close read handle: %ls",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::ConnectionError);
+ }
readHandle = INVALID_HANDLE_VALUE;
}
#else
@@ -413,6 +432,7 @@ bool PeakCanBackendPrivate::setConfigurationParameter(int key, const QVariant &v
case QCanBusDevice::DataBitRateKey: {
const int dataBitrate = value.toInt();
if (Q_UNLIKELY(dataBitrateString(dataBitrate).isEmpty())) {
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, "Unsupported data bitrate value: %d", dataBitrate);
q->setError(PeakCanBackend::tr("Unsupported data bitrate value: %1.").arg(dataBitrate),
QCanBusDevice::ConfigurationError);
return false;
@@ -420,6 +440,7 @@ bool PeakCanBackendPrivate::setConfigurationParameter(int key, const QVariant &v
return true;
}
default:
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, "Unsupported configuration key: %d", key);
q->setError(PeakCanBackend::tr("Unsupported configuration key: %1").arg(key),
QCanBusDevice::ConfigurationError);
return false;
@@ -558,8 +579,9 @@ void PeakCanBackendPrivate::startWrite()
::memcpy(message.DATA, payload.constData(), sizeof(message.DATA));
st = ::CAN_WriteFD(channelIndex, &message);
} else if (frame.hasFlexibleDataRateFormat()) {
- q->setError(PeakCanBackend::tr("Cannot send CAN FD frame format as CAN FD is not enabled."),
- QCanBusDevice::WriteError);
+ const char errorString[] = "Cannot send CAN FD frame format as CAN FD is not enabled.";
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN(), errorString);
+ q->setError(PeakCanBackend::tr(errorString), QCanBusDevice::WriteError);
} else {
TPCANMsg message;
::memset(&message, 0, sizeof(message));
@@ -576,10 +598,14 @@ void PeakCanBackendPrivate::startWrite()
st = ::CAN_Write(channelIndex, &message);
}
- if (Q_UNLIKELY(st != PCAN_ERROR_OK))
- q->setError(systemErrorString(st), QCanBusDevice::WriteError);
- else
+ if (Q_UNLIKELY(st != PCAN_ERROR_OK)) {
+ const QString errorString = systemErrorString(st);
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, "Cannot write frame: %ls",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::WriteError);
+ } else {
emit q->framesWritten(qint64(1));
+ }
if (q->hasOutgoingFrames() && !writeNotifier->isActive())
writeNotifier->start();
@@ -611,7 +637,7 @@ void PeakCanBackendPrivate::startRead()
continue;
const int size = dlcToSize(static_cast<CanFrameDlc>(message.DLC));
- QCanBusFrame frame(message.ID,
+ QCanBusFrame frame(TPCANLongToFrameID(message.ID),
QByteArray(reinterpret_cast<const char *>(message.DATA), size));
frame.setTimeStamp(QCanBusFrame::TimeStamp::fromMicroSeconds(static_cast<qint64>(timestamp)));
frame.setExtendedFrameFormat(message.MSGTYPE & PCAN_MESSAGE_EXTENDED);
@@ -641,7 +667,7 @@ void PeakCanBackendPrivate::startRead()
continue;
const int size = static_cast<int>(message.LEN);
- QCanBusFrame frame(message.ID,
+ QCanBusFrame frame(TPCANLongToFrameID(message.ID),
QByteArray(reinterpret_cast<const char *>(message.DATA), size));
const quint64 millis = timestamp.millis + Q_UINT64_C(0xFFFFFFFF) * timestamp.millis_overflow;
const quint64 micros = Q_UINT64_C(1000) * millis + timestamp.micros;
@@ -662,8 +688,9 @@ bool PeakCanBackendPrivate::verifyBitRate(int bitrate)
Q_Q(PeakCanBackend);
if (Q_UNLIKELY(isOpen)) {
- q->setError(PeakCanBackend::tr("Cannot change bitrate for already opened device."),
- QCanBusDevice::ConfigurationError);
+ const char errorString[] = "Cannot change bitrate for already opened device.";
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, errorString);
+ q->setError(PeakCanBackend::tr(errorString), QCanBusDevice::ConfigurationError);
return false;
}
@@ -674,6 +701,7 @@ bool PeakCanBackendPrivate::verifyBitRate(int bitrate)
isValidBitrate = bitrateCodeFromBitrate(bitrate) != PCAN_BAUD_INVALID;
if (Q_UNLIKELY(!isValidBitrate)) {
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, "Unsupported bitrate value: %d.", bitrate);
q->setError(PeakCanBackend::tr("Unsupported bitrate value: %1.").arg(bitrate),
QCanBusDevice::ConfigurationError);
}
@@ -689,6 +717,12 @@ PeakCanBackend::PeakCanBackend(const QString &name, QObject *parent)
d->setupChannel(name.toLatin1());
d->setupDefaultConfigurations();
+
+ std::function<void()> f = std::bind(&PeakCanBackend::resetController, this);
+ setResetControllerFunction(f);
+
+ std::function<CanBusStatus()> g = std::bind(&PeakCanBackend::busStatus, this);
+ setCanBusStatusGetter(g);
}
PeakCanBackend::~PeakCanBackend()
@@ -709,11 +743,11 @@ bool PeakCanBackend::open()
if (Q_UNLIKELY(!d->open()))
return false;
- // apply all stored configurations except bitrate, because
- // the bitrate can not be applied after opening of device
+ // Apply all stored configurations except bitrate, because
+ // the bitrate cannot be changed after opening the device
const auto keys = configurationKeys();
for (int key : keys) {
- if (key == QCanBusDevice::BitRateKey)
+ if (key == QCanBusDevice::BitRateKey || key == QCanBusDevice::DataBitRateKey)
continue;
const QVariant param = configurationParameter(key);
const bool success = d->setConfigurationParameter(key, param);
@@ -780,4 +814,29 @@ QString PeakCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
return QString();
}
+void PeakCanBackend::resetController()
+{
+ close();
+ open();
+}
+
+QCanBusDevice::CanBusStatus PeakCanBackend::busStatus() const
+{
+ const TPCANStatus status = ::CAN_GetStatus(d_ptr->channelIndex);
+
+ switch (status & PCAN_ERROR_ANYBUSERR) {
+ case PCAN_ERROR_OK:
+ return QCanBusDevice::CanBusStatus::Good;
+ case PCAN_ERROR_BUSWARNING:
+ return QCanBusDevice::CanBusStatus::Warning;
+ case PCAN_ERROR_BUSPASSIVE:
+ return QCanBusDevice::CanBusStatus::Error;
+ case PCAN_ERROR_BUSOFF:
+ return QCanBusDevice::CanBusStatus::BusOff;
+ default:
+ qCWarning(QT_CANBUS_PLUGINS_PEAKCAN, "Unknown CAN bus status: %lu.", ulong(status));
+ return QCanBusDevice::CanBusStatus::Unknown;
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/peakcan/peakcanbackend.h b/src/plugins/canbus/peakcan/peakcanbackend.h
index 7f7083e..a9e108e 100644
--- a/src/plugins/canbus/peakcan/peakcanbackend.h
+++ b/src/plugins/canbus/peakcan/peakcanbackend.h
@@ -72,6 +72,9 @@ public:
static QList<QCanBusDeviceInfo> interfaces();
private:
+ void resetController();
+ CanBusStatus busStatus() const;
+
PeakCanBackendPrivate * const d_ptr;
};
diff --git a/src/plugins/canbus/socketcan/libsocketcan.cpp b/src/plugins/canbus/socketcan/libsocketcan.cpp
new file mode 100644
index 0000000..c6144db
--- /dev/null
+++ b/src/plugins/canbus/socketcan/libsocketcan.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtSerialBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "libsocketcan.h"
+
+#include <QtCore/qloggingcategory.h>
+
+#if QT_CONFIG(library)
+# include <QtCore/qlibrary.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(QT_CANBUS_PLUGINS_SOCKETCAN)
+
+#define GENERATE_SYMBOL(returnType, symbolName, ...) \
+ typedef returnType (*fp_##symbolName)(__VA_ARGS__); \
+ static fp_##symbolName symbolName = nullptr;
+
+#define RESOLVE_SYMBOL(symbolName) \
+ symbolName = reinterpret_cast<fp_##symbolName>(library->resolve(#symbolName)); \
+ if (!symbolName) \
+ return false;
+
+struct can_bittiming {
+ quint32 bitrate = 0; /* Bit-rate in bits/second */
+ quint32 sample_point = 0; /* Sample point in one-tenth of a percent */
+ quint32 tq = 0; /* Time quanta (TQ) in nanoseconds */
+ quint32 prop_seg = 0; /* Propagation segment in TQs */
+ quint32 phase_seg1 = 0; /* Phase buffer segment 1 in TQs */
+ quint32 phase_seg2 = 0; /* Phase buffer segment 2 in TQs */
+ quint32 sjw = 0; /* Synchronization jump width in TQs */
+ quint32 brp = 0; /* Bit-rate prescaler */
+};
+
+enum can_state {
+ CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */
+ CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */
+ CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */
+ CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */
+ CAN_STATE_STOPPED, /* Device is stopped */
+ CAN_STATE_SLEEPING, /* Device is sleeping */
+ CAN_STATE_MAX
+};
+
+GENERATE_SYMBOL(int, can_do_restart, const char * /* name */)
+GENERATE_SYMBOL(int, can_do_stop, const char * /* name */)
+GENERATE_SYMBOL(int, can_do_start, const char * /* name */)
+GENERATE_SYMBOL(int, can_set_bitrate, const char * /* name */, quint32 /* bitrate */)
+GENERATE_SYMBOL(int, can_get_bittiming, const char * /* name */, struct can_bittiming * /* bt */)
+GENERATE_SYMBOL(int, can_get_state, const char * /* name */, int * /* state */)
+
+LibSocketCan::LibSocketCan(QString *errorString)
+{
+#if QT_CONFIG(library)
+ auto resolveSymbols = [](QLibrary *library) {
+ if (!library->isLoaded()) {
+ library->setFileName(QStringLiteral("socketcan"));
+ if (!library->load())
+ return false;
+ }
+
+ RESOLVE_SYMBOL(can_do_start);
+ RESOLVE_SYMBOL(can_do_stop);
+ RESOLVE_SYMBOL(can_do_restart);
+ RESOLVE_SYMBOL(can_set_bitrate);
+ RESOLVE_SYMBOL(can_get_bittiming);
+ RESOLVE_SYMBOL(can_get_state);
+
+ return true;
+ };
+
+ QLibrary lib;
+ if (Q_UNLIKELY(!resolveSymbols(&lib))) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "%ls", qUtf16Printable(lib.errorString()));
+ if (errorString)
+ *errorString = lib.errorString();
+ }
+#else
+ const QString error =
+ QObject::tr("Cannot load library libsocketcan as Qt was built without QLibrary.");
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "%ls", qUtf16Printable(error));
+ if (errorString)
+ *errorString = error;
+#endif
+}
+
+/*!
+ Brings the CAN \a interface up.
+
+ \internal
+ \note Requires appropriate permissions.
+*/
+bool LibSocketCan::start(const QString &interface)
+{
+ if (!::can_do_start) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_do_start() is not available.");
+ return false;
+ }
+
+ return ::can_do_start(interface.toLatin1().constData()) == 0;
+}
+
+/*!
+ Brings the CAN \a interface down.
+
+ \internal
+ \note Requires appropriate permissions.
+*/
+bool LibSocketCan::stop(const QString &interface)
+{
+ if (!::can_do_stop) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_do_stop() is not available.");
+ return false;
+ }
+
+ return ::can_do_stop(interface.toLatin1().constData()) == 0;
+}
+
+/*!
+ Performs a CAN controller reset on the CAN \a interface.
+
+ \internal
+ \note Reset can only be triggerd if the controller is in bus off
+ and the auto restart not turned on.
+ \note Requires appropriate permissions.
+ */
+bool LibSocketCan::restart(const QString &interface)
+{
+ if (!::can_do_restart) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_do_restart() is not available.");
+ return false;
+ }
+
+ return ::can_do_restart(interface.toLatin1().constData()) == 0;
+}
+
+/*!
+ Returns the configured bitrate for \a interface.
+ \internal
+*/
+quint32 LibSocketCan::bitrate(const QString &interface) const
+{
+ if (!::can_get_bittiming) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_get_bittiming() is not available.");
+ return 0;
+ }
+
+ struct can_bittiming bt;
+ if (::can_get_bittiming(interface.toLatin1().constData(), &bt) == 0)
+ return bt.bitrate;
+
+ return 0;
+}
+
+/*!
+ Sets the bitrate for the CAN \a interface.
+
+ \internal
+ \note Requires appropriate permissions.
+ */
+bool LibSocketCan::setBitrate(const QString &interface, quint32 bitrate)
+{
+ if (!::can_set_bitrate) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_set_bitrate() is not available.");
+ return false;
+ }
+
+ return ::can_set_bitrate(interface.toLatin1().constData(), bitrate) == 0;
+}
+
+bool LibSocketCan::hasBusStatus() const
+{
+ return ::can_get_state != nullptr;
+}
+
+QCanBusDevice::CanBusStatus LibSocketCan::busStatus(const QString &interface) const
+{
+ if (!::can_get_state) {
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "Function can_get_state() is not available.");
+ return QCanBusDevice::CanBusStatus::Unknown;
+ }
+
+ int status = 0;
+ int result = ::can_get_state(interface.toLatin1().constData(), &status);
+
+ if (result < 0)
+ return QCanBusDevice::CanBusStatus::Unknown;
+
+ switch (status) {
+ case CAN_STATE_ERROR_ACTIVE:
+ return QCanBusDevice::CanBusStatus::Good;
+ case CAN_STATE_ERROR_WARNING:
+ return QCanBusDevice::CanBusStatus::Warning;
+ case CAN_STATE_ERROR_PASSIVE:
+ return QCanBusDevice::CanBusStatus::Error;
+ case CAN_STATE_BUS_OFF:
+ return QCanBusDevice::CanBusStatus::BusOff;
+ default:
+ // Device is stopped or sleeping, so status is unknown
+ return QCanBusDevice::CanBusStatus::Unknown;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/canbus/socketcan/libsocketcan.h b/src/plugins/canbus/socketcan/libsocketcan.h
new file mode 100644
index 0000000..b77afa1
--- /dev/null
+++ b/src/plugins/canbus/socketcan/libsocketcan.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Andre Hartmann <aha_1980@gmx.de>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtSerialBus module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LIBSOCKETCAN_H
+#define LIBSOCKETCAN_H
+
+#include <QtCore/qglobal.h>
+#include <QtSerialBus/qcanbusdevice.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+class LibSocketCan final
+{
+public:
+ explicit LibSocketCan(QString *errorString = nullptr);
+
+ bool start(const QString &interface);
+ bool stop(const QString &interface);
+ bool restart(const QString &interface);
+
+ quint32 bitrate(const QString &interface) const;
+ bool setBitrate(const QString &interface, quint32 bitrate);
+
+ bool hasBusStatus() const;
+ QCanBusDevice::CanBusStatus busStatus(const QString &interface) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // LIBSOCKETCAN_H
diff --git a/src/plugins/canbus/socketcan/socketcan.pro b/src/plugins/canbus/socketcan/socketcan.pro
index 20a2c5d..cd731fd 100644
--- a/src/plugins/canbus/socketcan/socketcan.pro
+++ b/src/plugins/canbus/socketcan/socketcan.pro
@@ -3,9 +3,11 @@ TARGET = qtsocketcanbus
QT = core serialbus
HEADERS += \
+ libsocketcan.h \
socketcanbackend.h
SOURCES += \
+ libsocketcan.cpp \
main.cpp \
socketcanbackend.cpp
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.cpp b/src/plugins/canbus/socketcan/socketcanbackend.cpp
index a2da146..2ed1310 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.cpp
+++ b/src/plugins/canbus/socketcan/socketcanbackend.cpp
@@ -36,6 +36,10 @@
#include "socketcanbackend.h"
+#include "libsocketcan.h"
+
+#include <QtSerialBus/qcanbusdevice.h>
+
#include <QtCore/qdatastream.h>
#include <QtCore/qdebug.h>
#include <QtCore/qdiriterator.h>
@@ -182,7 +186,25 @@ QList<QCanBusDeviceInfo> SocketCanBackend::interfaces()
SocketCanBackend::SocketCanBackend(const QString &name) :
canSocketName(name)
{
+ QString errorString;
+ libSocketCan.reset(new LibSocketCan(&errorString));
+ if (Q_UNLIKELY(!errorString.isEmpty())) {
+ qCInfo(QT_CANBUS_PLUGINS_SOCKETCAN,
+ "Cannot load library libsocketcan, some functionality will not be available.\n%ls",
+ qUtf16Printable(errorString));
+ }
+
resetConfigurations();
+
+ std::function<void()> f = std::bind(&SocketCanBackend::resetController, this);
+ setResetControllerFunction(f);
+
+ if (hasBusStatus()) {
+ // Only register busStatus when libsocketcan is available
+ // QCanBusDevice::hasBusStatus() will return false otherwise
+ std::function<CanBusStatus()> g = std::bind(&SocketCanBackend::busStatus, this);
+ setCanBusStatusGetter(g);
+ }
}
SocketCanBackend::~SocketCanBackend()
@@ -201,6 +223,8 @@ void SocketCanBackend::resetConfigurations()
QVariant::fromValue(QCanBusFrame::FrameErrors(QCanBusFrame::AnyError)));
QCanBusDevice::setConfigurationParameter(
QCanBusDevice::CanFdKey, false);
+ QCanBusDevice::setConfigurationParameter(
+ QCanBusDevice::BitRateKey, 500000);
}
bool SocketCanBackend::open()
@@ -346,6 +370,12 @@ bool SocketCanBackend::applyConfigurationParameter(int key, const QVariant &valu
success = true;
break;
}
+ case QCanBusDevice::BitRateKey:
+ {
+ const quint32 bitRate = value.toUInt();
+ libSocketCan->setBitrate(canSocketName, bitRate);
+ break;
+ }
default:
setError(tr("SocketCanBackend: No such configuration as %1 in SocketCanBackend").arg(key),
QCanBusDevice::CanBusError::ConfigurationError);
@@ -359,7 +389,7 @@ bool SocketCanBackend::connectSocket()
{
struct ifreq interface;
- if (Q_UNLIKELY((canSocket = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)) < 0)) {
+ if (Q_UNLIKELY((canSocket = socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, protocol)) < 0)) {
setError(qt_error_string(errno),
QCanBusDevice::CanBusError::ConnectionError);
return false;
@@ -434,6 +464,16 @@ void SocketCanBackend::setConfigurationParameter(int key, const QVariant &value)
return;
}
}
+ } else if (key == QCanBusDevice::ProtocolKey) {
+ bool ok = false;
+ const int newProtocol = value.toInt(&ok);
+ if (Q_UNLIKELY(!ok || (newProtocol < 0))) {
+ const QString errorString = tr("Cannot set protocol to value %1.").arg(value.toString());
+ setError(errorString, QCanBusDevice::ConfigurationError);
+ qCWarning(QT_CANBUS_PLUGINS_SOCKETCAN, "%ls", qUtf16Printable(errorString));
+ return;
+ }
+ protocol = newProtocol;
}
// connected & params not applyable/invalid
if (canSocket != -1 && !applyConfigurationParameter(key, value))
@@ -731,4 +771,19 @@ void SocketCanBackend::readSocket()
enqueueReceivedFrames(newFrames);
}
+void SocketCanBackend::resetController()
+{
+ libSocketCan->restart(canSocketName);
+}
+
+bool SocketCanBackend::hasBusStatus() const
+{
+ return libSocketCan->hasBusStatus();
+}
+
+QCanBusDevice::CanBusStatus SocketCanBackend::busStatus() const
+{
+ return libSocketCan->busStatus(canSocketName);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/socketcan/socketcanbackend.h b/src/plugins/canbus/socketcan/socketcanbackend.h
index b49d267..0497244 100644
--- a/src/plugins/canbus/socketcan/socketcanbackend.h
+++ b/src/plugins/canbus/socketcan/socketcanbackend.h
@@ -52,8 +52,12 @@
#include <linux/can.h>
#include <sys/time.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
+class LibSocketCan;
+
class SocketCanBackend : public QCanBusDevice
{
Q_OBJECT
@@ -79,7 +83,11 @@ private:
void resetConfigurations();
bool connectSocket();
bool applyConfigurationParameter(int key, const QVariant &value);
+ void resetController();
+ bool hasBusStatus() const;
+ QCanBusDevice::CanBusStatus busStatus() const;
+ int protocol = CAN_RAW;
canfd_frame m_frame;
sockaddr_can m_address;
msghdr m_msg;
@@ -89,6 +97,7 @@ private:
qint64 canSocket = -1;
QSocketNotifier *notifier = nullptr;
+ std::unique_ptr<LibSocketCan> libSocketCan;
QString canSocketName;
bool canFdOptionEnabled = false;
};
diff --git a/src/plugins/canbus/systeccan/systeccan_symbols_p.h b/src/plugins/canbus/systeccan/systeccan_symbols_p.h
index 102817c..ce32422 100644
--- a/src/plugins/canbus/systeccan/systeccan_symbols_p.h
+++ b/src/plugins/canbus/systeccan/systeccan_symbols_p.h
@@ -81,6 +81,20 @@ typedef void (DRV_CALLBACK_TYPE *tCallbackFktEx) (tUcanHandle handle, quint32 ev
#define USBCAN_EVENT_FATALDISCON 8 // a USB-CANmodul has been disconnected during operation
#define USBCAN_EVENT_RESERVED1 0x80
+// CAN status flags (is returned with function UcanGetStatus() or UcanGetStatusEx() )
+#define USBCAN_CANERR_OK 0x0000 // no error
+#define USBCAN_CANERR_XMTFULL 0x0001 // Tx-buffer of the CAN controller is full
+#define USBCAN_CANERR_OVERRUN 0x0002 // Rx-buffer of the CAN controller is full
+#define USBCAN_CANERR_BUSLIGHT 0x0004 // Bus error: Error Limit 1 exceeded (refer to SJA1000 manual)
+#define USBCAN_CANERR_BUSHEAVY 0x0008 // Bus error: Error Limit 2 exceeded (refer to SJA1000 manual)
+#define USBCAN_CANERR_BUSOFF 0x0010 // Bus error: CAN controller has gone into Bus-Off state
+#define USBCAN_CANERR_QRCVEMPTY 0x0020 // RcvQueue is empty
+#define USBCAN_CANERR_QOVERRUN 0x0040 // RcvQueue overrun
+#define USBCAN_CANERR_QXMTFULL 0x0080 // transmit queue is full
+#define USBCAN_CANERR_REGTEST 0x0100 // Register test of the SJA1000 failed
+#define USBCAN_CANERR_MEMTEST 0x0200 // Memory test failed
+#define USBCAN_CANERR_TXMSGLOST 0x0400 // transmit CAN message was automatically deleted by firmware
+
#define kUcanModeNormal 0x00 // normal mode (send and receive)
#define kUcanModeListenOnly 0x01 // listen only mode (only receive)
#define kUcanModeTxEcho 0x02 // CAN messages which was sent will be received at UcanReadCanMsg..
@@ -88,8 +102,8 @@ typedef void (DRV_CALLBACK_TYPE *tCallbackFktEx) (tUcanHandle handle, quint32 ev
#define kUcanModeHighResTimer 0x08 // high resolution time stamps in received CAN messages (only available with STM derivates)
// ABR and ACR for mode "receive all CAN messages"
-#define USBCAN_AMR_ALL (quint32) 0xffffffff
-#define USBCAN_ACR_ALL (quint32) 0x00000000
+#define USBCAN_AMR_ALL 0xffffffffU
+#define USBCAN_ACR_ALL 0x00000000U
#define USBCAN_OCR_DEFAULT 0x1A // default OCR for standard GW-002
#define USBCAN_OCR_RS485_ISOLATED 0x1E // OCR for RS485 interface and galvanic isolation
@@ -143,6 +157,11 @@ typedef struct _tCanMsgStruct {
quint32 m_dwTime; // Time in ms
} tCanMsgStruct;
+typedef struct _tStatusStruct {
+ quint16 m_wCanStatus; // current CAN status
+ quint16 m_wUsbStatus; // current USB status
+} tStatusStruct;
+
// Function return codes (encoding)
#define USBCAN_SUCCESSFUL 0x00 // no error
#define USBCAN_ERR 0x01 // error in library; function has not been executed
@@ -280,7 +299,9 @@ GENERATE_SYMBOL_VARIABLE(UCANRET, UcanDeinitHardware, tUcanHandle)
GENERATE_SYMBOL_VARIABLE(UCANRET, UcanInitCanEx2, tUcanHandle, quint8 /* channel */, tUcanInitCanParam *)
GENERATE_SYMBOL_VARIABLE(UCANRET, UcanDeinitCanEx, tUcanHandle, quint8 /* channel */)
GENERATE_SYMBOL_VARIABLE(UCANRET, UcanReadCanMsgEx, tUcanHandle, quint8 *, tCanMsgStruct *, quint32 *)
+GENERATE_SYMBOL_VARIABLE(UCANRET, UcanResetCan, tUcanHandle)
GENERATE_SYMBOL_VARIABLE(UCANRET, UcanWriteCanMsgEx, tUcanHandle, quint8, tCanMsgStruct *, quint32 *)
+GENERATE_SYMBOL_VARIABLE(UCANRET, UcanGetStatus, tUcanHandle, tStatusStruct *)
inline bool resolveSymbols(QLibrary *systecLibrary)
{
@@ -300,7 +321,9 @@ inline bool resolveSymbols(QLibrary *systecLibrary)
RESOLVE_SYMBOL(UcanInitCanEx2);
RESOLVE_SYMBOL(UcanDeinitCanEx);
RESOLVE_SYMBOL(UcanReadCanMsgEx);
+ RESOLVE_SYMBOL(UcanResetCan);
RESOLVE_SYMBOL(UcanWriteCanMsgEx);
+ RESOLVE_SYMBOL(UcanGetStatus);
return true;
}
diff --git a/src/plugins/canbus/systeccan/systeccanbackend.cpp b/src/plugins/canbus/systeccan/systeccanbackend.cpp
index 3fdd135..0663f39 100644
--- a/src/plugins/canbus/systeccan/systeccanbackend.cpp
+++ b/src/plugins/canbus/systeccan/systeccanbackend.cpp
@@ -114,7 +114,7 @@ QList<QCanBusDeviceInfo> SystecCanBackend::interfaces()
{
QList<QCanBusDeviceInfo> result;
- ::UcanEnumerateHardware(&ucanEnumCallback, &result, false, 0, ~0, 0, ~0, 0, ~0);
+ ::UcanEnumerateHardware(&ucanEnumCallback, &result, false, 0, quint8(~0), 0, quint32(~0), 0, quint32(~0));
return result;
}
@@ -281,8 +281,8 @@ bool SystecCanBackendPrivate::setupChannel(const QString &interfaceName)
const QRegularExpressionMatch match = re.match(interfaceName);
if (Q_LIKELY(match.hasMatch())) {
- device = match.captured(1).toInt();
- channel = match.captured(2).toInt();
+ device = quint8(match.captured(1).toUShort());
+ channel = quint8(match.captured(2).toUShort());
} else {
q->setError(SystecCanBackend::tr("Invalid interface '%1'.")
.arg(interfaceName), QCanBusDevice::ConnectionError);
@@ -377,7 +377,7 @@ void SystecCanBackendPrivate::startWrite()
::memset(&message, 0, sizeof(message));
message.m_dwID = frame.frameId();
- message.m_bDLC = payload.size();
+ message.m_bDLC = quint8(payload.size());
message.m_bFF = frame.hasExtendedFrameFormat() ? USBCAN_MSG_FF_EXT : USBCAN_MSG_FF_STD;
@@ -454,6 +454,40 @@ bool SystecCanBackendPrivate::verifyBitRate(int bitrate)
return true;
}
+void SystecCanBackendPrivate::resetController()
+{
+ ::UcanResetCan(handle);
+}
+
+QCanBusDevice::CanBusStatus SystecCanBackendPrivate::busStatus()
+{
+ Q_Q(SystecCanBackend);
+
+ tStatusStruct status;
+ ::memset(&status, 0, sizeof(status));
+ const UCANRET result = ::UcanGetStatus(handle, &status);
+
+ if (Q_UNLIKELY(result != USBCAN_SUCCESSFUL)) {
+ qCWarning(QT_CANBUS_PLUGINS_SYSTECCAN, "Can not query CAN bus status.");
+ q->setError(SystecCanBackend::tr("Can not query CAN bus status."), QCanBusDevice::ConfigurationError);
+ return QCanBusDevice::CanBusStatus::Unknown;
+ }
+
+ if (status.m_wCanStatus & USBCAN_CANERR_BUSOFF)
+ return QCanBusDevice::CanBusStatus::BusOff;
+
+ if (status.m_wCanStatus & USBCAN_CANERR_BUSHEAVY)
+ return QCanBusDevice::CanBusStatus::Error;
+
+ if (status.m_wCanStatus & USBCAN_CANERR_BUSLIGHT)
+ return QCanBusDevice::CanBusStatus::Warning;
+
+ if (status.m_wCanStatus == USBCAN_CANERR_OK)
+ return QCanBusDevice::CanBusStatus::Good;
+
+ return QCanBusDevice::CanBusStatus::Unknown;
+}
+
SystecCanBackend::SystecCanBackend(const QString &name, QObject *parent) :
QCanBusDevice(parent),
d_ptr(new SystecCanBackendPrivate(this))
@@ -462,6 +496,12 @@ SystecCanBackend::SystecCanBackend(const QString &name, QObject *parent) :
d->setupChannel(name);
d->setupDefaultConfigurations();
+
+ std::function<void()> f = std::bind(&SystecCanBackend::resetController, this);
+ setResetControllerFunction(f);
+
+ std::function<CanBusStatus()> g = std::bind(&SystecCanBackend::busStatus, this);
+ setCanBusStatusGetter(g);
}
SystecCanBackend::~SystecCanBackend()
@@ -553,4 +593,17 @@ QString SystecCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
return QString();
}
+void SystecCanBackend::resetController()
+{
+ Q_D(SystecCanBackend);
+ d->resetController();
+}
+
+QCanBusDevice::CanBusStatus SystecCanBackend::busStatus()
+{
+ Q_D(SystecCanBackend);
+
+ return d->busStatus();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/systeccan/systeccanbackend.h b/src/plugins/canbus/systeccan/systeccanbackend.h
index cb62808..22c1193 100644
--- a/src/plugins/canbus/systeccan/systeccanbackend.h
+++ b/src/plugins/canbus/systeccan/systeccanbackend.h
@@ -76,6 +76,9 @@ public:
int channelNumber);
private:
+ void resetController();
+ QCanBusDevice::CanBusStatus busStatus();
+
SystecCanBackendPrivate * const d_ptr;
};
diff --git a/src/plugins/canbus/systeccan/systeccanbackend_p.h b/src/plugins/canbus/systeccan/systeccanbackend_p.h
index 28eb7ff..b2da322 100644
--- a/src/plugins/canbus/systeccan/systeccanbackend_p.h
+++ b/src/plugins/canbus/systeccan/systeccanbackend_p.h
@@ -94,6 +94,8 @@ public:
void startWrite();
void readAllReceivedMessages();
bool verifyBitRate(int bitrate);
+ void resetController();
+ QCanBusDevice::CanBusStatus busStatus();
SystecCanBackend * const q_ptr;
diff --git a/src/plugins/canbus/tinycan/tinycanbackend.cpp b/src/plugins/canbus/tinycan/tinycanbackend.cpp
index 3891186..411b917 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend.cpp
+++ b/src/plugins/canbus/tinycan/tinycanbackend.cpp
@@ -405,8 +405,7 @@ void TinyCanBackendPrivate::startRead()
} else {
if (status.CanStatus == CAN_STATUS_BUS_OFF) {
qCWarning(QT_CANBUS_PLUGINS_TINYCAN, "CAN bus is in off state, trying to reset the bus.");
- if (::CanSetMode(channelIndex, OP_CAN_RESET, CAN_CMD_NONE) < 0)
- q->setError(systemErrorString(ret), QCanBusDevice::CanBusError::ReadError);
+ resetController();
}
}
@@ -446,7 +445,8 @@ void TinyCanBackendPrivate::startupDriver()
::CanSetEvents(EVENT_ENABLE_RX_MESSAGES);
} else if (Q_UNLIKELY(driverRefCount < 0)) {
- qCritical("Wrong reference counter: %d", driverRefCount);
+ qCCritical(QT_CANBUS_PLUGINS_TINYCAN, "Wrong driver reference counter: %d",
+ driverRefCount);
return;
}
@@ -458,7 +458,8 @@ void TinyCanBackendPrivate::cleanupDriver()
--driverRefCount;
if (Q_UNLIKELY(driverRefCount < 0)) {
- qCritical("Wrong reference counter: %d", driverRefCount);
+ qCCritical(QT_CANBUS_PLUGINS_TINYCAN, "Wrong driver reference counter: %d",
+ driverRefCount);
driverRefCount = 0;
} else if (driverRefCount == 0) {
::CanSetEvents(EVENT_DISABLE_ALL);
@@ -466,6 +467,18 @@ void TinyCanBackendPrivate::cleanupDriver()
}
}
+void TinyCanBackendPrivate::resetController()
+{
+ Q_Q(TinyCanBackend);
+ qint32 ret = ::CanSetMode(channelIndex, OP_CAN_RESET, CAN_CMD_NONE);
+ if (Q_UNLIKELY(ret < 0)) {
+ const QString errorString = systemErrorString(ret);
+ qCWarning(QT_CANBUS_PLUGINS_TINYCAN, "Cannot perform hardware reset: %ls",
+ qUtf16Printable(errorString));
+ q->setError(errorString, QCanBusDevice::CanBusError::ConfigurationError);
+ }
+}
+
bool TinyCanBackendPrivate::setBitRate(int bitrate)
{
Q_Q(TinyCanBackend);
@@ -496,6 +509,9 @@ TinyCanBackend::TinyCanBackend(const QString &name, QObject *parent)
d->setupChannel(name);
d->setupDefaultConfigurations();
+
+ std::function<void()> f = std::bind(&TinyCanBackend::resetController, this);
+ setResetControllerFunction(f);
}
TinyCanBackend::~TinyCanBackend()
@@ -589,4 +605,10 @@ QString TinyCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
return QString();
}
+void TinyCanBackend::resetController()
+{
+ Q_D(TinyCanBackend);
+ d->resetController();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/tinycan/tinycanbackend.h b/src/plugins/canbus/tinycan/tinycanbackend.h
index 5f504ca..428e9bc 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend.h
+++ b/src/plugins/canbus/tinycan/tinycanbackend.h
@@ -72,6 +72,8 @@ public:
static QList<QCanBusDeviceInfo> interfaces();
private:
+ void resetController();
+
TinyCanBackendPrivate * const d_ptr;
};
diff --git a/src/plugins/canbus/tinycan/tinycanbackend_p.h b/src/plugins/canbus/tinycan/tinycanbackend_p.h
index 905175c..25316a2 100644
--- a/src/plugins/canbus/tinycan/tinycanbackend_p.h
+++ b/src/plugins/canbus/tinycan/tinycanbackend_p.h
@@ -75,6 +75,7 @@ public:
void startRead();
void startupDriver();
void cleanupDriver();
+ void resetController();
bool setBitRate(int bitrate);
diff --git a/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h b/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h
index 3f2501f..8c1ad52 100644
--- a/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h
+++ b/src/plugins/canbus/vectorcan/vectorcan_symbols_p.h
@@ -249,9 +249,27 @@ static_assert(sizeof(s_xl_can_msg) == 32, "Invalid size of s_xl_can_msg structur
#define XL_TRANSCEIVER_EVENT_ERROR 1
#define XL_TRANSCEIVER_EVENT_CHANGED 2
+#define XL_CHIPSTAT_BUSOFF 0x01
+#define XL_CHIPSTAT_ERROR_PASSIVE 0x02
+#define XL_CHIPSTAT_ERROR_WARNING 0x04
+#define XL_CHIPSTAT_ERROR_ACTIVE 0x08
+
+#define XL_CAN_STATE_FLAG_SJA_MODE 0x00000001
+
+// CAN Chip status
+struct s_xl_chip_state {
+ unsigned char busStatus;
+ unsigned char txErrorCounter;
+ unsigned char rxErrorCounter;
+ unsigned char chipState; // raw Status Register Value
+ unsigned int flags;
+};
+static_assert(sizeof(s_xl_chip_state) == 8, "Invalid size of s_xl_chip_state structure");
+
// basic bus message structure
union s_xl_tag_data {
struct s_xl_can_msg msg;
+ struct s_xl_chip_state chipState;
};
// event type definition (48 bytes)
@@ -456,6 +474,7 @@ GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanSetChannelBitrate, XLportHandle, XLacces
GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanTransmit, XLportHandle, XLaccess, quint32 *, void *)
GENERATE_SYMBOL_VARIABLE(XLstatus, xlReceive, XLportHandle, quint32 *, XLevent *)
GENERATE_SYMBOL_VARIABLE(XLstatus, xlSetNotification, XLportHandle, XLhandle *, int)
+GENERATE_SYMBOL_VARIABLE(XLstatus, xlCanRequestChipState, XLportHandle, XLaccess)
GENERATE_SYMBOL_VARIABLE(char *, xlGetErrorString, XLstatus)
inline bool resolveSymbols(QLibrary *vectorcanLibrary)
@@ -481,6 +500,7 @@ inline bool resolveSymbols(QLibrary *vectorcanLibrary)
RESOLVE_SYMBOL(xlCanTransmit)
RESOLVE_SYMBOL(xlReceive)
RESOLVE_SYMBOL(xlSetNotification)
+ RESOLVE_SYMBOL(xlCanRequestChipState)
RESOLVE_SYMBOL(xlGetErrorString)
return true;
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
index 9026888..9d3bdef 100644
--- a/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend.cpp
@@ -271,7 +271,8 @@ void VectorCanBackendPrivate::setupChannel(const QString &interfaceName)
}
}
- qCritical("Unable to parse the channel %ls", qUtf16Printable(interfaceName));
+ qCCritical(QT_CANBUS_PLUGINS_VECTORCAN, "Unable to parse the channel %ls",
+ qUtf16Printable(interfaceName));
}
void VectorCanBackendPrivate::setupDefaultConfigurations()
@@ -388,7 +389,8 @@ XLstatus VectorCanBackendPrivate::loadDriver()
return status;
} else if (Q_UNLIKELY(driverRefCount < 0)) {
- qCritical("Wrong reference counter: %d", driverRefCount);
+ qCCritical(QT_CANBUS_PLUGINS_VECTORCAN, "Wrong driver reference counter: %d",
+ driverRefCount);
return XL_ERR_CANNOT_OPEN_DRIVER;
}
@@ -412,7 +414,8 @@ void VectorCanBackendPrivate::cleanupDriver()
--driverRefCount;
if (Q_UNLIKELY(driverRefCount < 0)) {
- qCritical("Wrong reference counter: %d", driverRefCount);
+ qCCritical(QT_CANBUS_PLUGINS_VECTORCAN, "Wrong driver reference counter: %d",
+ driverRefCount);
driverRefCount = 0;
} else if (driverRefCount == 0) {
::xlCloseDriver();
@@ -443,6 +446,9 @@ VectorCanBackend::VectorCanBackend(const QString &name, QObject *parent)
d->setupChannel(name);
d->setupDefaultConfigurations();
+
+ std::function<CanBusStatus()> g = std::bind(&VectorCanBackend::busStatus, this);
+ setCanBusStatusGetter(g);
}
VectorCanBackend::~VectorCanBackend()
@@ -537,4 +543,48 @@ QString VectorCanBackend::interpretErrorFrame(const QCanBusFrame &errorFrame)
return QString();
}
+QCanBusDevice::CanBusStatus VectorCanBackend::busStatus()
+{
+ Q_D(VectorCanBackend);
+
+ const XLstatus requestStatus = ::xlCanRequestChipState(d->portHandle, d->channelMask);
+ if (Q_UNLIKELY(requestStatus != XL_SUCCESS)) {
+ const QString errorString = d->systemErrorString(requestStatus);
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Can not query CAN bus status: %ls.",
+ qUtf16Printable(errorString));
+ setError(errorString, QCanBusDevice::CanBusError::ReadError);
+ return QCanBusDevice::CanBusStatus::Unknown;
+ }
+
+ quint32 eventCount = 1;
+ XLevent event;
+ ::memset(&event, 0, sizeof(event));
+
+ const XLstatus receiveStatus = ::xlReceive(d->portHandle, &eventCount, &event);
+ if (Q_UNLIKELY(receiveStatus != XL_SUCCESS)) {
+ const QString errorString = d->systemErrorString(receiveStatus);
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Can not query CAN bus status: %ls.",
+ qUtf16Printable(errorString));
+ setError(errorString, QCanBusDevice::CanBusError::ReadError);
+ return QCanBusDevice::CanBusStatus::Unknown;
+ }
+
+ if (Q_LIKELY(event.tag == XL_CHIP_STATE)) {
+ switch (event.tagData.chipState.busStatus) {
+ case XL_CHIPSTAT_BUSOFF:
+ return QCanBusDevice::CanBusStatus::BusOff;
+ case XL_CHIPSTAT_ERROR_PASSIVE:
+ return QCanBusDevice::CanBusStatus::Error;
+ case XL_CHIPSTAT_ERROR_WARNING:
+ return QCanBusDevice::CanBusStatus::Warning;
+ case XL_CHIPSTAT_ERROR_ACTIVE:
+ return QCanBusDevice::CanBusStatus::Good;
+ }
+ }
+
+ qCWarning(QT_CANBUS_PLUGINS_VECTORCAN, "Unknown CAN bus status: %u",
+ uint(event.tagData.chipState.busStatus));
+ return QCanBusDevice::CanBusStatus::Unknown;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/canbus/vectorcan/vectorcanbackend.h b/src/plugins/canbus/vectorcan/vectorcanbackend.h
index 165d369..89b9da6 100644
--- a/src/plugins/canbus/vectorcan/vectorcanbackend.h
+++ b/src/plugins/canbus/vectorcan/vectorcanbackend.h
@@ -71,6 +71,8 @@ public:
static QList<QCanBusDeviceInfo> interfaces();
private:
+ QCanBusDevice::CanBusStatus busStatus();
+
VectorCanBackendPrivate * const d_ptr;
};
diff --git a/src/serialbus/doc/src/peakcan.qdoc b/src/serialbus/doc/src/peakcan.qdoc
index fd12ab7..a38ddf7 100644
--- a/src/serialbus/doc/src/peakcan.qdoc
+++ b/src/serialbus/doc/src/peakcan.qdoc
@@ -34,8 +34,9 @@
\l{http://www.peak-system.com/}{PEAK-System} CAN adapters.
This plugin requires the PCAN device drivers and the PCAN-Basic library
- version 4.0.0 or higher. Supported platforms are Windows (pcanbasic.dll)
- and Linux (libpcanbasic.so).
+ version 4.0.0 or higher on Windows (pcanbasic.dll) and Linux (libpcanbasic.so).
+ On macOS the plugin requires the PCBUSB library from
+ \l{http://www.mac-can.com}{UV Software}.
\section1 Creating CAN Bus Devices
@@ -70,6 +71,8 @@
\note Only the USB and PCI adapters are currently supported by this plugin.
+ \note On macOS, only USB adapters are currently supported by this plugin.
+
The device is now open for writing and reading CAN frames:
\code
@@ -117,4 +120,12 @@
this configuration parameter can only be adjusted while the QCanBusDevice is
not connected.
\endtable
+
+ PeakCAN supports the following additional functions:
+
+ \list
+ \li QCanBusDevice::resetController()
+ \li QCanBusDevice::busStatus()
+ \endlist
+
*/
diff --git a/src/serialbus/doc/src/socketcan.qdoc b/src/serialbus/doc/src/socketcan.qdoc
index df58dae..e578969 100644
--- a/src/serialbus/doc/src/socketcan.qdoc
+++ b/src/serialbus/doc/src/socketcan.qdoc
@@ -179,9 +179,13 @@
By default, the connection is configured to accept any CAN bus message.
\row
\li QCanBusDevice::BitRateKey
- \li This configuration is not supported by the socketcan plugin. However
- it is possible to set the rate when configuring the CAN network interface using
- the \c {ip link} command.
+ \li Determines the bit rate of the CAN bus connection. The following bit rates
+ are supported: 5000, 10000, 20000, 33000, 47000, 50000, 83000, 95000,
+ 100000, 125000, 250000, 500000, 800000, 1000000. Note that this configuration
+ parameter can only be adjusted while the QCanBusDevice is not connected. To set
+ this configuration parameter, the library libsocketcan is needed at runtime
+ http://www.pengutronix.de/software/libsocketcan
+ Usually, root rights are needed to set the CAN bus bitrate.
\row
\li QCanBusDevice::CanFdKey
\li This configuration option determines whether CANFD frames may be sent or received.
@@ -192,6 +196,10 @@
\li This configuration is not supported by the socketcan plugin. However
it is possible to set the data rate when configuring the CAN network interface
using the \c {ip link} command.
+ \row
+ \li QCanBusDevice::ProtocolKey
+ \li Allows to use another protocol inside the protocol family PF_CAN. The default
+ value for this configuration option is CAN_RAW (1).
\endtable
For example:
@@ -199,4 +207,12 @@
\snippet snippetmain.cpp SocketCan Filter Example
Extended frame format and flexible data-rate are supported in SocketCAN.
- */
+
+ SocketCAN supports the following additional functions:
+
+ \list
+ \li QCanBusDevice::resetController() (needs libsocketcan)
+ \li QCanBusDevice::busStatus() (needs libsocketcan)
+ \endlist
+
+*/
diff --git a/src/serialbus/doc/src/systeccan.qdoc b/src/serialbus/doc/src/systeccan.qdoc
index af34665..dc66023 100644
--- a/src/serialbus/doc/src/systeccan.qdoc
+++ b/src/serialbus/doc/src/systeccan.qdoc
@@ -109,4 +109,12 @@
is disabled by default. If this option is enabled, the therefore received frames
are marked with QCanBusFrame::hasLocalEcho()
\endtable
+
+ SystecCAN supports the following additional functions:
+
+ \list
+ \li QCanBusDevice::resetController()
+ \li QCanBusDevice::busStatus()
+ \endlist
+
*/
diff --git a/src/serialbus/doc/src/tinycan.qdoc b/src/serialbus/doc/src/tinycan.qdoc
index 43349dc..8479576 100644
--- a/src/serialbus/doc/src/tinycan.qdoc
+++ b/src/serialbus/doc/src/tinycan.qdoc
@@ -95,4 +95,11 @@
\li Determines the bit rate of the CAN bus connection. The following bit rates
are supported: 10000, 20000, 50000, 100000, 125000, 250000, 500000, 800000, 1000000.
\endtable
- */
+
+ TinyCAN supports the following additional functions:
+
+ \list
+ \li QCanBusDevice::resetController()
+ \endlist
+
+*/
diff --git a/src/serialbus/doc/src/vectorcan.qdoc b/src/serialbus/doc/src/vectorcan.qdoc
index eb4acdd..70b6521 100644
--- a/src/serialbus/doc/src/vectorcan.qdoc
+++ b/src/serialbus/doc/src/vectorcan.qdoc
@@ -106,4 +106,11 @@
was successful. If this option is enabled, the therefore received frames are marked
with QCanBusFrame::hasLocalEcho()
\endtable
+
+ VectorCAN supports the following additional functions:
+
+ \list
+ \li QCanBusDevice::busStatus()
+ \endlist
+
*/
diff --git a/src/serialbus/qcanbusdevice.cpp b/src/serialbus/qcanbusdevice.cpp
index 6723f77..222f19c 100644
--- a/src/serialbus/qcanbusdevice.cpp
+++ b/src/serialbus/qcanbusdevice.cpp
@@ -73,6 +73,11 @@ Q_LOGGING_CATEGORY(QT_CANBUS, "qt.canbus")
\value ConfigurationError An error occurred when attempting to set a configuration
parameter.
\value UnknownError An unknown error occurred.
+ \value OperationError An operation was attempted while the device was in
+ a state that did not permit it. This enum was introduced
+ in Qt 5.14.
+ \value TimeoutError An timeout occurred while waiting for frames written or
+ received. This enum was introduced in Qt 5.14.
*/
/*!
@@ -118,6 +123,9 @@ Q_LOGGING_CATEGORY(QT_CANBUS, "qt.canbus")
after the arbitration phase at the nominal bitrate is finished.
This enum value was introduced in Qt 5.9.
See also \c QCanBusDevice::BitRateKey
+ \value ProtocolKey This key allows to specify another protocol. For now, this
+ parameter can only be set and used in the SocketCAN plugin.
+ This enum value was introduced in Qt 5.14.
\value UserKey This key defines the range where custom keys start. Its most
common purpose is to permit platform-specific configuration
options.
@@ -142,6 +150,22 @@ Q_LOGGING_CATEGORY(QT_CANBUS, "qt.canbus")
*/
/*!
+ \fn bool operator==(const QCanBusDevice::Filter &a, const QCanBusDevice::Filter &b)
+ \relates QCanBusDevice::Filter
+
+ Returns true, if the filter \a a is equal to the filter \a b,
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool operator!=(const QCanBusDevice::Filter &a, const QCanBusDevice::Filter &b)
+ \relates QCanBusDevice::Filter
+
+ Returns true, if the filter \a a is not equal to the filter \a b,
+ otherwise returns false.
+*/
+
+/*!
\enum QCanBusDevice::Filter::FormatFilter
This enum describes the format pattern, which is used to filter incoming
CAN bus frames.
@@ -231,7 +255,7 @@ QCanBusDevice::QCanBusDevice(QObject *parent) :
CAN bus implementations must use this function to update the device's
error state.
- \sa error(), errorOccurred()
+ \sa error(), errorOccurred(), clearError()
*/
void QCanBusDevice::setError(const QString &errorText, CanBusError errorId)
{
@@ -244,6 +268,24 @@ void QCanBusDevice::setError(const QString &errorText, CanBusError errorId)
}
/*!
+ \since 5.14
+ Clears the error id and the human readable description of the last
+ device error.
+
+ CAN bus implementations must use this function to update the device's
+ error state.
+
+ \sa error(), errorOccurred(), setError()
+*/
+void QCanBusDevice::clearError()
+{
+ Q_D(QCanBusDevice);
+
+ d->errorText.clear();
+ d->lastError = NoError;
+}
+
+/*!
Appends \a newFrames to the internal list of frames which can be
accessed using \l readFrame() and emits the \l framesReceived()
signal.
@@ -303,6 +345,30 @@ bool QCanBusDevice::hasOutgoingFrames() const
}
/*!
+ * \since 5.14
+ * Called from the derived plugin to register a function that performs the
+ * CAN controller hardware reset when \a resetController() is called.
+ */
+void QCanBusDevice::setResetControllerFunction(std::function<void()> resetter)
+{
+ Q_D(QCanBusDevice);
+
+ d->m_resetControllerFunction = std::move(resetter);
+}
+
+/*!
+ * \since 5.14
+ * Called from the derived plugin to register a function that returns the
+ * CAN controller bus status when \a busStatus() is called.
+ */
+void QCanBusDevice::setCanBusStatusGetter(std::function<CanBusStatus()> busStatusGetter)
+{
+ Q_D(QCanBusDevice);
+
+ d->m_busStatusGetter = std::move(busStatusGetter);
+}
+
+/*!
Sets the configuration parameter \a key for the CAN bus connection
to \a value. The potential keys are represented by \l ConfigurationKey.
@@ -428,6 +494,82 @@ qint64 QCanBusDevice::framesToWrite() const
}
/*!
+ \since 5.14
+
+ Performs a CAN controller reset to release the CAN controller from
+ bus off state, if possible.
+
+ \note CAN controller resets disturb the running communication and
+ may take up to one second to complete. Only call this function to
+ recover from bus errors.
+
+ \note This function may not be implemented in all CAN plugins.
+ Please refer to the plugins help pages for more information.
+
+ \sa busStatus()
+*/
+void QCanBusDevice::resetController()
+{
+ if (d_func()->m_resetControllerFunction) {
+ d_func()->m_resetControllerFunction();
+ } else {
+ const char error[] = QT_TRANSLATE_NOOP("QCanBusDevice",
+ "This CAN bus plugin does not support hardware controller reset.");
+ qCWarning(QT_CANBUS, error);
+ setError(tr(error), QCanBusDevice::CanBusError::ConfigurationError);
+ }
+}
+
+/*!
+ \since 5.14
+
+ Return true, if the CAN plugin supports requesting the CAN bus status.
+
+ \sa busStatus()
+ */
+bool QCanBusDevice::hasBusStatus() const
+{
+ return d_func()->m_busStatusGetter != nullptr;
+}
+
+/*!
+ \since 5.14
+ \enum QCanBusDevice::CanBusStatus
+
+ This enum describes possible CAN bus status values.
+
+ \value Unknown The CAN bus status is unknown
+ (e.g. not supported by the CAN plugin).
+ \value Good The CAN controller is fully operational
+ \value Warning The CAN controller is in warning status
+ \value Error The CAN controller is in error status
+ (no longer sending CAN frames)
+ \value BusOff The CAN controller is in bus off status
+ (disconnected from the CAN bus)
+*/
+
+/*!
+ \since 5.14
+
+ Returns the current CAN bus status. If the status cannot be requested,
+ QCanBusDevice::UnknownStatus is returned.
+
+ \note This function may not be implemented in all CAN plugins.
+ Please refer to the plugins help pages for more information.
+ The function hasBusStatus() can be used at runtime to check if
+ the used CAN plugin has support for requesting the CAN bus status.
+
+ \sa hasBusStatus(), hardwareControllerReset()
+*/
+QCanBusDevice::CanBusStatus QCanBusDevice::busStatus() const
+{
+ if (d_func()->m_busStatusGetter)
+ return d_func()->m_busStatusGetter();
+
+ return QCanBusDevice::CanBusStatus::Unknown;
+}
+
+/*!
\since 5.12
\enum QCanBusDevice::Direction
@@ -454,8 +596,14 @@ void QCanBusDevice::clear(QCanBusDevice::Directions direction)
{
Q_D(QCanBusDevice);
- if (Q_UNLIKELY(d->state != ConnectedState))
+ if (Q_UNLIKELY(d->state != ConnectedState)) {
+ const QString error = tr("Cannot clear buffers as device is not connected.");
+ qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
+ setError(error, CanBusError::OperationError);
return;
+ }
+
+ clearError();
if (direction & Direction::Input) {
QMutexLocker(&d->incomingFramesGuard);
@@ -492,31 +640,46 @@ bool QCanBusDevice::waitForFramesWritten(int msecs)
"recursively. Check that no slot containing waitForFramesReceived() "
"is called in response to framesWritten(qint64) or "
"errorOccurred(CanBusError) signals.");
+ setError(tr("QCanBusDevice::waitForFramesWritten() must not be called recursively."),
+ CanBusError::OperationError);
return false;
}
- QScopedValueRollback<bool> guard(d_func()->waitForWrittenEntered);
- d_func()->waitForWrittenEntered = true;
-
- if (d_func()->state != ConnectedState)
+ if (Q_UNLIKELY(d_func()->state != ConnectedState)) {
+ const QString error = tr("Cannot wait for frames written as device is not connected.");
+ qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
+ setError(error, CanBusError::OperationError);
return false;
+ }
if (!framesToWrite())
return false; // nothing pending, nothing to wait upon
+ QScopedValueRollback<bool> guard(d_func()->waitForWrittenEntered);
+ d_func()->waitForWrittenEntered = true;
+
+ enum { Written = 0, Error, Timeout };
QEventLoop loop;
- connect(this, &QCanBusDevice::framesWritten, &loop, [&]() { loop.exit(0); });
- connect(this, &QCanBusDevice::errorOccurred, &loop, [&]() { loop.exit(1); });
+ connect(this, &QCanBusDevice::framesWritten, &loop, [&]() { loop.exit(Written); });
+ connect(this, &QCanBusDevice::errorOccurred, &loop, [&]() { loop.exit(Error); });
if (msecs >= 0)
- QTimer::singleShot(msecs, &loop, [&]() { loop.exit(2); });
+ QTimer::singleShot(msecs, &loop, [&]() { loop.exit(Timeout); });
- int result = 0;
+ int result = Written;
while (framesToWrite() > 0) {
// wait till all written or time out
result = loop.exec(QEventLoop::ExcludeUserInputEvents);
- if (result > 0)
+ if (Q_UNLIKELY(result == Timeout)) {
+ const QString error = tr("Timeout (%1 ms) during wait for frames written.").arg(msecs);
+ setError(error, CanBusError::TimeoutError);
+ qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
+ }
+
+ if (result > Written)
return false;
}
+
+ clearError();
return true;
}
@@ -545,25 +708,39 @@ bool QCanBusDevice::waitForFramesReceived(int msecs)
"recursively. Check that no slot containing waitForFramesReceived() "
"is called in response to framesReceived() or "
"errorOccurred(CanBusError) signals.");
+ setError(tr("QCanBusDevice::waitForFramesReceived() must not be called recursively."),
+ CanBusError::OperationError);
+ return false;
+ }
+
+ if (Q_UNLIKELY(d_func()->state != ConnectedState)) {
+ const QString error = tr("Cannot wait for frames received as device is not connected.");
+ qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
+ setError(error, CanBusError::OperationError);
return false;
}
QScopedValueRollback<bool> guard(d_func()->waitForReceivedEntered);
d_func()->waitForReceivedEntered = true;
- if (d_func()->state != ConnectedState)
- return false;
-
+ enum { Received = 0, Error, Timeout };
QEventLoop loop;
-
- connect(this, &QCanBusDevice::framesReceived, &loop, [&]() { loop.exit(0); });
- connect(this, &QCanBusDevice::errorOccurred, &loop, [&]() { loop.exit(1); });
+ connect(this, &QCanBusDevice::framesReceived, &loop, [&]() { loop.exit(Received); });
+ connect(this, &QCanBusDevice::errorOccurred, &loop, [&]() { loop.exit(Error); });
if (msecs >= 0)
- QTimer::singleShot(msecs, &loop, [&]() { loop.exit(2); });
+ QTimer::singleShot(msecs, &loop, [&]() { loop.exit(Timeout); });
int result = loop.exec(QEventLoop::ExcludeUserInputEvents);
- return result == 0;
+ if (Q_UNLIKELY(result == Timeout)) {
+ const QString error = tr("Timeout (%1 ms) during wait for frames received.").arg(msecs);
+ setError(error, CanBusError::TimeoutError);
+ qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
+ }
+
+ if (result == Received)
+ clearError();
+ return result == Received;
}
/*!
@@ -619,8 +796,14 @@ QCanBusFrame QCanBusDevice::readFrame()
{
Q_D(QCanBusDevice);
- if (Q_UNLIKELY(d->state != ConnectedState))
+ if (Q_UNLIKELY(d->state != ConnectedState)) {
+ const QString error = tr("Cannot read frame as device is not connected.");
+ qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
+ setError(error, CanBusError::OperationError);
return QCanBusFrame(QCanBusFrame::InvalidFrame);
+ }
+
+ clearError();
QMutexLocker locker(&d->incomingFramesGuard);
@@ -643,8 +826,14 @@ QVector<QCanBusFrame> QCanBusDevice::readAllFrames()
{
Q_D(QCanBusDevice);
- if (Q_UNLIKELY(d->state != ConnectedState))
+ if (Q_UNLIKELY(d->state != ConnectedState)) {
+ const QString error = tr("Cannot read frame as device is not connected.");
+ qCWarning(QT_CANBUS, "%ls", qUtf16Printable(error));
+ setError(error, CanBusError::OperationError);
return QVector<QCanBusFrame>();
+ }
+
+ clearError();
QMutexLocker locker(&d->incomingFramesGuard);
@@ -675,9 +864,10 @@ QVector<QCanBusFrame> QCanBusDevice::readAllFrames()
As per CAN bus specification, frames of type
\l {QCanBusFrame::RemoteRequestFrame} {remote transfer request (RTR)}
- do not have a payload, but a length from 0 to 8 (including). This length indicates
- the expected response payload length from the remote party. Therefore when sending a RTR frame using
- this function it may still be required to set an arbitrary payload on \a frame. The length of
+ do not have a payload, but a length from 0 to 8 (including). This length
+ indicates the expected response payload length from the remote party.
+ Therefore when sending a RTR frame using this function it may still
+ be required to set an arbitrary payload on \a frame. The length of
the arbitrary payload is what is set as size expectation for the RTR frame.
\sa QCanBusFrame::setPayload()
@@ -705,8 +895,10 @@ bool QCanBusDevice::connectDevice()
Q_D(QCanBusDevice);
if (Q_UNLIKELY(d->state != QCanBusDevice::UnconnectedState)) {
- setError(tr("Can not connect an already connected device"),
- QCanBusDevice::ConnectionError);
+ const char error[] = QT_TRANSLATE_NOOP("QCanBusDevice",
+ "Can not connect an already connected device.");
+ qCWarning(QT_CANBUS, error);
+ setError(tr(error), QCanBusDevice::ConnectionError);
return false;
}
@@ -717,6 +909,8 @@ bool QCanBusDevice::connectDevice()
return false;
}
+ clearError();
+
//Connected is set by backend -> might be delayed by event loop
return true;
}
diff --git a/src/serialbus/qcanbusdevice.h b/src/serialbus/qcanbusdevice.h
index a47fac4..5d2d976 100644
--- a/src/serialbus/qcanbusdevice.h
+++ b/src/serialbus/qcanbusdevice.h
@@ -41,6 +41,8 @@
#include <QtSerialBus/qcanbusframe.h>
#include <QtSerialBus/qcanbusdeviceinfo.h>
+#include <functional>
+
QT_BEGIN_NAMESPACE
class QCanBusDevicePrivate;
@@ -58,7 +60,9 @@ public:
WriteError,
ConnectionError,
ConfigurationError,
- UnknownError
+ UnknownError,
+ OperationError,
+ TimeoutError
};
Q_ENUM(CanBusError)
@@ -70,6 +74,15 @@ public:
};
Q_ENUM(CanBusDeviceState)
+ enum class CanBusStatus {
+ Unknown,
+ Good,
+ Warning,
+ Error,
+ BusOff
+ };
+ Q_ENUM(CanBusStatus)
+
enum ConfigurationKey {
RawFilterKey = 0,
ErrorFilterKey,
@@ -78,12 +91,24 @@ public:
BitRateKey,
CanFdKey,
DataBitRateKey,
+ ProtocolKey,
UserKey = 30
};
Q_ENUM(ConfigurationKey)
struct Filter
{
+ friend constexpr bool operator==(const Filter &a, const Filter &b) noexcept
+ {
+ return a.frameId == b.frameId && a.frameIdMask == b.frameIdMask
+ && a.type == b.type && a.format == b.format;
+ }
+
+ friend constexpr bool operator!=(const Filter &a, const Filter &b) noexcept
+ {
+ return !operator==(a, b);
+ }
+
enum FormatFilter {
MatchBaseFormat = 0x0001,
MatchExtendedFormat = 0x0002,
@@ -109,6 +134,10 @@ public:
qint64 framesAvailable() const;
qint64 framesToWrite() const;
+ void resetController();
+ bool hasBusStatus() const;
+ QCanBusDevice::CanBusStatus busStatus() const;
+
enum Direction {
Input = 1,
Output = 2,
@@ -140,6 +169,7 @@ Q_SIGNALS:
protected:
void setState(QCanBusDevice::CanBusDeviceState newState);
void setError(const QString &errorText, QCanBusDevice::CanBusError);
+ void clearError();
void enqueueReceivedFrames(const QVector<QCanBusFrame> &newFrames);
@@ -152,6 +182,9 @@ protected:
virtual bool open() = 0;
virtual void close() = 0;
+ void setResetControllerFunction(std::function<void()> resetter);
+ void setCanBusStatusGetter(std::function<CanBusStatus()> busStatusGetter);
+
static QCanBusDeviceInfo createDeviceInfo(const QString &name,
bool isVirtual = false,
bool isFlexibleDataRateCapable = false);
diff --git a/src/serialbus/qcanbusdevice_p.h b/src/serialbus/qcanbusdevice_p.h
index faeae65..e74168c 100644
--- a/src/serialbus/qcanbusdevice_p.h
+++ b/src/serialbus/qcanbusdevice_p.h
@@ -74,6 +74,9 @@ public:
bool waitForReceivedEntered = false;
bool waitForWrittenEntered = false;
+
+ std::function<void()> m_resetControllerFunction;
+ std::function<QCanBusDevice::CanBusStatus()> m_busStatusGetter;
};
QT_END_NAMESPACE
diff --git a/src/serialbus/qmodbusdevice.cpp b/src/serialbus/qmodbusdevice.cpp
index 9891d16..ab8e126 100644
--- a/src/serialbus/qmodbusdevice.cpp
+++ b/src/serialbus/qmodbusdevice.cpp
@@ -98,8 +98,8 @@ QModbusDevice::~QModbusDevice()
User options:
- \value UserParameter The first parameter that can be used for user-specific
- purposes. \c QVariant
+ \value UserParameter This enum value has been deprecated. There
+ will be no replacement.
*/
/*!
@@ -143,7 +143,7 @@ QVariant QModbusDevice::connectionParameter(int parameter) const
default:
break;
}
- return d->m_userConnectionParams.value(parameter);
+ return d->m_userConnectionParams.value(parameter); // ### Qt6: remove
}
/*!
@@ -182,7 +182,7 @@ void QModbusDevice::setConnectionParameter(int parameter, const QVariant &value)
d->m_networkAddress = value.toString();
break;
default:
- d->m_userConnectionParams.insert(parameter, value);
+ d->m_userConnectionParams.insert(parameter, value); // ### Qt6: remove
break;
}
}
@@ -337,6 +337,20 @@ QString QModbusDevice::errorString() const
}
/*!
+ \since 5.14
+
+ Returns the underlying \l QIODevice used for ModBus communication or
+ \c nullptr if the device was not yet fully initialized.
+
+ \note Do not store a pointer to the underlying device, because it can be
+ invalidated at any point in time.
+*/
+QIODevice *QModbusDevice::device() const
+{
+ return d_func()->device();
+}
+
+/*!
\fn bool QModbusDevice::open()
This function is called by connectDevice(). Subclasses must provide
diff --git a/src/serialbus/qmodbusdevice.h b/src/serialbus/qmodbusdevice.h
index 468fdf4..0e6dad7 100644
--- a/src/serialbus/qmodbusdevice.h
+++ b/src/serialbus/qmodbusdevice.h
@@ -82,7 +82,7 @@ public:
NetworkAddressParameter,
// Reserved
- UserParameter = 0x100
+ UserParameter = 0x100 // ### Qt6: remove
};
Q_ENUM(ConnectionParameter)
@@ -100,6 +100,8 @@ public:
Error error() const;
QString errorString() const;
+ QIODevice *device() const;
+
Q_SIGNALS:
void errorOccurred(QModbusDevice::Error error);
void stateChanged(QModbusDevice::State state);
diff --git a/src/serialbus/qmodbusdevice_p.h b/src/serialbus/qmodbusdevice_p.h
index a845a89..1526397 100644
--- a/src/serialbus/qmodbusdevice_p.h
+++ b/src/serialbus/qmodbusdevice_p.h
@@ -78,7 +78,9 @@ public:
int m_networkPort = 502;
QString m_networkAddress = QStringLiteral("127.0.0.1");
- QHash<int, QVariant> m_userConnectionParams;
+ QHash<int, QVariant> m_userConnectionParams; // ### Qt6: remove
+
+ virtual QIODevice *device() const { return nullptr; }
};
QT_END_NAMESPACE
diff --git a/src/serialbus/qmodbuspdu.cpp b/src/serialbus/qmodbuspdu.cpp
index c42352d..9ca9027 100644
--- a/src/serialbus/qmodbuspdu.cpp
+++ b/src/serialbus/qmodbuspdu.cpp
@@ -106,9 +106,9 @@ static int minimumDataSize(const QModbusPdu &pdu, Type type)
static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type type)
{
quint8 codeByte = 0;
- if (stream.readRawData((char *) (&codeByte), sizeof(quint8)) != sizeof(quint8))
+ if (stream.readRawData(reinterpret_cast<char *>(&codeByte), sizeof(quint8)) != sizeof(quint8))
return stream;
- QModbusPdu::FunctionCode code = (QModbusPdu::FunctionCode) codeByte;
+ QModbusPdu::FunctionCode code = QModbusPdu::FunctionCode(codeByte);
pdu.setFunctionCode(code);
auto needsAdditionalRead = [](QModbusPdu &pdu, int size) -> bool {
@@ -157,13 +157,13 @@ static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type typ
return stream; // early return to avoid second read
}
} else {
- data.resize(stream.device()->size() - 1); // One byte for the function code.
+ data.resize(int(stream.device()->size() - 1)); // One byte for the function code.
}
} else if (pdu.functionCode() == QModbusPdu::Diagnostics) {
quint16 subCode;
pdu.decodeData(&subCode);
if (subCode == Diagnostics::ReturnQueryData)
- data.resize(stream.device()->size() - 1); // One byte for the function code.
+ 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
@@ -439,7 +439,7 @@ static QDataStream &pduFromStream(QDataStream &stream, QModbusPdu &pdu, Type typ
QDebug operator<<(QDebug debug, const QModbusPdu &pdu)
{
QDebugStateSaver _(debug);
- debug.nospace().noquote() << "0x" << hex << qSetFieldWidth(2) << qSetPadChar('0')
+ debug.nospace().noquote() << "0x" << Qt::hex << qSetFieldWidth(2) << qSetPadChar('0')
<< (pdu.isException() ? pdu.functionCode() | QModbusPdu::ExceptionByte : pdu.functionCode())
<< qSetFieldWidth(0) << pdu.data().toHex();
return debug;
@@ -547,7 +547,7 @@ int QModbusRequest::minimumDataSize(const QModbusRequest &request)
int QModbusRequest::calculateDataSize(const QModbusRequest &request)
{
if (requestSizeCalculators.exists()) {
- if (auto ptr = requestSizeCalculators()->value(request.functionCode(), nullptr))
+ if (auto ptr = requestSizeCalculators()->value(quint8(request.functionCode()), nullptr))
return ptr(request);
}
@@ -604,7 +604,7 @@ int QModbusRequest::calculateDataSize(const QModbusRequest &request)
*/
void QModbusRequest::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr calculator)
{
- requestSizeCalculators()->insert(fc, calculator);
+ requestSizeCalculators()->insert(quint8(fc), calculator);
}
/*!
@@ -703,7 +703,7 @@ int QModbusResponse::minimumDataSize(const QModbusResponse &response)
int QModbusResponse::calculateDataSize(const QModbusResponse &response)
{
if (responseSizeCalculators.exists()) {
- if (auto ptr = responseSizeCalculators()->value(response.functionCode(), nullptr))
+ if (auto ptr = responseSizeCalculators()->value(quint8(response.functionCode()), nullptr))
return ptr(response);
}
@@ -765,7 +765,7 @@ int QModbusResponse::calculateDataSize(const QModbusResponse &response)
for (int i = 1; i < numOfObjects; ++i) {
if (data.size() <= nextSizeField)
break;
- objectSize = data[nextSizeField];
+ objectSize = quint8(data[nextSizeField]);
size += objectSize;
nextSizeField += objectSize + 2; // object size + object id field + object size field
}
@@ -790,7 +790,7 @@ int QModbusResponse::calculateDataSize(const QModbusResponse &response)
*/
void QModbusResponse::registerDataSizeCalculator(FunctionCode fc, CalcFuncPtr calculator)
{
- responseSizeCalculators()->insert(fc, calculator);
+ responseSizeCalculators()->insert(quint8(fc), calculator);
}
/*!
diff --git a/src/serialbus/qmodbuspdu.h b/src/serialbus/qmodbuspdu.h
index 14cef59..30904a7 100644
--- a/src/serialbus/qmodbuspdu.h
+++ b/src/serialbus/qmodbuspdu.h
@@ -101,7 +101,7 @@ public:
bool isException() const { return m_code & ExceptionByte; }
qint16 size() const { return dataSize() + 1; }
- qint16 dataSize() const { return m_data.size(); }
+ qint16 dataSize() const { return qint16(m_data.size()); }
FunctionCode functionCode() const {
return FunctionCode(quint8(m_code) &~ ExceptionByte);
diff --git a/src/serialbus/qmodbusrtuserialmaster_p.h b/src/serialbus/qmodbusrtuserialmaster_p.h
index 9672684..d206eec 100644
--- a/src/serialbus/qmodbusrtuserialmaster_p.h
+++ b/src/serialbus/qmodbusrtuserialmaster_p.h
@@ -310,7 +310,7 @@ public:
onBytesWritten(bytes);
});
- QObject::connect(m_serialPort, QOverload<QSerialPort::SerialPortError>::of(&QSerialPort::error),
+ QObject::connect(m_serialPort, &QSerialPort::errorOccurred,
q, [this](QSerialPort::SerialPortError error) {
onError(error);
});
@@ -427,6 +427,8 @@ public:
return false;
}
+ QIODevice *device() const override { return m_serialPort; }
+
Timer m_responseTimer;
QByteArray m_responseBuffer;
diff --git a/src/serialbus/qmodbusrtuserialslave_p.h b/src/serialbus/qmodbusrtuserialslave_p.h
index da59e5e..d6ff8d6 100644
--- a/src/serialbus/qmodbusrtuserialslave_p.h
+++ b/src/serialbus/qmodbusrtuserialslave_p.h
@@ -280,8 +280,7 @@ public:
storeModbusCommEvent(event); // store the final event after processing
});
- using TypeId = void (QSerialPort::*)(QSerialPort::SerialPortError);
- QObject::connect(m_serialPort, static_cast<TypeId>(&QSerialPort::error), q,
+ QObject::connect(m_serialPort, &QSerialPort::errorOccurred, q,
[this](QSerialPort::SerialPortError error) {
if (error == QSerialPort::NoError)
return;
@@ -355,6 +354,8 @@ public:
m_requestBuffer.clear();
}
+ QIODevice *device() const override { return m_serialPort; }
+
QByteArray m_requestBuffer;
bool m_processesBroadcast = false;
QSerialPort *m_serialPort = nullptr;
diff --git a/src/serialbus/qmodbustcpclient_p.h b/src/serialbus/qmodbustcpclient_p.h
index db1d4e4..649b48e 100644
--- a/src/serialbus/qmodbustcpclient_p.h
+++ b/src/serialbus/qmodbustcpclient_p.h
@@ -86,8 +86,8 @@ public:
cleanupTransactionStore();
});
- using TypeId = void (QAbstractSocket::*)(QAbstractSocket::SocketError);
- QObject::connect(m_socket, static_cast<TypeId>(&QAbstractSocket::error), q,
+ QObject::connect(m_socket,
+ QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), q,
[this](QAbstractSocket::SocketError /*error*/)
{
Q_Q(QModbusTcpClient);
@@ -121,7 +121,7 @@ public:
if (knownTransaction && m_transactionStore[transactionId].timer)
m_transactionStore[transactionId].timer->stop();
- qCDebug(QT_MODBUS) << "(TCP client) tid:" << hex << transactionId << "size:"
+ qCDebug(QT_MODBUS) << "(TCP client) tid:" << Qt::hex << transactionId << "size:"
<< bytesPdu << "server address:" << serverAddress;
// The length field is the byte count of the following fields, including the Unit
@@ -169,7 +169,7 @@ public:
return false;
}
qCDebug(QT_MODBUS_LOW) << "(TCP client) Sent TCP ADU:" << buffer.toHex();
- qCDebug(QT_MODBUS) << "(TCP client) Sent TCP PDU:" << request << "with tId:" << hex
+ qCDebug(QT_MODBUS) << "(TCP client) Sent TCP PDU:" << request << "with tId:" <<Qt:: hex
<< tId;
return true;
};
@@ -193,9 +193,8 @@ public:
});
if (element.timer) {
- using TypeId = void (QTimer::*)(int);
q->connect(q, &QModbusClient::timeoutChanged,
- element.timer.data(), static_cast<TypeId>(&QTimer::setInterval));
+ element.timer.data(), QOverload<int>::of(&QTimer::setInterval));
QObject::connect(element.timer.data(), &QTimer::timeout, q, [this, writeToSocket, tId]() {
if (!m_transactionStore.contains(tId))
return;
@@ -210,9 +209,9 @@ public:
return;
m_transactionStore.insert(tId, elem);
elem.timer->start();
- qCDebug(QT_MODBUS) << "(TCP client) Resend request with tId:" << hex << tId;
+ qCDebug(QT_MODBUS) << "(TCP client) Resend request with tId:" << Qt::hex << tId;
} else {
- qCDebug(QT_MODBUS) << "(TCP client) Timeout of request with tId:" << hex << tId;
+ qCDebug(QT_MODBUS) << "(TCP client) Timeout of request with tId:" <<Qt::hex << tId;
elem.reply->setError(QModbusDevice::TimeoutError,
QModbusClient::tr("Request timeout."));
}
@@ -220,7 +219,7 @@ public:
element.timer->start();
} else {
qCWarning(QT_MODBUS) << "(TCP client) No response timeout timer for request with tId:"
- << hex << tId << ". Expected timeout:" << m_responseTimeoutDuration;
+ << Qt::hex << tId << ". Expected timeout:" << m_responseTimeoutDuration;
}
incrementTransactionId();
@@ -255,6 +254,8 @@ public:
inline void incrementTransactionId() { m_transactionId++; }
inline int transactionId() const { return m_transactionId; }
+ QIODevice *device() const override { return m_socket; }
+
QTcpSocket *m_socket = nullptr;
QByteArray responseBuffer;
QHash<quint16, QueueElement> m_transactionStore;
diff --git a/src/serialbus/qmodbustcpserver_p.h b/src/serialbus/qmodbustcpserver_p.h
index 56c45e9..3e73de3 100644
--- a/src/serialbus/qmodbustcpserver_p.h
+++ b/src/serialbus/qmodbustcpserver_p.h
@@ -167,7 +167,7 @@ public:
input >> transactionId >> protocolId >> bytesPdu >> unitId;
qCDebug(QT_MODBUS_LOW) << "(TCP server) Request MBPA:" << "Transaction Id:"
- << hex << transactionId << "Protocol Id:" << protocolId << "PDU bytes:"
+ << Qt::hex << transactionId << "Protocol Id:" << protocolId << "PDU bytes:"
<< bytesPdu << "Unit Id:" << unitId;
// The length field is the byte count of the following fields, including the Unit
@@ -224,7 +224,7 @@ public:
});
}
- QTcpServer *m_tcpServer;
+ QTcpServer *m_tcpServer { nullptr };
QVector<QTcpSocket *> connections;
std::unique_ptr<QModbusTcpConnectionObserver> m_observer;
diff --git a/src/tools/canbusutil/canbusutil.cpp b/src/tools/canbusutil/canbusutil.cpp
index a4e1a58..b07d97c 100644
--- a/src/tools/canbusutil/canbusutil.cpp
+++ b/src/tools/canbusutil/canbusutil.cpp
@@ -53,9 +53,9 @@ void CanBusUtil::setShowTimeStamp(bool showTimeStamp)
m_readTask->setShowTimeStamp(showTimeStamp);
}
-void CanBusUtil::setShowFdFlags(bool showFdFlags)
+void CanBusUtil::setShowFlags(bool showFlags)
{
- m_readTask->setShowFdFlags(showFdFlags);
+ m_readTask->setShowFlags(showFlags);
}
void CanBusUtil::setConfigurationParameter(QCanBusDevice::ConfigurationKey key,
@@ -67,7 +67,7 @@ void CanBusUtil::setConfigurationParameter(QCanBusDevice::ConfigurationKey key,
bool CanBusUtil::start(const QString &pluginName, const QString &deviceName, const QString &data)
{
if (!m_canBus) {
- m_output << tr("Error: Cannot create QCanBus.") << endl;
+ m_output << tr("Error: Cannot create QCanBus.") << Qt::endl;
return false;
}
@@ -80,7 +80,7 @@ bool CanBusUtil::start(const QString &pluginName, const QString &deviceName, con
return false;
if (m_listening) {
- if (m_readTask->isShowFdFlags())
+ if (m_readTask->isShowFlags())
m_canDevice->setConfigurationParameter(QCanBusDevice::CanFdKey, true);
connect(m_canDevice.data(), &QCanBusDevice::framesReceived,
m_readTask, &ReadTask::handleFrames);
@@ -96,32 +96,32 @@ bool CanBusUtil::start(const QString &pluginName, const QString &deviceName, con
int CanBusUtil::printPlugins()
{
if (!m_canBus) {
- m_output << tr("Error: Cannot create QCanBus.") << endl;
+ m_output << tr("Error: Cannot create QCanBus.") << Qt::endl;
return 1;
}
const QStringList plugins = m_canBus->plugins();
for (const QString &plugin : plugins)
- m_output << plugin << endl;
+ m_output << plugin << Qt::endl;
return 0;
}
int CanBusUtil::printDevices(const QString &pluginName)
{
if (!m_canBus) {
- m_output << tr("Error: Cannot create QCanBus.") << endl;
+ m_output << tr("Error: Cannot create QCanBus.") << Qt::endl;
return 1;
}
QString errorMessage;
const QList<QCanBusDeviceInfo> devices = m_canBus->availableDevices(pluginName, &errorMessage);
if (!errorMessage.isEmpty()) {
- m_output << tr("Error gathering available devices: '%1'").arg(errorMessage) << endl;
+ m_output << tr("Error gathering available devices: '%1'").arg(errorMessage) << Qt::endl;
return 1;
}
for (const QCanBusDeviceInfo &info : devices)
- m_output << info.name() << endl;
+ m_output << info.name() << Qt::endl;
return 0;
}
@@ -129,7 +129,7 @@ bool CanBusUtil::parseDataField(quint32 &id, QString &payload)
{
int hashMarkPos = m_data.indexOf('#');
if (hashMarkPos < 0) {
- m_output << tr("Data field invalid: No hash mark found!") << endl;
+ m_output << tr("Data field invalid: No hash mark found!") << Qt::endl;
return false;
}
@@ -154,7 +154,7 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame)
return true;
}
- m_output << tr("Error: RTR frame length must be between 0 and 8 (including).") << endl;
+ m_output << tr("Error: RTR frame length must be between 0 and 8 (including).") << Qt::endl;
return false;
}
@@ -165,7 +165,7 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame)
const QRegularExpression re(QStringLiteral("^[0-9A-Fa-f]*$"));
if (!re.match(payload).hasMatch()) {
- m_output << tr("Data field invalid: Only hex numbers allowed.") << endl;
+ m_output << tr("Data field invalid: Only hex numbers allowed.") << Qt::endl;
return false;
}
@@ -177,7 +177,7 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame)
frame->setErrorStateIndicator(flags & ErrorStateIndicatorFlag);
payload.remove(0, 1);
} else {
- m_output << tr("Data field invalid: Size is not multiple of two.") << endl;
+ m_output << tr("Data field invalid: Size is not multiple of two.") << Qt::endl;
return false;
}
}
@@ -186,7 +186,7 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame)
const int maxSize = frame->hasFlexibleDataRateFormat() ? 64 : 8;
if (bytes.size() > maxSize) {
- m_output << tr("Data field invalid: Size is longer than %1 bytes.").arg(maxSize) << endl;
+ m_output << tr("Data field invalid: Size is longer than %1 bytes.").arg(maxSize) << Qt::endl;
return false;
}
@@ -198,13 +198,13 @@ bool CanBusUtil::setFrameFromPayload(QString payload, QCanBusFrame *frame)
bool CanBusUtil::connectCanDevice()
{
if (!m_canBus->plugins().contains(m_pluginName)) {
- m_output << tr("Cannot find CAN bus plugin '%1'.").arg(m_pluginName) << endl;
+ m_output << tr("Cannot find CAN bus plugin '%1'.").arg(m_pluginName) << Qt::endl;
return false;
}
m_canDevice.reset(m_canBus->createDevice(m_pluginName, m_deviceName));
if (!m_canDevice) {
- m_output << tr("Cannot create CAN bus device: '%1'").arg(m_deviceName) << endl;
+ m_output << tr("Cannot create CAN bus device: '%1'").arg(m_deviceName) << Qt::endl;
return false;
}
@@ -214,7 +214,7 @@ bool CanBusUtil::connectCanDevice()
connect(m_canDevice.data(), &QCanBusDevice::errorOccurred, m_readTask, &ReadTask::handleError);
if (!m_canDevice->connectDevice()) {
- m_output << tr("Cannot create CAN bus device: '%1'").arg(m_deviceName) << endl;
+ m_output << tr("Cannot create CAN bus device: '%1'").arg(m_deviceName) << Qt::endl;
return false;
}
@@ -234,7 +234,7 @@ bool CanBusUtil::sendData()
return false;
if (id > 0x1FFFFFFF) { // 29 bits
- m_output << tr("Cannot send invalid frame ID: '%1'").arg(id, 0, 16) << endl;
+ m_output << tr("Cannot send invalid frame ID: '%1'").arg(id, 0, 16) << Qt::endl;
return false;
}
diff --git a/src/tools/canbusutil/canbusutil.h b/src/tools/canbusutil/canbusutil.h
index 19b7868..4d1b7f4 100644
--- a/src/tools/canbusutil/canbusutil.h
+++ b/src/tools/canbusutil/canbusutil.h
@@ -57,7 +57,7 @@ public:
explicit CanBusUtil(QTextStream &output, QCoreApplication &app, QObject *parent = nullptr);
void setShowTimeStamp(bool showTimeStamp);
- void setShowFdFlags(bool showFdFlags);
+ void setShowFlags(bool showFlags);
void setConfigurationParameter(QCanBusDevice::ConfigurationKey key, const QVariant &value);
bool start(const QString &pluginName, const QString &deviceName, const QString &data = QString());
int printPlugins();
diff --git a/src/tools/canbusutil/main.cpp b/src/tools/canbusutil/main.cpp
index 3a71192..1277325 100644
--- a/src/tools/canbusutil/main.cpp
+++ b/src/tools/canbusutil/main.cpp
@@ -94,9 +94,10 @@ int main(int argc, char *argv[])
CanBusUtil::tr("Show timestamp for each received CAN bus frame."));
parser.addOption(showTimeStampOption);
- const QCommandLineOption showFdFlagsOption({"i", "info"},
- CanBusUtil::tr("Show extra info (CAN FD flags) for each received CAN bus frame."));
- parser.addOption(showFdFlagsOption);
+ const QCommandLineOption showFlagsOption({"i", "info"},
+ CanBusUtil::tr("Show flags bitrate switch, error indicator, and local echo"
+ " for each received CAN bus frame."));
+ parser.addOption(showFlagsOption);
const QCommandLineOption listDevicesOption({"d", "devices"},
CanBusUtil::tr("Show available CAN bus devices for the given plugin."));
@@ -149,14 +150,14 @@ int main(int argc, char *argv[])
if (parser.isSet(listeningOption)) {
util.setShowTimeStamp(parser.isSet(showTimeStampOption));
- util.setShowFdFlags(parser.isSet(showFdFlagsOption));
+ util.setShowFlags(parser.isSet(showFlagsOption));
} else if (args.size() == 3) {
data = args.at(2);
} else if (args.size() == 1 && parser.isSet(listDevicesOption)) {
return util.printDevices(args.at(0));
} else if (args.size() != 2) {
output << CanBusUtil::tr("Invalid number of arguments (%1 given).").arg(args.size());
- output << endl << endl << parser.helpText();
+ output << Qt::endl << Qt::endl << parser.helpText();
return 1;
}
diff --git a/src/tools/canbusutil/readtask.cpp b/src/tools/canbusutil/readtask.cpp
index 2bde509..86dfb73 100644
--- a/src/tools/canbusutil/readtask.cpp
+++ b/src/tools/canbusutil/readtask.cpp
@@ -45,14 +45,14 @@ void ReadTask::setShowTimeStamp(bool showTimeStamp)
m_showTimeStamp = showTimeStamp;
}
-bool ReadTask::isShowFdFlags() const
+bool ReadTask::isShowFlags() const
{
- return m_showFdFlags;
+ return m_showFlags;
}
-void ReadTask::setShowFdFlags(bool showFlags)
+void ReadTask::setShowFlags(bool showFlags)
{
- m_showFdFlags = showFlags;
+ m_showFlags = showFlags;
}
void ReadTask::handleFrames() {
@@ -73,12 +73,16 @@ void ReadTask::handleFrames() {
.arg(frame.timeStamp().microSeconds() / 100, 4, 10, QLatin1Char('0'));
}
- if (m_showFdFlags) {
- QString flags = QLatin1String("- - ");
+ if (m_showFlags) {
+ QString flags = QLatin1String("- - - ");
+
if (frame.hasBitrateSwitch())
flags[0] = QLatin1Char('B');
if (frame.hasErrorStateIndicator())
flags[2] = QLatin1Char('E');
+ if (frame.hasLocalEcho())
+ flags[4] = QLatin1Char('L');
+
view += flags;
}
@@ -87,7 +91,7 @@ void ReadTask::handleFrames() {
else
view += frame.toString();
- m_output << view << endl;
+ m_output << view << Qt::endl;
}
}
@@ -99,5 +103,5 @@ void ReadTask::handleError(QCanBusDevice::CanBusError /*error*/)
return;
}
- m_output << tr("Read error: '%1'").arg(canDevice->errorString()) << endl;
+ m_output << tr("Read error: '%1'").arg(canDevice->errorString()) << Qt::endl;
}
diff --git a/src/tools/canbusutil/readtask.h b/src/tools/canbusutil/readtask.h
index a866d3d..345af35 100644
--- a/src/tools/canbusutil/readtask.h
+++ b/src/tools/canbusutil/readtask.h
@@ -47,8 +47,8 @@ class ReadTask : public QObject
public:
explicit ReadTask(QTextStream &m_output, QObject *parent = nullptr);
void setShowTimeStamp(bool showStamp);
- bool isShowFdFlags() const;
- void setShowFdFlags(bool isShowFdFlags);
+ bool isShowFlags() const;
+ void setShowFlags(bool isShowFlags);
public slots:
void handleFrames();
@@ -57,7 +57,7 @@ public slots:
private:
QTextStream &m_output;
bool m_showTimeStamp = false;
- bool m_showFdFlags = false;
+ bool m_showFlags = false;
};
#endif // READTASK_H
diff --git a/src/tools/canbusutil/sigtermhandler.cpp b/src/tools/canbusutil/sigtermhandler.cpp
index 8611916..a882a55 100644
--- a/src/tools/canbusutil/sigtermhandler.cpp
+++ b/src/tools/canbusutil/sigtermhandler.cpp
@@ -47,7 +47,7 @@ SigTermHandler *SigTermHandler::instance()
void SigTermHandler::handle(int s)
{
QTextStream out(stdout);
- out << " Caught signal " << s << endl;
+ out << " Caught signal " << s << Qt::endl;
emit instance()->sigTermSignal();
}
diff --git a/tests/auto/qcanbusdevice/tst_qcanbusdevice.cpp b/tests/auto/qcanbusdevice/tst_qcanbusdevice.cpp
index 85d445f..61d30c0 100644
--- a/tests/auto/qcanbusdevice/tst_qcanbusdevice.cpp
+++ b/tests/auto/qcanbusdevice/tst_qcanbusdevice.cpp
@@ -44,6 +44,8 @@
#include <memory>
+Q_DECLARE_METATYPE(QCanBusDevice::Filter)
+
class tst_Backend : public QCanBusDevice
{
Q_OBJECT
@@ -84,8 +86,11 @@ public:
bool writeFrame(const QCanBusFrame &data)
{
- if (state() != QCanBusDevice::ConnectedState)
+ if (state() != QCanBusDevice::ConnectedState) {
+ setError(QStringLiteral("Cannot write frame as device is not connected"),
+ QCanBusDevice::OperationError);
return false;
+ }
if (writeBufferUsed) {
enqueueOutgoingFrame(data);
@@ -149,6 +154,8 @@ private slots:
void error();
void cleanupTestCase();
void tst_filtering();
+ void filterEqual_data();
+ void filterEqual();
void tst_bufferingAttribute();
void tst_waitForFramesReceived();
@@ -161,6 +168,7 @@ tst_QCanBusDevice::tst_QCanBusDevice()
{
qRegisterMetaType<QCanBusDevice::CanBusDeviceState>();
qRegisterMetaType<QCanBusDevice::CanBusError>();
+ qRegisterMetaType<QCanBusDevice::Filter>();
}
void tst_QCanBusDevice::initTestCase()
@@ -171,7 +179,9 @@ void tst_QCanBusDevice::initTestCase()
QSignalSpy stateSpy(device.data(), &QCanBusDevice::stateChanged);
QVERIFY(!device->connectDevice()); // first connect triggered to fail
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QVERIFY(device->connectDevice());
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
QCOMPARE(stateSpy.count(), 4);
QCOMPARE(stateSpy.at(0).at(0).value<QCanBusDevice::CanBusDeviceState>(),
@@ -233,7 +243,8 @@ void tst_QCanBusDevice::write()
stateSpy.clear();
QVERIFY(stateSpy.isEmpty());
- device->writeFrame(frame);
+ QVERIFY(!device->writeFrame(frame));
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
QCOMPARE(spy.count(), 0);
device->connectDevice();
@@ -244,7 +255,8 @@ void tst_QCanBusDevice::write()
QCOMPARE(stateSpy.at(1).at(0).value<QCanBusDevice::CanBusDeviceState>(),
QCanBusDevice::ConnectedState);
- device->writeFrame(frame);
+ QVERIFY(device->writeFrame(frame));
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QCOMPARE(spy.count(), 1);
}
@@ -257,6 +269,7 @@ void tst_QCanBusDevice::read()
stateSpy.clear();
const QCanBusFrame frame1 = device->readFrame();
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
QVERIFY(device->connectDevice());
QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
@@ -268,6 +281,7 @@ void tst_QCanBusDevice::read()
device->triggerNewFrame();
const QCanBusFrame frame2 = device->readFrame();
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QVERIFY(!frame1.frameId());
QVERIFY(!frame1.isValid());
QVERIFY(frame2.frameId());
@@ -278,6 +292,12 @@ void tst_QCanBusDevice::readAll()
{
enum { FrameNumber = 10 };
device->disconnectDevice();
+ QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::UnconnectedState, 5000);
+
+ const QVector<QCanBusFrame> empty = device->readAllFrames();
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
+ QVERIFY(empty.isEmpty());
+
QVERIFY(device->connectDevice());
QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
@@ -285,21 +305,30 @@ void tst_QCanBusDevice::readAll()
device->triggerNewFrame();
const QVector<QCanBusFrame> frames = device->readAllFrames();
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QCOMPARE(FrameNumber, frames.size());
QVERIFY(!device->framesAvailable());
}
void tst_QCanBusDevice::clearInputBuffer()
{
- if (device->state() != QCanBusDevice::ConnectedState) {
- QVERIFY(device->connectDevice());
- QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
- }
+ device->disconnectDevice();
+ QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::UnconnectedState, 5000);
+
+ device->clear(QCanBusDevice::Input);
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
+
+ QVERIFY(device->connectDevice());
+ QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
+
+ device->clear(QCanBusDevice::Input);
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
for (int i = 0; i < 10; ++i)
device->triggerNewFrame();
device->clear(QCanBusDevice::Input);
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QVERIFY(!device->framesAvailable());
}
@@ -308,11 +337,17 @@ void tst_QCanBusDevice::clearOutputBuffer()
{
// this test requires buffered writing
device->setWriteBuffered(true);
+ device->disconnectDevice();
+ QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::UnconnectedState, 5000);
- if (device->state() != QCanBusDevice::ConnectedState) {
- QVERIFY(device->connectDevice());
- QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
- }
+ device->clear(QCanBusDevice::Output);
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
+
+ QVERIFY(device->connectDevice());
+ QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
+
+ device->clear(QCanBusDevice::Output);
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
// first test buffered writing, frames will be written after some delay
QSignalSpy spy(device.data(), &QCanBusDevice::framesWritten);
@@ -326,6 +361,7 @@ void tst_QCanBusDevice::clearOutputBuffer()
device->writeFrame(QCanBusFrame(0x123, "output"));
device->clear(QCanBusDevice::Output);
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QTRY_VERIFY_WITH_TIMEOUT(spy.count() == 0, 5000);
}
@@ -421,6 +457,89 @@ void tst_QCanBusDevice::tst_filtering()
QVERIFY(!(newFilter.at(1).format & QCanBusDevice::Filter::MatchExtendedFormat));
}
+void tst_QCanBusDevice::filterEqual_data()
+{
+ using Filter = QCanBusDevice::Filter;
+ using Frame = QCanBusFrame;
+
+ QTest::addColumn<QCanBusDevice::Filter>("first");
+ QTest::addColumn<QCanBusDevice::Filter>("second");
+ QTest::addColumn<bool>("isEqual");
+
+ auto filter = [](quint32 frameId, quint32 frameIdMask,
+ Frame::FrameType type,
+ Filter::FormatFilter format) {
+ Filter result;
+ result.frameId = frameId;
+ result.frameIdMask = frameIdMask;
+ result.type = type;
+ result.format = format;
+ return result;
+ };
+
+ QTest::newRow("empty-equal")
+ << Filter()
+ << Filter()
+ << true;
+ QTest::newRow("empty-default-equal")
+ << Filter()
+ << filter(0, 0, Frame::InvalidFrame, Filter::MatchBaseAndExtendedFormat)
+ << true;
+ QTest::newRow("empty-non-default-different")
+ << Filter()
+ << filter(1, 2, Frame::ErrorFrame, Filter::MatchBaseFormat)
+ << false;
+
+ QTest::newRow("frame-id-equal")
+ << filter(0x345, 0x800, Frame::RemoteRequestFrame, Filter::MatchBaseFormat)
+ << filter(0x345, 0x800, Frame::RemoteRequestFrame, Filter::MatchBaseFormat)
+ << true;
+ QTest::newRow("frame-id-different")
+ << filter(0x345, 0x000, Frame::RemoteRequestFrame, Filter::MatchBaseFormat)
+ << filter(0x346, 0x000, Frame::RemoteRequestFrame, Filter::MatchBaseFormat)
+ << false;
+
+ QTest::newRow("frame-mask-equal")
+ << filter(0x123, 0x7FF, Frame::InvalidFrame, Filter::MatchBaseAndExtendedFormat)
+ << filter(0x123, 0x7FF, Frame::InvalidFrame, Filter::MatchBaseAndExtendedFormat)
+ << true;
+ QTest::newRow("frame-mask-different")
+ << filter(0x123, 0x7FF, Frame::InvalidFrame, Filter::MatchBaseAndExtendedFormat)
+ << filter(0x123, 0x7FE, Frame::InvalidFrame, Filter::MatchBaseAndExtendedFormat)
+ << false;
+
+ QTest::newRow("frame-type-equal")
+ << filter(0xFFF, 0xBFF, Frame::DataFrame, Filter::MatchBaseAndExtendedFormat)
+ << filter(0xFFF, 0xBFF, Frame::DataFrame, Filter::MatchBaseAndExtendedFormat)
+ << true;
+ QTest::newRow("frame-type-different")
+ << filter(0xFFF, 0xBFF, Frame::DataFrame, Filter::MatchBaseAndExtendedFormat)
+ << filter(0xFFF, 0xBFF, Frame::InvalidFrame, Filter::MatchBaseAndExtendedFormat)
+ << false;
+
+ QTest::newRow("filter-equal")
+ << filter(0xFFF, 0xBFF, Frame::ErrorFrame, Filter::MatchExtendedFormat)
+ << filter(0xFFF, 0xBFF, Frame::ErrorFrame, Filter::MatchExtendedFormat)
+ << true;
+ QTest::newRow("filter-different")
+ << filter(0xFFF, 0xBFF, Frame::ErrorFrame, Filter::MatchExtendedFormat)
+ << filter(0xFFF, 0xBFF, Frame::ErrorFrame, Filter::MatchBaseAndExtendedFormat)
+ << false;
+}
+
+void tst_QCanBusDevice::filterEqual()
+{
+ QFETCH(QCanBusDevice::Filter, first);
+ QFETCH(QCanBusDevice::Filter, second);
+ QFETCH(bool, isEqual);
+
+ if (isEqual) {
+ QCOMPARE(first, second);
+ } else {
+ QVERIFY(first != second);
+ }
+}
+
void tst_QCanBusDevice::tst_bufferingAttribute()
{
std::unique_ptr<tst_Backend> canDevice(new tst_Backend);
@@ -436,6 +555,10 @@ void tst_QCanBusDevice::tst_bufferingAttribute()
void tst_QCanBusDevice::tst_waitForFramesReceived()
{
+ device->disconnectDevice();
+ QVERIFY(!device->waitForFramesReceived(100));
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
+
if (device->state() != QCanBusDevice::ConnectedState) {
QVERIFY(device->connectDevice());
QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
@@ -445,9 +568,10 @@ void tst_QCanBusDevice::tst_waitForFramesReceived()
QVERIFY(device->triggerNewFrame());
QVERIFY(device->framesAvailable());
- // frame is available, function blocks and times out
- bool result = device->waitForFramesReceived(2000);
- QVERIFY(!result);
+ // frame is already available, but no new frame comes in
+ // while function blocks, therefore times out
+ QVERIFY(!device->waitForFramesReceived(2000));
+ QCOMPARE(device->error(), QCanBusDevice::TimeoutError);
QCanBusFrame frame = device->readFrame();
QVERIFY(frame.isValid());
@@ -457,16 +581,16 @@ void tst_QCanBusDevice::tst_waitForFramesReceived()
QElapsedTimer elapsed;
elapsed.start();
// no pending frame (should trigger active wait & timeout)
- result = device->waitForFramesReceived(5000);
+ QVERIFY(!device->waitForFramesReceived(5000));
QVERIFY(elapsed.hasExpired(4000)); // should have caused time elapse
- QVERIFY(!result);
+ QCOMPARE(device->error(), QCanBusDevice::TimeoutError);
QTimer::singleShot(2000, [&]() { device->triggerNewFrame(); });
elapsed.restart();
// frame will be inserted after 2s
- result = device->waitForFramesReceived(8000);
+ QVERIFY(device->waitForFramesReceived(8000));
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QVERIFY(!elapsed.hasExpired(8000));
- QVERIFY(result);
frame = device->readFrame();
QVERIFY(frame.isValid());
@@ -478,9 +602,8 @@ void tst_QCanBusDevice::tst_waitForFramesReceived()
});
elapsed.restart();
// error will be inserted after 2s
- result = device->waitForFramesReceived(8000);
+ QVERIFY(!device->waitForFramesReceived(8000));
QVERIFY(!elapsed.hasExpired(8000));
- QVERIFY(!result);
QCOMPARE(device->errorString(), QStringLiteral("TriggerError"));
QCOMPARE(device->error(), QCanBusDevice::ReadError);
@@ -494,56 +617,71 @@ void tst_QCanBusDevice::tst_waitForFramesReceived()
QObject::connect(device.data(), &QCanBusDevice::framesReceived, [this, &handleCounter]() {
handleCounter++;
// this should trigger a recursion which we want to catch
- device->waitForFramesReceived(5000);
+ QVERIFY(!device->waitForFramesReceived(5000));
+ // Only the first two frames create a recursion, as the outer
+ // waitForFramesReceived() will immediately exit once at least
+ // one frame was received. Therefore the third frame here leads
+ // to TimeoutError, as no further frame is received.
+ if (handleCounter < 3) {
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
+ } else {
+ QCOMPARE(device->error(), QCanBusDevice::TimeoutError);
+ }
});
- result = device->waitForFramesReceived(8000);
- QVERIFY(result);
+ QVERIFY(device->waitForFramesReceived(8000));
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QTRY_COMPARE_WITH_TIMEOUT(handleCounter, 3, 5000);
}
void tst_QCanBusDevice::tst_waitForFramesWritten()
{
+ device->disconnectDevice();
+ QVERIFY(!device->waitForFramesWritten(100));
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
+
if (device->state() != QCanBusDevice::ConnectedState) {
+ QVERIFY(!device->waitForFramesWritten(100));
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
+
QVERIFY(device->connectDevice());
QTRY_VERIFY_WITH_TIMEOUT(device->state() == QCanBusDevice::ConnectedState, 5000);
}
device->setWriteBuffered(false);
- bool result = device->waitForFramesWritten(1000);
- QVERIFY(!result); // no buffer, waiting not possible
+ QVERIFY(!device->waitForFramesWritten(1000)); // no buffer, waiting not possible
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
device->setWriteBuffered(true);
QVERIFY(device->framesToWrite() == 0);
- result = device->waitForFramesWritten(1000);
- QVERIFY(!result); // nothing in buffer, nothing to wait for
+ QVERIFY(!device->waitForFramesWritten(1000)); // nothing in buffer, nothing to wait for
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QCanBusFrame frame;
frame.setPayload(QByteArray("testData"));
// test error case
QTimer::singleShot(500, [&]() {
- device->emulateError(QStringLiteral("TriggerWriteError"), QCanBusDevice::ReadError);
+ device->emulateError(QStringLiteral("TriggerWriteError"), QCanBusDevice::WriteError);
});
device->writeFrame(frame);
QElapsedTimer elapsed;
elapsed.start();
// error will be triggered
- result = device->waitForFramesWritten(8000);
+ QVERIFY(!device->waitForFramesWritten(8000));
QVERIFY(!elapsed.hasExpired(8000));
- QVERIFY(!result);
QCOMPARE(device->errorString(), QStringLiteral("TriggerWriteError"));
- QCOMPARE(device->error(), QCanBusDevice::ReadError);
+ QCOMPARE(device->error(), QCanBusDevice::WriteError);
// flush remaining frames out to reset the test
QTRY_VERIFY_WITH_TIMEOUT(device->framesToWrite() == 0, 10000);
// test timeout
device->writeFrame(frame);
- result = device->waitForFramesWritten(500);
+ QVERIFY(!device->waitForFramesWritten(500));
+ QCOMPARE(device->error(), QCanBusDevice::TimeoutError);
QVERIFY(elapsed.hasExpired(500));
- QVERIFY(!result);
// flush remaining frames out to reset the test
QTRY_VERIFY_WITH_TIMEOUT(device->framesToWrite() == 0, 10000);
@@ -551,9 +689,9 @@ void tst_QCanBusDevice::tst_waitForFramesWritten()
device->writeFrame(frame);
device->writeFrame(frame);
elapsed.restart();
- result = device->waitForFramesWritten(8000);
+ QVERIFY(device->waitForFramesWritten(8000));
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QVERIFY(!elapsed.hasExpired(8000));
- QVERIFY(result);
// flush remaining frames out to reset the test
QTRY_VERIFY_WITH_TIMEOUT(device->framesToWrite() == 0, 10000);
@@ -566,10 +704,11 @@ void tst_QCanBusDevice::tst_waitForFramesWritten()
QObject::connect(device.data(), &QCanBusDevice::framesWritten, [this, &handleCounter]() {
handleCounter++;
// this should trigger a recursion which we want to catch
- device->waitForFramesWritten(5000);
+ QVERIFY(!device->waitForFramesWritten(5000));
+ QCOMPARE(device->error(), QCanBusDevice::OperationError);
});
- result = device->waitForFramesWritten(8000);
- QVERIFY(result);
+ QVERIFY(device->waitForFramesWritten(8000));
+ QCOMPARE(device->error(), QCanBusDevice::NoError);
QTRY_COMPARE_WITH_TIMEOUT(handleCounter, 3, 5000);
device->setWriteBuffered(false);