summaryrefslogtreecommitdiff
path: root/sap/saprotocol.h
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2016-01-01 22:05:42 +0100
committerJavier <dev.git@javispedro.com>2016-01-01 22:05:42 +0100
commita45977185a485624095bff1a15024e9199eee676 (patch)
tree6cc57d085bdd01e493477c870dbe0548137998e1 /sap/saprotocol.h
parenta24034bdfea259cdc09c74217be75d4f9de0dce5 (diff)
downloadsapd-a45977185a485624095bff1a15024e9199eee676.tar.gz
sapd-a45977185a485624095bff1a15024e9199eee676.zip
reorganize source files into SAP and agents
Diffstat (limited to 'sap/saprotocol.h')
-rw-r--r--sap/saprotocol.h246
1 files changed, 246 insertions, 0 deletions
diff --git a/sap/saprotocol.h b/sap/saprotocol.h
new file mode 100644
index 0000000..68434c1
--- /dev/null
+++ b/sap/saprotocol.h
@@ -0,0 +1,246 @@
+#ifndef SAPROTOCOL_H
+#define SAPROTOCOL_H
+
+#include <QtCore/QObject>
+#include <QtBluetooth/QBluetoothUuid>
+
+class SAProtocol
+{
+ Q_GADGET
+ Q_ENUMS(Role FrameType ControlFrameType)
+
+public:
+ static const QBluetoothUuid dataServiceUuid;
+ static const QBluetoothUuid nudgeServiceUuid;
+
+ enum Role {
+ ClientRole,
+ ServerRole
+ };
+
+ static const quint8 currentProtocolVersion = 0;
+
+ static const quint16 defaultSessionId = 0x3FF;
+ static const quint16 maxSessionId = 0x3FF;
+
+ static quint16 computeCrc16(const QByteArray &buf);
+
+ static const char peerDescriptionSeparator = ';';
+
+ /** One of the early connection setup messages. Seems to describe each
+ * other's capabilities and network settings to the remote peer. */
+ struct PeerDescription {
+ /** No idea: either 5 or 6. Wild guess: 5 is request, 6 is response. */
+ quint8 messageType;
+ quint16 accessoryProtocolVersion;
+ quint16 accessorySoftwareVersion;
+ /** Status code. 0 generally means "no error". */
+ quint8 status;
+ quint8 errorCode; /**< Used when status != 0 and messageType == 6 */
+
+ /* Seemingly network parameters, but I am not sure how the other end
+ * actually handles them. Seem to do nothing. */
+ quint32 APDUSize;
+ quint16 SSDUSize;
+ quint16 sessions; /**< Seemingly maximum number of sessions allowed. */
+ quint16 timeout; /**< Looks like a timeout, but no idea what for. */
+
+ /* No idea. */
+ quint8 unk_1;
+ quint16 unk_2;
+ quint8 unk_3;
+
+ /* No one cares about the ones below. Seemingly free-form text. */
+ QString product;
+ QString manufacturer;
+ QString name;
+ QString profile;
+ };
+
+ static PeerDescription unpackPeerDescription(const QByteArray &data);
+ static QByteArray packPeerDescription(const PeerDescription &desc);
+
+ enum SecurityFrameType {
+ SecurityAuthenticateRequest = 0x10,
+ SecurityAuthenticateResponse = 0x11,
+ SecurityAuthenticateConfirm = 0x12
+ };
+
+ struct SecurityFrame {
+ SecurityFrameType type;
+ quint8 authType; // ???
+ quint8 version; // Always 0 so far.
+ quint8 dataType; // ???
+ QByteArray data;
+ };
+
+ static SecurityFrame unpackSecurityFrame(const QByteArray &data);
+ static QByteArray packSecurityFrame(const SecurityFrame &sframe);
+
+ enum FrameType {
+ FrameData = 0,
+ FrameControl = 1
+ };
+
+ struct Frame {
+ quint8 protocolVersion; // Always 0 so far.
+ FrameType type;
+ quint16 sessionId;
+ QByteArray data;
+ };
+
+ static Frame unpackFrame(const QByteArray &data);
+ static QByteArray packFrame(const Frame& frame);
+ static QByteArray packFrame(quint16 sessionId, const QByteArray &data, FrameType type = FrameData);
+
+ enum FragmentStatus {
+ FragmentNone = 0,
+ FragmentMiddle = 1,
+ FragmentLast = 3
+ };
+
+ struct DataFrame {
+ bool withSeqNum; // (not actually present in frame)
+ // The following field is only present if "withSeqNum":
+ quint16 seqNum; // Monotonically increasing
+ bool withFragStatus; // (not actually present in frame)
+ FragmentStatus fragStatus;
+ QByteArray data;
+ };
+
+ static DataFrame unpackDataFrame(const QByteArray &data, bool withSeqNum, bool withFragStatus);
+ static QByteArray packDataFrame(const DataFrame& frame);
+
+ enum ControlFrameType {
+ ControlFrameImmediateAck = 0,
+ ControlFrameBlockAck = 1,
+ ControlFrameNak = 2
+ };
+
+ typedef QPair<quint16, quint16> SeqNumRange;
+
+ struct ControlFrame {
+ ControlFrameType type;
+ QList<SeqNumRange> seqNums; // Used for Naks only
+ quint16 seqNum;
+ };
+
+ static ControlFrame unpackControlFrame(const QByteArray &data);
+ static QByteArray packControlFrame(const ControlFrame& frame);
+
+ /* Default session messages */
+
+ enum DefaultSessionMessageType {
+ ServiceConnectionRequest = 1,
+ ServiceConnectionResponse = 2,
+ ServiceTerminationRequest = 3,
+ ServiceTerminationResponse = 4
+ };
+
+ /** The following settings map 1:1 to contents in service.xml files (thank god).
+ * That does not mean I understand what they do, specially the QoS part. */
+
+ struct ServiceConnectionRequestSession {
+ quint16 sessionId;
+ quint16 channelId;
+ quint8 qosType;
+ quint8 qosDataRate;
+ quint8 qosPriority;
+ quint8 payloadType;
+ };
+
+ struct ServiceConnectionRequestFrame {
+ quint8 messageType;
+ quint16 acceptorId;
+ quint16 initiatorId;
+ QString profile;
+ QList<ServiceConnectionRequestSession> sessions;
+ };
+
+ static ServiceConnectionRequestFrame unpackServiceConnectionRequestFrame(const QByteArray &data);
+ static QByteArray packServiceConnectionRequestFrame(const ServiceConnectionRequestFrame &frame);
+
+ struct ServiceConnectionResponseFrame {
+ quint8 messageType;
+ quint16 acceptorId;
+ quint16 initiatorId;
+ QString profile;
+ quint8 statusCode;
+ QList<quint16> sessions;
+ };
+
+ static ServiceConnectionResponseFrame unpackServiceConnectionResponseFrame(const QByteArray &data);
+ static QByteArray packServiceConnectionResponseFrame(const ServiceConnectionResponseFrame &frame);
+
+ struct ServiceTerminationRequestFrame {
+ quint8 messageType;
+ quint16 acceptorId;
+ quint16 initiatorId;
+ QString profile;
+ };
+
+ static ServiceTerminationRequestFrame unpackServiceTerminationRequestFrame(const QByteArray &data);
+ static QByteArray packServiceTerminationRequestFrame(const ServiceTerminationRequestFrame &frame);
+
+ struct ServiceTerminationResponseFrame {
+ quint8 messageType;
+ quint16 acceptorId;
+ quint16 initiatorId;
+ QString profile;
+ quint8 statusCode;
+ };
+
+ static ServiceTerminationResponseFrame unpackServiceTerminationResponseFrame(const QByteArray &data);
+ static QByteArray packServiceTerminationResponseFrame(const ServiceTerminationResponseFrame &frame);
+
+ /* Capability discovery messages */
+
+ static const QLatin1String capabilityDiscoveryProfile;
+ static const quint16 capabilityDiscoveryChannel = 255;
+ static const quint16 capabilityDiscoveryAgentId = 0xFFFF;
+
+ enum CapabilityDiscoveryMessageType {
+ CapabilityDiscoveryMessageTypeQuery = 1,
+ CapabilityDiscoveryMessageTypeResponse = 2
+ };
+
+ struct CapabilityDiscoveryQuery {
+ CapabilityDiscoveryMessageType messageType;
+ quint8 queryType;
+ quint32 checksum;
+ QList<QString> records;
+ };
+
+ static CapabilityDiscoveryQuery unpackCapabilityDiscoveryQuery(const QByteArray &data);
+ static QByteArray packCapabilityDiscoveryQuery(const CapabilityDiscoveryQuery &msg);
+
+ struct CapabilityDiscoveryService {
+ quint16 componentId;
+ quint16 aspVersion;
+ quint8 role;
+ quint16 connTimeout;
+ QString profile;
+ };
+
+ struct CapabilityDiscoveryProvider {
+ quint16 uuid;
+ QString name;
+ QList<CapabilityDiscoveryService> services;
+ };
+
+ struct CapabilityDiscoveryResponse {
+ CapabilityDiscoveryMessageType messageType;
+ quint8 queryType;
+ quint32 checksum;
+ QList<CapabilityDiscoveryProvider> providers;
+ };
+
+ static CapabilityDiscoveryResponse unpackCapabilityDiscoveryResponse(const QByteArray &data);
+ static QByteArray packCapabilityDiscoveryResponse(const CapabilityDiscoveryResponse &msg);
+
+private:
+ Q_DISABLE_COPY(SAProtocol)
+ SAProtocol();
+};
+
+#endif // SAPROTOCOL_H