From a45977185a485624095bff1a15024e9199eee676 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 1 Jan 2016 22:05:42 +0100 Subject: reorganize source files into SAP and agents --- sap/saprotocol.h | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 sap/saprotocol.h (limited to 'sap/saprotocol.h') 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 +#include + +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 SeqNumRange; + + struct ControlFrame { + ControlFrameType type; + QList 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 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 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 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 services; + }; + + struct CapabilityDiscoveryResponse { + CapabilityDiscoveryMessageType messageType; + quint8 queryType; + quint32 checksum; + QList providers; + }; + + static CapabilityDiscoveryResponse unpackCapabilityDiscoveryResponse(const QByteArray &data); + static QByteArray packCapabilityDiscoveryResponse(const CapabilityDiscoveryResponse &msg); + +private: + Q_DISABLE_COPY(SAProtocol) + SAProtocol(); +}; + +#endif // SAPROTOCOL_H -- cgit v1.2.3