LinkManager.cc 6.78 KB
Newer Older
pixhawk's avatar
pixhawk committed
1
/*=====================================================================
lm's avatar
lm committed
2 3 4 5 6 7 8 9

QGroundControl Open Source Ground Control Station

(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
pixhawk's avatar
pixhawk committed
10 11 12
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
lm's avatar
lm committed
13 14

    QGROUNDCONTROL is distributed in the hope that it will be useful,
pixhawk's avatar
pixhawk committed
15 16 17
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
lm's avatar
lm committed
18

pixhawk's avatar
pixhawk committed
19
    You should have received a copy of the GNU General Public License
lm's avatar
lm committed
20 21
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

pixhawk's avatar
pixhawk committed
22
======================================================================*/
23

pixhawk's avatar
pixhawk committed
24 25 26 27 28 29 30 31 32 33
/**
 * @file
 *   @brief Brief Description
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <QList>
#include <QApplication>
34 35
#include <QDebug>

36 37
#include "LinkManager.h"
#include "MainWindow.h"
Don Gagne's avatar
Don Gagne committed
38
#include "QGCMessageBox.h"
39
#include "QGCApplication.h"
40

41 42 43
LinkManager* LinkManager::_instance = NULL;

LinkManager* LinkManager::instance(void)
44 45
{
    if(_instance == 0) {
46 47
        _instance = new LinkManager(qgcApp());
        Q_CHECK_PTR(_instance);
48
    }
49 50 51
    
    Q_ASSERT(_instance);
    
52
    return _instance;
pixhawk's avatar
pixhawk committed
53 54
}

55 56 57 58 59 60
void LinkManager::deleteInstance(void)
{
    _instance = NULL;
    delete this;
}

pixhawk's avatar
pixhawk committed
61 62
/**
 * @brief Private singleton constructor
63
 *
pixhawk's avatar
pixhawk committed
64 65
 * This class implements the singleton design pattern and has therefore only a private constructor.
 **/
66 67
LinkManager::LinkManager(QObject* parent, bool registerSingleton) :
    QGCSingleton(parent, registerSingleton),
68
    _connectionsSuspended(false)
pixhawk's avatar
pixhawk committed
69
{
70 71
    _links = QList<LinkInterface*>();
    _protocolLinks = QMap<ProtocolInterface*, LinkInterface*>();
pixhawk's avatar
pixhawk committed
72 73 74 75 76
}

LinkManager::~LinkManager()
{
    disconnectAll();
77 78 79
    
    foreach (LinkInterface* link, _links) {
        Q_ASSERT(link);
80
        deleteLink(link);
Lorenz Meier's avatar
Lorenz Meier committed
81
    }
82
    _links.clear();
pixhawk's avatar
pixhawk committed
83 84 85 86
}

void LinkManager::add(LinkInterface* link)
{
87 88
    Q_ASSERT(link);
    
89 90 91
    // Take ownership for delete
    link->_ownedByLinkManager = true;
    
92 93
    _dataMutex.lock();
    
94
    if (!_links.contains(link)) {
95 96
        _links.append(link);
        _dataMutex.unlock();
97
        emit newLink(link);
98
    } else {
99
        _dataMutex.unlock();
100
    }
pixhawk's avatar
pixhawk committed
101 102 103 104
}

void LinkManager::addProtocol(LinkInterface* link, ProtocolInterface* protocol)
{
105 106 107
    Q_ASSERT(link);
    Q_ASSERT(protocol);
    
pixhawk's avatar
pixhawk committed
108 109
    // Connect link to protocol
    // the protocol will receive new bytes from the link
110 111
    _dataMutex.lock();
    QList<LinkInterface*> linkList = _protocolLinks.values(protocol);
112 113 114

    // If protocol has not been added before (list length == 0)
    // OR if link has not been added to protocol, add
Lorenz Meier's avatar
Lorenz Meier committed
115
    if (!linkList.contains(link))
Lorenz Meier's avatar
Lorenz Meier committed
116
    {
117 118
        // Protocol is new, add
        connect(link, SIGNAL(bytesReceived(LinkInterface*, QByteArray)), protocol, SLOT(receiveBytes(LinkInterface*, QByteArray)));
119 120
        // Add status
        connect(link, SIGNAL(connected(bool)), protocol, SLOT(linkStatusChanged(bool)));
121
        // Store the connection information in the protocol links map
122 123
        _protocolLinks.insertMulti(protocol, link);
        _dataMutex.unlock();
124 125
        // Make sure the protocol clears its metadata for this link.
        protocol->resetMetadataForLink(link);
126
    } else {
127
        _dataMutex.unlock();
128
    }
129
    //qDebug() << __FILE__ << __LINE__ << "ADDED LINK TO PROTOCOL" << link->getName() << protocol->getName() << "NEW SIZE OF LINK LIST:" << _protocolLinks.size();
pixhawk's avatar
pixhawk committed
130 131 132 133
}

QList<LinkInterface*> LinkManager::getLinksForProtocol(ProtocolInterface* protocol)
{
134 135 136
    _dataMutex.lock();
    QList<LinkInterface*> links = _protocolLinks.values(protocol);
    _dataMutex.unlock();
137
    return links;
pixhawk's avatar
pixhawk committed
138 139
}

140 141
ProtocolInterface* LinkManager::getProtocolForLink(LinkInterface* link)
{
142
    _dataMutex.lock();
143
    ProtocolInterface* protocol = _protocolLinks.key(link);
144
    _dataMutex.unlock();
145
	return protocol;
146
}
pixhawk's avatar
pixhawk committed
147 148 149

bool LinkManager::connectAll()
{
150 151 152 153
    if (_connectionsSuspendedMsg()) {
        return false;
    }
    
154 155
    bool allConnected = true;

156 157 158 159 160 161
    _dataMutex.lock();
    foreach (LinkInterface* link, _links) {
        Q_ASSERT(link);
        if (!link->_connect()) {
            allConnected = false;
        }
162
    }
163
    _dataMutex.unlock();
164 165

    return allConnected;
pixhawk's avatar
pixhawk committed
166 167 168 169
}

bool LinkManager::disconnectAll()
{
170 171
    bool allDisconnected = true;

172 173
    _dataMutex.lock();
    foreach (LinkInterface* link, _links)
Lorenz Meier's avatar
Lorenz Meier committed
174
    {
175
        Q_ASSERT(link);
176
        if (!link->_disconnect()) {
177 178
            allDisconnected = false;
        }
179
    }
180
    _dataMutex.unlock();
181 182

    return allDisconnected;
pixhawk's avatar
pixhawk committed
183 184 185 186
}

bool LinkManager::connectLink(LinkInterface* link)
{
187 188 189 190 191 192 193
    Q_ASSERT(link);
    
    if (_connectionsSuspendedMsg()) {
        return false;
    }

    return link->_connect();
pixhawk's avatar
pixhawk committed
194 195 196 197
}

bool LinkManager::disconnectLink(LinkInterface* link)
{
198 199
    Q_ASSERT(link);
    return link->_disconnect();
pixhawk's avatar
pixhawk committed
200 201
}

202
void LinkManager::deleteLink(LinkInterface* link)
203
{
204
    Q_ASSERT(link);
Don Gagne's avatar
Don Gagne committed
205 206
    
    _dataMutex.lock();
207 208 209 210 211
    
    Q_ASSERT(_links.contains(link));
    _links.removeOne(link);
    Q_ASSERT(!_links.contains(link));

Don Gagne's avatar
Don Gagne committed
212 213
    // Remove link from protocol map
    QList<ProtocolInterface* > protocols = _protocolLinks.keys(link);
214
    foreach (ProtocolInterface* proto, protocols) {
Don Gagne's avatar
Don Gagne committed
215 216
        _protocolLinks.remove(proto, link);
    }
217
             
Don Gagne's avatar
Don Gagne committed
218
    _dataMutex.unlock();
219
             
Don Gagne's avatar
Don Gagne committed
220
    // Emit removal of link
221 222 223 224 225
    emit linkDeleted(link);
    
    Q_ASSERT(link->_ownedByLinkManager);
    link->_deletedByLinkManager = true;   // Signal that this is a valid delete
    delete link;
pixhawk's avatar
pixhawk committed
226 227 228 229 230 231 232
}

/**
 *
 */
const QList<LinkInterface*> LinkManager::getLinks()
{
233 234 235
    _dataMutex.lock();
    QList<LinkInterface*> ret(_links);
    _dataMutex.unlock();
236
    return ret;
pixhawk's avatar
pixhawk committed
237
}
238 239 240

const QList<SerialLink*> LinkManager::getSerialLinks()
{
241
    _dataMutex.lock();
242 243
    QList<SerialLink*> s;

244
    foreach (LinkInterface* link, _links)
245
    {
246 247 248
        Q_ASSERT(link);
        
        SerialLink* serialLink = qobject_cast<SerialLink*>(link);
249

250 251
        if (serialLink)
            s.append(serialLink);
252
    }
253
    _dataMutex.unlock();
254 255 256

    return s;
}
257 258 259 260 261 262

/// @brief If all new connections should be suspended a message is displayed to the user and true
///         is returned;
bool LinkManager::_connectionsSuspendedMsg(void)
{
    if (_connectionsSuspended) {
Don Gagne's avatar
Don Gagne committed
263 264
        QGCMessageBox::information(tr("Connect not allowed"),
                                   tr("Connect not allowed: %1").arg(_connectionsSuspendedReason));
265 266 267 268 269 270 271 272 273 274 275 276
        return true;
    } else {
        return false;
    }
}

void LinkManager::setConnectionsSuspended(QString reason)
{
    _connectionsSuspended = true;
    _connectionsSuspendedReason = reason;
    Q_ASSERT(!reason.isEmpty());
}