From b8896d76b696b4652c9d8f19fb5094fbf76453b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A1n=20Inostroza?= Date: Sun, 29 Apr 2018 18:52:31 -0300 Subject: [PATCH 1/2] Make SavvyCAN aware of remote frames. --- blfhandler.cpp | 9 +- bus_protocols/isotp_handler.cpp | 1 + can_structs.h | 1 + canframemodel.cpp | 54 ++++++---- connections/gvretserial.cpp | 6 ++ connections/serialbusconnection.cpp | 13 ++- framefileio.cpp | 154 ++++++++++++++++++++-------- framesenderwindow.cpp | 129 ++++++++++++++++++----- mainwindow.cpp | 22 ++-- re/fuzzingwindow.cpp | 1 + 10 files changed, 285 insertions(+), 105 deletions(-) diff --git a/blfhandler.cpp b/blfhandler.cpp index b00c662..41ada14 100644 --- a/blfhandler.cpp +++ b/blfhandler.cpp @@ -4,6 +4,8 @@ #include #include +#define BLF_REMOTE_FLAG 0x80 + BLFHandler::BLFHandler() { @@ -70,8 +72,13 @@ bool BLFHandler::loadBLF(QString filename, QVector* frames) frame.ID = canObject.id & 0x1FFFFFFFull; frame.isReceived = true; frame.len = canObject.dlc; + if (canObject.flags & BLF_REMOTE_FLAG) { + frame.remote = true; + } else { + frame.remote = false; + for (int i = 0; i < 8; i++) frame.data[i] = canObject.data[i]; + } frame.timestamp = obj.header.uncompSize / 1000000.0; //uncompsize field also used for timestamp oddly enough - for (int i = 0; i < 8; i++) frame.data[i] = canObject.data[i]; frames->append(frame); } pos += obj.header.objSize + (obj.header.objSize % 4); diff --git a/bus_protocols/isotp_handler.cpp b/bus_protocols/isotp_handler.cpp index 67d3f83..1ba547c 100644 --- a/bus_protocols/isotp_handler.cpp +++ b/bus_protocols/isotp_handler.cpp @@ -51,6 +51,7 @@ void ISOTP_HANDLER::setReception(bool mode) void ISOTP_HANDLER::sendISOTPFrame(int bus, int ID, QVector data) { CANFrame frame; + frame.remote = false; int currByte = 0; int index = 0; if (bus < 0) return; diff --git a/can_structs.h b/can_structs.h index b19e901..da60766 100644 --- a/can_structs.h +++ b/can_structs.h @@ -11,6 +11,7 @@ public: uint32_t ID; uint32_t bus; bool extended; + bool remote; bool isReceived; //did we receive this or send it? uint32_t len; unsigned char data[8]; diff --git a/canframemodel.cpp b/canframemodel.cpp index 021f681..94f0e0a 100644 --- a/canframemodel.cpp +++ b/canframemodel.cpp @@ -6,6 +6,18 @@ #include #include "utility.h" +enum class Column { + TimeStamp = 0, ///< The timestamp when the frame was transmitted or received + FrameId = 1, ///< The frames CAN identifier (Standard: 11 or Extended: 29 bit) + Extended = 2, ///< True if the frames CAN identifier is 29 bit + Remote = 3, ///< True if the frames is a remote frame + Direction = 4, ///< Whether the frame was transmitted or received + Bus = 5, ///< The bus where the frame was transmitted or received + Length = 6, ///< The frames payload data length + ASCII = 7, ///< The payload interpreted as ASCII characters + Data = 8, ///< The frames payload data + NUM_COLUMN +}; CANFrameModel::~CANFrameModel() { @@ -40,7 +52,7 @@ int CANFrameModel::totalFrameCount() int CANFrameModel::columnCount(const QModelIndex &index) const { Q_UNUSED(index); - return 8; + return (int)Column::NUM_COLUMN; } CANFrameModel::CANFrameModel(QObject *parent) @@ -215,17 +227,6 @@ void CANFrameModel::recalcOverwrite() mutex.unlock(); } -enum class Column { - TimeStamp = 0, ///< The timestamp when the frame was transmitted or received - FrameId = 1, ///< The frames CAN identifier (Standard: 11 or Extended: 29 bit) - Extended = 2, ///< True if the frames CAN identifier is 29 bit - Direction = 3, ///< Whether the frame was transmitted or received - Bus = 4, ///< The bus where the frame was transmitted or received - Length = 5, ///< The frames payload data length - ASCII = 6, ///< The payload interpreted as ASCII characters - Data = 7 ///< The frames payload data -}; - QVariant CANFrameModel::data(const QModelIndex &index, int role) const { int dLen; @@ -276,6 +277,8 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const return Utility::formatCANID(thisFrame.ID, thisFrame.extended); case Column::Extended: return QString::number(thisFrame.extended); + case Column::Remote: + return QString::number(thisFrame.remote); case Column::Direction: if (thisFrame.isReceived) return QString(tr("Rx")); return QString(tr("Tx")); @@ -291,14 +294,16 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const return tempString; } dLen = thisFrame.len; - if (dLen < 0) dLen = 0; - if (dLen > 8) dLen = 8; - for (int i = 0; i < dLen; i++) - { - quint8 byt = thisFrame.data[i]; - if (byt < 0x20) byt = 0x2E; //A dot - if (byt > 0x7E) byt = 0x2E; - tempString.append(QString::fromUtf8((char *)&byt, 1)); + if (!thisFrame.remote) { + if (dLen < 0) dLen = 0; + if (dLen > 8) dLen = 8; + for (int i = 0; i < dLen; i++) + { + quint8 byt = thisFrame.data[i]; + if (byt < 0x20) byt = 0x2E; //A dot + if (byt > 0x7E) byt = 0x2E; + tempString.append(QString::fromUtf8((char *)&byt, 1)); + } } return tempString; case Column::Data: @@ -306,6 +311,9 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const if (dLen < 0) dLen = 0; if (dLen > 8) dLen = 8; //if (useHexMode) tempString.append("0x "); + if (thisFrame.remote) { + return tempString; + } for (int i = 0; i < dLen; i++) { if (useHexMode) tempString.append( QString::number(thisFrame.data[i], 16).toUpper().rightJustified(2, '0')); @@ -332,6 +340,8 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const } } return tempString; + default: + return tempString; } } @@ -354,6 +364,8 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation, return QString(tr("ID")); case Column::Extended: return QString(tr("Ext")); + case Column::Remote: + return QString(tr("Rem")); case Column::Direction: return QString(tr("Dir")); case Column::Bus: @@ -364,6 +376,8 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation, return QString(tr("ASCII")); case Column::Data: return QString(tr("Data")); + default: + return QString(""); } } diff --git a/connections/gvretserial.cpp b/connections/gvretserial.cpp index 83a53ec..8c96d38 100644 --- a/connections/gvretserial.cpp +++ b/connections/gvretserial.cpp @@ -236,6 +236,11 @@ bool GVRetSerial::piSendFrame(const CANFrame& frame) if (!serial->isOpen()) return false; //if (!isConnected) return false; + // Doesn't make sense to send an error frame + // to an adapter + if (frame.ID & 0x20000000) { + return true; + } ID = frame.ID; if (frame.extended) ID |= 1 << 31; @@ -639,6 +644,7 @@ void GVRetSerial::procRXChar(unsigned char c) //qDebug() << "GVRET got frame on bus " << frame_p->bus; /* copy frame */ *frame_p = buildFrame; + frame_p->remote = false; checkTargettedFrame(buildFrame); /* enqueue frame */ getQueue().queue(); diff --git a/connections/serialbusconnection.cpp b/connections/serialbusconnection.cpp index f2f4cd2..a054a4e 100644 --- a/connections/serialbusconnection.cpp +++ b/connections/serialbusconnection.cpp @@ -117,9 +117,13 @@ bool SerialBusConnection::piSendFrame(const CANFrame& pFrame) QCanBusFrame frame; frame.setFrameId(pFrame.ID); frame.setExtendedFrameFormat(pFrame.extended); + if (pFrame.remote) { + frame.setFrameType(QCanBusFrame::FrameType::RemoteRequestFrame); + } else { + frame.setFrameType(QCanBusFrame::FrameType::DataFrame); + } frame.setPayload(QByteArray(reinterpret_cast(pFrame.data), static_cast(pFrame.len))); - return mDev_p->writeFrame(frame); } @@ -187,7 +191,12 @@ void SerialBusConnection::framesReceived() if(frame_p) { frame_p->len = static_cast(recFrame.payload().length()); frame_p->bus = 0; - memcpy(frame_p->data, recFrame.payload().data(), frame_p->len); + if (recFrame.frameType() == QCanBusFrame::FrameType::RemoteRequestFrame) { + frame_p->remote = true; + } else { + frame_p->remote = false; + memcpy(frame_p->data, recFrame.payload().data(), frame_p->len); + } frame_p->extended = recFrame.hasExtendedFrameFormat(); frame_p->ID = recFrame.frameId(); frame_p->isReceived = true; diff --git a/framefileio.cpp b/framefileio.cpp index 53fd2e2..966ae6a 100644 --- a/framefileio.cpp +++ b/framefileio.cpp @@ -551,15 +551,25 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector* frames) thisFrame.len = line.mid(38,1).toInt(); thisFrame.isReceived = true; thisFrame.bus = 0; - thisFrame.extended = false; - QList tokens = line.mid(41, thisFrame.len * 3).split(' '); - for (unsigned int d = 0; d < thisFrame.len; d++) - { - if (tokens[d] != "") + if (line.at(28) == ' ') { + thisFrame.extended = true; + } else { + thisFrame.extended = false; + } + + if (line.at(41) == 'R') { + thisFrame.remote = true; + } else { + QList tokens = line.mid(41, thisFrame.len * 3).split(' '); + thisFrame.remote = false; + for (unsigned int d = 0; d < thisFrame.len; d++) { - thisFrame.data[d] = tokens[d].toInt(NULL, 16); + if (tokens[d] != "") + { + thisFrame.data[d] = tokens[d].toInt(NULL, 16); + } + else thisFrame.data[d] = 0; } - else thisFrame.data[d] = 0; } frames->append(thisFrame); } @@ -574,15 +584,24 @@ bool FrameFileIO::loadPCANFile(QString filename, QVector* frames) qDebug() << thisFrame.len; thisFrame.isReceived = true; thisFrame.bus = 0; - thisFrame.extended = false; - QList tokens = line.mid(40, thisFrame.len * 3).split(' '); - for (unsigned int d = 0; d < thisFrame.len; d++) - { - if (tokens[d] != "") + if (line.at(25) == ' ') { + thisFrame.extended = false; + } else { + thisFrame.extended = true; + } + if (line.at(40) == 'R') { + thisFrame.remote = true; + } else { + QList tokens = line.mid(40, thisFrame.len * 3).split(' '); + thisFrame.remote = false; + for (unsigned int d = 0; d < thisFrame.len; d++) { - thisFrame.data[d] = tokens[d].toInt(NULL, 16); + if (tokens[d] != "") + { + thisFrame.data[d] = tokens[d].toInt(NULL, 16); + } + else thisFrame.data[d] = 0; } - else thisFrame.data[d] = 0; } frames->append(thisFrame); } @@ -610,6 +629,7 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector* frames) int lineCounter = 0; bool foundErrors = false; bool inHeader = true; + thisFrame.remote = false; if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -640,6 +660,7 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector* frames) thisFrame.isReceived = tokens[3].toUpper().contains("RX"); thisFrame.bus = tokens[1].toUInt(); thisFrame.extended = (thisFrame.ID > 0x7FF); + thisFrame.remote = false; for (unsigned int d = 6; d < (6 + thisFrame.len); d++) { if (tokens.count() > d) @@ -677,6 +698,7 @@ bool FrameFileIO::loadNativeCSVFile(QString filename, QVector* frames) long long timeStamp = Utility::GetTimeMS(); int lineCounter = 0; bool foundErrors = false; + thisFrame.remote = false; if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -899,6 +921,7 @@ bool FrameFileIO::loadGenericCSVFile(QString filename, QVector* frames long long timeStamp = Utility::GetTimeMS(); int lineCounter = 0; bool foundErrors = false; + thisFrame.remote = false; if (!inFile->open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -989,7 +1012,7 @@ tokens: 1 = Transmission direction 2 = Channel 3 = ID -4 = Type (s = standard, I believe x = extended) +4 = Type (s = standard, x = extended, sr = standard remote, xr = extended remote) 5 = Data byte length 6-x = The data bytes @@ -1053,12 +1076,26 @@ bool FrameFileIO::loadLogFile(QString filename, QVector* frames) if (tokens[1].at(0) == 'R') thisFrame.isReceived = true; else thisFrame.isReceived = false; thisFrame.ID = tokens[3].right(tokens[3].length() - 2).toInt(NULL, 16); - if (tokens[4] == "s") thisFrame.extended = false; - else thisFrame.extended = true; + if (tokens[4] == "S") { + thisFrame.extended = false; + thisFrame.remote = false; + } else if (tokens[4] == "X") { + thisFrame.extended = true; + thisFrame.remote = false; + } else if (tokens[4] == "SR") { + thisFrame.extended = false; + thisFrame.remote = true; + } else { // XR + thisFrame.extended = true; + thisFrame.remote = true; + } thisFrame.bus = tokens[2].toInt() - 1; thisFrame.len = tokens[5].toUInt(); if (thisFrame.len > 8) thisFrame.len = 8; - for (unsigned int d = 0; d < thisFrame.len; d++) thisFrame.data[d] = tokens[d + 6].toInt(NULL, 16); + if (!thisFrame.remote) { + for (unsigned int d = 0; d < thisFrame.len; d++) + thisFrame.data[d] = tokens[d + 6].toInt(NULL, 16); + } frames->append(thisFrame); } else foundErrors = true; @@ -1083,7 +1120,7 @@ bool FrameFileIO::saveLogFile(QString filename, const QVector* frames) return false; } - outFile->write("***BUSMASTER Ver 2.4.0***\n"); + outFile->write("***BUSMASTER Ver 3.2.0***\n"); outFile->write("***PROTOCOL CAN***\n"); outFile->write("***NOTE: PLEASE DO NOT EDIT THIS DOCUMENT***\n"); outFile->write("***[START LOGGING SESSION]***\n"); @@ -1095,8 +1132,8 @@ bool FrameFileIO::saveLogFile(QString filename, const QVector* frames) outFile->write("***START CHANNEL BAUD RATE***\n"); outFile->write("***CHANNEL 1 - Kvaser - Kvaser Leaf Light HS #0 (Channel 0), Serial Number- 0, Firmware- 0x00000037 0x00020000 - 500000 bps***\n"); outFile->write("***END CHANNEL BAUD RATE***\n"); - outFile->write("***START DATABASE FILES (DBF/DBC)***\n"); - outFile->write("***END OF DATABASE FILES (DBF/DBC)***\n"); + outFile->write("***START DATABASE FILES***\n"); + outFile->write("***END OF DATABASE FILES***\n"); outFile->write("***