/*! @file * @brief Generic Attribute Profile handling. */ /* * Copyright (c) 2015 Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2) Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3) Neither the name of Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __BT_GATT_H #define __BT_GATT_H #include /* GATT attribute permission bitfield values */ /*! @def BT_GATT_PERM_READ * @brief Attribute read permission. */ #define BT_GATT_PERM_READ 0x01 /*! @def BT_GATT_PERM_WRITE * @brief Attribute write permission. */ #define BT_GATT_PERM_WRITE 0x02 /*! @def BT_GATT_PERM_READ_ENCRYPT * @brief Attribute read permission with encryption. * * If set, requires encryption for read access. */ #define BT_GATT_PERM_READ_ENCRYPT 0x04 /*! @def BT_GATT_PERM_WRITE_ENCRYPT * @brief Attribute write permission with encryption. * * If set, requires encryption for write access. */ #define BT_GATT_PERM_WRITE_ENCRYPT 0x08 /*! @def BT_GATT_PERM_READ_AUTHEN * @brief Attribute read permission with authentication. * * If set, requires encryption using authenticated link-key for read access. */ #define BT_GATT_PERM_READ_AUTHEN 0x10 /*! @def BT_GATT_PERM_WRITE_AUTHEN * @brief Attribute write permission with authentication. * * If set, requires encryption using authenticated link-key for write access. */ #define BT_GATT_PERM_WRITE_AUTHEN 0x20 /*! @def BT_GATT_PERM_AUTHOR * @brief Attribute authorization permission. */ #define BT_GATT_PERM_AUTHOR 0x40 /* GATT attribute flush flags */ /*! @def BT_GATT_FLUSH_DISCARD * @brief Attribute flush discard flag. */ #define BT_GATT_FLUSH_DISCARD 0x00 /*! @def BT_GATT_FLUSH_DISCARD * @brief Attribute flush syncronize flag. */ #define BT_GATT_FLUSH_SYNC 0x01 /*! @brief GATT Attribute structure. */ struct bt_gatt_attr { /*! Attribute handle */ uint16_t handle; /*! Attribute UUID */ const struct bt_uuid *uuid; /*! Attribute permissions */ uint8_t perm; /*! Attribute read callback */ int (*read)(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, void *buf, uint8_t len, uint16_t offset); /*! Attribute write callback */ int (*write)(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, const void *buf, uint8_t len, uint16_t offset); /*! Attribute flush callback */ int (*flush)(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, uint8_t flags); /*! Attribute user data */ void *user_data; }; /*! @brief Service Attribute Value. */ struct bt_gatt_service { /*! Service UUID. */ const struct bt_uuid *uuid; }; /*! @brief Include Attribute Value. */ struct bt_gatt_include { /*! Service start handle. */ uint16_t start_handle; /*! Service end handle. */ uint16_t end_handle; /*! Service UUID. */ const struct bt_uuid *uuid; }; /* Characteristic Properties Bitfield values */ /*! @def BT_GATT_CHRC_BROADCAST * @brief Characteristic broadcast property. * * If set, permits broadcasts of the Characteristic Value using Server * Characteristic Configuration Descriptor. */ #define BT_GATT_CHRC_BROADCAST 0x01 /*! @def BT_GATT_CHRC_READ * @brief Characteristic read property. * * If set, permits reads of the Characteristic Value. */ #define BT_GATT_CHRC_READ 0x02 /*! @def BT_GATT_CHRC_WRITE_WITHOUT_RESP * @brief Characteristic write without response property. * * If set, permits write of the Characteristic Value without response. */ #define BT_GATT_CHRC_WRITE_WITHOUT_RESP 0x04 /*! @def BT_GATT_CHRC_WRITE * @brief Characteristic write with response property. * * If set, permits write of the Characteristic Value with response. */ #define BT_GATT_CHRC_WRITE 0x08 /*! @def BT_GATT_CHRC_NOTIFY * @brief Characteristic notify property. * * If set, permits notifications of a Characteristic Value without * acknowledgement. */ #define BT_GATT_CHRC_NOTIFY 0x10 /*! @def BT_GATT_CHRC_INDICATE * @brief Characteristic indicate property. * * If set, permits indications of a Characteristic Value with acknowledgement. */ #define BT_GATT_CHRC_INDICATE 0x20 /*! @def BT_GATT_CHRC_AUTH * @brief Characteristic Authenticated Signed Writes property. * * If set, permits signed writes to the Characteristic Value. */ #define BT_GATT_CHRC_AUTH 0x40 /*! @def BT_GATT_CHRC_EXT_PROP * @brief Characteristic Extended Properties property. * * If set, additional characteristic properties are defined in the * Characteristic Extended Properties Descriptor. */ #define BT_GATT_CHRC_EXT_PROP 0x80 /*! @brief Characteristic Attribute Value. */ struct bt_gatt_chrc { /*! Characteristic properties. */ uint8_t properties; /*! Characteristic value handle. */ uint16_t value_handle; /*! Characteristic UUID. */ const struct bt_uuid *uuid; }; /* Characteristic Extended Properties Bitfield values */ #define BT_GATT_CEP_RELIABLE_WRITE 0x0001 #define BT_GATT_CEP_WRITABLE_AUX 0x0002 /*! @brief Characteristic Extended Properties Attribute Value. */ struct bt_gatt_cep { /*! Characteristic Extended properties */ uint16_t properties; }; /*! @brief Characteristic User Description Attribute Value. */ struct bt_gatt_cud { /*! Characteristic User Description string. */ char *string; }; /* Client Characteristic Configuration Values */ /*! @def BT_GATT_CCC_NOTIFY * @brief Client Characteristic Configuration Notification. * * If set, changes to Characteristic Value shall be notified. */ #define BT_GATT_CCC_NOTIFY 0x0001 /*! @def BT_GATT_CCC_INDICATE * @brief Client Characteristic Configuration Indication. * * If set, changes to Characteristic Value shall be indicated. */ #define BT_GATT_CCC_INDICATE 0x0002 /* Client Characteristic Configuration Attribute Value */ struct bt_gatt_ccc { /*! Client Characteristic Configuration flags */ uint16_t flags; }; /* Server API */ /*! @brief Register attribute database. * * Register GATT attribute database table. Applications can make use of * macros such as BT_GATT_PRIMARY_SERVICE, BT_GATT_CHARACTERISTIC, * BT_GATT_DESCRIPTOR, etc. * * @param attrs Database table containing the available attributes. * @param count Size of the database table. */ void bt_gatt_register(const struct bt_gatt_attr *attrs, size_t count); enum { BT_GATT_ITER_STOP = 0, BT_GATT_ITER_CONTINUE, }; /*! @brief Attribute iterator callback. * * @param attr Attribute found. * @param user_data Data given. * * @return BT_GATT_ITER_CONTINUE if should continue to the next attribute * or BT_GATT_ITER_STOP to stop. */ typedef uint8_t (*bt_gatt_attr_func_t)(const struct bt_gatt_attr *attr, void *user_data); /*! @brief Attribute iterator. * * Iterate attributes in the given range. * * @param start_handle Start handle. * @param end_handle End handle. * @param func Callback function. * @param user_data Data to pass to the callback. */ void bt_gatt_foreach_attr(uint16_t start_handle, uint16_t end_handle, bt_gatt_attr_func_t func, void *user_data); /*! @brief Generic Read Attribute value helper. * * Read attribute value storing the result into buffer. * * @param peer Remote address. * @param attr Attribute to read. * @param buf Buffer to store the value. * @param buf_len Buffer length. * @param offset Start offset. * @param value Attribute value. * @param value_len Length of the attribute value. * * @return int number of bytes read in case of success or negative values in * case of error. */ int bt_gatt_attr_read(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, void *buf, uint8_t buf_len, uint16_t offset, const void *value, uint8_t value_len); /*! @brief Read Service Attribute helper. * * Read service attribute value storing the result into buffer after * enconding it. * NOTE: Only use this with attributes which user_data is a bt_uuid. * * @param peer Remote address. * @param attr Attribute to read. * @param buf Buffer to store the value read. * @param len Buffer length. * @param offset Start offset. * * @return int number of bytes read in case of success or negative values in * case of error. */ int bt_gatt_attr_read_service(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, void *buf, uint8_t len, uint16_t offset); /*! @def BT_GATT_SERVICE * @brief Generic Service Declaration Macro. * * Helper macro to declare a service attribute. * * @param _handle Service attribute handle. * @param _uuid Service attribute type. * @param _data Service attribute value. */ #define BT_GATT_SERVICE(_handle, _uuid, _service) \ { \ .handle = _handle, \ .uuid = _uuid, \ .perm = BT_GATT_PERM_READ, \ .read = bt_gatt_attr_read_service, \ .user_data = _service, \ } /*! @def BT_GATT_PRIMARY_SERVICE * @brief Primary Service Declaration Macro. * * Helper macro to declare a primary service attribute. * * @param _handle Service attribute handle. * @param _service Service attribute value. */ #define BT_GATT_PRIMARY_SERVICE(_handle, _service) \ { \ .handle = _handle, \ .uuid = (&(struct bt_uuid) { .type = BT_UUID_16, \ .u16 = BT_UUID_GATT_PRIMARY }), \ .perm = BT_GATT_PERM_READ, \ .read = bt_gatt_attr_read_service, \ .user_data = _service, \ } /*! @def BT_GATT_SECONDARY_SERVICE * @brief Secondary Service Declaration Macro. * * Helper macro to declare a secondary service attribute. * * @param _handle Service attribute handle. * @param _service Service attribute value. */ #define BT_GATT_SECONDARY_SERVICE(_handle, _service) \ { \ .handle = _handle, \ .uuid = (&(struct bt_uuid) { .type = BT_UUID_16, \ .u16 = BT_UUID_GATT_SECONDARY }), \ .perm = BT_GATT_PERM_READ, \ .read = bt_gatt_attr_read_service, \ .user_data = _service, \ } /*! @brief Read Include Attribute helper. * * Read include service attribute value storing the result into buffer after * enconding it. * NOTE: Only use this with attributes which user_data is a bt_gatt_include. * * @param peer Remote address. * @param attr Attribute to read. * @param buf Buffer to store the value read. * @param len Buffer length. * @param offset Start offset. * * @return int number of bytes read in case of success or negative values in * case of error. */ int bt_gatt_attr_read_included(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, void *buf, uint8_t len, uint16_t offset); /*! @def BT_GATT_INCLUDE_SERVICE * @brief Include Service Declaration Macro. * * Helper macro to declare a include service attribute. * * @param _handle Service attribute handle. * @param _service Service attribute value. */ #define BT_GATT_INCLUDE_SERVICE(_handle, _service) \ { \ .handle = _handle, \ .uuid = (&(struct bt_uuid) { .type = BT_UUID_16, \ .u16 = BT_UUID_GATT_INCLUDE }), \ .perm = BT_GATT_PERM_READ, \ .read = bt_gatt_attr_read_included, \ .user_data = _service, \ } /*! @brief Read Characteristic Attribute helper. * * Read characteristic attribute value storing the result into buffer after * enconding it. * NOTE: Only use this with attributes which user_data is a bt_gatt_chrc. * * @param peer Remote address. * @param attr Attribute to read. * @param buf Buffer to store the value read. * @param len Buffer length. * @param offset Start offset. * * @return number of bytes read in case of success or negative values in * case of error. */ int bt_gatt_attr_read_chrc(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, void *buf, uint8_t len, uint16_t offset); /*! @def BT_GATT_CHARACTERISTIC * @brief Characteristic Declaration Macro. * * Helper macro to declare a characteristic attribute. * * @param _handle Characteristic attribute handle. * @param _value Characteristic attribute value. */ #define BT_GATT_CHARACTERISTIC(_handle, _value) \ { \ .handle = _handle, \ .uuid = (&(struct bt_uuid) { .type = BT_UUID_16, \ .u16 = BT_UUID_GATT_CHRC }), \ .perm = BT_GATT_PERM_READ, \ .read = bt_gatt_attr_read_chrc, \ .user_data = _value, \ } /*! @brief GATT CCC configuration entry. */ struct bt_gatt_ccc_cfg { /*! Config peer address. */ bt_addr_le_t peer; /*! Config peer value. */ uint16_t value; /*! Config valid flag. */ uint8_t valid; }; /* Internal representation of CCC value */ struct _bt_gatt_ccc { struct bt_gatt_ccc_cfg *cfg; size_t cfg_len; uint16_t value; uint16_t value_handle; void (*cfg_changed)(uint16_t value); }; /*! @brief Read Client Characteristic Configuration Attribute helper. * * Read CCC attribute value storing the result into buffer after * enconding it. * NOTE: Only use this with attributes which user_data is a _bt_gatt_ccc. * * @param peer Remote address. * @param attr Attribute to read. * @param buf Buffer to store the value read. * @param len Buffer length. * @param offset Start offset. * * @return number of bytes read in case of success or negative values in * case of error. */ int bt_gatt_attr_read_ccc(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, void *buf, uint8_t len, uint16_t offset); /*! @brief Write Client Characteristic Configuration Attribute helper. * * Write value in the buffer into CCC attribute. * NOTE: Only use this with attributes which user_data is a _bt_gatt_ccc. * * @param peer Remote address. * @param attr Attribute to read. * @param buf Buffer to store the value read. * @param len Buffer length. * @param offset Start offset. * * @return number of bytes written in case of success or negative values in * case of error. */ int bt_gatt_attr_write_ccc(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, const void *buf, uint8_t len, uint16_t offset); /*! @def BT_GATT_CCC * @brief Client Characteristic Configuration Declaration Macro. * * Helper macro to declare a CCC attribute. * * @param _handle Descriptor attribute handle. * @param _value_handle Characteristic attribute value handle. * @param _cfg Initial configuration. * @param _cfg_changed Configuration changed callback. */ #define BT_GATT_CCC(_handle, _value_handle, _cfg, _cfg_changed) \ { \ .handle = _handle, \ .uuid = (&(struct bt_uuid) { .type = BT_UUID_16, \ .u16 = BT_UUID_GATT_CCC }), \ .perm = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, \ .read = bt_gatt_attr_read_ccc, \ .write = bt_gatt_attr_write_ccc, \ .user_data = (&(struct _bt_gatt_ccc) { .cfg = _cfg, \ .cfg_len = ARRAY_SIZE(_cfg), \ .value_handle = _value_handle, \ .cfg_changed = _cfg_changed, }),\ } /*! @brief Read Characteristic Extended Properties Attribute helper * * Read CEP attribute value storing the result into buffer after * enconding it. * NOTE: Only use this with attributes which user_data is a bt_gatt_cep. * * @param peer Remote address * @param attr Attribute to read * @param buf Buffer to store the value read * @param len Buffer length * @param offset Start offset * * @return number of bytes read in case of success or negative values in * case of error. */ int bt_gatt_attr_read_cep(const bt_addr_le_t *peer, const struct bt_gatt_attr *attr, void *buf, uint8_t len, uint16_t offset); /*! @def BT_GATT_CEP * @brief Characteristic Extended Properties Declaration Macro. * * Helper macro to declare a CEP attribute. * * @param _handle Descriptor attribute handle. * @param _value Descriptor attribute value. */ #define BT_GATT_CEP(_handle, _value) \ { \ .handle = _handle, \ .uuid = (&(struct bt_uuid) { .type = BT_UUID_16, \ .u16 = BT_UUID_GATT_CEP }), \ .perm = BT_GATT_PERM_READ, \ .read = bt_gatt_attr_read_cep, \ .user_data = _value, \ } /*! @def BT_GATT_DESCRIPTOR * @brief Descriptor Declaration Macro. * * Helper macro to declare a descriptor attribute. * * @param _handle Descriptor attribute handle. * @param _value Descriptor attribute value. * @param _perm Descriptor attribute access permissions. * @param _read Descriptor attribute read callback. * @param _write Descriptor attribute write callback. * @param _value Descriptor attribute value. */ #define BT_GATT_DESCRIPTOR(_handle, _uuid, _perm, _read, _write, _value) \ { \ .handle = _handle, \ .uuid = _uuid, \ .perm = _perm, \ .read = _read, \ .write = _write, \ .user_data = _value, \ } /*! @def BT_GATT_LONG_DESCRIPTOR * @brief Descriptor Declaration Macro. * * Helper macro to declare a descriptor attribute. * * @param _handle Descriptor attribute handle. * @param _value Descriptor attribute value. * @param _perm Descriptor attribute access permissions. * @param _read Descriptor attribute read callback. * @param _write Descriptor attribute write callback. * @param _flush Descriptor attribute flush callback. * @param _value Descriptor attribute value. */ #define BT_GATT_LONG_DESCRIPTOR(_handle, _uuid, _perm, _read, _write, _flush, \ _value) \ { \ .handle = _handle, \ .uuid = _uuid, \ .perm = _perm, \ .read = _read, \ .write = _write, \ .flush = _flush, \ .user_data = _value, \ } /*! @brief Notify attribute value change. * * Send notification of attribute value change. * Note: This function should only be called if CCC is declared with * BT_GATT_CCC otherwise it cannot find a valid peer configuration. * * @param handle Attribute handle. * @param value Attribute value. * @param len Attribute value length. */ void bt_gatt_notify(uint16_t handle, const void *data, size_t len); /*! @brief connected callback. * * @param conn Connection object. */ void bt_gatt_connected(struct bt_conn *conn); /*! @brief disconnected callback. * * @param conn Connection object. */ void bt_gatt_disconnected(struct bt_conn *conn); #endif /* __BT_GATT_H */