mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-29 14:52:12 +01:00
Attempt to fix GCS crashes on USB disconnect: please confirm on other operating systems it is still working fine in all situations.
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@3066 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
2e5863281c
commit
9d0ce95b37
@ -106,50 +106,44 @@ void ConnectionManager::init()
|
|||||||
*/
|
*/
|
||||||
bool ConnectionManager::connectDevice()
|
bool ConnectionManager::connectDevice()
|
||||||
{
|
{
|
||||||
devListItem connection_device = findDevice(m_availableDevList->currentText());
|
devListItem connection_device = findDevice(m_availableDevList->currentText());
|
||||||
if (!connection_device.connection)
|
if (!connection_device.connection)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QIODevice *io_dev = connection_device.connection->openDevice(connection_device.devName);
|
QIODevice *io_dev = connection_device.connection->openDevice(connection_device.devName);
|
||||||
if (!io_dev)
|
if (!io_dev)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
io_dev->open(QIODevice::ReadWrite);
|
io_dev->open(QIODevice::ReadWrite);
|
||||||
|
|
||||||
// check if opening the device worked
|
// check if opening the device worked
|
||||||
if (!io_dev->isOpen())
|
if (!io_dev->isOpen()) {
|
||||||
{
|
qDebug() << "Error: io_dev->isOpen() returned FALSE .. could not open connection to " << connection_device.devName
|
||||||
qDebug() << "Error: io_dev->isOpen() returned FALSE .. could not open connection to " << connection_device.devName
|
<< ": " << io_dev->errorString();
|
||||||
<< ": " << io_dev->errorString();
|
|
||||||
|
|
||||||
// close the device
|
// close the device
|
||||||
try
|
// EDOUARD: why do we close if we could not open ???
|
||||||
{
|
try {
|
||||||
connection_device.connection->closeDevice(connection_device.devName);
|
connection_device.connection->closeDevice(connection_device.devName);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...) { // handle exception
|
||||||
{ // handle exception
|
qDebug() << "Exception: connection_device.connection->closeDevice(" << connection_device.devName << ")";
|
||||||
qDebug() << "Exception: connection_device.connection->closeDevice(" << connection_device.devName << ")";
|
}
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
// we appear to have connected to the device OK
|
||||||
}
|
// remember the connection/device details
|
||||||
|
m_connectionDevice = connection_device;
|
||||||
|
m_ioDev = io_dev;
|
||||||
|
|
||||||
// we appear to have connected to the device OK
|
connect(m_connectionDevice.connection, SIGNAL(destroyed(QObject *)), this, SLOT(onConnectionDestroyed(QObject *)), Qt::QueuedConnection);
|
||||||
|
|
||||||
// remember the connection/device details
|
// signal interested plugins that we connected to the device
|
||||||
m_connectionDevice = connection_device;
|
emit deviceConnected(m_ioDev);
|
||||||
m_ioDev = io_dev;
|
m_connectBtn->setText("Disconnect");
|
||||||
|
m_availableDevList->setEnabled(false);
|
||||||
connect(m_connectionDevice.connection, SIGNAL(destroyed(QObject *)), this, SLOT(onConnectionDestroyed(QObject *)), Qt::QueuedConnection);
|
return true;
|
||||||
|
|
||||||
m_connectBtn->setText("Disconnect");
|
|
||||||
m_availableDevList->setEnabled(false);
|
|
||||||
|
|
||||||
// signal interested plugins that we connected to the device
|
|
||||||
emit deviceConnected(m_ioDev);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,30 +152,32 @@ bool ConnectionManager::connectDevice()
|
|||||||
*/
|
*/
|
||||||
bool ConnectionManager::disconnectDevice()
|
bool ConnectionManager::disconnectDevice()
|
||||||
{
|
{
|
||||||
if (!m_ioDev)
|
if (!m_ioDev) {
|
||||||
{ // apparently we are already disconnected
|
// apparently we are already disconnected: this can
|
||||||
|
// happen if a plugin tries to force a disconnect whereas
|
||||||
|
// we are not connected. Just return.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_connectionDevice.connection = NULL;
|
// We are connected - disconnect from the device
|
||||||
m_ioDev = NULL;
|
|
||||||
|
|
||||||
return false;
|
// signal interested plugins that user is disconnecting his device
|
||||||
}
|
emit deviceAboutToDisconnect();
|
||||||
|
|
||||||
// we appear to be connected - disconnect from the device
|
try {
|
||||||
|
if (m_connectionDevice.connection)
|
||||||
|
m_connectionDevice.connection->closeDevice(m_connectionDevice.devName);
|
||||||
|
} catch (...) { // handle exception
|
||||||
|
qDebug() << "Exception: m_connectionDevice.connection->closeDevice(" << m_connectionDevice.devName << ")";
|
||||||
|
}
|
||||||
|
|
||||||
try
|
m_connectionDevice.connection = NULL;
|
||||||
{
|
m_ioDev = NULL;
|
||||||
if (m_connectionDevice.connection)
|
|
||||||
m_connectionDevice.connection->closeDevice(m_connectionDevice.devName);
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{ // handle exception
|
|
||||||
qDebug() << "Exception: m_connectionDevice.connection->closeDevice(" << m_connectionDevice.devName << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
onConnectionClosed(m_connectionDevice.connection);
|
m_connectBtn->setText("Connect");
|
||||||
|
m_availableDevList->setEnabled(true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -222,24 +218,11 @@ void ConnectionManager::aboutToRemoveObject(QObject *obj)
|
|||||||
m_connectionsList.removeAt(m_connectionsList.indexOf(connection));
|
m_connectionsList.removeAt(m_connectionsList.indexOf(connection));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionManager::onConnectionClosed(QObject *obj) // Pip
|
|
||||||
{
|
|
||||||
if (!m_connectionDevice.connection || m_connectionDevice.connection != obj)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_connectionDevice.connection = NULL;
|
|
||||||
m_ioDev = NULL;
|
|
||||||
|
|
||||||
m_connectBtn->setText("Connect");
|
|
||||||
m_availableDevList->setEnabled(true);
|
|
||||||
|
|
||||||
// signal interested plugins that user is disconnecting his device
|
|
||||||
emit deviceDisconnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionManager::onConnectionDestroyed(QObject *obj) // Pip
|
void ConnectionManager::onConnectionDestroyed(QObject *obj) // Pip
|
||||||
{
|
{
|
||||||
onConnectionClosed(obj);
|
//onConnectionClosed(obj);
|
||||||
|
disconnectDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -247,13 +230,14 @@ void ConnectionManager::onConnectionDestroyed(QObject *obj) // Pip
|
|||||||
*/
|
*/
|
||||||
void ConnectionManager::onConnectPressed()
|
void ConnectionManager::onConnectPressed()
|
||||||
{
|
{
|
||||||
if (!m_ioDev || !m_connectionDevice.connection)
|
// Check if we have a ioDev already created:
|
||||||
{ // connecting
|
if (!m_ioDev)
|
||||||
connectDevice();
|
{ // connecting
|
||||||
|
connectDevice();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // disconnecting
|
{ // disconnecting
|
||||||
disconnectDevice();
|
disconnectDevice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +302,8 @@ void ConnectionManager::unregisterAll(IConnection *connection)
|
|||||||
{
|
{
|
||||||
if (m_connectionDevice.connection && m_connectionDevice.connection == connection)
|
if (m_connectionDevice.connection && m_connectionDevice.connection == connection)
|
||||||
{ // we are currently using the one we are about to erase
|
{ // we are currently using the one we are about to erase
|
||||||
onConnectionClosed(m_connectionDevice.connection);
|
//onConnectionClosed(m_connectionDevice.connection);
|
||||||
|
disconnectDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = m_devList.erase(iter);
|
iter = m_devList.erase(iter);
|
||||||
|
@ -81,7 +81,7 @@ protected:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void deviceConnected(QIODevice *dev);
|
void deviceConnected(QIODevice *dev);
|
||||||
void deviceDisconnected();
|
void deviceAboutToDisconnect();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void objectAdded(QObject *obj);
|
void objectAdded(QObject *obj);
|
||||||
@ -90,7 +90,7 @@ private slots:
|
|||||||
void onConnectPressed();
|
void onConnectPressed();
|
||||||
void devChanged(IConnection *connection);
|
void devChanged(IConnection *connection);
|
||||||
|
|
||||||
void onConnectionClosed(QObject *obj);
|
// void onConnectionClosed(QObject *obj);
|
||||||
void onConnectionDestroyed(QObject *obj);
|
void onConnectionDestroyed(QObject *obj);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -94,7 +94,7 @@ QStringList RawHIDConnection::availableDevices()
|
|||||||
QIODevice *RawHIDConnection::openDevice(const QString &deviceName)
|
QIODevice *RawHIDConnection::openDevice(const QString &deviceName)
|
||||||
{
|
{
|
||||||
//added by andrew
|
//added by andrew
|
||||||
if (RawHidHandle)
|
if (RawHidHandle)
|
||||||
closeDevice(deviceName);
|
closeDevice(deviceName);
|
||||||
//end added by andrew
|
//end added by andrew
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent)
|
|||||||
// running the scopes if we are not connected and not replaying logs
|
// running the scopes if we are not connected and not replaying logs
|
||||||
// Also listen to disconnect actions from the user
|
// Also listen to disconnect actions from the user
|
||||||
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
|
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
|
||||||
connect(cm, SIGNAL(deviceDisconnected()), this, SLOT(stopPlotting()));
|
connect(cm, SIGNAL(deviceAboutToDisconnect()), this, SLOT(stopPlotting()));
|
||||||
connect(cm, SIGNAL(deviceConnected(QIODevice*)), this, SLOT(startPlotting()));
|
connect(cm, SIGNAL(deviceConnected(QIODevice*)), this, SLOT(startPlotting()));
|
||||||
|
|
||||||
m_csvLoggingStarted=0;
|
m_csvLoggingStarted=0;
|
||||||
@ -89,7 +89,7 @@ ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent)
|
|||||||
m_csvLoggingStartTime = QDateTime::currentDateTime();
|
m_csvLoggingStartTime = QDateTime::currentDateTime();
|
||||||
|
|
||||||
//Listen to autopilot connection events
|
//Listen to autopilot connection events
|
||||||
connect(cm, SIGNAL(deviceDisconnected()), this, SLOT(csvLoggingDisconnect()));
|
connect(cm, SIGNAL(deviceAboutToDisconnect()), this, SLOT(csvLoggingDisconnect()));
|
||||||
connect(cm, SIGNAL(deviceConnected(QIODevice*)), this, SLOT(csvLoggingConnect()));
|
connect(cm, SIGNAL(deviceConnected(QIODevice*)), this, SLOT(csvLoggingConnect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ const quint8 UAVTalk::crc_table[256] = {
|
|||||||
UAVTalk::UAVTalk(QIODevice* iodev, UAVObjectManager* objMngr)
|
UAVTalk::UAVTalk(QIODevice* iodev, UAVObjectManager* objMngr)
|
||||||
{
|
{
|
||||||
io = iodev;
|
io = iodev;
|
||||||
|
|
||||||
this->objMngr = objMngr;
|
this->objMngr = objMngr;
|
||||||
|
|
||||||
rxState = STATE_SYNC;
|
rxState = STATE_SYNC;
|
||||||
@ -67,23 +68,17 @@ UAVTalk::UAVTalk(QIODevice* iodev, UAVObjectManager* objMngr)
|
|||||||
|
|
||||||
memset(&stats, 0, sizeof(ComStats));
|
memset(&stats, 0, sizeof(ComStats));
|
||||||
|
|
||||||
if (io) // Pip
|
connect(io, SIGNAL(readyRead()), this, SLOT(processInputStream()));
|
||||||
connect(io, SIGNAL(readyRead()), this, SLOT(processInputStream()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UAVTalk::~UAVTalk()
|
UAVTalk::~UAVTalk()
|
||||||
{
|
{
|
||||||
// Pip
|
|
||||||
mutex->lock();
|
|
||||||
io = NULL;
|
|
||||||
objMngr = NULL;
|
|
||||||
mutex->unlock();
|
|
||||||
|
|
||||||
// According to Qt, it is not necessary to disconnect upon
|
// According to Qt, it is not necessary to disconnect upon
|
||||||
// object deletion.
|
// object deletion.
|
||||||
//disconnect(io, SIGNAL(readyRead()), this, SLOT(processInputStream()));
|
//disconnect(io, SIGNAL(readyRead()), this, SLOT(processInputStream()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the statistics counters
|
* Reset the statistics counters
|
||||||
*/
|
*/
|
||||||
@ -109,24 +104,9 @@ void UAVTalk::processInputStream()
|
|||||||
{
|
{
|
||||||
quint8 tmp;
|
quint8 tmp;
|
||||||
|
|
||||||
while (true)
|
while (io->bytesAvailable() > 0)
|
||||||
{
|
{
|
||||||
mutex->lock(); // Pip
|
io->read((char*)&tmp, 1);
|
||||||
if (!io)
|
|
||||||
{
|
|
||||||
mutex->unlock();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!io->isOpen() || io->bytesAvailable() <= 0)
|
|
||||||
{
|
|
||||||
mutex->unlock();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
qint64 bytes_read = io->read((char*)&tmp, sizeof(tmp));
|
|
||||||
mutex->unlock();
|
|
||||||
|
|
||||||
if (bytes_read <= 0) break; // Pip
|
|
||||||
|
|
||||||
processInputByte(tmp);
|
processInputByte(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,9 +196,6 @@ bool UAVTalk::objectTransaction(UAVObject* obj, quint8 type, bool allInstances)
|
|||||||
*/
|
*/
|
||||||
bool UAVTalk::processInputByte(quint8 rxbyte)
|
bool UAVTalk::processInputByte(quint8 rxbyte)
|
||||||
{
|
{
|
||||||
if (!objMngr || !io) // Pip
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Update stats
|
// Update stats
|
||||||
stats.rxBytes++;
|
stats.rxBytes++;
|
||||||
|
|
||||||
@ -429,10 +406,7 @@ bool UAVTalk::receiveObject(quint8 type, quint32 objId, quint16 instId, quint8*
|
|||||||
{
|
{
|
||||||
Q_UNUSED(length);
|
Q_UNUSED(length);
|
||||||
|
|
||||||
if (!objMngr || !io) // Pip
|
UAVObject* obj = NULL;
|
||||||
return false;
|
|
||||||
|
|
||||||
UAVObject* obj = NULL;
|
|
||||||
bool error = false;
|
bool error = false;
|
||||||
bool allInstances = (instId == ALL_INSTANCES? true : false);
|
bool allInstances = (instId == ALL_INSTANCES? true : false);
|
||||||
|
|
||||||
@ -531,10 +505,7 @@ bool UAVTalk::receiveObject(quint8 type, quint32 objId, quint16 instId, quint8*
|
|||||||
*/
|
*/
|
||||||
UAVObject* UAVTalk::updateObject(quint32 objId, quint16 instId, quint8* data)
|
UAVObject* UAVTalk::updateObject(quint32 objId, quint16 instId, quint8* data)
|
||||||
{
|
{
|
||||||
if (!objMngr || !io) // Pip
|
// Get object
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// Get object
|
|
||||||
UAVObject* obj = objMngr->getObject(objId, instId);
|
UAVObject* obj = objMngr->getObject(objId, instId);
|
||||||
// If the instance does not exist create it
|
// If the instance does not exist create it
|
||||||
if (obj == NULL)
|
if (obj == NULL)
|
||||||
@ -589,10 +560,7 @@ void UAVTalk::updateAck(UAVObject* obj)
|
|||||||
*/
|
*/
|
||||||
bool UAVTalk::transmitObject(UAVObject* obj, quint8 type, bool allInstances)
|
bool UAVTalk::transmitObject(UAVObject* obj, quint8 type, bool allInstances)
|
||||||
{
|
{
|
||||||
if (!objMngr || !io) // Pip
|
// If all instances are requested on a single instance object it is an error
|
||||||
return false;
|
|
||||||
|
|
||||||
// If all instances are requested on a single instance object it is an error
|
|
||||||
if (allInstances && obj->isSingleInstance())
|
if (allInstances && obj->isSingleInstance())
|
||||||
{
|
{
|
||||||
allInstances = false;
|
allInstances = false;
|
||||||
@ -654,10 +622,7 @@ bool UAVTalk::transmitSingleObject(UAVObject* obj, quint8 type, bool allInstance
|
|||||||
quint16 instId;
|
quint16 instId;
|
||||||
quint16 allInstId = ALL_INSTANCES;
|
quint16 allInstId = ALL_INSTANCES;
|
||||||
|
|
||||||
if (!objMngr || !io) // Pip
|
// Setup type and object id fields
|
||||||
return false;
|
|
||||||
|
|
||||||
// Setup type and object id fields
|
|
||||||
objId = obj->getObjID();
|
objId = obj->getObjID();
|
||||||
txBuffer[0] = SYNC_VAL;
|
txBuffer[0] = SYNC_VAL;
|
||||||
txBuffer[1] = type;
|
txBuffer[1] = type;
|
||||||
|
@ -1,127 +1,127 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*
|
*
|
||||||
* @file uavtalk.h
|
* @file uavtalk.h
|
||||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
* @{
|
* @{
|
||||||
* @addtogroup UAVTalkPlugin UAVTalk Plugin
|
* @addtogroup UAVTalkPlugin UAVTalk Plugin
|
||||||
* @{
|
* @{
|
||||||
* @brief The UAVTalk protocol plugin
|
* @brief The UAVTalk protocol plugin
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but
|
* This program is distributed in the hope that it will be useful, but
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along
|
* You should have received a copy of the GNU General Public License along
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#ifndef UAVTALK_H
|
#ifndef UAVTALK_H
|
||||||
#define UAVTALK_H
|
#define UAVTALK_H
|
||||||
|
|
||||||
#include <QIODevice>
|
#include <QIODevice>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QSemaphore>
|
#include <QSemaphore>
|
||||||
#include "uavobjectmanager.h"
|
#include "uavobjectmanager.h"
|
||||||
#include "uavtalk_global.h"
|
#include "uavtalk_global.h"
|
||||||
|
|
||||||
class UAVTALK_EXPORT UAVTalk: public QObject
|
class UAVTALK_EXPORT UAVTalk: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef struct {
|
typedef struct {
|
||||||
quint32 txBytes;
|
quint32 txBytes;
|
||||||
quint32 rxBytes;
|
quint32 rxBytes;
|
||||||
quint32 txObjectBytes;
|
quint32 txObjectBytes;
|
||||||
quint32 rxObjectBytes;
|
quint32 rxObjectBytes;
|
||||||
quint32 rxObjects;
|
quint32 rxObjects;
|
||||||
quint32 txObjects;
|
quint32 txObjects;
|
||||||
quint32 txErrors;
|
quint32 txErrors;
|
||||||
quint32 rxErrors;
|
quint32 rxErrors;
|
||||||
} ComStats;
|
} ComStats;
|
||||||
|
|
||||||
UAVTalk(QIODevice* iodev, UAVObjectManager* objMngr);
|
UAVTalk(QIODevice* iodev, UAVObjectManager* objMngr);
|
||||||
~UAVTalk();
|
~UAVTalk();
|
||||||
bool sendObject(UAVObject* obj, bool acked, bool allInstances);
|
bool sendObject(UAVObject* obj, bool acked, bool allInstances);
|
||||||
bool sendObjectRequest(UAVObject* obj, bool allInstances);
|
bool sendObjectRequest(UAVObject* obj, bool allInstances);
|
||||||
void cancelTransaction();
|
void cancelTransaction();
|
||||||
ComStats getStats();
|
ComStats getStats();
|
||||||
void resetStats();
|
void resetStats();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void transactionCompleted(UAVObject* obj);
|
void transactionCompleted(UAVObject* obj);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void processInputStream(void);
|
void processInputStream(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constants
|
// Constants
|
||||||
static const int TYPE_MASK = 0xFC;
|
static const int TYPE_MASK = 0xFC;
|
||||||
static const int TYPE_VER = 0x20;
|
static const int TYPE_VER = 0x20;
|
||||||
static const int TYPE_OBJ = (TYPE_VER | 0x00);
|
static const int TYPE_OBJ = (TYPE_VER | 0x00);
|
||||||
static const int TYPE_OBJ_REQ = (TYPE_VER | 0x01);
|
static const int TYPE_OBJ_REQ = (TYPE_VER | 0x01);
|
||||||
static const int TYPE_OBJ_ACK = (TYPE_VER | 0x02);
|
static const int TYPE_OBJ_ACK = (TYPE_VER | 0x02);
|
||||||
static const int TYPE_ACK = (TYPE_VER | 0x03);
|
static const int TYPE_ACK = (TYPE_VER | 0x03);
|
||||||
|
|
||||||
static const int MIN_HEADER_LENGTH = 8; // sync(1), type (1), size(2), object ID(4)
|
static const int MIN_HEADER_LENGTH = 8; // sync(1), type (1), size(2), object ID(4)
|
||||||
static const int MAX_HEADER_LENGTH = 10; // sync(1), type (1), size(2), object ID (4), instance ID(2, not used in single objects)
|
static const int MAX_HEADER_LENGTH = 10; // sync(1), type (1), size(2), object ID (4), instance ID(2, not used in single objects)
|
||||||
|
|
||||||
static const int CHECKSUM_LENGTH = 1;
|
static const int CHECKSUM_LENGTH = 1;
|
||||||
|
|
||||||
static const int MAX_PAYLOAD_LENGTH = 256;
|
static const int MAX_PAYLOAD_LENGTH = 256;
|
||||||
|
|
||||||
static const int MAX_PACKET_LENGTH = (MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + CHECKSUM_LENGTH);
|
static const int MAX_PACKET_LENGTH = (MAX_HEADER_LENGTH + MAX_PAYLOAD_LENGTH + CHECKSUM_LENGTH);
|
||||||
|
|
||||||
static const quint16 ALL_INSTANCES = 0xFFFF;
|
static const quint16 ALL_INSTANCES = 0xFFFF;
|
||||||
static const int TX_BUFFER_SIZE = 2*1024;
|
static const int TX_BUFFER_SIZE = 2*1024;
|
||||||
static const quint8 crc_table[256];
|
static const quint8 crc_table[256];
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
typedef enum {STATE_SYNC, STATE_TYPE, STATE_SIZE, STATE_OBJID, STATE_INSTID, STATE_DATA, STATE_CS} RxStateType;
|
typedef enum {STATE_SYNC, STATE_TYPE, STATE_SIZE, STATE_OBJID, STATE_INSTID, STATE_DATA, STATE_CS} RxStateType;
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
QIODevice* io;
|
QIODevice* io;
|
||||||
UAVObjectManager* objMngr;
|
UAVObjectManager* objMngr;
|
||||||
QMutex* mutex;
|
QMutex* mutex;
|
||||||
UAVObject* respObj;
|
UAVObject* respObj;
|
||||||
bool respAllInstances;
|
bool respAllInstances;
|
||||||
quint8 rxBuffer[MAX_PACKET_LENGTH];
|
quint8 rxBuffer[MAX_PACKET_LENGTH];
|
||||||
quint8 txBuffer[MAX_PACKET_LENGTH];
|
quint8 txBuffer[MAX_PACKET_LENGTH];
|
||||||
// Variables used by the receive state machine
|
// Variables used by the receive state machine
|
||||||
quint8 rxTmpBuffer[4];
|
quint8 rxTmpBuffer[4];
|
||||||
quint8 rxType;
|
quint8 rxType;
|
||||||
quint32 rxObjId;
|
quint32 rxObjId;
|
||||||
quint16 rxInstId;
|
quint16 rxInstId;
|
||||||
quint16 rxLength;
|
quint16 rxLength;
|
||||||
quint16 rxPacketLength;
|
quint16 rxPacketLength;
|
||||||
|
|
||||||
quint8 rxCSPacket, rxCS;
|
quint8 rxCSPacket, rxCS;
|
||||||
qint32 rxCount;
|
qint32 rxCount;
|
||||||
qint32 packetSize;
|
qint32 packetSize;
|
||||||
RxStateType rxState;
|
RxStateType rxState;
|
||||||
ComStats stats;
|
ComStats stats;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
bool objectTransaction(UAVObject* obj, quint8 type, bool allInstances);
|
bool objectTransaction(UAVObject* obj, quint8 type, bool allInstances);
|
||||||
bool processInputByte(quint8 rxbyte);
|
bool processInputByte(quint8 rxbyte);
|
||||||
bool receiveObject(quint8 type, quint32 objId, quint16 instId, quint8* data, qint32 length);
|
bool receiveObject(quint8 type, quint32 objId, quint16 instId, quint8* data, qint32 length);
|
||||||
UAVObject* updateObject(quint32 objId, quint16 instId, quint8* data);
|
UAVObject* updateObject(quint32 objId, quint16 instId, quint8* data);
|
||||||
void updateAck(UAVObject* obj);
|
void updateAck(UAVObject* obj);
|
||||||
bool transmitObject(UAVObject* obj, quint8 type, bool allInstances);
|
bool transmitObject(UAVObject* obj, quint8 type, bool allInstances);
|
||||||
bool transmitSingleObject(UAVObject* obj, quint8 type, bool allInstances);
|
bool transmitSingleObject(UAVObject* obj, quint8 type, bool allInstances);
|
||||||
quint8 updateCRC(quint8 crc, const quint8 data);
|
quint8 updateCRC(quint8 crc, const quint8 data);
|
||||||
quint8 updateCRC(quint8 crc, const quint8* data, qint32 length);
|
quint8 updateCRC(quint8 crc, const quint8* data, qint32 length);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // UAVTALK_H
|
#endif // UAVTALK_H
|
||||||
|
@ -31,27 +31,29 @@
|
|||||||
|
|
||||||
UAVTalkPlugin::UAVTalkPlugin()
|
UAVTalkPlugin::UAVTalkPlugin()
|
||||||
{
|
{
|
||||||
telMngr = NULL; // Pip
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UAVTalkPlugin::~UAVTalkPlugin()
|
UAVTalkPlugin::~UAVTalkPlugin()
|
||||||
{
|
{
|
||||||
if (telMngr) // Pip
|
|
||||||
telMngr->stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UAVTalkPlugin::extensionsInitialized()
|
void UAVTalkPlugin::extensionsInitialized()
|
||||||
{
|
{
|
||||||
|
// Get UAVObjectManager instance
|
||||||
|
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
|
||||||
|
objMngr = pm->getObject<UAVObjectManager>();
|
||||||
|
|
||||||
// Create TelemetryManager
|
// Create TelemetryManager
|
||||||
telMngr = new TelemetryManager();
|
telMngr = new TelemetryManager();
|
||||||
if (!telMngr) return; // Pip
|
|
||||||
addAutoReleasedObject(telMngr);
|
addAutoReleasedObject(telMngr);
|
||||||
|
|
||||||
// Connect to connection manager so we get notified when the user connect to his device
|
// Connect to connection manager so we get notified when the user connect to his device
|
||||||
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
|
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
|
||||||
QObject::connect(cm, SIGNAL(deviceConnected(QIODevice *)),
|
QObject::connect(cm, SIGNAL(deviceConnected(QIODevice *)),
|
||||||
this, SLOT(onDeviceConnect(QIODevice *)));
|
this, SLOT(onDeviceConnect(QIODevice *)));
|
||||||
QObject::connect(cm, SIGNAL(deviceDisconnected()),
|
QObject::connect(cm, SIGNAL(deviceAboutToDisconnect()),
|
||||||
this, SLOT(onDeviceDisconnect()));
|
this, SLOT(onDeviceDisconnect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,18 +67,17 @@ bool UAVTalkPlugin::initialize(const QStringList & arguments, QString * errorStr
|
|||||||
|
|
||||||
void UAVTalkPlugin::shutdown()
|
void UAVTalkPlugin::shutdown()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UAVTalkPlugin::onDeviceConnect(QIODevice *dev)
|
void UAVTalkPlugin::onDeviceConnect(QIODevice *dev)
|
||||||
{
|
{
|
||||||
if (telMngr) // Pip
|
telMngr->start(dev);
|
||||||
telMngr->start(dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UAVTalkPlugin::onDeviceDisconnect()
|
void UAVTalkPlugin::onDeviceDisconnect()
|
||||||
{
|
{
|
||||||
if (telMngr) // Pip
|
telMngr->stop();
|
||||||
telMngr->stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_EXPORT_PLUGIN(UAVTalkPlugin)
|
Q_EXPORT_PLUGIN(UAVTalkPlugin)
|
||||||
|
@ -43,14 +43,6 @@ UploaderGadgetWidget::UploaderGadgetWidget(QWidget *parent) : QWidget(parent)
|
|||||||
connect(telMngr, SIGNAL(connected()), this, SLOT(onAutopilotConnect()));
|
connect(telMngr, SIGNAL(connected()), this, SLOT(onAutopilotConnect()));
|
||||||
connect(telMngr, SIGNAL(disconnected()), this, SLOT(onAutopilotDisconnect()));
|
connect(telMngr, SIGNAL(disconnected()), this, SLOT(onAutopilotDisconnect()));
|
||||||
|
|
||||||
// Note: remove listening to the connection manager, it overlaps with
|
|
||||||
// listening to the telemetry manager, we should only listen to one, not both.
|
|
||||||
|
|
||||||
// Also listen to disconnect actions from the user:
|
|
||||||
// Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
|
|
||||||
// connect(cm, SIGNAL(deviceDisconnected()), this, SLOT(onAutopilotDisconnect()));
|
|
||||||
|
|
||||||
|
|
||||||
connect(m_config->haltButton, SIGNAL(clicked()), this, SLOT(goToBootloader()));
|
connect(m_config->haltButton, SIGNAL(clicked()), this, SLOT(goToBootloader()));
|
||||||
connect(m_config->resetButton, SIGNAL(clicked()), this, SLOT(systemReset()));
|
connect(m_config->resetButton, SIGNAL(clicked()), this, SLOT(systemReset()));
|
||||||
connect(m_config->bootButton, SIGNAL(clicked()), this, SLOT(systemBoot()));
|
connect(m_config->bootButton, SIGNAL(clicked()), this, SLOT(systemBoot()));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user