diff --git a/canconnectionmodel.cpp b/canconnectionmodel.cpp index 084d2cc..b7216aa 100644 --- a/canconnectionmodel.cpp +++ b/canconnectionmodel.cpp @@ -96,7 +96,8 @@ QVariant CANConnectionModel::data(const QModelIndex &index, int role) const switch (index.column()) { case 0: //bus - return QString::number(busId); + //return QString::number(busId); + return QString::number(index.row()); break; case 1: //type if (conn_p) diff --git a/connections/canconmanager.cpp b/connections/canconmanager.cpp index 5f645d1..33c4892 100644 --- a/connections/canconmanager.cpp +++ b/connections/canconmanager.cpp @@ -41,6 +41,16 @@ void CANConManager::remove(CANConnection* pConn_p) 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() { @@ -92,3 +102,47 @@ void CANConManager::refreshConnection(CANConnection* pConn_p) 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& pFrames) +{ + foreach(const CANFrame& frame, pFrames) + { + if(!sendFrame(frame)) + return false; + } + + return true; +} diff --git a/connections/canconmanager.h b/connections/canconmanager.h index 66896f1..d9c7e40 100644 --- a/connections/canconmanager.h +++ b/connections/canconmanager.h @@ -20,6 +20,19 @@ public: CANConnection* getByName(const QString& pName) const; + int getNumBuses(); + + /** + * @brief sendFrame sends a single frame out the desired bus + * @param pFrame - reference to a CANFrame struct that has been filled out for sending + * @return bool specifying whether the send succeeded or not + * @note Finds which CANConnection object is responsible for this bus and automatically converts bus number to pass properly to CANConnection + */ + bool sendFrame(const CANFrame& pFrame); + + //just the multi-frame version of above function. + bool sendFrames(const QList& pFrames); + signals: void framesReceived(CANConnection* pConn_p, QVector& pFrames); diff --git a/connections/gvretserial.cpp b/connections/gvretserial.cpp index d9408b3..c76a5ee 100644 --- a/connections/gvretserial.cpp +++ b/connections/gvretserial.cpp @@ -141,7 +141,52 @@ void GVRetSerial::piSetBusSettings(int pBusIdx, CANBus bus) } -bool GVRetSerial::piSendFrame(const CANFrame&) {return false;} +bool GVRetSerial::piSendFrame(const CANFrame& frame) +{ + QByteArray buffer; + int c; + int ID; + CANFrame tempFrame = frame; + tempFrame.isReceived = false; + tempFrame.timestamp = ((QDateTime::currentMSecsSinceEpoch() - txTimestampBasis) * 1000); + + //qDebug() << "Sending out frame with id " << frame->ID; + + //show our sent frames in the list too. This happens even if we're not connected. + /* model lives in UI thread, we need to call invokeMethod */ + //QMetaObject::invokeMethod(model, "addFrame", + // Qt::QueuedConnection, + // Q_ARG(CANFrame, tempFrame), + // Q_ARG(bool, false)); + + framesRapid++; + + if (serial == NULL) return false; + if (!serial->isOpen()) return false; + //if (!isConnected) return false; + + ID = frame.ID; + if (frame.extended) ID |= 1 << 31; + + buffer[0] = (char)0xF1; //start of a command over serial + buffer[1] = 0; //command ID for sending a CANBUS frame + buffer[2] = (unsigned char)(ID & 0xFF); //four bytes of ID LSB first + buffer[3] = (unsigned char)(ID >> 8); + buffer[4] = (unsigned char)(ID >> 16); + buffer[5] = (unsigned char)(ID >> 24); + buffer[6] = (unsigned char)((frame.bus) & 1); + buffer[7] = (unsigned char)frame.len; + for (c = 0; c < frame.len; c++) + { + buffer[8 + c] = frame.data[c]; + } + buffer[8 + frame.len] = 0; + + //qDebug() << "writing " << buffer.length() << " bytes to serial port"; + serial->write(buffer); + + return true; +} diff --git a/fuzzingwindow.cpp b/fuzzingwindow.cpp index 45e564c..0ae427f 100644 --- a/fuzzingwindow.cpp +++ b/fuzzingwindow.cpp @@ -3,6 +3,7 @@ #include "utility.h" #include #include "mainwindow.h" +#include "connections/canconmanager.h" FuzzingWindow::FuzzingWindow(const QVector *frames, QWidget *parent) : QDialog(parent), @@ -36,9 +37,10 @@ FuzzingWindow::FuzzingWindow(const QVector *frames, QWidget *parent) : fuzzTimer->setInterval(ui->spinTiming->value()); - ui->cbBuses->addItem(tr("0")); - ui->cbBuses->addItem(tr("1")); - ui->cbBuses->addItem(tr("Both")); + int numBuses = CANConManager::getInstance()->getNumBuses(); + for (int n = 0; n < numBuses; n++) ui->cbBuses->addItem(QString::number(n)); + ui->cbBuses->addItem(tr("All")); + } FuzzingWindow::~FuzzingWindow() @@ -111,8 +113,7 @@ void FuzzingWindow::timerTriggered() { CANFrame thisFrame; sendingBuffer.clear(); - int buses = ui->cbBuses->currentIndex() + 1; - if (buses == 0) buses = 1; + int buses = ui->cbBuses->currentIndex(); for (int count = 0; count < ui->spinBurst->value(); count++) { thisFrame.ID = currentID; @@ -121,22 +122,26 @@ void FuzzingWindow::timerTriggered() else thisFrame.extended = false; thisFrame.bus = 0; //hard coded for now. TODO: do not hard code thisFrame.len = ui->spinBytes->value(); - if (buses & 1) + + if (buses < (ui->cbBuses->count() - 1)) { - thisFrame.bus = 0; + thisFrame.bus = buses; sendingBuffer.append(thisFrame); } - if (buses & 2) + else //fuzz all the buses! HACK THE PLANET! Er, something... { - thisFrame.bus = 1; - sendingBuffer.append(thisFrame); + for (int j = 0; j < ui->cbBuses->count() - 1; j++) + { + thisFrame.bus = j; + sendingBuffer.append(thisFrame); + } } calcNextID(); calcNextBitPattern(); numSentFrames++; } - emit sendFrameBatch(&sendingBuffer); + CANConManager::getInstance()->sendFrames(sendingBuffer); ui->lblNumFrames->setText("# of sent frames: " + QString::number(numSentFrames)); } diff --git a/mainwindow.cpp b/mainwindow.cpp index 27546b4..802d571 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -918,8 +918,6 @@ void MainWindow::showFuzzingWindow() if (!fuzzingWindow) { fuzzingWindow = new FuzzingWindow(model->getListReference()); - connect(fuzzingWindow, SIGNAL(sendCANFrame(const CANFrame*)), connectionWindow, SLOT(sendFrame(const CANFrame*))); - connect(fuzzingWindow, SIGNAL(sendFrameBatch(const QList*)), connectionWindow, SLOT(sendFrameBatch(const QList*))); } fuzzingWindow->show(); } @@ -929,7 +927,7 @@ void MainWindow::showUDSScanWindow() if (!udsScanWindow) { udsScanWindow = new UDSScanWindow(model->getListReference()); - connect(udsScanWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), connectionWindow, SLOT(sendFrame(const CANFrame*))); + //connect(udsScanWindow, SIGNAL(sendCANFrame(const CANFrame*,int)), connectionWindow, SLOT(sendFrame(const CANFrame*))); } udsScanWindow->show(); }