Files
giesCANne/connections/canconmanager.cpp
T
Collin Kidder b4c8aa49db First pass at turning on functionality to allow frame sending from the new connection system.
The fuzzing window has been modified to use the new system. This validates that it mostly works now.
More screens will be modified to work soon.
2016-08-09 20:03:57 -04:00

149 lines
3.8 KiB
C++

#include "canconmanager.h"
CANConManager* CANConManager::mInstance = NULL;
CANConManager* CANConManager::getInstance()
{
if(!mInstance)
mInstance = new CANConManager();
return mInstance;
}
CANConManager::CANConManager(QObject *parent): QObject(parent)
{
connect(&mTimer, SIGNAL(timeout()), this, SLOT(refreshCanList()));
mTimer.setInterval(250); /*tick 4 times a second */
mTimer.setSingleShot(false);
mTimer.start();
}
CANConManager::~CANConManager()
{
mTimer.stop();
mInstance = NULL;
}
void CANConManager::add(CANConnection* pConn_p)
{
connect(pConn_p, SIGNAL(notify()), this, SLOT(refreshCanList()));
mConns.append(pConn_p);
}
void CANConManager::remove(CANConnection* pConn_p)
{
disconnect(pConn_p, 0, this, 0);
mConns.removeOne(pConn_p);
}
//Get total number of buses currently registered with the program
int CANConManager::getNumBuses()
{
int buses = 0;
foreach(CANConnection* conn_p, mConns)
{
buses += conn_p->getNumBuses();
}
return buses;
}
void CANConManager::refreshCanList()
{
QObject* sender_p = QObject::sender();
if( sender_p != &mTimer)
{
/* if we are not the sender, the signal is coming from a connection */
/* refresh only the given connection */
if(mConns.contains((CANConnection*) sender_p))
refreshConnection((CANConnection*)sender_p);
}
else
{
foreach (CANConnection* conn_p, mConns)
refreshConnection((CANConnection*)conn_p);
}
}
QList<CANConnection*>& CANConManager::getConnections()
{
return mConns;
}
CANConnection* CANConManager::getByName(const QString& pName) const
{
foreach(CANConnection* conn_p, mConns)
{
if(conn_p->getPort() == pName)
return conn_p;
}
return NULL;
}
void CANConManager::refreshConnection(CANConnection* pConn_p)
{
CANFrame* frame_p = NULL;
QVector<CANFrame> frames;
while( (frame_p = pConn_p->getQueue().peek() ) ) {
frames.append(*frame_p);
pConn_p->getQueue().dequeue();
}
if(frames.size())
emit framesReceived(pConn_p, frames);
}
/*
* Uses the requested bus to look up which CANConnection object handles this bus based on the order of
* the objects and how many buses they implement. For instance, if the request is to send on bus 2
* and there is a GVRET object first then a socketcan object it'll send on the socketcan object as
* gvret will have claimed buses 0 and 1 and socketcan bus 2. But, each actual CANConnection expects
* its own bus numbers to start at zero so the frame bus number has to be offset accordingly.
* Also keep in mind that the CANConnection "sendFrame" function uses a blocking queued connection
* and so will force the frame to be delivered before it keeps going. This allows on the stack variables
* to be used but is slow. This function uses an on the stack copy of the frame so the way it works
* is a good thing but performance will suffer. TODO: Investigate a way to use non-blocking calls.
*/
bool CANConManager::sendFrame(const CANFrame& pFrame)
{
int busBase = 0;
CANFrame workingFrame = pFrame;
CANFrame *txFrame;
foreach (CANConnection* conn, mConns)
{
//check if this CAN connection is supposed to handle the requested bus
if (pFrame.bus <= busBase + conn->getNumBuses())
{
workingFrame.bus -= busBase;
txFrame = conn->getQueue().get();
*txFrame = workingFrame;
conn->getQueue().queue();
return conn->sendFrame(workingFrame);
}
busBase += conn->getNumBuses();
}
return false;
}
bool CANConManager::sendFrames(const QList<CANFrame>& pFrames)
{
foreach(const CANFrame& frame, pFrames)
{
if(!sendFrame(frame))
return false;
}
return true;
}