add filters & callback support
This commit is contained in:
@@ -19,6 +19,13 @@ namespace CANCon {
|
||||
SOCKETCAN,
|
||||
NONE
|
||||
};
|
||||
|
||||
/* test */
|
||||
enum cbtype
|
||||
{
|
||||
READ,
|
||||
WRITE
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CANCONCONST_H
|
||||
|
||||
+100
-20
@@ -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,
|
||||
@@ -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()";
|
||||
@@ -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) {
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "canbus.h"
|
||||
#include "canconconst.h"
|
||||
|
||||
struct BusData;
|
||||
|
||||
class CANConnection : public QObject
|
||||
{
|
||||
@@ -64,6 +65,13 @@ public:
|
||||
*/
|
||||
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 */
|
||||
@@ -76,6 +84,11 @@ signals:
|
||||
//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
|
||||
@@ -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:
|
||||
|
||||
/**
|
||||
@@ -186,6 +207,22 @@ protected:
|
||||
*/
|
||||
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:
|
||||
|
||||
/**************************************************************/
|
||||
@@ -236,16 +273,24 @@ protected:
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -44,18 +44,6 @@ public:
|
||||
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();
|
||||
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,18 +18,6 @@ public:
|
||||
SocketCan(QString portName);
|
||||
virtual ~SocketCan();
|
||||
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user