Skip to content
SerialLink.cc 21.6 KiB
Newer Older
pixhawk's avatar
pixhawk committed
/*=====================================================================
======================================================================*/
/**
 * @file
 *   @brief Cross-platform support for serial ports
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <QTimer>
#include <QDebug>
#include <QSettings>
pixhawk's avatar
pixhawk committed
#include <QMutexLocker>
Bill Bonney's avatar
Bill Bonney committed
#include <qserialport.h>
#include <qserialportinfo.h>
pixhawk's avatar
pixhawk committed
#include "SerialLink.h"
#include "LinkManager.h"
#include "QGC.h"
pixhawk's avatar
pixhawk committed
#include <MG.h>

SerialLink::SerialLink(QString portname, int baudRate, bool hardwareFlowControl, bool parity,
                       int dataBits, int stopBits) :
Bill Bonney's avatar
Bill Bonney committed
    m_bytesRead(0),
    m_port(NULL),
pixhawk's avatar
pixhawk committed
{
    // Setup settings
Bill Bonney's avatar
Bill Bonney committed
    m_portName = portname.trimmed();
    if (m_portName == "" && getCurrentPorts().size() > 0)
        m_portName = m_ports.first().trimmed();
pixhawk's avatar
pixhawk committed
    // Set unique ID and add link to the list of links
Bill Bonney's avatar
Bill Bonney committed
    m_id = getNextLinkId();

    m_baud = baudRate;
    if (hardwareFlowControl)
    {
Bill Bonney's avatar
Bill Bonney committed
        m_flowControl = QSerialPort::HardwareControl;
Bill Bonney's avatar
Bill Bonney committed
        m_flowControl = QSerialPort::NoFlowControl;
Bill Bonney's avatar
Bill Bonney committed
        m_parity = QSerialPort::EvenParity;
Bill Bonney's avatar
Bill Bonney committed
        m_parity = QSerialPort::NoParity;
Bill Bonney's avatar
Bill Bonney committed

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

lm's avatar
lm committed
    loadSettings();
Lorenz Meier's avatar
Lorenz Meier committed

    qDebug() << "create SerialLink " << portname << baudRate << hardwareFlowControl
             << parity << dataBits << stopBits;
    qDebug() << "m_portName " << m_portName;

    LinkManager::instance()->add(this);
pixhawk's avatar
pixhawk committed
}
void SerialLink::requestReset()
{
    QMutexLocker locker(&this->m_stoppMutex);
    m_reqReset = true;
}
pixhawk's avatar
pixhawk committed

SerialLink::~SerialLink()
{
    disconnect();
Bill Bonney's avatar
Bill Bonney committed
    if(m_port) delete m_port;
    m_port = NULL;
QList<QString> SerialLink::getCurrentPorts()
    QList<QSerialPortInfo> portList =  QSerialPortInfo::availablePorts();
    if( portList.count() == 0){
        qDebug() << "No Ports Found" << m_ports;
    foreach (const QSerialPortInfo &info, portList)
Bill Bonney's avatar
Bill Bonney committed
//        qDebug() << "PortName    : " << info.portName()
//                 << "Description : " << info.description();
//        qDebug() << "Manufacturer: " << info.manufacturer();
        m_ports.append(info.portName());
Bill Bonney's avatar
Bill Bonney committed
    return m_ports;
pixhawk's avatar
pixhawk committed
}

void SerialLink::loadSettings()
{
    // Load defaults from settings
    QSettings settings(QGC::ORG_NAME, QGC::APPNAME);
    if (settings.contains("SERIALLINK_COMM_PORT"))
    {
Bill Bonney's avatar
Bill Bonney committed
        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();
    }
}

void SerialLink::writeSettings()
{
    // Store settings
    QSettings settings(QGC::ORG_NAME, QGC::APPNAME);
    settings.setValue("SERIALLINK_COMM_PORT", getPortName());
    settings.setValue("SERIALLINK_COMM_BAUD", getBaudRateType());
    settings.setValue("SERIALLINK_COMM_PARITY", getParityType());
    settings.setValue("SERIALLINK_COMM_STOPBITS", getStopBits());
    settings.setValue("SERIALLINK_COMM_DATABITS", getDataBits());
    settings.setValue("SERIALLINK_COMM_FLOW_CONTROL", getFlowType());
pixhawk's avatar
pixhawk committed

/**
 * @brief Runs the thread
 *
 **/
pixhawk's avatar
pixhawk committed
    // Initialize the connection
    if (!hardwareConnect()) {
        emit communicationError(getName(),"Error connecting: " + m_port->errorString());
        disconnect(); // This tidies up and sends the necessary signals
        emit communicationError(tr("Serial Port %1").arg(getPortName()), tr("Cannot read / write data - check physical USB and cable connections."));
pixhawk's avatar
pixhawk committed

    // Qt way to make clear what a while(1) loop does
    qint64 msecs = QDateTime::currentMSecsSinceEpoch();
    qint64 initialmsecs = QDateTime::currentMSecsSinceEpoch();
    quint64 bytes = 0;
    bool triedreset = false;
    bool triedDTR = false;
    qint64 timeout = 5000;
    int linkErrorCount = 0;
    forever {
            QMutexLocker locker(&this->m_stoppMutex);
            if(m_stopp) {
                m_stopp = false;
                break; // exit the thread
            }
            if (m_reqReset) {
                m_reqReset = false;
                emit communicationUpdate(getName(),"Reset requested via DTR signal");
                m_port->setDataTerminalReady(true);
                msleep(250);
                m_port->setDataTerminalReady(false);
            }
        // If there are too many errors on this link, disconnect.
Lorenz Meier's avatar
Lorenz Meier committed
        if (isConnected() && (linkErrorCount > 1000)) {
            qDebug() << "linkErrorCount too high: disconnecting!";
            linkErrorCount = 0;
            emit communicationUpdate(getName(), tr("Disconnecting on too many link errors"));
        // Write all our buffered data out the serial port.
        if (m_transmitBuffer.count() > 0) {
            QMutexLocker writeLocker(&m_writeMutex);
            int numWritten = m_port->write(m_transmitBuffer);
            bool txSuccess = m_port->waitForBytesWritten(5);
            if (!txSuccess || (numWritten != m_transmitBuffer.count())) {
                linkErrorCount++;
                qDebug() << "TX Error! wrote" << numWritten << ", asked for " << m_transmitBuffer.count() << "bytes";

                // Since we were successful, reset out error counter.
                linkErrorCount = 0;
            }
            m_transmitBuffer =  m_transmitBuffer.remove(0, numWritten);
        //wait n msecs for data to be ready
        //[TODO][BB] lower to SerialLink::poll_interval?
        bool success = m_port->waitForReadyRead(10);
            QByteArray readData = m_port->readAll();
            while (m_port->waitForReadyRead(10))
                readData += m_port->readAll();
            if (readData.length() > 0) {
                emit bytesReceived(this, readData);

                m_bytesRead += readData.length();
                linkErrorCount = 0;
            linkErrorCount++;
        if (bytes != m_bytesRead) { // i.e things are good and data is being read.
            bytes = m_bytesRead;
        else {
            if (QDateTime::currentMSecsSinceEpoch() - msecs > timeout) {
                //It's been 10 seconds since the last data came in. Reset and try again
                msecs = QDateTime::currentMSecsSinceEpoch();
                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;
                }
                if (!triedDTR && triedreset) {
                    emit communicationUpdate(getName(),"No data to receive on COM port. Attempting to reset via DTR signal");
                    qDebug() << "No data!!! Attempting reset via DTR.";
                    m_port->setDataTerminalReady(true);
                    msleep(250);
                    m_port->setDataTerminalReady(false);
                else if (!triedreset) {
                    qDebug() << "No data!!! Attempting reset via reboot command.";
                    emit communicationUpdate(getName(),"No data to receive on COM port. Assuming possible terminal mode, attempting to reset via \"reboot\" command");
                    m_port->write("reboot\r\n",8);
                else {
                    emit communicationUpdate(getName(),"No data to receive on COM port....");
pixhawk's avatar
pixhawk committed
        MG::SLEEP::msleep(SerialLink::poll_interval);
    } // end of forever
    
    if (m_port) { // [TODO][BB] Not sure we need to close the port here
        qDebug() << "Closing Port #"<< __LINE__ << m_port->portName();
        m_port->close();
        delete m_port;
        m_port = NULL;
pixhawk's avatar
pixhawk committed

        emit disconnected();
        emit connected(false);
pixhawk's avatar
pixhawk committed
}

void SerialLink::writeBytes(const char* data, qint64 size)
{
Bill Bonney's avatar
Bill Bonney committed
    if(m_port && m_port->isOpen()) {
pixhawk's avatar
pixhawk committed

        QByteArray byteArray(data, size);
        {
            QMutexLocker writeLocker(&m_writeMutex);
            m_transmitBuffer.append(byteArray);
        }
        // Extra debug logging
//            qDebug() << byteArray->toHex();
    } else {
        disconnect();
        // Error occured
        emit communicationError(getName(), tr("Could not send data - link %1 is disconnected!").arg(getName()));
pixhawk's avatar
pixhawk committed
    }
}

/**
 * @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
 **/
Bill Bonney's avatar
Bill Bonney committed
    m_dataMutex.lock();
    if(m_port && m_port->isOpen()) {
        const qint64 maxLength = 2048;
        char data[maxLength];
Bill Bonney's avatar
Bill Bonney committed
        qint64 numBytes = m_port->bytesAvailable();
        if(numBytes > 0) {
pixhawk's avatar
pixhawk committed
            /* Read as much data in buffer as possible without overflow */
            if(maxLength < numBytes) numBytes = maxLength;

Bill Bonney's avatar
Bill Bonney committed
            m_port->read(data, numBytes);
pixhawk's avatar
pixhawk committed
            QByteArray b(data, numBytes);
            emit bytesReceived(this, b);
        }
    }
Bill Bonney's avatar
Bill Bonney committed
    m_dataMutex.unlock();
pixhawk's avatar
pixhawk committed
}


/**
 * @brief Get the number of bytes to read.
 *
 * @return The number of bytes to read
 **/
Bill Bonney's avatar
Bill Bonney committed
    if (m_port) {
        return m_port->bytesAvailable();
pixhawk's avatar
pixhawk committed
}

/**
 * @brief Disconnect the connection.
 *
 * @return True if connection has been disconnected, false if connection couldn't be disconnected.
 **/
    qDebug() << "disconnect";
    if (m_port)
        qDebug() << m_port->portName();
Bill Bonney's avatar
Bill Bonney committed

    if (isRunning())
        qDebug() << "running so disconnect" << m_port->portName();
Bill Bonney's avatar
Bill Bonney committed
            QMutexLocker locker(&m_stoppMutex);
            m_stopp = true;
Bill Bonney's avatar
Bill Bonney committed
        wait(); // This will terminate the thread and close the serial port
pixhawk's avatar
pixhawk committed

Bill Bonney's avatar
Bill Bonney committed
        emit disconnected(); // [TODO] There are signals from QSerialPort we should use
pixhawk's avatar
pixhawk committed

    m_transmitBuffer.clear(); //clear the output buffer to avoid sending garbage at next connect

    qDebug() << "already disconnected";
    return true;
pixhawk's avatar
pixhawk committed
}

/**
 * @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
    if (isRunning())
        disconnect();
    {
        QMutexLocker locker(&this->m_stoppMutex);
Bill Bonney's avatar
Bill Bonney committed
        m_stopp = false;
Bill Bonney's avatar
Bill Bonney committed

    start(LowPriority);
    return true;
pixhawk's avatar
pixhawk committed
}

/**
 * @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.
 **/
Bill Bonney's avatar
Bill Bonney committed
        qDebug() << "SerialLink:" << QString::number((long)this, 16) << "closing port";
        m_port->close();
        delete m_port;
        m_port = NULL;
Bill Bonney's avatar
Bill Bonney committed
    qDebug() << "SerialLink: hardwareConnect to " << m_portName;
    m_port = new QSerialPort(m_portName);
pixhawk's avatar
pixhawk committed

    if (m_port == NULL) {
Bill Bonney's avatar
Bill Bonney committed
        emit communicationUpdate(getName(),"Error opening port: " + m_port->errorString());
        return false; // couldn't create serial port.
Bill Bonney's avatar
Bill Bonney committed

    QObject::connect(m_port,SIGNAL(aboutToClose()),this,SIGNAL(disconnected()));
    QObject::connect(m_port, SIGNAL(error(SerialLinkPortError_t)),
                     this, SLOT(linkError(SerialLinkPortError_t)));
Bill Bonney's avatar
Bill Bonney committed

//    port->setCommTimeouts(QSerialPort::CtScheme_NonBlockingRead);

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

Bill Bonney's avatar
Bill Bonney committed
    // 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));
pixhawk's avatar
pixhawk committed

Bill Bonney's avatar
Bill Bonney committed
    emit connected();
    emit connected(true);
Bill Bonney's avatar
Bill Bonney committed
    qDebug() << "CONNECTING LINK: " << __FILE__ << __LINE__ << "with settings" << m_port->portName()
             << getBaudRate() << getDataBits() << getParityType() << getStopBits();
Bill Bonney's avatar
Bill Bonney committed
    return true; // successful connection
pixhawk's avatar
pixhawk committed
}
void SerialLink::linkError(SerialLinkPortError_t error)
pixhawk's avatar
pixhawk committed
/**
 * @brief Check if connection is active.
 *
 * @return True if link is connected, false otherwise.
 **/
bool SerialLink::isConnected() const
Bill Bonney's avatar
Bill Bonney committed

    if (m_port) {
        bool isConnected = m_port->isOpen();
//        qDebug() << "SerialLink #" << __LINE__ << ":"<<  m_port->portName()
//                 << " isConnected =" << QString::number(isConnected);
Bill Bonney's avatar
Bill Bonney committed
        return isConnected;
//        qDebug() << "SerialLink #" << __LINE__ << ":" <<  m_portName
//                 << " isConnected = NULL";
lm's avatar
lm committed
        return false;
    }
pixhawk's avatar
pixhawk committed
}

pixhawk's avatar
pixhawk committed
{
Bill Bonney's avatar
Bill Bonney committed
    return m_id;
pixhawk's avatar
pixhawk committed
}

QString SerialLink::getName() const
pixhawk's avatar
pixhawk committed
{
pixhawk's avatar
pixhawk committed
}

/**
  * This function maps baud rate constants to numerical equivalents.
  * It relies on the mapping given in qportsettings.h from the QSerialPort library.
  */
qint64 SerialLink::getNominalDataRate() const
Bill Bonney's avatar
Bill Bonney committed
    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
    }
    return dataRate;
}

QString SerialLink::getPortName() const
Bill Bonney's avatar
Bill Bonney committed
    return m_portName;
pixhawk's avatar
pixhawk committed
}

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

int SerialLink::getBaudRate() const
pixhawk's avatar
pixhawk committed
    return getNominalDataRate();
}

int SerialLink::getBaudRateType() const
Bill Bonney's avatar
Bill Bonney committed
    int baudRate;
    if (m_port) {
        baudRate = m_port->baudRate();
    } else {
        baudRate = m_baud;
    }
    return baudRate;
pixhawk's avatar
pixhawk committed
}

int SerialLink::getFlowType() const
Bill Bonney's avatar
Bill Bonney committed
    int flowControl;
    if (m_port) {
        flowControl = m_port->flowControl();
    } else {
        flowControl = m_flowControl;
    }
    return flowControl;
pixhawk's avatar
pixhawk committed
}

int SerialLink::getParityType() const
Bill Bonney's avatar
Bill Bonney committed
    int parity;
    if (m_port) {
        parity = m_port->parity();
    } else {
        parity = m_parity;
    }
    return parity;
pixhawk's avatar
pixhawk committed
}

int SerialLink::getDataBitsType() const
Bill Bonney's avatar
Bill Bonney committed
    int dataBits;
    if (m_port) {
        dataBits = m_port->dataBits();
    } else {
        dataBits = m_dataBits;
    }
    return dataBits;
pixhawk's avatar
pixhawk committed
}

int SerialLink::getStopBitsType() const
Bill Bonney's avatar
Bill Bonney committed
    int stopBits;
    if (m_port) {
        stopBits = m_port->stopBits();
    } else {
        stopBits = m_stopBits;
    }
    return stopBits;
pixhawk's avatar
pixhawk committed
}

int SerialLink::getDataBits() const
Bill Bonney's avatar
Bill Bonney committed
    int ret;
    int dataBits;
    if (m_port) {
        dataBits = m_port->dataBits();
    } else {
        dataBits = m_dataBits;
    }

    switch (dataBits) {
    case QSerialPort::Data5:
Bill Bonney's avatar
Bill Bonney committed
    case QSerialPort::Data6:
Bill Bonney's avatar
Bill Bonney committed
    case QSerialPort::Data7:
Bill Bonney's avatar
Bill Bonney committed
    case QSerialPort::Data8:
int SerialLink::getStopBits() const
Bill Bonney's avatar
Bill Bonney committed
    int stopBits;
    if (m_port) {
        stopBits = m_port->stopBits();
    } else {
        stopBits = m_stopBits;
    }
Bill Bonney's avatar
Bill Bonney committed
    switch (stopBits) {
    case QSerialPort::OneStop:
Bill Bonney's avatar
Bill Bonney committed
    case QSerialPort::TwoStop:
        ret = 2;
        break;
    default:
        ret = -1;
        break;
    }
pixhawk's avatar
pixhawk committed
bool SerialLink::setPortName(QString portName)
{
Bill Bonney's avatar
Bill Bonney committed
    qDebug() << "current portName " << m_portName;
    qDebug() << "setPortName to " << portName;
    bool accepted = false;
    if ((portName != m_portName)
            && (portName.trimmed().length() > 0)) {
        m_portName = portName.trimmed();
        if(m_port)
            m_port->setPortName(portName);
        emit nameChanged(m_portName); // [TODO] maybe we can eliminate this
        emit updateLink(this);
Bill Bonney's avatar
Bill Bonney committed
        return accepted;
pixhawk's avatar
pixhawk committed
    }
Bill Bonney's avatar
Bill Bonney committed
    return false;
pixhawk's avatar
pixhawk committed
}


bool SerialLink::setBaudRateType(int rateIndex)
{
Bill Bonney's avatar
Bill Bonney committed
    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
Bill Bonney's avatar
Bill Bonney committed
    const int minBaud = (int)QSerialPort::Baud1200;
    const int maxBaud = (int)QSerialPort::Baud115200;
Bill Bonney's avatar
Bill Bonney committed
    if (m_port && (rateIndex >= minBaud && rateIndex <= maxBaud))
        result = m_port->setBaudRate(static_cast<QSerialPort::BaudRate>(rateIndex));
        emit updateLink(this);
        return result;
pixhawk's avatar
pixhawk committed
    }

Bill Bonney's avatar
Bill Bonney committed
    return false;
pixhawk's avatar
pixhawk committed
}

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

bool SerialLink::setBaudRate(int rate)
{
Bill Bonney's avatar
Bill Bonney committed
    bool accepted = false;
    if (rate != m_baud) {
        m_baud = rate;
        accepted = true;
        if (m_port)
            accepted = m_port->setBaudRate(rate);
        emit updateLink(this);
pixhawk's avatar
pixhawk committed
    }
pixhawk's avatar
pixhawk committed
}

bool SerialLink::setFlowType(int flow)
{
Bill Bonney's avatar
Bill Bonney committed
    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));
        emit updateLink(this);
pixhawk's avatar
pixhawk committed
    }
    return accepted;
}

bool SerialLink::setParityType(int parity)
{
Bill Bonney's avatar
Bill Bonney committed
    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;
                }
            emit updateLink(this);
Bill Bonney's avatar
Bill Bonney committed
        }
pixhawk's avatar
pixhawk committed
    }
    return accepted;
}

bool SerialLink::setDataBits(int dataBits)
Bill Bonney's avatar
Bill Bonney committed
    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));
        emit updateLink(this);
pixhawk's avatar
pixhawk committed
    }
    return accepted;
}

bool SerialLink::setStopBits(int stopBits)
Bill Bonney's avatar
Bill Bonney committed
    // 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));
        emit updateLink(this);
pixhawk's avatar
pixhawk committed
    }
    return accepted;
}

bool SerialLink::setDataBitsType(int dataBits)
{
    bool accepted = false;
Bill Bonney's avatar
Bill Bonney committed
    if (dataBits != m_dataBits) {
        m_dataBits = static_cast<QSerialPort::DataBits>(dataBits);
Bill Bonney's avatar
Bill Bonney committed
        if (m_port)
            accepted = m_port->setDataBits(static_cast<QSerialPort::DataBits>(dataBits));
        emit updateLink(this);
    }
    return accepted;
}

bool SerialLink::setStopBitsType(int stopBits)
{
    bool accepted = false;
Bill Bonney's avatar
Bill Bonney committed
    if (stopBits != m_stopBits) {
        m_stopBits = static_cast<QSerialPort::StopBits>(stopBits);
Bill Bonney's avatar
Bill Bonney committed
        if (m_port)
            accepted = m_port->setStopBits(static_cast<QSerialPort::StopBits>(stopBits));
        emit updateLink(this);