SerialLink.cc 21.8 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11 12
/*=====================================================================
======================================================================*/
/**
 * @file
 *   @brief Cross-platform support for serial ports
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <QTimer>
#include <QDebug>
13
#include <QSettings>
pixhawk's avatar
pixhawk committed
14
#include <QMutexLocker>
Bill Bonney's avatar
Bill Bonney committed
15 16
#include <qserialport.h>
#include <qserialportinfo.h>
pixhawk's avatar
pixhawk committed
17 18
#include "SerialLink.h"
#include "LinkManager.h"
19
#include "QGC.h"
pixhawk's avatar
pixhawk committed
20 21
#include <MG.h>

22 23
SerialLink::SerialLink(QString portname, int baudRate, bool hardwareFlowControl, bool parity,
                       int dataBits, int stopBits) :
Bill Bonney's avatar
Bill Bonney committed
24 25 26
    m_bytesRead(0),
    m_port(NULL),
    m_ports(new QVector<QString>()),
27
    m_stopp(false),
28
    m_reqReset(false)
pixhawk's avatar
pixhawk committed
29 30
{
    // Setup settings
Bill Bonney's avatar
Bill Bonney committed
31
    m_portName = portname.trimmed();
32

Bill Bonney's avatar
Bill Bonney committed
33
    if (m_portName == "" && getCurrentPorts()->size() > 0)
34
    {
Bill Bonney's avatar
Bill Bonney committed
35
        m_portName = m_ports->first().trimmed();
36 37
    }

pixhawk's avatar
pixhawk committed
38
    // Set unique ID and add link to the list of links
Bill Bonney's avatar
Bill Bonney committed
39 40 41
    m_id = getNextLinkId();

    m_baud = baudRate;
42

43 44
    if (hardwareFlowControl)
    {
Bill Bonney's avatar
Bill Bonney committed
45
        m_flowControl = QSerialPort::HardwareControl;
46 47 48
    }
    else
    {
Bill Bonney's avatar
Bill Bonney committed
49
        m_flowControl = QSerialPort::NoFlowControl;
50 51 52
    }
    if (parity)
    {
Bill Bonney's avatar
Bill Bonney committed
53
        m_parity = QSerialPort::EvenParity;
54 55 56
    }
    else
    {
Bill Bonney's avatar
Bill Bonney committed
57
        m_parity = QSerialPort::NoParity;
58
    }
Bill Bonney's avatar
Bill Bonney committed
59 60 61

    m_dataBits = dataBits;
    m_stopBits = stopBits;
pixhawk's avatar
pixhawk committed
62 63

    // Set the port name
Bill Bonney's avatar
Bill Bonney committed
64
    if (m_portName == "")
65
    {
Bill Bonney's avatar
Bill Bonney committed
66
        m_name = tr("Serial Link ") + QString::number(getId());
pixhawk's avatar
pixhawk committed
67
    }
68 69
    else
    {
Bill Bonney's avatar
Bill Bonney committed
70
        m_name = portname.trimmed();
pixhawk's avatar
pixhawk committed
71
    }
lm's avatar
lm committed
72
    loadSettings();
pixhawk's avatar
pixhawk committed
73
}
74 75 76 77 78
void SerialLink::requestReset()
{
    QMutexLocker locker(&this->m_stoppMutex);
    m_reqReset = true;
}
pixhawk's avatar
pixhawk committed
79 80 81 82

SerialLink::~SerialLink()
{
    disconnect();
Bill Bonney's avatar
Bill Bonney committed
83 84 85 86
    if(m_port) delete m_port;
    m_port = NULL;
    if (m_ports) delete m_ports;
    m_ports = NULL;
87 88 89 90
}

QVector<QString>* SerialLink::getCurrentPorts()
{
Bill Bonney's avatar
Bill Bonney committed
91 92 93 94
    Q_ASSERT_X(m_ports != NULL, "getCurrentPorts", "m_ports is NULL");
    m_ports->clear();
    // Example use QSerialPortInfo
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
95
    {
Bill Bonney's avatar
Bill Bonney committed
96 97 98
//        qDebug() << "PortName    : " << info.portName()
//                 << "Description : " << info.description();
//        qDebug() << "Manufacturer: " << info.manufacturer();
99

Bill Bonney's avatar
Bill Bonney committed
100
        m_ports->append(info.portName());
101
    }
Bill Bonney's avatar
Bill Bonney committed
102
    return m_ports;
pixhawk's avatar
pixhawk committed
103 104
}

105 106 107 108 109
void SerialLink::loadSettings()
{
    // Load defaults from settings
    QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
    settings.sync();
110 111
    if (settings.contains("SERIALLINK_COMM_PORT"))
    {
Bill Bonney's avatar
Bill Bonney committed
112 113 114 115 116 117
        m_portName = settings.value("SERIALLINK_COMM_PORT").toString();
        m_baud = settings.value("SERIALLINK_COMM_BAUD").toInt();
        m_parity = settings.value("SERIALLINK_COMM_PARITY").toInt();
        m_stopBits = settings.value("SERIALLINK_COMM_STOPBITS").toInt();
        m_dataBits = settings.value("SERIALLINK_COMM_DATABITS").toInt();
        m_flowControl = settings.value("SERIALLINK_COMM_FLOW_CONTROL").toInt();
118 119 120 121 122 123 124
    }
}

void SerialLink::writeSettings()
{
    // Store settings
    QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
125
    settings.setValue("SERIALLINK_COMM_PORT", getPortName());
126 127
    settings.setValue("SERIALLINK_COMM_BAUD", getBaudRateType());
    settings.setValue("SERIALLINK_COMM_PARITY", getParityType());
128 129 130
    settings.setValue("SERIALLINK_COMM_STOPBITS", getStopBits());
    settings.setValue("SERIALLINK_COMM_DATABITS", getDataBits());
    settings.setValue("SERIALLINK_COMM_FLOW_CONTROL", getFlowType());
131 132 133
    settings.sync();
}

pixhawk's avatar
pixhawk committed
134 135 136 137 138

/**
 * @brief Runs the thread
 *
 **/
139 140
void SerialLink::run()
{
pixhawk's avatar
pixhawk committed
141
    // Initialize the connection
142 143 144
    if (!hardwareConnect())
    {
        //Need to error out here.
Bill Bonney's avatar
Bill Bonney committed
145
        emit communicationError(getName(),"Error connecting: " + m_port->errorString());
146
        return;
147 148

    }
pixhawk's avatar
pixhawk committed
149 150

    // Qt way to make clear what a while(1) loop does
Bill Bonney's avatar
Bill Bonney committed
151 152
    qint64 msecs = QDateTime::currentMSecsSinceEpoch();
    qint64 initialmsecs = QDateTime::currentMSecsSinceEpoch();
153 154 155
    quint64 bytes = 0;
    bool triedreset = false;
    bool triedDTR = false;
Bill Bonney's avatar
Bill Bonney committed
156 157
    qint64 timeout = 5000;

158 159
    forever
    {
160 161 162 163 164 165 166
        {
            QMutexLocker locker(&this->m_stoppMutex);
            if(this->m_stopp)
            {
                this->m_stopp = false;
                break;
            }
167 168 169 170
            if (m_reqReset)
            {
                this->m_reqReset = false;
                communicationUpdate(getName(),"Reset requested via DTR signal");
Bill Bonney's avatar
Bill Bonney committed
171
                m_port->setDataTerminalReady(true);
172
                this->msleep(250);
Bill Bonney's avatar
Bill Bonney committed
173
                m_port->setDataTerminalReady(false);
174
            }
175
        }
pixhawk's avatar
pixhawk committed
176 177
        // Check if new bytes have arrived, if yes, emit the notification signal
        checkForBytes();
Bill Bonney's avatar
Bill Bonney committed
178
        if (bytes != m_bytesRead)
179
        {
Bill Bonney's avatar
Bill Bonney committed
180
            bytes = m_bytesRead;
181 182 183 184
            msecs = QDateTime::currentMSecsSinceEpoch();
        }
        else
        {
185
            if (QDateTime::currentMSecsSinceEpoch() - msecs > timeout)
186 187 188
            {
                //It's been 10 seconds since the last data came in. Reset and try again
                msecs = QDateTime::currentMSecsSinceEpoch();
189 190 191 192 193 194 195 196 197
                if (msecs - initialmsecs > 25000)
                {
                    //After initial 25 seconds, timeouts are increased to 30 seconds.
                    //This prevents temporary silences from things like calibration commands
                    //from screwing things up. In all reality, timeouts should be enabled/disabled
                    //for events like that on a case by case basis.
                    //TODO ^^
                    timeout = 30000;
                }
198 199 200
                if (!triedDTR && triedreset)
                {
                    triedDTR = true;
201
                    communicationUpdate(getName(),"No data to receive on COM port. Attempting to reset via DTR signal");
202
                    qDebug() << "No data!!! Attempting reset via DTR.";
Bill Bonney's avatar
Bill Bonney committed
203
                    m_port->setDataTerminalReady(true);
204
                    this->msleep(250);
Bill Bonney's avatar
Bill Bonney committed
205
                    m_port->setDataTerminalReady(false);
206 207 208 209
                }
                else if (!triedreset)
                {
                    qDebug() << "No data!!! Attempting reset via reboot command.";
210
                    communicationUpdate(getName(),"No data to receive on COM port. Assuming possible terminal mode, attempting to reset via \"reboot\" command");
Bill Bonney's avatar
Bill Bonney committed
211
                    m_port->write("reboot\r\n",8);
212 213 214 215
                    triedreset = true;
                }
                else
                {
216
                    communicationUpdate(getName(),"No data to receive on COM port....");
217 218 219 220
                    qDebug() << "No data!!!";
                }
            }
        }
pixhawk's avatar
pixhawk committed
221 222 223 224
        /* Serial data isn't arriving that fast normally, this saves the thread
                 * from consuming too much processing time
                 */
        MG::SLEEP::msleep(SerialLink::poll_interval);
Bill Bonney's avatar
Bill Bonney committed
225 226 227 228 229 230
    } // end forever loop

    if (m_port) {
        m_port->close();
        delete m_port;
        m_port = NULL;
231
    }
pixhawk's avatar
pixhawk committed
232 233 234
}


235 236
void SerialLink::checkForBytes()
{
pixhawk's avatar
pixhawk committed
237
    /* Check if bytes are available */
Bill Bonney's avatar
Bill Bonney committed
238
    if(m_port && m_port->isOpen() && m_port->isWritable())
239
    {
Bill Bonney's avatar
Bill Bonney committed
240 241 242
        m_dataMutex.lock();
        qint64 available = m_port->bytesAvailable();
        m_dataMutex.unlock();
pixhawk's avatar
pixhawk committed
243

244 245
        if(available > 0)
        {
246
            readBytes();
Bill Bonney's avatar
Bill Bonney committed
247
            m_bytesRead += available;
pixhawk's avatar
pixhawk committed
248
        }
249 250
        else if (available < 0) {
            /* Error, close port */
Bill Bonney's avatar
Bill Bonney committed
251
            m_port->close();
252 253
            emit disconnected();
            emit connected(false);
Bill Bonney's avatar
Bill Bonney committed
254
            emit communicationError(this->getName(), tr("Could not read data - link %1 is disconnected!").arg(this->getName()));
255
        }
256
    }
257 258 259 260 261
//    else
//    {
//        emit disconnected();
//        emit connected(false);
//    }
pixhawk's avatar
pixhawk committed
262 263 264

}

265 266
void SerialLink::writeBytes(const char* data, qint64 size)
{
Bill Bonney's avatar
Bill Bonney committed
267 268 269
    if(m_port && m_port->isOpen()) {
        qDebug() << "writeBytes" << m_portName << "attempting to tx " << size << "bytes.";
        int b = m_port->write(data, size);
pixhawk's avatar
pixhawk committed
270

271
        if (b > 0) {
Bill Bonney's avatar
Bill Bonney committed
272
            Q_ASSERT_X(b = size, "writeBytes", "failed to write all bytes");
273

Bill Bonney's avatar
Bill Bonney committed
274
            qDebug() << "writeBytes " << m_portName << "tx'd" << b << "bytes:";
pixhawk's avatar
pixhawk committed
275

276
            // Increase write counter
Bill Bonney's avatar
Bill Bonney committed
277 278 279 280 281
            m_bitsSentTotal += size * 8;
            QByteArray* byteArray = new QByteArray(data,size);

            qDebug() << byteArray->toHex();
            delete byteArray;
282

283
        } else {
284 285
            disconnect();
            // Error occured
Bill Bonney's avatar
Bill Bonney committed
286
            emit communicationError(getName(), tr("Could not send data - link %1 is disconnected!").arg(getName()));
287
        }
pixhawk's avatar
pixhawk committed
288 289 290 291 292 293 294 295 296
    }
}

/**
 * @brief Read a number of bytes from the interface.
 *
 * @param data Pointer to the data byte array to write the bytes to
 * @param maxLength The maximum number of bytes to write
 **/
297 298
void SerialLink::readBytes()
{
Bill Bonney's avatar
Bill Bonney committed
299 300
    m_dataMutex.lock();
    if(m_port && m_port->isOpen()) {
301 302
        const qint64 maxLength = 2048;
        char data[maxLength];
Bill Bonney's avatar
Bill Bonney committed
303
        qint64 numBytes = m_port->bytesAvailable();
James Goppert's avatar
James Goppert committed
304
        //qDebug() << "numBytes: " << numBytes;
305

306
        if(numBytes > 0) {
pixhawk's avatar
pixhawk committed
307 308 309
            /* Read as much data in buffer as possible without overflow */
            if(maxLength < numBytes) numBytes = maxLength;

Bill Bonney's avatar
Bill Bonney committed
310
            m_port->read(data, numBytes);
pixhawk's avatar
pixhawk committed
311 312 313 314 315 316 317 318 319 320 321
            QByteArray b(data, numBytes);
            emit bytesReceived(this, b);

            //qDebug() << "SerialLink::readBytes()" << std::hex << data;
            //            int i;
            //            for (i=0; i<numBytes; i++){
            //                unsigned int v=data[i];
            //
            //                fprintf(stderr,"%02x ", v);
            //            }
            //            fprintf(stderr,"\n");
Bill Bonney's avatar
Bill Bonney committed
322
            m_bitsReceivedTotal += numBytes * 8;
pixhawk's avatar
pixhawk committed
323 324
        }
    }
Bill Bonney's avatar
Bill Bonney committed
325
    m_dataMutex.unlock();
pixhawk's avatar
pixhawk committed
326 327 328 329 330 331 332 333
}


/**
 * @brief Get the number of bytes to read.
 *
 * @return The number of bytes to read
 **/
334 335
qint64 SerialLink::bytesAvailable()
{
Bill Bonney's avatar
Bill Bonney committed
336 337
    if (m_port) {
        return m_port->bytesAvailable();
338
    } else {
339 340
        return 0;
    }
pixhawk's avatar
pixhawk committed
341 342 343 344 345 346 347
}

/**
 * @brief Disconnect the connection.
 *
 * @return True if connection has been disconnected, false if connection couldn't be disconnected.
 **/
348 349
bool SerialLink::disconnect()
{
Bill Bonney's avatar
Bill Bonney committed
350 351 352 353
    qDebug() << "disconnect" << m_port->portName();
    Q_ASSERT_X(m_port != NULL, "disconnect", "m_port is NULL");

    if (isRunning())
354 355
    {
        {
Bill Bonney's avatar
Bill Bonney committed
356 357
            QMutexLocker locker(&m_stoppMutex);
            m_stopp = true;
358
        }
Bill Bonney's avatar
Bill Bonney committed
359
        wait(); // This will terminate the thread and close the serial port
pixhawk's avatar
pixhawk committed
360

Bill Bonney's avatar
Bill Bonney committed
361
        emit disconnected(); // [TODO] There are signals from QSerialPort we should use
362
        emit connected(false);
Bill Bonney's avatar
Bill Bonney committed
363 364 365
        return true;
    } else {
        m_port->close();
366 367
        return true;
    }
pixhawk's avatar
pixhawk committed
368 369 370 371 372 373 374 375 376
}

/**
 * @brief Connect the connection.
 *
 * @return True if connection has been established, false if connection couldn't be established.
 **/
bool SerialLink::connect()
{
Bill Bonney's avatar
Bill Bonney committed
377 378
    if (isRunning())
        disconnect();
379 380
    {
        QMutexLocker locker(&this->m_stoppMutex);
Bill Bonney's avatar
Bill Bonney committed
381
        m_stopp = false;
382
    }
Bill Bonney's avatar
Bill Bonney committed
383 384

    start(LowPriority);
385
    return true;
pixhawk's avatar
pixhawk committed
386 387 388 389 390 391 392 393 394 395
}

/**
 * @brief This function is called indirectly by the connect() call.
 *
 * The connect() function starts the thread and indirectly calls this method.
 *
 * @return True if the connection could be established, false otherwise
 * @see connect() For the right function to establish the connection.
 **/
396 397
bool SerialLink::hardwareConnect()
{
Bill Bonney's avatar
Bill Bonney committed
398 399 400 401 402 403
    if(m_port)
    {
        qDebug() << "SerialLink:" << QString::number((long)this, 16) << "closing port";
        m_port->close();
        delete m_port;
        m_port = NULL;
404
    }
Bill Bonney's avatar
Bill Bonney committed
405 406
    qDebug() << "SerialLink: hardwareConnect to " << m_portName;
    m_port = new QSerialPort(m_portName);
pixhawk's avatar
pixhawk committed
407

Bill Bonney's avatar
Bill Bonney committed
408
    if (m_port == NULL)
409
    {
Bill Bonney's avatar
Bill Bonney committed
410 411
        emit communicationUpdate(getName(),"Error opening port: " + m_port->errorString());
        return false; // couldn't create serial port.
412
    }
Bill Bonney's avatar
Bill Bonney committed
413 414 415 416 417 418 419

    QObject::connect(m_port,SIGNAL(aboutToClose()),this,SIGNAL(disconnected()));

//    port->setCommTimeouts(QSerialPort::CtScheme_NonBlockingRead);
    m_connectionStartTime = MG::TIME::getGroundTimeNow();

    if (!m_port->open(QIODevice::ReadWrite))
420
    {
Bill Bonney's avatar
Bill Bonney committed
421 422 423
        emit communicationUpdate(getName(),"Error opening port: " + m_port->errorString());
        m_port->close();
        return false; // couldn't open serial port
424
    }
425

Bill Bonney's avatar
Bill Bonney committed
426
    emit communicationUpdate(getName(),"Opened port!");
pixhawk's avatar
pixhawk committed
427

Bill Bonney's avatar
Bill Bonney committed
428 429 430 431 432 433
    // Need to configure the port
    m_port->setBaudRate(m_baud);
    m_port->setDataBits(static_cast<QSerialPort::DataBits>(m_dataBits));
    m_port->setFlowControl(static_cast<QSerialPort::FlowControl>(m_flowControl));
    m_port->setStopBits(static_cast<QSerialPort::StopBits>(m_stopBits));
    m_port->setParity(static_cast<QSerialPort::Parity>(m_parity));
434

Bill Bonney's avatar
Bill Bonney committed
435 436 437 438 439
    emit connected();
    emit connected(true);

    qDebug() << "CONNECTING LINK: " << __FILE__ << __LINE__ << "with settings" << m_port->portName()
             << getBaudRate() << getDataBits() << getParityType() << getStopBits();
440

441 442
    writeSettings();

Bill Bonney's avatar
Bill Bonney committed
443
    return true; // successful connection
pixhawk's avatar
pixhawk committed
444
}
445 446


pixhawk's avatar
pixhawk committed
447 448 449 450 451
/**
 * @brief Check if connection is active.
 *
 * @return True if link is connected, false otherwise.
 **/
452 453
bool SerialLink::isConnected()
{
Bill Bonney's avatar
Bill Bonney committed
454 455 456 457 458 459

    if (m_port) {
        bool isConnected = m_port->isOpen();
        qDebug() << "SerialLink #" << __LINE__ << ":"<<  m_port->portName()
                 << " isConnected =" << QString::number(isConnected);
        return isConnected;
460
    } else {
Bill Bonney's avatar
Bill Bonney committed
461 462
        qDebug() << "SerialLink #" << __LINE__ << ":" <<  m_portName
                 << " isConnected = NULL";
lm's avatar
lm committed
463 464
        return false;
    }
pixhawk's avatar
pixhawk committed
465 466 467 468
}

int SerialLink::getId()
{
Bill Bonney's avatar
Bill Bonney committed
469
    return m_id;
pixhawk's avatar
pixhawk committed
470 471 472 473
}

QString SerialLink::getName()
{
Bill Bonney's avatar
Bill Bonney committed
474
    return m_name;
pixhawk's avatar
pixhawk committed
475 476
}

477 478 479 480
/**
  * This function maps baud rate constants to numerical equivalents.
  * It relies on the mapping given in qportsettings.h from the QSerialPort library.
  */
481 482
qint64 SerialLink::getNominalDataRate()
{
Bill Bonney's avatar
Bill Bonney committed
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
    int baudRate;
    if (m_port) {
        baudRate = m_port->baudRate();
    } else {
        baudRate = m_baud;
    }
    qint64 dataRate;
    switch (baudRate)
    {
        case QSerialPort::Baud1200:
            dataRate = 1200;
            break;
        case QSerialPort::Baud2400:
            dataRate = 2400;
            break;
        case QSerialPort::Baud4800:
            dataRate = 4800;
            break;
        case QSerialPort::Baud9600:
            dataRate = 9600;
            break;
        case QSerialPort::Baud19200:
            dataRate = 19200;
            break;
        case QSerialPort::Baud38400:
            dataRate = 38400;
            break;
        case QSerialPort::Baud57600:
            dataRate = 57600;
            break;
        case QSerialPort::Baud115200:
            dataRate = 115200;
            break;
            // Otherwise do nothing.
        case QSerialPort::UnknownBaud:
        default:
            dataRate = -1;
            break;
pixhawk's avatar
pixhawk committed
521 522 523 524
    }
    return dataRate;
}

525 526
qint64 SerialLink::getTotalUpstream()
{
Bill Bonney's avatar
Bill Bonney committed
527 528 529
    m_statisticsMutex.lock();
    return m_bitsSentTotal / ((MG::TIME::getGroundTimeNow() - m_connectionStartTime) / 1000);
    m_statisticsMutex.unlock();
pixhawk's avatar
pixhawk committed
530 531
}

532 533
qint64 SerialLink::getCurrentUpstream()
{
pixhawk's avatar
pixhawk committed
534 535 536
    return 0; // TODO
}

537 538
qint64 SerialLink::getMaxUpstream()
{
pixhawk's avatar
pixhawk committed
539 540 541
    return 0; // TODO
}

542 543
qint64 SerialLink::getBitsSent()
{
Bill Bonney's avatar
Bill Bonney committed
544
    return m_bitsSentTotal;
pixhawk's avatar
pixhawk committed
545 546
}

547 548
qint64 SerialLink::getBitsReceived()
{
Bill Bonney's avatar
Bill Bonney committed
549
    return m_bitsReceivedTotal;
pixhawk's avatar
pixhawk committed
550 551
}

552 553
qint64 SerialLink::getTotalDownstream()
{
Bill Bonney's avatar
Bill Bonney committed
554 555 556
    m_statisticsMutex.lock();
    return m_bitsReceivedTotal / ((MG::TIME::getGroundTimeNow() - m_connectionStartTime) / 1000);
    m_statisticsMutex.unlock();
pixhawk's avatar
pixhawk committed
557 558
}

559 560
qint64 SerialLink::getCurrentDownstream()
{
pixhawk's avatar
pixhawk committed
561 562 563
    return 0; // TODO
}

564 565
qint64 SerialLink::getMaxDownstream()
{
pixhawk's avatar
pixhawk committed
566 567 568
    return 0; // TODO
}

569 570
bool SerialLink::isFullDuplex()
{
pixhawk's avatar
pixhawk committed
571 572 573 574
    /* Serial connections are always half duplex */
    return false;
}

575 576
int SerialLink::getLinkQuality()
{
pixhawk's avatar
pixhawk committed
577 578 579 580
    /* This feature is not supported with this interface */
    return -1;
}

581 582
QString SerialLink::getPortName()
{
Bill Bonney's avatar
Bill Bonney committed
583
    return m_portName;
pixhawk's avatar
pixhawk committed
584 585
}

Bill Bonney's avatar
Bill Bonney committed
586 587
// We should replace the accessors below with one to get the QSerialPort

588 589
int SerialLink::getBaudRate()
{
pixhawk's avatar
pixhawk committed
590 591 592
    return getNominalDataRate();
}

593 594
int SerialLink::getBaudRateType()
{
Bill Bonney's avatar
Bill Bonney committed
595 596 597 598 599 600 601
    int baudRate;
    if (m_port) {
        baudRate = m_port->baudRate();
    } else {
        baudRate = m_baud;
    }
    return baudRate;
pixhawk's avatar
pixhawk committed
602 603
}

604 605
int SerialLink::getFlowType()
{
Bill Bonney's avatar
Bill Bonney committed
606 607 608 609 610 611 612
    int flowControl;
    if (m_port) {
        flowControl = m_port->flowControl();
    } else {
        flowControl = m_flowControl;
    }
    return flowControl;
pixhawk's avatar
pixhawk committed
613 614
}

615 616
int SerialLink::getParityType()
{
Bill Bonney's avatar
Bill Bonney committed
617 618 619 620 621 622 623
    int parity;
    if (m_port) {
        parity = m_port->parity();
    } else {
        parity = m_parity;
    }
    return parity;
pixhawk's avatar
pixhawk committed
624 625
}

626 627
int SerialLink::getDataBitsType()
{
Bill Bonney's avatar
Bill Bonney committed
628 629 630 631 632 633 634
    int dataBits;
    if (m_port) {
        dataBits = m_port->dataBits();
    } else {
        dataBits = m_dataBits;
    }
    return dataBits;
pixhawk's avatar
pixhawk committed
635 636
}

637 638
int SerialLink::getStopBitsType()
{
Bill Bonney's avatar
Bill Bonney committed
639 640 641 642 643 644 645
    int stopBits;
    if (m_port) {
        stopBits = m_port->stopBits();
    } else {
        stopBits = m_stopBits;
    }
    return stopBits;
pixhawk's avatar
pixhawk committed
646 647
}

648 649
int SerialLink::getDataBits()
{
Bill Bonney's avatar
Bill Bonney committed
650 651 652 653 654 655 656 657 658 659
    int ret;
    int dataBits;
    if (m_port) {
        dataBits = m_port->dataBits();
    } else {
        dataBits = m_dataBits;
    }

    switch (dataBits) {
    case QSerialPort::Data5:
660 661
        ret = 5;
        break;
Bill Bonney's avatar
Bill Bonney committed
662
    case QSerialPort::Data6:
663 664
        ret = 6;
        break;
Bill Bonney's avatar
Bill Bonney committed
665
    case QSerialPort::Data7:
666 667
        ret = 7;
        break;
Bill Bonney's avatar
Bill Bonney committed
668
    case QSerialPort::Data8:
669 670 671
        ret = 8;
        break;
    default:
672
        ret = -1;
673 674 675 676 677 678 679
        break;
    }
    return ret;
}

int SerialLink::getStopBits()
{
Bill Bonney's avatar
Bill Bonney committed
680 681 682 683 684 685
    int stopBits;
    if (m_port) {
        stopBits = m_port->stopBits();
    } else {
        stopBits = m_stopBits;
    }
686
    int ret = -1;
Bill Bonney's avatar
Bill Bonney committed
687 688
    switch (stopBits) {
    case QSerialPort::OneStop:
689 690
        ret = 1;
        break;
Bill Bonney's avatar
Bill Bonney committed
691
    case QSerialPort::TwoStop:
692 693 694 695 696 697
        ret = 2;
        break;
    default:
        ret = -1;
        break;
    }
698 699 700
    return ret;
}

pixhawk's avatar
pixhawk committed
701 702
bool SerialLink::setPortName(QString portName)
{
Bill Bonney's avatar
Bill Bonney committed
703 704 705 706 707 708 709 710 711
    qDebug() << "current portName " << m_portName;
    qDebug() << "setPortName to " << portName;
    bool accepted = false;
    if ((portName != m_portName)
            && (portName.trimmed().length() > 0)) {
        m_portName = portName.trimmed();
        m_name = tr("serial port ") + portName.trimmed(); // [TODO] Do we need this?
        if(m_port)
            m_port->setPortName(portName);
712

Bill Bonney's avatar
Bill Bonney committed
713 714
        emit nameChanged(m_name); // [TODO] maybe we can eliminate this
        return accepted;
pixhawk's avatar
pixhawk committed
715
    }
Bill Bonney's avatar
Bill Bonney committed
716
    return false;
pixhawk's avatar
pixhawk committed
717 718 719 720 721
}


bool SerialLink::setBaudRateType(int rateIndex)
{
Bill Bonney's avatar
Bill Bonney committed
722 723 724 725
    Q_ASSERT_X(m_port != NULL, "setBaudRateType", "m_port is NULL");
    // These minimum and maximum baud rates were based on those enumerated in qserialport.h
    const int minBaud = (int)QSerialPort::Baud1200;
    const int maxBaud = (int)QSerialPort::Baud115200;
726

Bill Bonney's avatar
Bill Bonney committed
727
    if (m_port && (rateIndex >= minBaud && rateIndex <= maxBaud))
728
    {
Bill Bonney's avatar
Bill Bonney committed
729
        return m_port->setBaudRate(static_cast<QSerialPort::BaudRate>(rateIndex));
pixhawk's avatar
pixhawk committed
730 731
    }

Bill Bonney's avatar
Bill Bonney committed
732
    return false;
pixhawk's avatar
pixhawk committed
733 734
}

735 736 737 738 739 740 741
bool SerialLink::setBaudRateString(const QString& rate)
{
    bool ok;
    int intrate = rate.toInt(&ok);
    if (!ok) return false;
    return setBaudRate(intrate);
}
pixhawk's avatar
pixhawk committed
742 743 744

bool SerialLink::setBaudRate(int rate)
{
Bill Bonney's avatar
Bill Bonney committed
745 746 747 748 749 750
    bool accepted = false;
    if (rate != m_baud) {
        m_baud = rate;
        accepted = true;
        if (m_port)
            accepted = m_port->setBaudRate(rate);
pixhawk's avatar
pixhawk committed
751
    }
752
    return accepted;
pixhawk's avatar
pixhawk committed
753 754
}

755 756
bool SerialLink::setFlowType(int flow)
{
Bill Bonney's avatar
Bill Bonney committed
757 758 759 760 761 762
    bool accepted = false;
    if (flow != m_flowControl) {
        m_flowControl = static_cast<QSerialPort::FlowControl>(flow);
        accepted = true;
        if (m_port)
            accepted = m_port->setFlowControl(static_cast<QSerialPort::FlowControl>(flow));
pixhawk's avatar
pixhawk committed
763 764 765 766
    }
    return accepted;
}

767 768
bool SerialLink::setParityType(int parity)
{
Bill Bonney's avatar
Bill Bonney committed
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
    bool accepted = false;
    if (parity != m_parity) {
        m_parity = static_cast<QSerialPort::Parity>(parity);
        accepted = true;
        if (m_port) {
            switch (parity) {
                case QSerialPort::NoParity:
                accepted = m_port->setParity(QSerialPort::NoParity);
                break;
                case 1: // Odd Parity setting for backwards compatibilty
                    accepted = m_port->setParity(QSerialPort::OddParity);
                    break;
                case QSerialPort::EvenParity:
                    accepted = m_port->setParity(QSerialPort::EvenParity);
                    break;
                case QSerialPort::OddParity:
                    accepted = m_port->setParity(QSerialPort::OddParity);
                    break;
                default:
                    // If none of the above cases matches, there must be an error
                    accepted = false;
                    break;
                }
        }
pixhawk's avatar
pixhawk committed
793 794 795 796
    }
    return accepted;
}

797

798
bool SerialLink::setDataBits(int dataBits)
799
{
Bill Bonney's avatar
Bill Bonney committed
800 801 802 803 804 805
    bool accepted = false;
    if (dataBits != m_dataBits) {
        m_dataBits = static_cast<QSerialPort::DataBits>(dataBits);
        accepted = true;
        if (m_port)
            accepted = m_port->setDataBits(static_cast<QSerialPort::DataBits>(dataBits));
pixhawk's avatar
pixhawk committed
806 807 808 809
    }
    return accepted;
}

810
bool SerialLink::setStopBits(int stopBits)
811
{
Bill Bonney's avatar
Bill Bonney committed
812 813 814 815 816 817 818
    // Note 3 is OneAndAHalf stopbits.
    bool accepted = false;
    if (stopBits != m_stopBits) {
        m_stopBits = static_cast<QSerialPort::StopBits>(stopBits);
        accepted = true;
        if (m_port)
            accepted = m_port->setStopBits(static_cast<QSerialPort::StopBits>(stopBits));
pixhawk's avatar
pixhawk committed
819 820 821
    }
    return accepted;
}
822 823 824 825

bool SerialLink::setDataBitsType(int dataBits)
{
    bool accepted = false;
Bill Bonney's avatar
Bill Bonney committed
826 827
    if (dataBits != m_dataBits) {
        m_dataBits = static_cast<QSerialPort::DataBits>(dataBits);
828
        accepted = true;
Bill Bonney's avatar
Bill Bonney committed
829 830
        if (m_port)
            accepted = m_port->setDataBits(static_cast<QSerialPort::DataBits>(dataBits));
831 832 833 834 835 836 837
    }
    return accepted;
}

bool SerialLink::setStopBitsType(int stopBits)
{
    bool accepted = false;
Bill Bonney's avatar
Bill Bonney committed
838 839
    if (stopBits != m_stopBits) {
        m_stopBits = static_cast<QSerialPort::StopBits>(stopBits);
840
        accepted = true;
Bill Bonney's avatar
Bill Bonney committed
841 842
        if (m_port)
            accepted = m_port->setStopBits(static_cast<QSerialPort::StopBits>(stopBits));
843 844 845
    }
    return accepted;
}