#pragma once #include #include "ble/ByteBuffer.h" #include "ble/misc.h" namespace trygvis { namespace bluetooth { using ::trygvis::compiler::variant; using ::trygvis::compiler::monostate; /** * BLUETOOTH SPECIFICATION Version 4.0 [Vol 3] - Attribute Protocol (ATT) - 3.4.8 Attribute Opcode Summary * Table 3.37 */ enum AttPduType { ERROR = 0x01, EXCHANGE_MTU_REQ = 0x02, EXCHANGE_MTU_RES = 0x03, FIND_INFORMATION_REQ = 0x04, FIND_INFORMATION_RES = 0x05, FIND_BY_TYPE_VALUE_REQ = 0x06, FIND_BY_TYPE_VALUE_RES = 0x07, READ_BY_TYPE_REQ = 0x08, READ_BY_TYPE_RES = 0x09, READ_REQ = 0x0a, READ_RES = 0x0b, READ_BLOB_REQ = 0x0c, READ_BLOB_RES = 0x0d, READ_MULTIPLE_REQ = 0x0e, READ_MULTIPLE_RES = 0x0f, READ_BY_GROUP_TYPE_REQ = 0x10, READ_BY_GROUP_TYPE_RES = 0x11, WRITE_REQ = 0x12, WRITE_RES = 0x13, WRITE_CMD = 0x52, PREPARE_WRITE_REQ = 0x16, PREPARE_WRITE_RES = 0x17, EXECUTE_WRITE_REQ = 0x18, EXECUTE_WRITE_RES = 0x19, HANDLE_VALUE_NOTIFICATION = 0x1b, HANDLE_VALUE_INDICATION = 0x1d, HANDLE_VALUE_CONFIRMATION = 0x1e, SIGNED_WRITE_COMMAND = 0xd2, }; std::string to_string(AttPduType t); class AttributeData; class InformationData; /** * Application Error 0x80 – 0xFF Application error code defined by a higher layer specification. * * BLUETOOTH SPECIFICATION Version 4.0 [Vol 3] - 3.4.1.1 Error Response - Table 3.3 */ enum ErrorCode : uint8_t { INVALID_HANDLE = 0x01, ///< The attribute handle given was not valid on this server. READ_NOT_PERMITTED = 0x02,///< The attribute cannot be read. WRITE_NOT_PERMITTED = 0x03,///< The attribute cannot be written. INVALID_PDU = 0x04, /// information; }; struct ReadByGroupTypeRes { static constexpr auto att_pdu_type = AttPduType::READ_BY_GROUP_TYPE_RES; std::vector attributes; }; struct ReadByTypeRes { static constexpr auto att_pdu_type = AttPduType::READ_BY_TYPE_RES; std::vector attributes; }; struct HandleValueNotification { static constexpr auto att_pdu_type = AttPduType::HANDLE_VALUE_NOTIFICATION; uint16_t handle; ByteBuffer data; }; struct HandleValueIndication { static constexpr auto att_pdu_type = AttPduType::HANDLE_VALUE_INDICATION; uint16_t handle; ByteBuffer data; }; using AttVariant = variant; o attPduType(const AttVariant &v); class AttPdu { public: explicit AttPdu(ByteBuffer &bytes); AttPdu(ByteBuffer &bytes, AttPduType type); AttPduType getType(); static AttVariant parse(ByteBuffer &bytes); static ExchangeMtuReq parseExchangeMtuReq(ByteBuffer &bytes); static ExchangeMtuRes parseExchangeMtuRes(ByteBuffer &bytes); static FindInformationRes parseFindInformationRes(ByteBuffer &bytes); static HandleValueNotification parseHandleValueNotification(ByteBuffer &bytes); static HandleValueIndication parseHandleValueIndication(ByteBuffer &bytes); static void parseRead(ByteBuffer &bytes); static void parseWrite(ByteBuffer &bytes); static void makeExchangeMtuRes(ByteBuffer &bytes, uint16_t serverRxMtu); static void makeFindInformationReq(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle); static void makeReadByGroupType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, ShortUuid uuid); static void makeReadByType(ByteBuffer &bytes, uint16_t startHandle, uint16_t endHandle, ShortUuid uuid); static void makeRead(ByteBuffer &bytes, uint16_t handle); static void makeWrite(ByteBuffer &req, uint16_t handle, const ByteBuffer &bytes); private: // static void checkType(ByteBuffer &bytes, AttPduType type); static std::vector parseAttributeData(ByteBuffer &bytes); ByteBuffer &bytes; }; class AttributeData { public: ~AttributeData(); static AttributeData fromByteBuffer(ByteBuffer &value); const uint16_t handle; ByteBuffer value; private: AttributeData(uint16_t handle, ByteBuffer value, std::shared_ptr raw); std::shared_ptr raw; }; class InformationData { public: static constexpr uint8_t FORMAT_SHORT_UUID = 0x01; static constexpr uint8_t FORMAT_LONG_UUID = 0x02; ~InformationData() = default; static InformationData fromByteBufferShortUuid(ByteBuffer &value); static InformationData fromByteBufferLongUuid(ByteBuffer &value); const uint16_t handle; const Uuid uuid; private: InformationData(uint16_t handle, const Uuid &uuid); }; } // namespace bluetooth } // namespace trygvis