feat(simu): cross-platform connection of host serial ports to simu radio (#5584)
This commit is contained in:
@@ -13,6 +13,7 @@ find_package(Qt5LinguistTools)
|
||||
find_package(Qt5PrintSupport)
|
||||
find_package(Qt5Multimedia)
|
||||
find_package(Qt5Svg)
|
||||
find_package(Qt5SerialPort)
|
||||
|
||||
if(Qt5Core_FOUND)
|
||||
message(STATUS "Qt Version: ${Qt5Core_VERSION}")
|
||||
|
||||
@@ -191,6 +191,7 @@ target_link_libraries(common
|
||||
Qt5::Core
|
||||
Qt5::Xml
|
||||
Qt5::Widgets
|
||||
Qt5::SerialPort
|
||||
${PTHREAD_LIBRARY}
|
||||
${SDL2_LIBRARIES}
|
||||
${WIN_LINK_LIBRARIES}
|
||||
|
||||
@@ -19,6 +19,8 @@ set(${PROJECT_NAME}_NAMES
|
||||
widgets/lcdwidget
|
||||
widgets/radiowidget
|
||||
widgets/virtualjoystickwidget
|
||||
serialportsdialog
|
||||
hostserialconnector
|
||||
)
|
||||
|
||||
if(SDL2_FOUND)
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "hostserialconnector.h"
|
||||
#include <QMessageBox>
|
||||
|
||||
HostSerialConnector::HostSerialConnector(QObject *parent, SimulatorInterface *simulator)
|
||||
: simulator(simulator)
|
||||
{
|
||||
for (int i = 0; i < MAX_HOST_SERIAL; i++) {
|
||||
hostAuxPorts[i] = nullptr;
|
||||
hostAuxPortsEncoding[i] = SERIAL_ENCODING_8N1;
|
||||
hostAuxPortsBaudRate[i] = 9600;
|
||||
hostAuxPortsOpen[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
HostSerialConnector::~HostSerialConnector()
|
||||
{
|
||||
for (int i = 0; i < MAX_HOST_SERIAL; i++) {
|
||||
if (hostAuxPorts[i] != nullptr) {
|
||||
hostAuxPorts[i]->close();
|
||||
hostAuxPorts[i]->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString HostSerialConnector::getConnectedSerialPortName(int index)
|
||||
{
|
||||
if (index >= MAX_HOST_SERIAL)
|
||||
return QString("");
|
||||
|
||||
QMutexLocker locker(&hostAuxPortsMutex);
|
||||
|
||||
QSerialPort * port = hostAuxPorts[index];
|
||||
if (port == nullptr)
|
||||
return QString("");
|
||||
|
||||
return port->portName();
|
||||
}
|
||||
|
||||
void HostSerialConnector::connectSerialPort(int index, QString portName)
|
||||
{
|
||||
if (index >= MAX_HOST_SERIAL)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&hostAuxPortsMutex);
|
||||
|
||||
QSerialPort * port = hostAuxPorts[index];
|
||||
if (port != nullptr) {
|
||||
port->close();
|
||||
port->deleteLater();
|
||||
}
|
||||
|
||||
if (portName.isEmpty()) {
|
||||
hostAuxPorts[index] = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
port = new QSerialPort(portName, this);
|
||||
hostAuxPorts[index] = port;
|
||||
|
||||
setSerialEncoding(index, hostAuxPortsEncoding[index]);
|
||||
setSerialBaudRate(index, hostAuxPortsBaudRate[index]);
|
||||
|
||||
connect(port, &QSerialPort::readyRead, [this, index, port]() {
|
||||
QByteArray data = port->readAll();
|
||||
simulator->receiveAuxSerialData(index, data);
|
||||
});
|
||||
|
||||
if (hostAuxPortsOpen[index])
|
||||
serialStart(index);
|
||||
}
|
||||
|
||||
void HostSerialConnector::sendSerialData(const quint8 index, const QByteArray & data)
|
||||
{
|
||||
if (index >= MAX_HOST_SERIAL)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&hostAuxPortsMutex);
|
||||
|
||||
QSerialPort * port = hostAuxPorts[index];
|
||||
if (port == nullptr)
|
||||
return;
|
||||
|
||||
port->write(data);
|
||||
}
|
||||
|
||||
void HostSerialConnector::setSerialEncoding(const quint8 index, const quint8 encoding)
|
||||
{
|
||||
if (index >= MAX_HOST_SERIAL)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&hostAuxPortsMutex);
|
||||
|
||||
hostAuxPortsEncoding[index] = encoding;
|
||||
|
||||
QSerialPort * port = hostAuxPorts[index];
|
||||
if (port == nullptr)
|
||||
return;
|
||||
|
||||
switch(encoding) {
|
||||
case SERIAL_ENCODING_8N1:
|
||||
port->setDataBits(QSerialPort::Data8);
|
||||
port->setParity(QSerialPort::NoParity);
|
||||
port->setStopBits(QSerialPort::OneStop);
|
||||
break;
|
||||
case SERIAL_ENCODING_8E2:
|
||||
port->setDataBits(QSerialPort::Data8);
|
||||
port->setParity(QSerialPort::EvenParity);
|
||||
port->setStopBits(QSerialPort::TwoStop);
|
||||
break;
|
||||
default:
|
||||
// Do nothing, QSerialPort can't do SERIAL_ENCODING_PXX1_PWM
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HostSerialConnector::setSerialBaudRate(const quint8 index, const quint32 baudrate)
|
||||
{
|
||||
if (index >= MAX_HOST_SERIAL)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&hostAuxPortsMutex);
|
||||
|
||||
hostAuxPortsBaudRate[index] = baudrate;
|
||||
|
||||
QSerialPort * port = hostAuxPorts[index];
|
||||
if (port == nullptr)
|
||||
return;
|
||||
|
||||
if (!port->setBaudRate(baudrate))
|
||||
qDebug() << "Failed to set baudrate";
|
||||
}
|
||||
|
||||
void HostSerialConnector::serialStart(const quint8 index)
|
||||
{
|
||||
if (index >= MAX_HOST_SERIAL)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&hostAuxPortsMutex);
|
||||
|
||||
hostAuxPortsOpen[index] = true;
|
||||
|
||||
QSerialPort * port = hostAuxPorts[index];
|
||||
if (port == nullptr)
|
||||
return;
|
||||
|
||||
if (port->open(QIODevice::ReadWrite))
|
||||
qDebug() << "Opened host serial " << index;
|
||||
else
|
||||
QMessageBox::warning(nullptr, tr("Host Serial Error"), port->errorString(), QMessageBox::Cancel, QMessageBox::Cancel);
|
||||
}
|
||||
|
||||
void HostSerialConnector::serialStop(const quint8 index)
|
||||
{
|
||||
if (index >= MAX_HOST_SERIAL)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&hostAuxPortsMutex);
|
||||
|
||||
hostAuxPortsOpen[index] = false;
|
||||
|
||||
QSerialPort * port = hostAuxPorts[index];
|
||||
if (port == nullptr)
|
||||
return;
|
||||
|
||||
port->close();
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "simulatorinterface.h"
|
||||
|
||||
#include <QSerialPort>
|
||||
#include <QMutex>
|
||||
|
||||
#define MAX_HOST_SERIAL 2
|
||||
|
||||
class HostSerialConnector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HostSerialConnector(QObject * parent, SimulatorInterface * simulator);
|
||||
~HostSerialConnector();
|
||||
|
||||
QString getConnectedSerialPortName(int index);
|
||||
|
||||
public slots:
|
||||
void connectSerialPort(int index, QString portName);
|
||||
void sendSerialData(const quint8 index, const QByteArray & data);
|
||||
void setSerialEncoding(const quint8 index, const quint8 encoding);
|
||||
void setSerialBaudRate(const quint8 index, const quint32 baudrate);
|
||||
void serialStart(const quint8 index);
|
||||
void serialStop(const quint8 index);
|
||||
|
||||
private:
|
||||
SimulatorInterface * simulator;
|
||||
|
||||
QRecursiveMutex hostAuxPortsMutex;
|
||||
QSerialPort * hostAuxPorts[MAX_HOST_SERIAL];
|
||||
quint8 hostAuxPortsEncoding[MAX_HOST_SERIAL];
|
||||
quint32 hostAuxPortsBaudRate[MAX_HOST_SERIAL];
|
||||
bool hostAuxPortsOpen[MAX_HOST_SERIAL];
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "serialportsdialog.h"
|
||||
#include "ui_serialportsdialog.h"
|
||||
|
||||
SerialPortsDialog::SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator, HostSerialConnector *connector) :
|
||||
QDialog(parent),
|
||||
simulator(simulator),
|
||||
connector(connector),
|
||||
ui(new Ui::SerialPortsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
aux1 = connector->getConnectedSerialPortName(0);
|
||||
aux2 = connector->getConnectedSerialPortName(1);
|
||||
|
||||
populateSerialPortCombo(ui->aux1Combo, aux1);
|
||||
populateSerialPortCombo(ui->aux2Combo, aux2);
|
||||
|
||||
ui->aux1Combo->setEnabled(simulator->getCapability(SimulatorInterface::Capability::CAP_SERIAL_AUX1));
|
||||
ui->aux2Combo->setEnabled(simulator->getCapability(SimulatorInterface::Capability::CAP_SERIAL_AUX2));
|
||||
}
|
||||
|
||||
SerialPortsDialog::~SerialPortsDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SerialPortsDialog::populateSerialPortCombo(QComboBox * cb, QString currentPortName)
|
||||
{
|
||||
cb->clear();
|
||||
cb->addItem(tr("Not Assigned"), "");
|
||||
if (currentPortName == "") {
|
||||
cb->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
const auto serialPortInfos = QSerialPortInfo::availablePorts();
|
||||
for (int i = 0; i < serialPortInfos.size(); i++) {
|
||||
const auto portInfo = serialPortInfos[i];
|
||||
cb->addItem(portInfo.portName(), portInfo.portName());
|
||||
if (portInfo.portName() == currentPortName)
|
||||
cb->setCurrentIndex(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialPortsDialog::on_cancelButton_clicked()
|
||||
{
|
||||
this->reject();
|
||||
}
|
||||
|
||||
void SerialPortsDialog::on_okButton_clicked()
|
||||
{
|
||||
this->accept();
|
||||
}
|
||||
|
||||
void SerialPortsDialog::on_refreshButton_clicked()
|
||||
{
|
||||
populateSerialPortCombo(ui->aux1Combo, aux1);
|
||||
populateSerialPortCombo(ui->aux2Combo, aux2);
|
||||
}
|
||||
|
||||
void SerialPortsDialog::on_aux1Combo_currentIndexChanged(int index)
|
||||
{
|
||||
aux1 = ui->aux1Combo->itemData(index).toString();
|
||||
}
|
||||
|
||||
void SerialPortsDialog::on_aux2Combo_currentIndexChanged(int index)
|
||||
{
|
||||
aux2 = ui->aux2Combo->itemData(index).toString();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QSerialPort>
|
||||
#include <QSerialPortInfo>
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "simulatorinterface.h"
|
||||
#include "hostserialconnector.h"
|
||||
|
||||
class QComboBox;
|
||||
|
||||
namespace Ui {
|
||||
class SerialPortsDialog;
|
||||
}
|
||||
|
||||
class SerialPortsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator, HostSerialConnector *connector);
|
||||
~SerialPortsDialog();
|
||||
QString aux1;
|
||||
QString aux2;
|
||||
SimulatorInterface *simulator;
|
||||
HostSerialConnector *connector;
|
||||
|
||||
private:
|
||||
Ui::SerialPortsDialog *ui;
|
||||
|
||||
private slots:
|
||||
void populateSerialPortCombo(QComboBox * cb, QString currentPortName);
|
||||
void on_cancelButton_clicked();
|
||||
void on_okButton_clicked();
|
||||
void on_refreshButton_clicked();
|
||||
void on_aux1Combo_currentIndexChanged(int index);
|
||||
void on_aux2Combo_currentIndexChanged(int index);
|
||||
};
|
||||
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SerialPortsDialog</class>
|
||||
<widget class="QDialog" name="SerialPortsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>558</width>
|
||||
<height>108</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure Serial Ports</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>534</width>
|
||||
<height>89</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="aux1Label">
|
||||
<property name="text">
|
||||
<string>AUX1 Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>360</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="cancelButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="aux2Label">
|
||||
<property name="text">
|
||||
<string>AUX2 Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="aux1Combo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="aux2Combo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="okButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ok</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="refreshButton">
|
||||
<property name="text">
|
||||
<string>Search for Serial Ports</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <QDir>
|
||||
#include <QLibrary>
|
||||
#include <QMap>
|
||||
#include <QSerialPort>
|
||||
|
||||
#define SIMULATOR_INTERFACE_HEARTBEAT_PERIOD 1000 // ms
|
||||
|
||||
@@ -44,6 +45,13 @@ enum SimulatorTelemetryProtocol {
|
||||
SIMU_TELEMETRY_PROTOCOL_COUNT
|
||||
};
|
||||
|
||||
enum SimulatorSerialEncoding {
|
||||
SERIAL_ENCODING_8N1 = 0,
|
||||
SERIAL_ENCODING_8E2,
|
||||
SERIAL_ENCODING_PXX1_PWM,
|
||||
SERIAL_ENCODING_COUNT
|
||||
};
|
||||
|
||||
class SimulatorInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -84,6 +92,8 @@ class SimulatorInterface : public QObject
|
||||
CAP_ROTARY_ENC, // ROTARY_ENCODERS
|
||||
CAP_ROTARY_ENC_NAV, // ROTARY_ENCODER_NAVIGATION
|
||||
CAP_TELEM_FRSKY_SPORT, // TELEMETRY_FRSKY_SPORT
|
||||
CAP_SERIAL_AUX1, // Does AUX1 exist on this radio?
|
||||
CAP_SERIAL_AUX2, // Does AUX2 exist on this radio?
|
||||
CAP_ENUM_COUNT
|
||||
};
|
||||
|
||||
@@ -160,6 +170,7 @@ class SimulatorInterface : public QObject
|
||||
virtual void setLuaStateReloadPermanentScripts() = 0;
|
||||
virtual void addTracebackDevice(QIODevice * device) = 0;
|
||||
virtual void removeTracebackDevice(QIODevice * device) = 0;
|
||||
virtual void receiveAuxSerialData(const quint8 port_num, const QByteArray & data) = 0;
|
||||
|
||||
signals:
|
||||
|
||||
@@ -176,6 +187,11 @@ class SimulatorInterface : public QObject
|
||||
void trimRangeChange(quint8 index, qint32 min, qint16 max);
|
||||
void gVarValueChange(quint8 index, qint32 value);
|
||||
void outputValueChange(int type, quint8 index, qint32 value);
|
||||
void auxSerialSendData(const quint8 port_num, const QByteArray & data);
|
||||
void auxSerialSetEncoding(const quint8 port_num, const quint8 encoding);
|
||||
void auxSerialSetBaudrate(const quint8 port_num, const quint32 baudrate);
|
||||
void auxSerialStart(const quint8 port_num);
|
||||
void auxSerialStop(const quint8 port_num);
|
||||
};
|
||||
|
||||
class SimulatorFactory {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#ifdef JOYSTICKS
|
||||
#include "joystickdialog.h"
|
||||
#endif
|
||||
#include "serialportsdialog.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
@@ -82,6 +83,8 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, const QString & simula
|
||||
m_simulator->moveToThread(&simuThread);
|
||||
simuThread.start();
|
||||
|
||||
hostSerialConnector = new HostSerialConnector(this, m_simulator);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
|
||||
@@ -131,6 +134,7 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, const QString & simula
|
||||
|
||||
connect(ui->actionShowKeymap, &QAction::triggered, this, &SimulatorMainWindow::showHelp);
|
||||
connect(ui->actionJoystickSettings, &QAction::triggered, this, &SimulatorMainWindow::openJoystickDialog);
|
||||
connect(ui->actionSerialPorts, &QAction::triggered, this, &SimulatorMainWindow::openSerialPortsDialog);
|
||||
connect(ui->actionToggleMenuBar, &QAction::toggled, this, &SimulatorMainWindow::showMenuBar);
|
||||
connect(ui->actionFixedRadioWidth, &QAction::toggled, this, &SimulatorMainWindow::showRadioFixedWidth);
|
||||
connect(ui->actionFixedRadioHeight, &QAction::toggled, this, &SimulatorMainWindow::showRadioFixedHeight);
|
||||
@@ -150,6 +154,12 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, const QString & simula
|
||||
connect(ui->actionScreenshot, &QAction::triggered, m_simulatorWidget, &SimulatorWidget::captureScreenshot);
|
||||
connect(m_simulatorWidget, &SimulatorWidget::windowTitleChanged, this, &SimulatorMainWindow::setWindowTitle);
|
||||
}
|
||||
|
||||
connect(m_simulator, &SimulatorInterface::auxSerialSendData, hostSerialConnector, &HostSerialConnector::sendSerialData);
|
||||
connect(m_simulator, &SimulatorInterface::auxSerialSetEncoding, hostSerialConnector, &HostSerialConnector::setSerialEncoding);
|
||||
connect(m_simulator, &SimulatorInterface::auxSerialSetBaudrate, hostSerialConnector, &HostSerialConnector::setSerialBaudRate);
|
||||
connect(m_simulator, &SimulatorInterface::auxSerialStart, hostSerialConnector, &HostSerialConnector::serialStart);
|
||||
connect(m_simulator, &SimulatorInterface::auxSerialStop, hostSerialConnector, &HostSerialConnector::serialStop);
|
||||
}
|
||||
|
||||
SimulatorMainWindow::~SimulatorMainWindow()
|
||||
@@ -171,6 +181,8 @@ SimulatorMainWindow::~SimulatorMainWindow()
|
||||
}
|
||||
delete m_simulator;
|
||||
}
|
||||
|
||||
delete hostSerialConnector;
|
||||
SimulatorLoader::unloadSimulator(m_simulatorId);
|
||||
}
|
||||
|
||||
@@ -470,6 +482,16 @@ void SimulatorMainWindow::openJoystickDialog(bool)
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimulatorMainWindow::openSerialPortsDialog(bool)
|
||||
{
|
||||
SerialPortsDialog * dialog = new SerialPortsDialog(this, m_simulator, hostSerialConnector);
|
||||
if (dialog->exec() == QDialog::Accepted && m_simulator) {
|
||||
hostSerialConnector->connectSerialPort(0, dialog->aux1);
|
||||
hostSerialConnector->connectSerialPort(1, dialog->aux2);
|
||||
}
|
||||
dialog->deleteLater();
|
||||
}
|
||||
|
||||
void SimulatorMainWindow::showHelp(bool show)
|
||||
{
|
||||
QString helpText = ""
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "simulator.h"
|
||||
#include "hostserialconnector.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QFile>
|
||||
@@ -80,6 +81,7 @@ class SimulatorMainWindow : public QMainWindow
|
||||
void setRadioSizePolicy(int fixType);
|
||||
void toggleRadioDocked(bool dock);
|
||||
void openJoystickDialog(bool);
|
||||
void openSerialPortsDialog(bool);
|
||||
void showHelp(bool show);
|
||||
|
||||
protected:
|
||||
@@ -87,6 +89,7 @@ class SimulatorMainWindow : public QMainWindow
|
||||
void addTool(QDockWidget * widget, Qt::DockWidgetArea area, QIcon icon = QIcon(), QKeySequence shortcut = QKeySequence());
|
||||
|
||||
SimulatorInterface * m_simulator;
|
||||
HostSerialConnector * hostSerialConnector;
|
||||
|
||||
Ui::SimulatorMainWindow * ui;
|
||||
SimulatorWidget * m_simulatorWidget;
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
<addaction name="actionScreenshot"/>
|
||||
<addaction name="actionJoystickSettings"/>
|
||||
<addaction name="actionShowKeymap"/>
|
||||
<addaction name="actionSerialPorts"/>
|
||||
</widget>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuReload"/>
|
||||
@@ -216,6 +217,11 @@
|
||||
<string>Set radio widget height to be a fixed size.</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSerialPorts">
|
||||
<property name="text">
|
||||
<string>Serial Ports</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../companion.qrc"/>
|
||||
|
||||
@@ -74,6 +74,7 @@ class SimulatorWidget : public QWidget
|
||||
void setUiAreaStyle(const QString & style);
|
||||
void captureScreenshot(bool);
|
||||
void setupJoysticks();
|
||||
void setupSerialPorts(QSerialPort *aux1, QSerialPort *aux2);
|
||||
|
||||
QString getSdPath() const { return sdCardPath; }
|
||||
QString getDataPath() const { return radioDataPath; }
|
||||
|
||||
@@ -20,20 +20,8 @@ set(SIMU_DRIVERS
|
||||
bt_driver.cpp
|
||||
timers_driver.cpp
|
||||
abnormal_reboot.cpp
|
||||
rs232-linux.c
|
||||
)
|
||||
|
||||
option(SIMU_AUX "Allow the simulator to use the host's RS-232 port" OFF)
|
||||
set(SIMU_COM_PORT "2" CACHE STRING "Set COM port number to use")
|
||||
|
||||
if (SIMU_AUX)
|
||||
if(WIN32)
|
||||
set(SIMU_DRIVERS ${SIMU_DRIVERS} rs232-win.c)
|
||||
else()
|
||||
set(SIMU_DRIVERS ${SIMU_DRIVERS} rs232-linux.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(HW_DESC_JSON ${FLAVOUR}.json)
|
||||
AddHardwareDefTarget(${HW_DESC_JSON})
|
||||
AddHWGenTarget(${HW_DESC_JSON} simu_keys simu_keys.inc)
|
||||
@@ -112,7 +100,7 @@ if(Qt5Widgets_FOUND)
|
||||
|
||||
target_compile_options(${SIMULATOR_TARGET} PRIVATE ${SIMU_SRC_OPTIONS})
|
||||
target_compile_definitions(${SIMULATOR_TARGET} PUBLIC ${APP_COMMON_DEFINES})
|
||||
target_link_libraries(${SIMULATOR_TARGET} ${SDL2_LIBRARIES} Qt5::Core)
|
||||
target_link_libraries(${SIMULATOR_TARGET} ${SDL2_LIBRARIES} Qt5::Core Qt5::SerialPort)
|
||||
|
||||
# Remove debug symbols on release builds
|
||||
if(NOT CLANG)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "edgetx.h"
|
||||
#include "simulcd.h"
|
||||
#include "switches.h"
|
||||
#include "serial.h"
|
||||
|
||||
#include "hal/adc_driver.h"
|
||||
#include "hal/rotary_encoder.h"
|
||||
@@ -41,6 +42,16 @@
|
||||
int16_t g_anas[MAX_ANALOG_INPUTS];
|
||||
QVector<QIODevice *> OpenTxSimulator::tracebackDevices;
|
||||
|
||||
typedef struct {
|
||||
uint8_t index;
|
||||
QMutex mutex;
|
||||
QQueue<uint8_t> receiveBuffer;
|
||||
OpenTxSimulator * simulator;
|
||||
} simulated_serial_port_t;
|
||||
|
||||
simulated_serial_port_t simulatedSerialPorts[MAX_AUX_SERIAL];
|
||||
extern etx_serial_port_t * serialPorts[MAX_AUX_SERIAL];
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
tmr10ms_t downTime = 0;
|
||||
tmr10ms_t tapTime = 0;
|
||||
@@ -74,6 +85,94 @@ void firmwareTraceCb(const char * text)
|
||||
}
|
||||
}
|
||||
|
||||
// Serial port handling needs to know about OpenTxSimulator, so we we
|
||||
// need to update what's in simpgmspace.cpp when we have a simulator
|
||||
// to point at.
|
||||
|
||||
static void* simulator_host_drv_init(void* hw_def, const etx_serial_init* dev)
|
||||
{
|
||||
if (hw_def == nullptr)
|
||||
return nullptr;
|
||||
|
||||
simulated_serial_port_t *port = (simulated_serial_port_t *)hw_def;
|
||||
|
||||
port->simulator->drv_auxSerialInit(port->index, dev);
|
||||
|
||||
// Return the port definition as the context
|
||||
return (void *)port;
|
||||
}
|
||||
|
||||
static void simulator_host_drv_deinit(void* ctx)
|
||||
{
|
||||
if (ctx == nullptr)
|
||||
return;
|
||||
|
||||
simulated_serial_port_t *port = (simulated_serial_port_t *)ctx;
|
||||
port->simulator->drv_auxSerialDeinit(port->index);
|
||||
}
|
||||
|
||||
static void simulator_host_drv_send_byte(void* ctx, uint8_t b)
|
||||
{
|
||||
if (ctx == nullptr)
|
||||
return;
|
||||
|
||||
simulated_serial_port_t *port = (simulated_serial_port_t *)ctx;
|
||||
|
||||
port->simulator->drv_auxSerialSendByte(port->index, b);
|
||||
}
|
||||
|
||||
static void simulator_host_drv_send_buffer(void* ctx, const uint8_t* b, uint32_t l)
|
||||
{
|
||||
if (ctx == nullptr)
|
||||
return;
|
||||
|
||||
simulated_serial_port_t *port = (simulated_serial_port_t *)ctx;
|
||||
|
||||
port->simulator->drv_auxSerialSendBuffer(port->index, b, l);
|
||||
}
|
||||
|
||||
static int simulator_host_drv_get_byte(void* ctx, uint8_t* b)
|
||||
{
|
||||
if (ctx == nullptr)
|
||||
return 0;
|
||||
|
||||
simulated_serial_port_t *port = (simulated_serial_port_t *)ctx;
|
||||
|
||||
return port->simulator->drv_auxSerialGetByte(port->index, b);
|
||||
}
|
||||
|
||||
static void simulator_host_drv_set_baudrate(void* ctx, uint32_t baudrate)
|
||||
{
|
||||
if (ctx == nullptr)
|
||||
return;
|
||||
|
||||
simulated_serial_port_t *port = (simulated_serial_port_t *)ctx;
|
||||
port->simulator->drv_auxSerialSetBaudrate(port->index, baudrate);
|
||||
}
|
||||
|
||||
static const etx_serial_driver_t simulator_host_drv = {
|
||||
.init = simulator_host_drv_init,
|
||||
.deinit = simulator_host_drv_deinit,
|
||||
.sendByte = simulator_host_drv_send_byte,
|
||||
.sendBuffer = simulator_host_drv_send_buffer,
|
||||
.txCompleted = nullptr,
|
||||
.waitForTxCompleted = nullptr,
|
||||
.enableRx = nullptr,
|
||||
.getByte = simulator_host_drv_get_byte,
|
||||
.getLastByte = nullptr,
|
||||
.getBufferedBytes = nullptr,
|
||||
.copyRxBuffer = nullptr,
|
||||
.clearRxBuffer = nullptr,
|
||||
.getBaudrate = nullptr,
|
||||
.setBaudrate = simulator_host_drv_set_baudrate,
|
||||
.setPolarity = nullptr,
|
||||
.setHWOption = nullptr,
|
||||
.setReceiveCb = nullptr,
|
||||
.setIdleCb = nullptr,
|
||||
.setBaudrateCb = nullptr,
|
||||
};
|
||||
|
||||
|
||||
OpenTxSimulator::OpenTxSimulator() :
|
||||
SimulatorInterface(),
|
||||
m_timer10ms(nullptr),
|
||||
@@ -82,6 +181,17 @@ OpenTxSimulator::OpenTxSimulator() :
|
||||
{
|
||||
tracebackDevices.clear();
|
||||
traceCallback = firmwareTraceCb;
|
||||
|
||||
// When we create the simulator, we change the UART driver
|
||||
for (int i = 0; i < MAX_AUX_SERIAL; i++) {
|
||||
etx_serial_port_t * port = serialPorts[i];
|
||||
if (port != nullptr) {
|
||||
port->uart = &simulator_host_drv;
|
||||
port->hw_def = &(simulatedSerialPorts[i]);
|
||||
simulatedSerialPorts[i].index = i;
|
||||
simulatedSerialPorts[i].simulator = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpenTxSimulator::~OpenTxSimulator()
|
||||
@@ -89,6 +199,13 @@ OpenTxSimulator::~OpenTxSimulator()
|
||||
traceCallback = nullptr;
|
||||
tracebackDevices.clear();
|
||||
|
||||
for (int i = 0; i < MAX_AUX_SERIAL; i++) {
|
||||
etx_serial_port_t * port = serialPorts[i];
|
||||
if (port != nullptr) {
|
||||
port->hw_def = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_timer10ms)
|
||||
delete m_timer10ms;
|
||||
|
||||
@@ -507,6 +624,14 @@ const int OpenTxSimulator::getCapability(Capability cap)
|
||||
case CAP_TELEM_FRSKY_SPORT :
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case CAP_SERIAL_AUX1:
|
||||
ret = (auxSerialGetPort(SP_AUX1) != nullptr);
|
||||
break;
|
||||
|
||||
case CAP_SERIAL_AUX2:
|
||||
ret = (auxSerialGetPort(SP_AUX2) != nullptr);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -539,6 +664,74 @@ void OpenTxSimulator::removeTracebackDevice(QIODevice * device)
|
||||
}
|
||||
}
|
||||
|
||||
void OpenTxSimulator::receiveAuxSerialData(quint8 port_nr, const QByteArray & data)
|
||||
{
|
||||
if (port_nr >= MAX_AUX_SERIAL)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&(simulatedSerialPorts[port_nr].mutex));
|
||||
|
||||
for (uint8_t byte : data)
|
||||
simulatedSerialPorts[port_nr].receiveBuffer.enqueue(byte);
|
||||
}
|
||||
|
||||
void OpenTxSimulator::drv_auxSerialSetBaudrate(quint8 port_nr, quint32 baudrate)
|
||||
{
|
||||
emit auxSerialSetBaudrate(port_nr, baudrate);
|
||||
}
|
||||
|
||||
void OpenTxSimulator::drv_auxSerialInit(quint8 port_nr, const etx_serial_init* dev)
|
||||
{
|
||||
switch(dev->encoding) {
|
||||
case ETX_Encoding_8N1:
|
||||
emit auxSerialSetEncoding(port_nr, SERIAL_ENCODING_8N1);
|
||||
break;
|
||||
case ETX_Encoding_8E2:
|
||||
emit auxSerialSetEncoding(port_nr, SERIAL_ENCODING_8E2);
|
||||
break;
|
||||
default:
|
||||
// Do nothing, host hardware can't do SERIAL_ENCODING_PXX1_PWM
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->baudrate != 0)
|
||||
emit auxSerialSetBaudrate(port_nr, dev->baudrate);
|
||||
|
||||
emit auxSerialStart(port_nr);
|
||||
}
|
||||
|
||||
void OpenTxSimulator::drv_auxSerialDeinit(quint8 port_nr)
|
||||
{
|
||||
emit auxSerialStop(port_nr);
|
||||
}
|
||||
|
||||
void OpenTxSimulator::drv_auxSerialSendByte(quint8 port_nr, uint8_t b)
|
||||
{
|
||||
QByteArray data = QByteArray((const char *)&b, 1);
|
||||
|
||||
emit auxSerialSendData(port_nr, data);
|
||||
}
|
||||
|
||||
void OpenTxSimulator::drv_auxSerialSendBuffer(quint8 port_nr, const uint8_t* b, uint32_t l)
|
||||
{
|
||||
QByteArray data = QByteArray((const char *)b, l);
|
||||
|
||||
emit auxSerialSendData(port_nr, data);
|
||||
}
|
||||
|
||||
int OpenTxSimulator::drv_auxSerialGetByte(quint8 port_nr, uint8_t *b)
|
||||
{
|
||||
// Obtain the port's mutex before messing with the buffer
|
||||
QMutexLocker locker(&(simulatedSerialPorts[port_nr].mutex));
|
||||
|
||||
if (simulatedSerialPorts[port_nr].receiveBuffer.isEmpty())
|
||||
return 0;
|
||||
|
||||
uint8_t byte = simulatedSerialPorts[port_nr].receiveBuffer.dequeue();
|
||||
|
||||
*b = byte;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*** Protected functions ***/
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "simulatorinterface.h"
|
||||
#include "dataconstants.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
@@ -58,6 +59,13 @@ class DLLEXPORT OpenTxSimulator : public SimulatorInterface
|
||||
|
||||
static QVector<QIODevice *> tracebackDevices;
|
||||
|
||||
void drv_auxSerialInit(quint8 port_num, const etx_serial_init* dev);
|
||||
void drv_auxSerialDeinit(quint8 port_num);
|
||||
void drv_auxSerialSetBaudrate(quint8 port_num, uint32_t baudrate);
|
||||
void drv_auxSerialSendByte(quint8 port_num, uint8_t byte);
|
||||
void drv_auxSerialSendBuffer(quint8 port_num, const uint8_t* data, uint32_t size);
|
||||
int drv_auxSerialGetByte(quint8 port_num, uint8_t* data);
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void init();
|
||||
@@ -83,6 +91,7 @@ class DLLEXPORT OpenTxSimulator : public SimulatorInterface
|
||||
virtual void setLuaStateReloadPermanentScripts();
|
||||
virtual void addTracebackDevice(QIODevice * device);
|
||||
virtual void removeTracebackDevice(QIODevice * device);
|
||||
virtual void receiveAuxSerialData(const quint8 port_num, const QByteArray & data);
|
||||
|
||||
protected slots:
|
||||
void run();
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
/*
|
||||
Cross-platform serial / RS232 library
|
||||
Version 0.21, 11/10/2015
|
||||
-> LINUX and MacOS implementation
|
||||
-> rs232-linux.c
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 Frédéric Meslin, Florent Touchard
|
||||
Email: fredericmeslin@hotmail.com
|
||||
Website: www.fredslab.net
|
||||
Twitter: @marzacdev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#if defined(__unix__) || defined(__unix) || \
|
||||
defined(__APPLE__) && defined(__MACH__)
|
||||
|
||||
#define _DARWIN_C_SOURCE
|
||||
|
||||
#include "rs232.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#define __USE_MISC // For CRTSCTS
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#define __USE_SVID // For strdup
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Base name for COM devices */
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
static const char * devBases[] = {
|
||||
"tty."
|
||||
};
|
||||
static int noBases = 1;
|
||||
#else
|
||||
static const char * devBases[] = {
|
||||
"ttyACM", "ttyUSB", "rfcomm", "ttyS"
|
||||
};
|
||||
static int noBases = 4;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef struct {
|
||||
char * port;
|
||||
int handle;
|
||||
} COMDevice;
|
||||
|
||||
#define COM_MAXDEVICES 64
|
||||
static COMDevice comDevices[COM_MAXDEVICES];
|
||||
static int noDevices = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Private functions */
|
||||
void _AppendDevices(const char * base);
|
||||
int _BaudFlag(int BaudRate);
|
||||
|
||||
/*****************************************************************************/
|
||||
int comEnumerate()
|
||||
{
|
||||
for (int i = 0; i < noDevices; i++) {
|
||||
if (comDevices[i].port) free(comDevices[i].port);
|
||||
comDevices[i].port = NULL;
|
||||
}
|
||||
noDevices = 0;
|
||||
for (int i = 0; i < noBases; i++)
|
||||
_AppendDevices(devBases[i]);
|
||||
return noDevices;
|
||||
}
|
||||
|
||||
void comTerminate()
|
||||
{
|
||||
comCloseAll();
|
||||
for (int i = 0; i < noDevices; i++) {
|
||||
if (comDevices[i].port) free(comDevices[i].port);
|
||||
comDevices[i].port = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int comGetNoPorts()
|
||||
{
|
||||
return noDevices;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int comFindPort(const char * name)
|
||||
{
|
||||
int p;
|
||||
for (p = 0; p < noDevices; p++)
|
||||
if (strcmp(name, comDevices[p].port) == 0)
|
||||
return p;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char * comGetInternalName(int index)
|
||||
{
|
||||
#define COM_MAXNAME 128
|
||||
static char name[COM_MAXNAME];
|
||||
if (index >= noDevices || index < 0)
|
||||
return NULL;
|
||||
sprintf(name, "/dev/%s", comDevices[index].port);
|
||||
return name;
|
||||
}
|
||||
|
||||
const char * comGetPortName(int index) {
|
||||
if (index >= noDevices || index < 0)
|
||||
return NULL;
|
||||
return comDevices[index].port;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int comOpen(int index, int baudrate)
|
||||
{
|
||||
if (index >= noDevices || index < 0)
|
||||
return 0;
|
||||
// Close if already open
|
||||
COMDevice * com = &comDevices[index];
|
||||
if (com->handle >= 0) comClose(index);
|
||||
// Open port
|
||||
printf("Try %s \n", comGetInternalName(index));
|
||||
int handle = open(comGetInternalName(index), O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (handle < 0)
|
||||
return 0;
|
||||
printf("Open %s \n", comGetInternalName(index));
|
||||
// General configuration
|
||||
struct termios config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
tcgetattr(handle, &config);
|
||||
config.c_iflag &= ~(INLCR | ICRNL);
|
||||
config.c_iflag |= IGNPAR | IGNBRK;
|
||||
config.c_oflag &= ~(OPOST | ONLCR | OCRNL);
|
||||
config.c_cflag &= ~(PARENB | PARODD | CSTOPB | CSIZE | CRTSCTS);
|
||||
config.c_cflag |= CLOCAL | CREAD | CS8;
|
||||
config.c_lflag &= ~(ICANON | ISIG | ECHO);
|
||||
int flag = _BaudFlag(baudrate);
|
||||
cfsetospeed(&config, flag);
|
||||
cfsetispeed(&config, flag);
|
||||
// Timeouts configuration
|
||||
config.c_cc[VTIME] = 1;
|
||||
config.c_cc[VMIN] = 0;
|
||||
//fcntl(handle, F_SETFL, FNDELAY);
|
||||
// Validate configuration
|
||||
if (tcsetattr(handle, TCSANOW, &config) < 0) {
|
||||
close(handle);
|
||||
return 0;
|
||||
}
|
||||
com->handle = handle;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void comClose(int index)
|
||||
{
|
||||
if (index >= noDevices || index < 0)
|
||||
return;
|
||||
COMDevice * com = &comDevices[index];
|
||||
if (com->handle < 0)
|
||||
return;
|
||||
tcdrain(com->handle);
|
||||
close(com->handle);
|
||||
com->handle = -1;
|
||||
}
|
||||
|
||||
void comCloseAll()
|
||||
{
|
||||
for (int i = 0; i < noDevices; i++)
|
||||
comClose(i);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int comWrite(int index, const char * buffer, size_t len)
|
||||
{
|
||||
if (index >= noDevices || index < 0)
|
||||
return 0;
|
||||
if (comDevices[index].handle <= 0)
|
||||
return 0;
|
||||
int res = write(comDevices[index].handle, buffer, len);
|
||||
if (res < 0)
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
int comRead(int index, char * buffer, size_t len)
|
||||
{
|
||||
if (index >= noDevices || index < 0)
|
||||
return 0;
|
||||
if (comDevices[index].handle <= 0)
|
||||
return 0;
|
||||
int res = read(comDevices[index].handle, buffer, len);
|
||||
if (res < 0)
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int _BaudFlag(int BaudRate)
|
||||
{
|
||||
switch(BaudRate)
|
||||
{
|
||||
case 50: return B50; break;
|
||||
case 110: return B110; break;
|
||||
case 134: return B134; break;
|
||||
case 150: return B150; break;
|
||||
case 200: return B200; break;
|
||||
case 300: return B300; break;
|
||||
case 600: return B600; break;
|
||||
case 1200: return B1200; break;
|
||||
case 1800: return B1800; break;
|
||||
case 2400: return B2400; break;
|
||||
case 4800: return B4800; break;
|
||||
case 9600: return B9600; break;
|
||||
case 19200: return B19200; break;
|
||||
case 38400: return B38400; break;
|
||||
case 57600: return B57600; break;
|
||||
case 115200: return B115200; break;
|
||||
case 230400: return B230400; break;
|
||||
default : return B0; break;
|
||||
}
|
||||
}
|
||||
|
||||
void _AppendDevices(const char * base)
|
||||
{
|
||||
int baseLen = strlen(base);
|
||||
struct dirent * dp;
|
||||
// Enumerate devices
|
||||
DIR * dirp = opendir("/dev");
|
||||
while ((dp = readdir(dirp)) && noDevices < COM_MAXDEVICES) {
|
||||
if (strlen(dp->d_name) >= baseLen) {
|
||||
if (memcmp(base, dp->d_name, baseLen) == 0) {
|
||||
COMDevice * com = &comDevices[noDevices ++];
|
||||
com->port = (char *) strdup(dp->d_name);
|
||||
com->handle = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
#endif // unix
|
||||
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
Cross-platform serial / RS232 library
|
||||
Version 0.21, 11/10/2015
|
||||
-> WIN32 implementation
|
||||
-> rs232-win.c
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 Frédéric Meslin, Florent Touchard
|
||||
Email: fredericmeslin@hotmail.com
|
||||
Website: www.fredslab.net
|
||||
Twitter: @marzacdev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "rs232.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef int bool;
|
||||
#define true -1
|
||||
#define false 0
|
||||
|
||||
typedef struct {
|
||||
int port;
|
||||
void * handle;
|
||||
} COMDevice;
|
||||
|
||||
/*****************************************************************************/
|
||||
#define COM_MAXDEVICES 64
|
||||
static COMDevice comDevices[COM_MAXDEVICES];
|
||||
static int noDevices = 0;
|
||||
|
||||
#define COM_MINDEVNAME 16384
|
||||
const char * comPtn = "COM???";
|
||||
|
||||
/*****************************************************************************/
|
||||
const char * findPattern(const char * string, const char * pattern, int * value);
|
||||
const char * portInternalName(int index);
|
||||
|
||||
/*****************************************************************************/
|
||||
typedef struct _COMMTIMEOUTS {
|
||||
uint32_t ReadIntervalTimeout;
|
||||
uint32_t ReadTotalTimeoutMultiplier;
|
||||
uint32_t ReadTotalTimeoutConstant;
|
||||
uint32_t WriteTotalTimeoutMultiplier;
|
||||
uint32_t WriteTotalTimeoutConstant;
|
||||
} COMMTIMEOUTS;
|
||||
|
||||
typedef struct _DCB {
|
||||
uint32_t DCBlength;
|
||||
uint32_t BaudRate;
|
||||
uint32_t fBinary :1;
|
||||
uint32_t fParity :1;
|
||||
uint32_t fOutxCtsFlow :1;
|
||||
uint32_t fOutxDsrFlow :1;
|
||||
uint32_t fDtrControl :2;
|
||||
uint32_t fDsrSensitivity :1;
|
||||
uint32_t fTXContinueOnXoff :1;
|
||||
uint32_t fOutX :1;
|
||||
uint32_t fInX :1;
|
||||
uint32_t fErrorChar :1;
|
||||
uint32_t fNull :1;
|
||||
uint32_t fRtsControl :2;
|
||||
uint32_t fAbortOnError :1;
|
||||
uint32_t fDummy2 :17;
|
||||
uint16_t wReserved;
|
||||
uint16_t XonLim;
|
||||
uint16_t XoffLim;
|
||||
uint8_t ByteSize;
|
||||
uint8_t Parity;
|
||||
uint8_t StopBits;
|
||||
int8_t XonChar;
|
||||
int8_t XoffChar;
|
||||
int8_t ErrorChar;
|
||||
int8_t EofChar;
|
||||
int8_t EvtChar;
|
||||
uint16_t wReserved1;
|
||||
} DCB;
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Windows system constants */
|
||||
#define ERROR_INSUFFICIENT_BUFFER 122
|
||||
#define INVALID_HANDLE_VALUE ((void *) -1)
|
||||
#define GENERIC_READ 0x80000000
|
||||
#define GENERIC_WRITE 0x40000000
|
||||
#define OPEN_EXISTING 3
|
||||
#define MAX_DWORD 0xFFFFFFFF
|
||||
|
||||
/*****************************************************************************/
|
||||
/** Windows system functions */
|
||||
void * __stdcall CreateFileA(const char * lpFileName, uint32_t dwDesiredAccess, uint32_t dwShareMode, void * lpSecurityAttributes, uint32_t dwCreationDisposition, uint32_t dwFlagsAndAttributes, void * hTemplateFile);
|
||||
bool __stdcall WriteFile(void * hFile, const void * lpBuffer, uint32_t nNumberOfBytesToWrite, uint32_t * lpNumberOfBytesWritten, void * lpOverlapped);
|
||||
bool __stdcall ReadFile(void * hFile, void * lpBuffer, uint32_t nNumberOfBytesToRead, uint32_t * lpNumberOfBytesRead, void * lpOverlapped);
|
||||
bool __stdcall CloseHandle(void * hFile);
|
||||
|
||||
uint32_t __stdcall GetLastError(void);
|
||||
void __stdcall SetLastError(uint32_t dwErrCode);
|
||||
|
||||
uint32_t __stdcall QueryDosDeviceA(const char * lpDeviceName, char * lpTargetPath, uint32_t ucchMax);
|
||||
|
||||
bool __stdcall GetCommState(void * hFile, DCB * lpDCB);
|
||||
bool __stdcall GetCommTimeouts(void * hFile, COMMTIMEOUTS * lpCommTimeouts);
|
||||
bool __stdcall SetCommState(void * hFile, DCB * lpDCB);
|
||||
bool __stdcall SetCommTimeouts(void * hFile, COMMTIMEOUTS * lpCommTimeouts);
|
||||
bool __stdcall SetupComm(void * hFile, uint32_t dwInQueue, uint32_t dwOutQueue);
|
||||
|
||||
/*****************************************************************************/
|
||||
int comEnumerate()
|
||||
{
|
||||
// Get devices information text
|
||||
size_t size = COM_MINDEVNAME;
|
||||
char * list = (char *) malloc(size);
|
||||
SetLastError(0);
|
||||
QueryDosDeviceA(NULL, list, size);
|
||||
while (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
size *= 2;
|
||||
char * nlist = realloc(list, size);
|
||||
if (!nlist) {
|
||||
free(list);
|
||||
return 0;
|
||||
}
|
||||
list = nlist;
|
||||
SetLastError(0);
|
||||
QueryDosDeviceA(NULL, list, size);
|
||||
}
|
||||
// Gather all COM ports
|
||||
int port;
|
||||
const char * nlist = findPattern(list, comPtn, &port);
|
||||
noDevices = 0;
|
||||
while(port > 0 && noDevices < COM_MAXDEVICES) {
|
||||
COMDevice * com = &comDevices[noDevices ++];
|
||||
com->port = port;
|
||||
com->handle = 0;
|
||||
nlist = findPattern(nlist, comPtn, &port);
|
||||
}
|
||||
free(list);
|
||||
return noDevices;
|
||||
}
|
||||
|
||||
void comTerminate()
|
||||
{
|
||||
comCloseAll();
|
||||
}
|
||||
|
||||
int comGetNoPorts()
|
||||
{
|
||||
return noDevices;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
const char * comGetPortName(int index)
|
||||
{
|
||||
#define COM_MAXNAME 32
|
||||
static char name[COM_MAXNAME];
|
||||
if (index < 0 || index >= noDevices)
|
||||
return 0;
|
||||
sprintf(name, "COM%i", comDevices[index].port);
|
||||
return name;
|
||||
}
|
||||
|
||||
int comFindPort(const char * name)
|
||||
{
|
||||
for (int i = 0; i < noDevices; i++)
|
||||
if (strcmp(name, comGetPortName(i)) == 0)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char * comGetInternalName(int index)
|
||||
{
|
||||
#define COM_MAXNAME 32
|
||||
static char name[COM_MAXNAME];
|
||||
if (index < 0 || index >= noDevices)
|
||||
return 0;
|
||||
sprintf(name, "//./COM%i", comDevices[index].port);
|
||||
return name;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int comOpen(int index, int baudrate)
|
||||
{
|
||||
DCB config;
|
||||
COMMTIMEOUTS timeouts;
|
||||
if (index < 0 || index >= noDevices)
|
||||
return 0;
|
||||
// Close if already open
|
||||
COMDevice * com = &comDevices[index];
|
||||
if (com->handle) comClose(index);
|
||||
// Open COM port
|
||||
void * handle = CreateFileA(comGetInternalName(index), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
com->handle = handle;
|
||||
// Prepare read / write timeouts
|
||||
SetupComm(handle, 64, 64);
|
||||
timeouts.ReadIntervalTimeout = MAX_DWORD;
|
||||
timeouts.ReadTotalTimeoutConstant = 0;
|
||||
timeouts.WriteTotalTimeoutConstant = 0;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
SetCommTimeouts(handle, &timeouts);
|
||||
// Prepare serial communication format
|
||||
GetCommState(handle, &config);
|
||||
config.BaudRate = baudrate;
|
||||
config.fBinary = true;
|
||||
config.fParity = 0;
|
||||
config.fErrorChar = 0;
|
||||
config.fNull = 0;
|
||||
config.fAbortOnError = 0;
|
||||
config.ByteSize = 8;
|
||||
config.Parity = 0;
|
||||
config.StopBits = 0;
|
||||
config.EvtChar = '\n';
|
||||
// Set the port state
|
||||
if (SetCommState(handle, &config) == 0) {
|
||||
CloseHandle(handle);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void comClose(int index)
|
||||
{
|
||||
if (index < 0 || index >= noDevices)
|
||||
return;
|
||||
COMDevice * com = &comDevices[index];
|
||||
if (!com->handle)
|
||||
return;
|
||||
CloseHandle(com->handle);
|
||||
com->handle = 0;
|
||||
}
|
||||
|
||||
void comCloseAll()
|
||||
{
|
||||
for (int i = 0; i < noDevices; i++)
|
||||
comClose(i);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int comWrite(int index, const char * buffer, size_t len)
|
||||
{
|
||||
if (index < 0 || index >= noDevices)
|
||||
return 0;
|
||||
COMDevice * com = &comDevices[index];
|
||||
uint32_t bytes = 0;
|
||||
WriteFile(com->handle, buffer, len, &bytes, NULL);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int comRead(int index, char * buffer, size_t len)
|
||||
{
|
||||
if (index < 0 || index >= noDevices)
|
||||
return 0;
|
||||
COMDevice * com = &comDevices[index];
|
||||
uint32_t bytes = 0;
|
||||
ReadFile(com->handle, buffer, len, &bytes, NULL);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
const char * findPattern(const char * string, const char * pattern, int * value)
|
||||
{
|
||||
char c, n = 0;
|
||||
const char * sp = string;
|
||||
const char * pp = pattern;
|
||||
// Check for the string pattern
|
||||
while (1) {
|
||||
c = *sp ++;
|
||||
if (c == '\0') {
|
||||
if (*pp == '?') break;
|
||||
if (*sp == '\0') break;
|
||||
n = 0;
|
||||
pp = pattern;
|
||||
}else{
|
||||
if (*pp == '?') {
|
||||
// Expect a digit
|
||||
if (c >= '0' && c <= '9') {
|
||||
n = n * 10 + (c - '0');
|
||||
if (*pp ++ == '\0') break;
|
||||
}else{
|
||||
n = 0;
|
||||
pp = comPtn;
|
||||
}
|
||||
}else{
|
||||
// Expect a character
|
||||
if (c == *pp) {
|
||||
if (*pp ++ == '\0') break;
|
||||
}else{
|
||||
n = 0;
|
||||
pp = comPtn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the value
|
||||
* value = n;
|
||||
return sp;
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
Cross-platform serial / RS232 library
|
||||
Version 0.21, 11/10/2015
|
||||
-> All platforms header
|
||||
-> rs232.h
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 Frédéric Meslin, Florent Touchard
|
||||
Email: fredericmeslin@hotmail.com
|
||||
Website: www.fredslab.net
|
||||
Twitter: @marzacdev
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Doxywizard specific */
|
||||
/**
|
||||
* \mainpage RS232
|
||||
* \section intro_sec C / C++ RS232 cross-platform serial library
|
||||
* <b>Version 0.21 - 11/10/2015</b>
|
||||
*
|
||||
* Supported platforms:
|
||||
* - Windows (XP / Win7, possibly 8 and 10)
|
||||
* - Linux
|
||||
* - MacOS X
|
||||
*
|
||||
* Copyright (c) 2013-2015 Frédéric Meslin, Florent Touchard <br>
|
||||
* Email: fredericmeslin@hotmail.com <br>
|
||||
* Website: www.fredslab.net <br>
|
||||
* Twitter: \@marzacdev <br>
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* \fn int comEnumerate()
|
||||
* \brief Enumerate available serial ports (Serial, USB serial, Bluetooth serial)
|
||||
* \return number of enumerated ports
|
||||
*/
|
||||
int comEnumerate();
|
||||
|
||||
/**
|
||||
* \fn int comGetNoPorts()
|
||||
* \brief Return the number of enumerated ports
|
||||
* \return number of enumerated ports
|
||||
*/
|
||||
int comGetNoPorts();
|
||||
|
||||
/**
|
||||
* \fn int comTerminate()
|
||||
* \brief Release ports and memory resources used by the library
|
||||
*/
|
||||
void comTerminate();
|
||||
|
||||
/**
|
||||
* \fn const char * comGetPortName(int index)
|
||||
* \brief Get port user-friendly name
|
||||
* \param[in] index port index
|
||||
* \return null terminated port name
|
||||
*/
|
||||
const char * comGetPortName(int index);
|
||||
|
||||
/**
|
||||
* \fn const char * comGetInternalName(int index)
|
||||
* \brief Get port operating-system name
|
||||
* \param[in] index port index
|
||||
* \return null terminated port name
|
||||
*/
|
||||
const char * comGetInternalName(int index);
|
||||
|
||||
/**
|
||||
* \fn int comFindPort(const char * name)
|
||||
* \brief Try to find a port given its user-friendly name
|
||||
* \param[in] name port name (case sensitive)
|
||||
* \return index of found port or -1 if not enumerated
|
||||
*/
|
||||
int comFindPort(const char * name);
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* \fn int comOpen(int index, int baudrate)
|
||||
* \brief Try to open a port at a specific baudrate
|
||||
* \brief (No parity, single stop bit, no hardware flow control)
|
||||
* \param[in] index port index
|
||||
* \param[in] baudrate port baudrate
|
||||
* \return 1 if opened, 0 if not available
|
||||
*/
|
||||
int comOpen(int index, int baudrate);
|
||||
|
||||
/**
|
||||
* \fn void comClose(int index)
|
||||
* \brief Close an opened port
|
||||
* \param[in] index port index
|
||||
*/
|
||||
void comClose(int index);
|
||||
|
||||
/**
|
||||
* \fn void comCloseAll()
|
||||
* \brief Close all opened ports
|
||||
*/
|
||||
void comCloseAll();
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* \fn int comWrite(int index, const char * buffer, size_t len)
|
||||
* \brief Write data to the port (non-blocking)
|
||||
* \param[in] index port index
|
||||
* \param[in] buffer pointer to transmit buffer
|
||||
* \param[in] len length of transmit buffer in bytes
|
||||
* \return number of bytes transferred
|
||||
*/
|
||||
int comWrite(int index, const char * buffer, size_t len);
|
||||
|
||||
/**
|
||||
* \fn int comRead(int index, const char * buffer, size_t len)
|
||||
* \brief Read data from the port (non-blocking)
|
||||
* \param[in] index port index
|
||||
* \param[in] buffer pointer to receive buffer
|
||||
* \param[in] len length of receive buffer in bytes
|
||||
* \return number of bytes transferred
|
||||
*/
|
||||
int comRead(int index, char * buffer, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -36,9 +36,6 @@
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
#ifdef SIMU_COM_PORT
|
||||
#include "rs232.h"
|
||||
#endif
|
||||
|
||||
#if !defined (_MSC_VER) || defined (__GNUC__)
|
||||
#include <chrono>
|
||||
@@ -601,78 +598,47 @@ const etx_serial_port_t UsbSerialPort = { "USB-VCP", nullptr, nullptr };
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
|
||||
static void* _fake_drv_init(void* n, const etx_serial_init* dev) {
|
||||
#ifdef SIMU_COM_PORT
|
||||
static bool init = false;
|
||||
if (!init) {
|
||||
comEnumerate();
|
||||
init=true;
|
||||
}
|
||||
comOpen(SIMU_COM_PORT, dev->baudrate);
|
||||
#endif
|
||||
return (void*)1;
|
||||
}
|
||||
static void _fake_drv_fct1(void*) {
|
||||
#ifdef SIMU_COM_PORT
|
||||
comClose(SIMU_COM_PORT);
|
||||
#endif
|
||||
}
|
||||
static void _fake_drv_send_byte(void*, uint8_t b) {
|
||||
#ifdef SIMU_COM_PORT
|
||||
comWrite(SIMU_COM_PORT, (char*)&b, 1);
|
||||
#endif
|
||||
}
|
||||
static void _fake_drv_send_buffer(void*, const uint8_t* b, uint32_t l) {
|
||||
#ifdef SIMU_COM_PORT
|
||||
comWrite(SIMU_COM_PORT, (char*)b, l);
|
||||
#endif
|
||||
}
|
||||
static int _fake_drv_get_byte(void*, uint8_t* b) {
|
||||
#ifdef SIMU_COM_PORT
|
||||
return comRead(SIMU_COM_PORT, (char*)b, 1);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
static void _fake_drv_set_baudrate(void*, uint32_t baudrate) {
|
||||
#ifdef SIMU_COM_PORT
|
||||
comClose(SIMU_COM_PORT);
|
||||
comOpen(SIMU_COM_PORT, baudrate);
|
||||
#endif
|
||||
}
|
||||
static const etx_serial_driver_t _fake_drv = {
|
||||
.init = _fake_drv_init,
|
||||
.deinit = _fake_drv_fct1,
|
||||
.sendByte = _fake_drv_send_byte,
|
||||
.sendBuffer = _fake_drv_send_buffer,
|
||||
static void* null_drv_init(void* hw_def, const etx_serial_init* dev) { return nullptr; }
|
||||
static void null_drv_deinit(void* ctx) { }
|
||||
static void null_drv_send_byte(void* ctx, uint8_t b) { }
|
||||
static void null_drv_send_buffer(void* ctx, const uint8_t* b, uint32_t l) { }
|
||||
static int null_drv_get_byte(void* ctx, uint8_t* b) { return 0; }
|
||||
static void null_drv_set_baudrate(void* ctx, uint32_t baudrate) { }
|
||||
|
||||
const etx_serial_driver_t null_drv = {
|
||||
.init = null_drv_init,
|
||||
.deinit = null_drv_deinit,
|
||||
.sendByte = null_drv_send_byte,
|
||||
.sendBuffer = null_drv_send_buffer,
|
||||
.txCompleted = nullptr,
|
||||
.waitForTxCompleted = nullptr,
|
||||
.enableRx = nullptr,
|
||||
.getByte = _fake_drv_get_byte,
|
||||
.getByte = null_drv_get_byte,
|
||||
.getLastByte = nullptr,
|
||||
.getBufferedBytes = nullptr,
|
||||
.copyRxBuffer = nullptr,
|
||||
.clearRxBuffer = nullptr,
|
||||
.getBaudrate = nullptr,
|
||||
.setBaudrate = _fake_drv_set_baudrate,
|
||||
.setBaudrate = null_drv_set_baudrate,
|
||||
.setPolarity = nullptr,
|
||||
.setHWOption = nullptr,
|
||||
.setReceiveCb = nullptr,
|
||||
.setIdleCb = nullptr,
|
||||
.setBaudrateCb = nullptr,
|
||||
};
|
||||
|
||||
static void null_pwr_aux(uint8_t) {}
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
#if defined(AUX_SERIAL_PWR_GPIO)
|
||||
static void _fake_pwr_aux(uint8_t) {}
|
||||
#define AUX_SERIAL_PWR _fake_pwr_aux
|
||||
#define AUX_SERIAL_PWR null_pwr_aux
|
||||
#else
|
||||
#define AUX_SERIAL_PWR nullptr
|
||||
#endif
|
||||
static const etx_serial_port_t auxSerialPort = {
|
||||
static etx_serial_port_t auxSerialPort = {
|
||||
"AUX1",
|
||||
&_fake_drv,
|
||||
&null_drv,
|
||||
nullptr,
|
||||
AUX_SERIAL_PWR
|
||||
};
|
||||
@@ -683,14 +649,13 @@ static const etx_serial_port_t auxSerialPort = {
|
||||
|
||||
#if defined(AUX2_SERIAL)
|
||||
#if defined(AUX_SERIAL_PWR_GPIO)
|
||||
static void _fake_pwr_aux2(uint8_t) {}
|
||||
#define AUX2_SERIAL_PWR _fake_pwr_aux2
|
||||
#define AUX2_SERIAL_PWR null_pwr_aux
|
||||
#else
|
||||
#define AUX2_SERIAL_PWR nullptr
|
||||
#endif
|
||||
static const etx_serial_port_t aux2SerialPort = {
|
||||
static etx_serial_port_t aux2SerialPort = {
|
||||
"AUX2",
|
||||
&_fake_drv,
|
||||
&null_drv,
|
||||
nullptr,
|
||||
AUX2_SERIAL_PWR
|
||||
};
|
||||
@@ -699,7 +664,7 @@ static const etx_serial_port_t aux2SerialPort = {
|
||||
#define AUX2_SERIAL_PORT nullptr
|
||||
#endif // AUX2_SERIAL
|
||||
|
||||
static const etx_serial_port_t* serialPorts[MAX_AUX_SERIAL] = {
|
||||
etx_serial_port_t* serialPorts[MAX_AUX_SERIAL] = {
|
||||
AUX_SERIAL_PORT,
|
||||
AUX2_SERIAL_PORT,
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ if [[ $PAUSEAFTEREACHLINE == "true" ]]; then
|
||||
fi
|
||||
|
||||
echo "=== Step $((STEP++)): Installing packages ==="
|
||||
sudo apt-get -y install build-essential cmake gcc git lib32ncurses-dev lib32z1 libfox-1.6-dev libsdl2-dev qt5-default qtmultimedia5-dev qttools5-dev qttools5-dev-tools qtcreator libqt5svg5-dev software-properties-common wget zip python-pip-whl python-pil libgtest-dev python3-pip python3-tk python3-setuptools clang-7 python-clang-7 libusb-1.0-0-dev stlink-tools openocd npm pv libncurses5:i386 libpython2.7:i386 libclang-6.0-dev python-is-python3
|
||||
sudo apt-get -y install build-essential cmake gcc git lib32ncurses-dev lib32z1 libfox-1.6-dev libsdl2-dev qt5-default qtmultimedia5-dev qttools5-dev qttools5-dev-tools qtcreator libqt5svg5-dev libqt5serialport5-dev software-properties-common wget zip python-pip-whl python-pil libgtest-dev python3-pip python3-tk python3-setuptools clang-7 python-clang-7 libusb-1.0-0-dev stlink-tools openocd npm pv libncurses5:i386 libpython2.7:i386 libclang-6.0-dev python-is-python3
|
||||
if [[ $PAUSEAFTEREACHLINE == "true" ]]; then
|
||||
echo "Step finished. Please check the output above and press Enter to continue or Ctrl+C to stop."
|
||||
read
|
||||
|
||||
@@ -42,7 +42,7 @@ if [[ $PAUSEAFTEREACHLINE == "true" ]]; then
|
||||
fi
|
||||
|
||||
echo "=== Step $((STEP++)): Installing packages ==="
|
||||
sudo apt-get -y install build-essential cmake gcc git lib32ncurses-dev lib32z1 libfox-1.6-dev libsdl2-dev qtbase5-dev qt5-qmake qtmultimedia5-dev qttools5-dev qttools5-dev-tools qtcreator libqt5svg5-dev software-properties-common wget zip python3-pip-whl python3-pil libgtest-dev python3-pip python3-tk python3-setuptools clang python3-clang libusb-1.0-0-dev stlink-tools openocd npm pv libncurses5:i386 libpython2.7:i386 libclang-dev python-is-python3
|
||||
sudo apt-get -y install build-essential cmake gcc git lib32ncurses-dev lib32z1 libfox-1.6-dev libsdl2-dev qtbase5-dev qt5-qmake qtmultimedia5-dev qttools5-dev qttools5-dev-tools qtcreator libqt5svg5-dev libqt5serialport5-dev software-properties-common wget zip python3-pip-whl python3-pil libgtest-dev python3-pip python3-tk python3-setuptools clang python3-clang libusb-1.0-0-dev stlink-tools openocd npm pv libncurses5:i386 libpython2.7:i386 libclang-dev python-is-python3
|
||||
if [[ $PAUSEAFTEREACHLINE == "true" ]]; then
|
||||
echo "Step finished. Please check the output above and press Enter to continue or Ctrl+C to stop."
|
||||
read
|
||||
|
||||
Reference in New Issue
Block a user