Skip to content

Commit

Permalink
Add support for loading BLF files. Only loads CAN frames at this point.
Browse files Browse the repository at this point in the history
  • Loading branch information
collin80 committed Feb 9, 2018
1 parent 43bc8c0 commit 80cf438
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 2 deletions.
6 changes: 4 additions & 2 deletions SavvyCAN.pro
Expand Up @@ -64,7 +64,8 @@ SOURCES += main.cpp\
bus_protocols/uds_handler.cpp \
jsedit.cpp \
frameplaybackobject.cpp \
helpwindow.cpp
helpwindow.cpp \
blfhandler.cpp

HEADERS += mainwindow.h \
can_structs.h \
Expand Down Expand Up @@ -119,7 +120,8 @@ HEADERS += mainwindow.h \
bus_protocols/isotp_message.h \
jsedit.h \
frameplaybackobject.h \
helpwindow.h
helpwindow.h \
blfhandler.h

FORMS += ui/candatagrid.ui \
ui/connectionwindow.ui \
Expand Down
86 changes: 86 additions & 0 deletions blfhandler.cpp
@@ -0,0 +1,86 @@
#include "blfhandler.h"
#include <QDebug>
#include <QFile>
#include <QString>
#include <QtEndian>

BLFHandler::BLFHandler()
{

}


/*
Written while peeking at source code here:
https://python-can.readthedocs.io/en/latest/_modules/can/io/blf.html
All the code actually below is freshly written though.
*/
bool BLFHandler::loadBLF(QString filename, QVector<CANFrame>* frames)
{
BLF_OBJ_HEADER objHeader;
QByteArray fileData;
QByteArray uncompressedData;
QByteArray junk;
BLF_OBJECT obj;
uint32_t pos;
BLF_CAN_OBJ canObject;

QFile *inFile = new QFile(filename);

if (!inFile->open(QIODevice::ReadOnly))
{
delete inFile;
return false;
}
inFile->read((char *)&header, sizeof(header));
if (qFromLittleEndian(header.sig) == 0x47474F4C)
{
}
else return false;

while (!inFile->atEnd())
{
inFile->read((char *)&objHeader, sizeof(objHeader));
if (qFromLittleEndian(objHeader.sig) == 0x4A424F4C)
{
int readSize = objHeader.objSize - sizeof(BLF_OBJ_HEADER);
fileData = inFile->read(readSize);
junk = inFile->read(readSize % 4); //file is padded so sizes must always end up on even multiple of 4
if (objHeader.objType == BLF_CONTAINER)
{
fileData.prepend(objHeader.uncompSize & 0xFF);
fileData.prepend((objHeader.uncompSize >> 8) & 0xFF);
fileData.prepend((objHeader.uncompSize >> 16) & 0xFF);
fileData.prepend((objHeader.uncompSize >> 24) & 0xFF);
uncompressedData += qUncompress(fileData);
pos = 0;
while (pos + sizeof(BLF_OBJ_HEADER) < uncompressedData.count())
{
memcpy(&obj.header, uncompressedData.mid(pos, sizeof(BLF_OBJ_HEADER)).constData(), sizeof(BLF_OBJ_HEADER));
if (qFromLittleEndian(objHeader.sig) == 0x4A424F4C)
{
fileData = uncompressedData.mid(pos + sizeof(BLF_OBJ_HEADER), obj.header.objSize - sizeof(BLF_OBJ_HEADER));
if (obj.header.objType == BLF_CAN_MSG)
{
memcpy(&canObject, fileData.constData(), sizeof(BLF_CAN_OBJ));
CANFrame frame;
frame.bus = canObject.channel;
frame.extended = (canObject.id & 0x80000000ull)?true:false;
frame.ID = canObject.id & 0x1FFFFFFFull;
frame.isReceived = true;
frame.len = canObject.dlc;
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);
}
}
uncompressedData.remove(0, pos);
}
}
else return false;
}
return false;
}
78 changes: 78 additions & 0 deletions blfhandler.h
@@ -0,0 +1,78 @@
#ifndef BLFHANDLER_H
#define BLFHANDLER_H

#include <Qt>
#include <QByteArray>
#include <QList>
#include "can_structs.h"

enum
{
BLF_CAN_MSG = 1,
BLF_CAN_ERR = 2,
BLF_CONTAINER = 10,
BLF_GLOBAL_MARKER = 96,
};

struct BLF_FILE_HEADER
{
uint32_t sig;
uint32_t headerSize;
uint8_t appID;
uint8_t appVerMajor;
uint8_t appVerMinor;
uint8_t appVerBuild;
uint8_t binLogVerMajor;
uint8_t binLogVerMinor;
uint8_t binLogVerBuild;
uint8_t binLogVerPatch;
uint64_t fileSize;
uint64_t uncompressedFileSize;
uint32_t countObjs;
uint32_t countObjsRead;
uint8_t startTime[16];
uint8_t stopTime[16];
uint8_t unused[72];
}; //144 bytes

struct BLF_OBJ_HEADER
{
uint32_t sig;
uint16_t headerSize;
uint16_t headerVersion;
uint32_t objSize;
uint32_t objType;
uint32_t flags;
uint16_t nothing;
uint16_t objVer;
uint64_t uncompSize;
}; //32 bytes

struct BLF_OBJECT
{
BLF_OBJ_HEADER header;
QByteArray data;
};

struct BLF_CAN_OBJ
{
uint16_t channel;
uint8_t flags;
uint8_t dlc;
uint32_t id;
uint8_t data[8];
};


class BLFHandler
{
public:
BLFHandler();
bool loadBLF(QString filename, QVector<CANFrame>* frames);

private:
BLF_FILE_HEADER header;
QList<BLF_OBJECT> objects;
};

#endif // BLFHANDLER_H
9 changes: 9 additions & 0 deletions framefileio.cpp
Expand Up @@ -6,6 +6,7 @@
#include <iostream>

#include "utility.h"
#include "blfhandler.h"

QFile FrameFileIO::continuousFile;

Expand Down Expand Up @@ -138,6 +139,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector<CANFrame>* frameCache
filters.append(QString(tr("Kvaser Log Decimal (*.txt *.TXT)")));
filters.append(QString(tr("Kvaser Log Hex (*.txt *.TXT)")));
filters.append(QString(tr("CANalyzer Ascii Log (*.asc *.ASC)")));
filters.append(QString(tr("CANalyzer Binary Log Files (*.blf *.BLF)")));

dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setNameFilters(filters);
Expand Down Expand Up @@ -171,6 +173,7 @@ bool FrameFileIO::loadFrameFile(QString &fileName, QVector<CANFrame>* frameCache
if (dialog.selectedNameFilter() == filters[11]) result = loadKvaserFile(filename, frameCache, false);
if (dialog.selectedNameFilter() == filters[12]) result = loadKvaserFile(filename, frameCache, true);
if (dialog.selectedNameFilter() == filters[13]) result = loadCanalyzerASC(filename, frameCache);
if (dialog.selectedNameFilter() == filters[14]) result = loadCanalyzerBLF(filename, frameCache);

progress.cancel();

Expand Down Expand Up @@ -588,6 +591,12 @@ bool FrameFileIO::loadCanalyzerASC(QString filename, QVector<CANFrame>* frames)
return !foundErrors;
}

bool FrameFileIO::loadCanalyzerBLF(QString filename, QVector<CANFrame> *frames)
{
BLFHandler blf;
blf.loadBLF(filename, frames);
}

//The "native" file format for this program
bool FrameFileIO::loadNativeCSVFile(QString filename, QVector<CANFrame>* frames)
{
Expand Down
1 change: 1 addition & 0 deletions framefileio.h
Expand Up @@ -43,6 +43,7 @@ class FrameFileIO: public QObject
static bool loadPCANFile(QString, QVector<CANFrame>*);
static bool loadKvaserFile(QString, QVector<CANFrame>*, bool);
static bool loadCanalyzerASC(QString, QVector<CANFrame>*);
static bool loadCanalyzerBLF(QString, QVector<CANFrame>*);
static bool saveCRTDFile(QString, const QVector<CANFrame>*);
static bool saveNativeCSVFile(QString, const QVector<CANFrame>*);
static bool saveGenericCSVFile(QString, const QVector<CANFrame>*);
Expand Down

0 comments on commit 80cf438

Please sign in to comment.