#include #include #include "canconnection.h" CANConnection::CANConnection(QString pPort, QString pDriver, CANCon::type pType, int pNumBuses, int pQueueLen, bool pUseThread) : mNumBuses(pNumBuses), mQueue(), mPort(pPort), mDriver(pDriver), mType(pType), mIsCapSuspended(false), mStatus(CANCon::NOT_CONNECTED), mStarted(false), mThread_p(nullptr) { /* register types */ qRegisterMetaType("CANBus"); qRegisterMetaType("CANFrame"); qRegisterMetaType("CANConStatus"); qRegisterMetaType("CANFlt"); /* set queue size */ mQueue.setSize(pQueueLen); /*TODO add check on returned value */ /* allocate buses */ /* TODO: change those tables for a vector */ mBusData.resize(mNumBuses); for(int i=0 ; iquit(); mThread_p->wait(); delete mThread_p; mThread_p = nullptr; } mBusData.clear(); } void CANConnection::start() { if( mThread_p && (mThread_p != QThread::currentThread()) ) { /* move ourself to the thread */ moveToThread(mThread_p); /*TODO handle errors */ /* connect started() */ connect(mThread_p, SIGNAL(started()), this, SLOT(start())); /* start the thread */ mThread_p->start(QThread::HighPriority); return; } /* set started flag */ mStarted = true; QSettings settings; if (settings.value("Main/TimeClock", false).toBool()) { useSystemTime = true; } else useSystemTime = false; /* in multithread case, this will be called before entering thread event loop */ return piStarted(); } void CANConnection::suspend(bool pSuspend) { /* execute in mThread_p context */ if( mThread_p && (mThread_p != QThread::currentThread()) ) { QMetaObject::invokeMethod(this, "suspend", Qt::BlockingQueuedConnection, Q_ARG(bool, pSuspend)); return; } return piSuspend(pSuspend); } void CANConnection::stop() { /* 1) execute in mThread_p context */ if( mThread_p && mStarted && (mThread_p != QThread::currentThread()) ) { /* if thread is finished, it means we call this function for the second time so we can leave */ if( !mThread_p->isFinished() ) { /* we need to call piStop() */ QMetaObject::invokeMethod(this, "stop", Qt::BlockingQueuedConnection); /* 3) stop thread */ mThread_p->quit(); if(!mThread_p->wait()) { qDebug() << "can't stop thread"; } } return; } /* 2) call piStop in mThread context */ return piStop(); } bool CANConnection::getBusSettings(int pBusIdx, CANBus& pBus) { /* make sure we execute in mThread context */ if( mThread_p && (mThread_p != QThread::currentThread()) ) { bool ret; QMetaObject::invokeMethod(this, "getBusSettings", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), Q_ARG(int , pBusIdx), Q_ARG(CANBus& , pBus)); return ret; } return piGetBusSettings(pBusIdx, pBus); } void CANConnection::setBusSettings(int pBusIdx, CANBus pBus) { /* make sure we execute in mThread context */ if( mThread_p && (mThread_p != QThread::currentThread()) ) { QMetaObject::invokeMethod(this, "setBusSettings", Qt::BlockingQueuedConnection, Q_ARG(int, pBusIdx), Q_ARG(CANBus, pBus)); return; } return piSetBusSettings(pBusIdx, pBus); } bool CANConnection::sendFrame(const CANFrame& pFrame) { /* make sure we execute in mThread context */ if( mThread_p && (mThread_p != QThread::currentThread()) ) { bool ret; QMetaObject::invokeMethod(this, "sendFrame", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), Q_ARG(const CANFrame&, pFrame)); return ret; } return piSendFrame(pFrame); } bool CANConnection::sendFrames(const QList& pFrames) { /* make sure we execute in mThread context */ if( mThread_p && (mThread_p != QThread::currentThread()) ) { bool ret; QMetaObject::invokeMethod(this, "sendFrames", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), Q_ARG(const QList&, pFrames)); return ret; } return piSendFrames(pFrames); } int CANConnection::getNumBuses() const{ return mNumBuses; } bool CANConnection::isConfigured(int pBusId) { if( pBusId < 0 || pBusId >= getNumBuses()) return false; return mBusData[pBusId].mConfigured; } void CANConnection::setConfigured(int pBusId, bool pConfigured) { if( pBusId < 0 || pBusId >= getNumBuses()) return; mBusData[pBusId].mConfigured = pConfigured; } bool CANConnection::getBusConfig(int pBusId, CANBus& pBus) { if( pBusId < 0 || pBusId >= getNumBuses() || !isConfigured(pBusId)) return false; qDebug() << "getBusConfig id: " << pBusId; pBus = mBusData[pBusId].mBus; return true; } void CANConnection::setBusConfig(int pBusId, CANBus& pBus) { if( pBusId < 0 || pBusId >= getNumBuses()) return; mBusData[pBusId].mConfigured = true; mBusData[pBusId].mBus = pBus; } QString CANConnection::getPort() { return mPort; } QString CANConnection::getDriver() { return mDriver; } LFQueue& CANConnection::getQueue() { return mQueue; } CANCon::type CANConnection::getType() { return mType; } CANCon::status CANConnection::getStatus() { return (CANCon::status) mStatus.load(); } void CANConnection::setStatus(CANCon::status pStatus) { mStatus.store(pStatus); } bool CANConnection::isCapSuspended() { return mIsCapSuspended; } void CANConnection::setCapSuspended(bool pIsSuspended) { mIsCapSuspended = pIsSuspended; } void CANConnection::debugInput(QByteArray bytes) { Q_UNUSED(bytes) } bool CANConnection::addTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver) { /* if( mThread_p && (mThread_p != QThread::currentThread()) ) { bool ret; QMetaObject::invokeMethod(this, "addTargettedFrame", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), Q_ARG(int, pBusId), Q_ARG(uint32_t , ID), Q_ARG(uint32_t , mask), Q_ARG(QObject *, receiver)); return ret; } */ /* sanity checks */ if(pBusId < -1 || pBusId >= getNumBuses()) return false; qDebug() << "Connection is registering a new targetted frame filter, local bus " << pBusId; CANFltObserver target; target.id = ID; target.mask = mask; target.observer = receiver; mBusData[pBusId].mTargettedFrames.append(target); return true; } bool CANConnection::removeTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QObject *receiver) { /* if( mThread_p && (mThread_p != QThread::currentThread()) ) { bool ret; QMetaObject::invokeMethod(this, "removeTargettedFrame", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, ret), Q_ARG(int, pBusId), Q_ARG(uint32_t , ID), Q_ARG(uint32_t , mask), Q_ARG(QObject *, receiver)); return ret; } */ /* sanity checks */ if(pBusId < -1 || pBusId >= getNumBuses()) return false; CANFltObserver target; target.id = ID; target.mask = mask; target.observer = receiver; mBusData[pBusId].mTargettedFrames.removeAll(target); return true; } bool CANConnection::removeAllTargettedFrames(QObject *receiver) { for (int i = 0; i < getNumBuses(); i++) { foreach (const CANFltObserver filt, mBusData[i].mTargettedFrames) { if (filt.observer == receiver) mBusData[i].mTargettedFrames.removeOne(filt); } } return true; } void CANConnection::checkTargettedFrame(CANFrame &frame) { unsigned int maskedID; //qDebug() << "Got frame with ID " << frame.ID << " on bus " << frame.bus; if (mBusData.count() == 0) return; if (mBusData[frame.bus].mTargettedFrames.length() == 0) return; foreach (const CANFltObserver filt, mBusData[frame.bus].mTargettedFrames) { //qDebug() << "Checking filter with id " << filt.id << " mask " << filt.mask; maskedID = frame.frameId() & filt.mask; if (maskedID == filt.id) { qDebug() << "In connection object I got a targetted frame. Forwarding it."; QMetaObject::invokeMethod(filt.observer, "gotTargettedFrame",Qt::QueuedConnection, Q_ARG(CANFrame, frame)); } } } bool CANConnection::piSendFrames(const QList& pFrames) { foreach(const CANFrame& frame, pFrames) { if(!piSendFrame(frame)) return false; } return true; }