Skip to content

Commit

Permalink
add filters & callback support
Browse files Browse the repository at this point in the history
  • Loading branch information
canpadawan committed Jun 20, 2016
1 parent 8216e15 commit 1a195fe
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 52 deletions.
7 changes: 7 additions & 0 deletions connections/canconconst.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ namespace CANCon {
SOCKETCAN,
NONE
};

/* test */
enum cbtype
{
READ,
WRITE
};
}

#endif // CANCONCONST_H
120 changes: 100 additions & 20 deletions connections/canconnection.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
#include <QThread>
#include "canconnection.h"


struct BusData {
CANBus mBus;
bool mConfigured;
QVector<CANFlt> mFilters;
bool mFilterOut;
};


CANConnection::CANConnection(QString pPort,
CANCon::type pType,
int pNumBuses,
Expand All @@ -12,6 +21,8 @@ CANConnection::CANConnection(QString pPort,
mType(pType),
mIsCapSuspended(false),
mStatus(CANCon::NOT_CONNECTED),
mStarted(false),
mCallback(NULL),
mThread_p(NULL)
{
qDebug() << "CANConnection()";
Expand All @@ -20,16 +31,18 @@ CANConnection::CANConnection(QString pPort,
qRegisterMetaType<CANBus>("CANBus");
qRegisterMetaType<CANFrame>("CANFrame");
qRegisterMetaType<CANCon::status>("CANCon::status");
qRegisterMetaType<CANFlt>("CANFlt");

/* set queue size */
mQueue.setSize(pQueueLen); /*TODO add check on returned value */

/* allocate buses */
mBus = new CANBus[mNumBuses];
mConfigured = new bool[mNumBuses];

for(int i=0 ; i<mNumBuses ; i++)
mConfigured[i] = false;
/* TODO: change those tables for a vector */
mBusData_p = new BusData[mNumBuses];
for(int i=0 ; i<mNumBuses ; i++) {
mBusData_p[i].mConfigured = false;
mBusData_p[i].mFilterOut = false;
}

/* if needed, create a thread and move ourself into it */
if(pUseThread) {
Expand All @@ -49,12 +62,10 @@ CANConnection::~CANConnection()
mThread_p = NULL;
}

/* delete bus table */
delete[] mBus;
mBus = NULL;
/* configured table */
delete[] mConfigured;
mConfigured = NULL;
if(mBusData_p) {
delete[] mBusData_p;
mBusData_p = NULL;
}
}


Expand All @@ -71,6 +82,9 @@ void CANConnection::start()
return;
}

/* set started flag */
mStarted = true;

/* in multithread case, this will be called before entering thread event loop */
return piStarted();
}
Expand Down Expand Up @@ -181,33 +195,33 @@ int CANConnection::getNumBuses() {


bool CANConnection::isConfigured(int pBusId) {
if( pBusId < 0 || pBusId >= mNumBuses)
if( pBusId < 0 || pBusId >= getNumBuses())
return false;
return mConfigured[pBusId];
return mBusData_p[pBusId].mConfigured;
}

void CANConnection::setConfigured(int pBusId, bool pConfigured) {
if( pBusId < 0 || pBusId >= mNumBuses)
if( pBusId < 0 || pBusId >= getNumBuses())
return;
mConfigured[pBusId] = pConfigured;
mBusData_p[pBusId].mConfigured = pConfigured;
}


bool CANConnection::getBusConfig(int pBusId, CANBus& pBus) {
if( pBusId < 0 || pBusId >= mNumBuses || !isConfigured(pBusId))
if( pBusId < 0 || pBusId >= getNumBuses() || !isConfigured(pBusId))
return false;

pBus = mBus[pBusId];
pBus = mBusData_p[pBusId].mBus;
return true;
}


void CANConnection::setBusConfig(int pBusId, CANBus& pBus) {
if( pBusId < 0 || pBusId >= mNumBuses)
if( pBusId < 0 || pBusId >= getNumBuses())
return;

mConfigured[pBusId] = true;
mBus[pBusId] = pBus;
mBusData_p[pBusId].mConfigured = true;
mBusData_p[pBusId].mBus = pBus;
}


Expand All @@ -231,6 +245,13 @@ CANCon::status CANConnection::getStatus() {
}


bool CANConnection::setCallback(std::function<void(CANCon::cbtype)> pCallback) {
if(mStarted || !pCallback) return false;
mCallback = pCallback;
return true;
}


void CANConnection::setStatus(CANCon::status pStatus) {
mStatus.store(pStatus);
}
Expand All @@ -243,3 +264,62 @@ void CANConnection::setCapSuspended(bool pIsSuspended) {
mIsCapSuspended = pIsSuspended;
}

void CANConnection::callback(CANCon::cbtype pCbType) {
if(mCallback)
mCallback(pCbType);
}

bool CANConnection::setFilters(int pBusId, const QVector<CANFlt>& pFilters, bool pFilterOut)
{
/* make sure we execute in mThread context */
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
bool ret;
QMetaObject::invokeMethod(this, "setFilters",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, ret),
Q_ARG(int , pBusId),
Q_ARG(const QVector<CANFlt>&, pFilters),
Q_ARG(bool , pFilterOut));
return ret;
}

/* sanity checks */
if(pBusId<0 || pBusId>=getNumBuses())
return false;

/* copy filters */
mBusData_p[pBusId].mFilters = pFilters;
mBusData_p[pBusId].mFilterOut = pFilterOut;

/* set hardware filtering if available */
if(pFilterOut)
piSetFilters(pBusId, pFilters);

return true;
}


bool CANConnection::discard(int pBusId, quint32 pId, bool& pNotify)
{
if(pBusId<0 || pBusId>=getNumBuses())
return true;

foreach (const CANFlt& filter, mBusData_p[pBusId].mFilters)
{
if( (filter.id & filter.mask) == (pId & filter.mask) )
{
if(filter.notify)
pNotify = true;
return false;
}
}
return mBusData_p[pBusId].mFilterOut;
}


/* default implementation of piSetFilters */
void CANConnection::piSetFilters(int pBusId, const QVector<CANFlt>& pFilters)
{
Q_UNUSED(pBusId);
Q_UNUSED(pFilters);
}
49 changes: 47 additions & 2 deletions connections/canconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "canbus.h"
#include "canconconst.h"

struct BusData;

class CANConnection : public QObject
{
Expand Down Expand Up @@ -64,6 +65,13 @@ class CANConnection : public QObject
*/
CANCon::status getStatus();

/**
* @brief set the callback function, this call has to be placed before calling start
* @param pCallback
* @return true if callback can be set
*/
bool setCallback(std::function<void(CANCon::cbtype)> pCallback);


signals:
/*not implemented yet */
Expand All @@ -76,6 +84,11 @@ class CANConnection : public QObject
//being passed. Just set for things that really are being updated.
void busStatus(int, int, int);

/**
* @brief event sent when a frame matching a filter set with notification hs been received
*/
void notify();

/**
* @brief event emitted when the CANCon::status of the connection changes (connected->not_connected or the other way round)
* @param pStatus: the new status of the device
Expand Down Expand Up @@ -136,6 +149,14 @@ public slots:
*/
void sendFrameBatch(const QList<CANFrame>& pFrames);

/**
* @brief sets a filter list. Filters can be used to send a signal or filter out messages
* @param pFilters: a vector of can filters
* @param pFilterOut: if set to true, can frames not matching a filter are discarded
* @return true if filters have been set, false if busid is invalid
*/
bool setFilters(int pBusId, const QVector<CANFlt>& pFilters, bool pFilterOut);

protected:

/**
Expand Down Expand Up @@ -186,6 +207,22 @@ public slots:
*/
void setCapSuspended(bool pIsSuspended);

/**
* @brief call callback function
* @param pCbType callback type (read or write)
*/
void callback(CANCon::cbtype pCbType);

/**
* @brief used to check if a message shall be discarded. The function also update pNotify if a notification is expected for that message
* @param pBusId: the bus id on which the frame has been received
* @param pId: the id of the message to filter
* @param pNotify: set to true if a notification is expected, else pNotify is not set
* @return true if message shall be discarded
*/
bool discard(int pBusId, quint32 pId, bool& pNotify);


protected:

/**************************************************************/
Expand Down Expand Up @@ -236,16 +273,24 @@ public slots:
*/
virtual void piSendFrameBatch(const QList<CANFrame>&) = 0;

/**
* @brief sets a hardware filter list
* @param pBusId: the bus id on which filters have to be set
* @param pFilters: a vector of can filters, the notification flag of CANFilter is ignored
* @note implementing this function is optional
*/
virtual void piSetFilters(int pBusId, const QVector<CANFlt>& pFilters);

private:
CANBus* mBus;
bool* mConfigured;
LFQueue<CANFrame> mQueue;
const int mNumBuses;
const QString mPort;
const CANCon::type mType;
bool mIsCapSuspended;
QAtomicInt mStatus;
bool mStarted;
std::function<void(CANCon::cbtype)> mCallback;
BusData* mBusData_p;
QThread* mThread_p;
};

Expand Down
12 changes: 0 additions & 12 deletions connections/gvretserial.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,6 @@ class GVRetSerial : public CANConnection
GVRetSerial(QString portName);
virtual ~GVRetSerial();

signals:
void error(const QString &);

void status(CANCon::status);
void deviceInfo(int, int); //First param = driver version (or version of whatever you want), second param a status byte

//bus number, bus speed, status (bit 0 = enabled, 1 = single wire, 2 = listen only)
//3 = Use value stored for enabled, 4 = use value passed for single wire, 5 = use value passed for listen only
//6 = use value passed for speed. This allows bus status to be updated but set that some things aren't really
//being passed. Just set for things that really are being updated.
void busStatus(int, int, int);

protected:

virtual void piStarted();
Expand Down
24 changes: 18 additions & 6 deletions connections/socketcan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ void SocketCan::framesWritten(qint64 count)

void SocketCan::framesReceived()
{
/* test */
bool enqueued = false;
bool sndNotif = false;

/* sanity checks */
if(!mDev_p)
return;
Expand All @@ -153,15 +157,16 @@ void SocketCan::framesReceived()

/* exit case */
if(!recFrame.isValid())
return;
break;

/* drop frame if capture is suspended */
if(isCapSuspended())
continue;

/* check frame */
if(!recFrame.payload().isEmpty() &&
recFrame.payload().length()<=8)
if( !recFrame.payload().isEmpty() &&
recFrame.payload().length()<=8 &&
!discard(0, recFrame.frameId(), sndNotif) )
{
CANFrame* frame_p = getQueue().get();
if(frame_p) {
Expand All @@ -175,13 +180,20 @@ void SocketCan::framesReceived()

/* enqueue frame */
getQueue().queue();
/* set enqueued */
enqueued = true;
}
else
qDebug() << "can't get a frame, ERROR";
}
else {
qDebug() << "invalid frame";
}
}

if(enqueued) {
callback(CANCon::READ);
}

if(sndNotif) {
emit notify();
}
}

Expand Down
Loading

0 comments on commit 1a195fe

Please sign in to comment.