From d8d8fc7a0d139e7b864eee3b573bd208f823ad4f Mon Sep 17 00:00:00 2001 From: Javier Date: Sun, 19 Oct 2014 18:45:03 +0200 Subject: initial import, no crypto --- saprotocol.h | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 saprotocol.h (limited to 'saprotocol.h') diff --git a/saprotocol.h b/saprotocol.h new file mode 100644 index 0000000..469a293 --- /dev/null +++ b/saprotocol.h @@ -0,0 +1,195 @@ +#ifndef SAPROTOCOL_H +#define SAPROTOCOL_H + +#include + +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) +#include +QT_USE_NAMESPACE_BLUETOOTH +#else +#include +QTM_USE_NAMESPACE +#endif + +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; + 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); + + 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); + + // TODO service conn termination request. probably trivial. + + 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