-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented basic RTXLink for OpenRTX devices. Addresses #251.
- Loading branch information
1 parent
87838df
commit f9c66f3
Showing
8 changed files
with
337 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
#include "openrtx_link.hh" | ||
|
||
|
||
/* ******************************************************************************************** * | ||
* Implements the OpenRTX link stream socket | ||
* ******************************************************************************************** */ | ||
OpenRTXLinkStream::OpenRTXLinkStream(OpenRTXLink::Protocol proto, OpenRTXLink *link) | ||
: QIODevice(link), _proto(proto), _inBuffer(), _link(link) | ||
{ | ||
// pass... | ||
} | ||
|
||
qint64 | ||
OpenRTXLinkStream::writeData(const char *data, qint64 len) { | ||
QByteArray buffer(data, len); | ||
|
||
ErrorStack err; | ||
if (! _link->send(OpenRTXLink::Protocol::Stdio, buffer, -1, err)) { | ||
setErrorString(err.format()); | ||
return -1; | ||
} | ||
|
||
return len; | ||
} | ||
|
||
qint64 | ||
OpenRTXLinkStream::readData(char *data, qint64 maxlen) { | ||
ErrorStack err; | ||
qint64 n_read = 0, n_toread=maxlen; | ||
|
||
while (0 < n_toread) { | ||
if (_inBuffer.size()) { | ||
qint64 n = std::min((qint64)_inBuffer.size(), n_toread); | ||
memcpy(data, _inBuffer.data(), n); | ||
_inBuffer.remove(0, n); | ||
n_toread -= n; data+= n; n_read += n; | ||
} | ||
if (0 == n_toread) | ||
return n_read; | ||
if (! _link->receive(OpenRTXLink::Protocol::Stdio, _inBuffer, -1, err)) { | ||
setErrorString(err.format()); | ||
return -1; | ||
} | ||
} | ||
|
||
return n_read; | ||
} | ||
|
||
|
||
|
||
/* ******************************************************************************************** * | ||
* Implements the OpenRTX link datagram socket | ||
* ******************************************************************************************** */ | ||
OpenRTXLinkDatagram::OpenRTXLinkDatagram(OpenRTXLink::Protocol proto, OpenRTXLink *link) | ||
: PacketStream(link), _proto(proto), _link(link) | ||
{ | ||
// pass... | ||
} | ||
|
||
bool | ||
OpenRTXLinkDatagram::receive(QByteArray &buffer, int timeout, const ErrorStack &err) { | ||
return _link->receive(_proto, buffer, timeout, err); | ||
} | ||
|
||
bool | ||
OpenRTXLinkDatagram::send(const QByteArray &buffer, int timeout, const ErrorStack &err) { | ||
return _link->send(_proto, buffer, timeout, err); | ||
} | ||
|
||
|
||
/* ******************************************************************************************** * | ||
* Implements the OpenRTX CAT interface | ||
* ******************************************************************************************** */ | ||
OpenRTXCAT::OpenRTXCAT(OpenRTXLink *link) | ||
: OpenRTXLinkDatagram(OpenRTXLink::Protocol::CAT, link) | ||
{ | ||
// pass... | ||
} | ||
|
||
|
||
/* ******************************************************************************************** * | ||
* Implements the OpenRTX link protocol dispatcher | ||
* ******************************************************************************************** */ | ||
OpenRTXLink::OpenRTXLink(PacketStream *link, QObject *parent) | ||
: QObject{parent}, _link(link), | ||
_stdio(new OpenRTXLinkStream(Protocol::Stdio, this)), | ||
_cat(new OpenRTXCAT(this)), | ||
_fmp(new OpenRTXLinkDatagram(Protocol::FMP, this)), | ||
_xmodem(new OpenRTXLinkStream(Protocol::XMODEM, this)) | ||
{ | ||
// pass... | ||
} | ||
|
||
OpenRTXLinkStream * | ||
OpenRTXLink::stdio() const { | ||
return _stdio; | ||
} | ||
|
||
OpenRTXCAT *OpenRTXLink::cat() const { | ||
return _cat; | ||
} | ||
|
||
OpenRTXLinkDatagram * | ||
OpenRTXLink::fmp() const { | ||
return _fmp; | ||
} | ||
|
||
OpenRTXLinkStream * | ||
OpenRTXLink::xmodem() const { | ||
return _xmodem; | ||
} | ||
|
||
uint8_t | ||
OpenRTXLink::crc8(const QByteArray &data) { | ||
constexpr uint8_t poly = 0xA6; | ||
uint8_t crc = 0; | ||
for (int i=0; i<data.size(); i++) { | ||
crc ^= data[i]; | ||
for (int j=0; j<8; j++) { | ||
if (crc & 0x80) | ||
crc = ( (crc<<1) ^ poly ); | ||
else | ||
crc <<= 1; | ||
} | ||
} | ||
return crc; | ||
} | ||
|
||
bool | ||
OpenRTXLink::send(Protocol proto, const QByteArray &data, int timeout, const ErrorStack &err) { | ||
QByteArray packet; packet.reserve(data.size()+2); | ||
packet.append((char)proto); | ||
packet.append(data); | ||
packet.append(crc8(packet)); | ||
return this->_link->send(packet, timeout, err); | ||
} | ||
|
||
bool | ||
OpenRTXLink::receive(Protocol proto, QByteArray &data, int timeout, const ErrorStack &err) { | ||
QByteArray buffer; | ||
while (true) { | ||
// Receive a datagram | ||
if (! this->_link->receive(buffer, timeout, err)) | ||
return false; | ||
|
||
// Check CRC | ||
if (0 != crc8(buffer)) { | ||
errMsg(err) << "Invalid CRC in RTXLink packet."; | ||
return false; | ||
} | ||
|
||
// Dispatch by type | ||
Protocol rxProto = (Protocol)buffer.at(0); | ||
// If requested type matches -> done | ||
if (proto == rxProto) { | ||
data = buffer.mid(1, buffer.size()-2); | ||
return true; | ||
} | ||
|
||
// Otherwise, store and receive next | ||
if (! _inBuffers.contains((unsigned int)rxProto)) | ||
_inBuffers.insert((unsigned int)rxProto, QList<QByteArray>()); | ||
_inBuffers[(unsigned int)rxProto].append(buffer.mid(1,buffer.size()-2)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
#ifndef OPENRTXLINK_HH | ||
#define OPENRTXLINK_HH | ||
|
||
#include <QObject> | ||
|
||
#include "packetstream.hh" | ||
|
||
// Forward declaration | ||
class OpenRTXLink; | ||
class OpenRTXLinkStream; | ||
class OpenRTXLinkDatagram; | ||
class OpenRTXCAT; | ||
|
||
|
||
/** Implements the OpenRTX link protocol. This is a datagram-oriented protocol, that dispatches | ||
* several different protocols to talk to the radio. It provides a stream, to the stdio of the | ||
* radio, a CAT interface, a file-system management protocol (FMP) as well as XMODEM to transfer | ||
* files. The file transfer must be initialized via the FMP. | ||
* | ||
* All these protocols are exposed through specialized interface objects, accessible through this | ||
* classs. | ||
* | ||
* @code | ||
* +------------------+-------------------+-------------------+------------------+ | ||
* | stdio | CAT | FMP | XMODEM | | ||
* +------------------+-------------------+-------------------+------------------+ | ||
* | OpenRTXLink | | ||
* +-----------------------------------------------------------------------------+ | ||
* | SLIP (SlipStream) | | ||
* +-----------------------------------------------------------------------------+ | ||
* | USB CDC-ACM (VCOM/Serial-over-USB, USBSerial) | | ||
* +-----------------------------------------------------------------------------+ | ||
* @endcode | ||
* @ingroup ortx */ | ||
class OpenRTXLink: public QObject | ||
{ | ||
Q_OBJECT | ||
|
||
protected: | ||
/** The possible protocols, encapsulated in OpenRTX link. */ | ||
enum class Protocol { | ||
Stdio = 0, CAT = 1, FMP = 2, XMODEM = 3 | ||
}; | ||
|
||
public: | ||
/** Constructor. | ||
* @param link Specifies the datagram socket to talk to the radio (SLIP). | ||
* @param parent Specifies the QObject parent. */ | ||
explicit OpenRTXLink(PacketStream *link, QObject *parent = nullptr); | ||
|
||
/** Returns a stream to the stdio of the radio. Implements the @c QIODevice interface. */ | ||
OpenRTXLinkStream *stdio() const; | ||
/** The CAT interface to the radio. */ | ||
OpenRTXCAT *cat() const; | ||
/** The file-system management protocol interface to the radio. */ | ||
OpenRTXLinkDatagram *fmp() const; | ||
/** An XMODEM channel to transfer files. */ | ||
OpenRTXLinkStream *xmodem() const; | ||
|
||
protected: | ||
/** Dispatcher to receive datagrams over OpenRTXLink. */ | ||
bool receive(Protocol proto, QByteArray &data, int timeout=-1, const ErrorStack &err=ErrorStack()); | ||
/** Dispatcher to send datagrams over OpenRTXLink. */ | ||
bool send(Protocol proto, const QByteArray &data, int timeout=-1, const ErrorStack &err=ErrorStack()); | ||
|
||
static uint8_t crc8(const QByteArray &data); | ||
|
||
protected: | ||
PacketStream *_link; | ||
QHash<unsigned int, QList<QByteArray>> _inBuffers; | ||
OpenRTXLinkStream *_stdio; | ||
OpenRTXCAT *_cat; | ||
OpenRTXLinkDatagram *_fmp; | ||
OpenRTXLinkStream *_xmodem; | ||
|
||
friend class OpenRTXLinkStream; | ||
friend class OpenRTXLinkDatagram; | ||
friend class OpenRTXCAT; | ||
}; | ||
|
||
|
||
class OpenRTXLinkStream: public QIODevice | ||
{ | ||
Q_OBJECT | ||
|
||
protected: | ||
OpenRTXLinkStream(OpenRTXLink::Protocol proto, OpenRTXLink *link); | ||
|
||
protected: | ||
qint64 writeData(const char *data, qint64 len); | ||
qint64 readData(char *data, qint64 maxlen); | ||
|
||
protected: | ||
OpenRTXLink::Protocol _proto; | ||
QByteArray _inBuffer; | ||
OpenRTXLink *_link; | ||
|
||
friend class OpenRTXLink; | ||
}; | ||
|
||
|
||
class OpenRTXLinkDatagram: public PacketStream | ||
{ | ||
Q_OBJECT | ||
|
||
protected: | ||
OpenRTXLinkDatagram(OpenRTXLink::Protocol proto, OpenRTXLink *link); | ||
|
||
public: | ||
bool receive(QByteArray &buffer, int timeout, const ErrorStack &err); | ||
bool send(const QByteArray &buffer, int timeout, const ErrorStack &err); | ||
|
||
protected: | ||
OpenRTXLink::Protocol _proto; | ||
OpenRTXLink *_link; | ||
|
||
friend class OpenRTXLink; | ||
}; | ||
|
||
|
||
class OpenRTXCAT: public OpenRTXLinkDatagram | ||
{ | ||
Q_OBJECT | ||
|
||
protected: | ||
/** Hidden constrcutor. An instance of this class can be obtained from @c OpenRTXLink. | ||
* @param link Specifies the unerlying RTX-link to the the device. */ | ||
explicit OpenRTXCAT(OpenRTXLink *link); | ||
|
||
friend class OpenRTXLink; | ||
}; | ||
|
||
#endif // OPENRTXLINK_HH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,4 +53,6 @@ private: | |
static const char ESCAPED_DB = '\xDD'; | ||
}; | ||
|
||
|
||
|
||
#endif // PACKETSTREAM_HH |
Oops, something went wrong.