diff options
Diffstat (limited to 'src/BLEDescriptor.cpp')
-rw-r--r-- | src/BLEDescriptor.cpp | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/src/BLEDescriptor.cpp b/src/BLEDescriptor.cpp new file mode 100644 index 0000000..4a7fda6 --- /dev/null +++ b/src/BLEDescriptor.cpp @@ -0,0 +1,278 @@ +/* + * BLEDescriptor.cpp + * + * Created on: Jun 22, 2017 + * Author: kolban + */ +#include "sdkconfig.h" +#if defined(CONFIG_BT_ENABLED) +#include <sstream> +#include <string.h> +#include <iomanip> +#include <stdlib.h> +#include "sdkconfig.h" +#include <esp_log.h> +#include <esp_err.h> +#include "BLEService.h" +#include "BLEDescriptor.h" +#include "GeneralUtils.h" + +static const char* LOG_TAG = "BLEDescriptor"; + + +#define NULL_HANDLE (0xffff) + + +/** + * @brief BLEDescriptor constructor. + */ +BLEDescriptor::BLEDescriptor(const char* uuid) : BLEDescriptor(BLEUUID(uuid)) { +} + +/** + * @brief BLEDescriptor constructor. + */ +BLEDescriptor::BLEDescriptor(BLEUUID uuid) { + m_bleUUID = uuid; + m_value.attr_value = (uint8_t *)malloc(ESP_GATT_MAX_ATTR_LEN); // Allocate storage for the value. + m_value.attr_len = 0; + m_value.attr_max_len = ESP_GATT_MAX_ATTR_LEN; + m_handle = NULL_HANDLE; + m_pCharacteristic = nullptr; // No initial characteristic. + +} // BLEDescriptor + + +/** + * @brief BLEDescriptor destructor. + */ +BLEDescriptor::~BLEDescriptor() { + free(m_value.attr_value); +} // ~BLEDescriptor + + +/** + * @brief Execute the creation of the descriptor with the BLE runtime in ESP. + * @param [in] pCharacteristic The characteristic to which to register this descriptor. + */ +void BLEDescriptor::executeCreate(BLECharacteristic* pCharacteristic) { + ESP_LOGD(LOG_TAG, ">> executeCreate(): %s", toString().c_str()); + + if (m_handle != NULL_HANDLE) { + ESP_LOGE(LOG_TAG, "Descriptor already has a handle."); + return; + } + + m_pCharacteristic = pCharacteristic; // Save the characteristic associated with this service. + + esp_attr_control_t control; + control.auto_rsp = ESP_GATT_RSP_BY_APP; + m_semaphoreCreateEvt.take("executeCreate"); + esp_err_t errRc = ::esp_ble_gatts_add_char_descr( + pCharacteristic->getService()->getHandle(), + getUUID().getNative(), + (esp_gatt_perm_t)(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE), + &m_value, + &control); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "<< esp_ble_gatts_add_char_descr: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + return; + } + + m_semaphoreCreateEvt.wait("executeCreate"); + ESP_LOGD(LOG_TAG, "<< executeCreate"); +} // executeCreate + + +/** + * @brief Get the BLE handle for this descriptor. + * @return The handle for this descriptor. + */ +uint16_t BLEDescriptor::getHandle() { + return m_handle; +} // getHandle + + +/** + * @brief Get the length of the value of this descriptor. + * @return The length (in bytes) of the value of this descriptor. + */ +size_t BLEDescriptor::getLength() { + return m_value.attr_len; +} // getLength + + +/** + * @brief Get the UUID of the descriptor. + */ +BLEUUID BLEDescriptor::getUUID() { + return m_bleUUID; +} // getUUID + + + +/** + * @brief Get the value of this descriptor. + * @return A pointer to the value of this descriptor. + */ +uint8_t* BLEDescriptor::getValue() { + return m_value.attr_value; +} // getValue + + +/** + * @brief Handle GATT server events for the descripttor. + * @param [in] event + * @param [in] gatts_if + * @param [in] param + */ +void BLEDescriptor::handleGATTServerEvent( + esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) { + switch(event) { + // ESP_GATTS_ADD_CHAR_DESCR_EVT + // + // add_char_descr: + // - esp_gatt_status_t status + // - uint16_t attr_handle + // - uint16_t service_handle + // - esp_bt_uuid_t char_uuid + case ESP_GATTS_ADD_CHAR_DESCR_EVT: { + /* + ESP_LOGD(LOG_TAG, "DEBUG: m_pCharacteristic: %x", (uint32_t)m_pCharacteristic); + ESP_LOGD(LOG_TAG, "DEBUG: m_bleUUID: %s, add_char_descr.char_uuid: %s, equals: %d", + m_bleUUID.toString().c_str(), + BLEUUID(param->add_char_descr.char_uuid).toString().c_str(), + m_bleUUID.equals(BLEUUID(param->add_char_descr.char_uuid))); + ESP_LOGD(LOG_TAG, "DEBUG: service->getHandle: %x, add_char_descr.service_handle: %x", + m_pCharacteristic->getService()->getHandle(), param->add_char_descr.service_handle); + ESP_LOGD(LOG_TAG, "DEBUG: service->lastCharacteristic: %x", + (uint32_t)m_pCharacteristic->getService()->getLastCreatedCharacteristic()); + */ + if (m_pCharacteristic != nullptr && + m_bleUUID.equals(BLEUUID(param->add_char_descr.char_uuid)) && + m_pCharacteristic->getService()->getHandle() == param->add_char_descr.service_handle && + m_pCharacteristic == m_pCharacteristic->getService()->getLastCreatedCharacteristic()) { + setHandle(param->add_char_descr.attr_handle); + m_semaphoreCreateEvt.give(); + } + break; + } // ESP_GATTS_ADD_CHAR_DESCR_EVT + + // ESP_GATTS_WRITE_EVT - A request to write the value of a descriptor has arrived. + // + // write: + // - uint16_t conn_id + // - uint16_t trans_id + // - esp_bd_addr_t bda + // - uint16_t handle + // - uint16_t offset + // - bool need_rsp + // - bool is_prep + // - uint16_t len + // - uint8_t *value + case ESP_GATTS_WRITE_EVT: { + if (param->write.handle == m_handle) { + setValue(param->write.value, param->write.len); + esp_gatt_rsp_t rsp; + rsp.attr_value.len = getLength(); + rsp.attr_value.handle = m_handle; + rsp.attr_value.offset = 0; + rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; + memcpy(rsp.attr_value.value, getValue(), rsp.attr_value.len); + esp_err_t errRc = ::esp_ble_gatts_send_response( + gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, &rsp); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + } + } + break; + } // ESP_GATTS_WRITE_EVT + + // ESP_GATTS_READ_EVT - A request to read the value of a descriptor has arrived. + // + // read: + // - uint16_t conn_id + // - uint32_t trans_id + // - esp_bd_addr_t bda + // - uint16_t handle + // - uint16_t offset + // - bool is_long + // - bool need_rsp + // + case ESP_GATTS_READ_EVT: { + ESP_LOGD(LOG_TAG, "- Testing: Sought handle: 0x%.2x == descriptor handle: 0x%.2x ?", param->read.handle, m_handle); + if (param->read.handle == m_handle) { + ESP_LOGD(LOG_TAG, "Sending a response (esp_ble_gatts_send_response)"); + if (param->read.need_rsp) { + esp_gatt_rsp_t rsp; + rsp.attr_value.len = getLength(); + rsp.attr_value.handle = param->read.handle; + rsp.attr_value.offset = 0; + rsp.attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; + memcpy(rsp.attr_value.value, getValue(), rsp.attr_value.len); + esp_err_t errRc = ::esp_ble_gatts_send_response( + gatts_if, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp); + if (errRc != ESP_OK) { + ESP_LOGE(LOG_TAG, "esp_ble_gatts_send_response: rc=%d %s", errRc, GeneralUtils::errorToString(errRc)); + } + } + } // ESP_GATTS_READ_EVT + break; + } // ESP_GATTS_READ_EVT + default: { + break; + } + }// switch event +} // handleGATTServerEvent + + +/** + * @brief Set the handle of this descriptor. + * Set the handle of this descriptor to be the supplied value. + * @param [in] handle The handle to be associated with this descriptor. + * @return N/A. + */ +void BLEDescriptor::setHandle(uint16_t handle) { + ESP_LOGD(LOG_TAG, ">> setHandle(0x%.2x): Setting descriptor handle to be 0x%.2x", handle, handle); + m_handle = handle; + ESP_LOGD(LOG_TAG, "<< setHandle()"); +} // setHandle + + +/** + * @brief Set the value of the descriptor. + * @param [in] data The data to set for the descriptor. + * @param [in] length The length of the data in bytes. + */ +void BLEDescriptor::setValue(uint8_t* data, size_t length) { + if (length > ESP_GATT_MAX_ATTR_LEN) { + ESP_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, ESP_GATT_MAX_ATTR_LEN); + return; + } + m_value.attr_len = length; + memcpy(m_value.attr_value, data, length); +} // setValue + + +/** + * @brief Set the value of the descriptor. + * @param [in] value The value of the descriptor in string form. + */ +void BLEDescriptor::setValue(std::string value) { + setValue((uint8_t *)value.data(), value.length()); +} // setValue + + +/** + * @brief Return a string representation of the descriptor. + * @return A string representation of the descriptor. + */ +std::string BLEDescriptor::toString() { + std::stringstream stringstream; + stringstream << std::hex << std::setfill('0'); + stringstream << "UUID: " << m_bleUUID.toString() + ", handle: 0x" << std::setw(2) << m_handle; + return stringstream.str(); +} // toString +#endif /* CONFIG_BT_ENABLED */ |