aboutsummaryrefslogtreecommitdiff
path: root/include/ble/att.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ble/att.h')
-rw-r--r--include/ble/att.h186
1 files changed, 186 insertions, 0 deletions
diff --git a/include/ble/att.h b/include/ble/att.h
new file mode 100644
index 0000000..3c7914f
--- /dev/null
+++ b/include/ble/att.h
@@ -0,0 +1,186 @@
+#pragma once
+
+#include <experimental/optional>
+#include <variant>
+#include <vector>
+
+#include "ble/ByteBuffer.h"
+#include "ble/misc.h"
+
+namespace trygvis {
+namespace bluetooth {
+
+template<typename T>
+using o = std::experimental::optional<T>;
+
+/**
+ * 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;
+
+/**
+ * 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, ///<The attribute PDU was invalid.
+ INSUFFICIENT_AUTHENTICATION = 0x05, ///<The attribute requires authentication before it can be read or written.
+ REQUEST_NOT_SUPPORTED = 0x06, ///<Attribute server does not support the request received from the client.
+ INVALID_OFFSET = 0x07, ///<Offset specified was past the end of the attribute.
+ INSUFFICIENT_AUTHORIZATION = 0x08, ///<The attribute requires authorization before it can be read or written.
+ PREPARE_QUEUE_FULL = 0x09, ///<Too many prepare writes have been queued.
+ ATTRIBUTE_NOT_FOUND = 0x0a, ///<No attribute found within the given attribute handle range.
+ ATTRIBUTE_NOT_LONG = 0x0b, ///<The attribute cannot be read or written using the Read Blob Request
+ INSUFFICIENT_ENCRYPTION_KEY_SIZE = 0x0c, ///<The Encryption Key Size used for encrypting this link is insufficient.
+ INVALID_ATTRIBUTE_VALUE_LENGTH = 0x0d, ///<The attribute value length is invalid for the operation
+ UNLIKELY_ERROR = 0x0e, ///<The attribute request that was requested has encountered an error that was unlikely, and therefore could not be completed as requested.
+ INSUFFICIENT_ENCRYPTION = 0x0f, ///<The attribute requires encryption before it can be read or written.
+ UNSUPPORTED_GROUP_TYPE = 0x10, ///<The attribute type is not a supported grouping attribute as defined by a higher layer specification.
+ INSUFFICIENT_RESOURCES = 0x11, ///<Insufficient Resources to complete the request Reserved 0x012 – 0x7F Reserved for future use.
+};
+
+struct ErrorRes {
+ static constexpr auto att_pdu_type = AttPduType::EXCHANGE_MTU_REQ;
+
+ /**
+ * The request that generated this error response.
+ */
+ uint8_t requestOpcode;
+
+ /**
+ * The attribute handle that generated this error response.
+ */
+ uint16_t attributeHandle;
+
+ /**
+ * The reason why the request has generated an error response.
+ */
+ uint8_t errorCode;
+
+ static ErrorRes parse(ByteBuffer& buffer) {
+ return {buffer.read8(), buffer.read16le(), buffer.read8()};
+ }
+};
+
+struct ExchangeMtuReq {
+ static constexpr auto att_pdu_type = AttPduType::EXCHANGE_MTU_REQ;
+
+ uint16_t clientRxMtu;
+};
+
+struct ExchangeMtuRes {
+ static constexpr auto att_pdu_type = AttPduType::EXCHANGE_MTU_RES;
+
+ uint16_t serverRxMtu;
+};
+
+struct ReadByGroupTypeRes {
+ static constexpr auto att_pdu_type = AttPduType::READ_BY_GROUP_TYPE_RES;
+
+ std::vector<AttributeData> attributes;
+};
+
+struct ReadByTypeRes {
+ static constexpr auto att_pdu_type = AttPduType::READ_BY_TYPE_RES;
+
+ std::vector<AttributeData> attributes;
+};
+
+using AttVariant = std::variant<std::monostate,
+ ErrorRes,
+ ExchangeMtuReq, ExchangeMtuRes,
+ ReadByGroupTypeRes, ReadByTypeRes>;
+
+o<AttPduType> 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 void parseRead(ByteBuffer &bytes);
+
+ static void parseWrite(ByteBuffer &bytes);
+
+ static void makeExchangeMtuRes(ByteBuffer &bytes, uint16_t serverRxMtu);
+
+ 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<AttributeData> 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<uint8_t[]> raw);
+
+ std::shared_ptr<uint8_t[]> raw;
+};
+
+} // namespace bluetooth
+} // namespace trygvis