summaryrefslogtreecommitdiff
path: root/src/BLECharacteristic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/BLECharacteristic.cpp')
-rw-r--r--src/BLECharacteristic.cpp95
1 files changed, 66 insertions, 29 deletions
diff --git a/src/BLECharacteristic.cpp b/src/BLECharacteristic.cpp
index 6d746cf..5e5aa2a 100644
--- a/src/BLECharacteristic.cpp
+++ b/src/BLECharacteristic.cpp
@@ -15,6 +15,7 @@
#include <esp_err.h>
#include "BLECharacteristic.h"
#include "BLEService.h"
+#include "BLEDevice.h"
#include "BLEUtils.h"
#include "BLE2902.h"
#include "GeneralUtils.h"
@@ -107,7 +108,7 @@ void BLECharacteristic::executeCreate(BLEService* pService) {
esp_err_t errRc = ::esp_ble_gatts_add_char(
m_pService->getHandle(),
getUUID().getNative(),
- static_cast<esp_gatt_perm_t>(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE),
+ static_cast<esp_gatt_perm_t>(m_permissions),
getProperties(),
//&value,
nullptr,
@@ -163,6 +164,9 @@ uint16_t BLECharacteristic::getHandle() {
return m_handle;
} // getHandle
+void BLECharacteristic::setAccessPermissions(esp_gatt_perm_t perm) {
+ m_permissions = perm;
+}
esp_gatt_char_prop_t BLECharacteristic::getProperties() {
return m_properties;
@@ -195,17 +199,27 @@ std::string BLECharacteristic::getValue() {
} // getValue
+/**
+ * Handle a GATT server event.
+ */
void BLECharacteristic::handleGATTServerEvent(
esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t* param) {
+ ESP_LOGD(LOG_TAG, ">> handleGATTServerEvent: %s", BLEUtils::gattServerEventTypeToString(event).c_str());
+
switch(event) {
// Events handled:
+ //
// ESP_GATTS_ADD_CHAR_EVT
- // ESP_GATTS_WRITE_EVT
+ // ESP_GATTS_CONF_EVT
+ // ESP_GATTS_CONNECT_EVT
+ // ESP_GATTS_DISCONNECT_EVT
+ // ESP_GATTS_EXEC_WRITE_EVT
// ESP_GATTS_READ_EVT
- //
+ // ESP_GATTS_WRITE_EVT
+ //
// ESP_GATTS_EXEC_WRITE_EVT
// When we receive this event it is an indication that a previous write long needs to be committed.
//
@@ -213,7 +227,7 @@ void BLECharacteristic::handleGATTServerEvent(
// - uint16_t conn_id
// - uint32_t trans_id
// - esp_bd_addr_t bda
- // - uint8_t exec_write_flag
+ // - uint8_t exec_write_flag - Either ESP_GATT_PREP_WRITE_EXEC or ESP_GATT_PREP_WRITE_CANCEL
//
case ESP_GATTS_EXEC_WRITE_EVT: {
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
@@ -321,20 +335,18 @@ void BLECharacteristic::handleGATTServerEvent(
// - bool need_rsp
//
case ESP_GATTS_READ_EVT: {
- ESP_LOGD(LOG_TAG, "- Testing: 0x%.2x == 0x%.2x", param->read.handle, m_handle);
if (param->read.handle == m_handle) {
- if (m_pCallbacks != nullptr) {
- m_pCallbacks->onRead(this); // Invoke the read callback.
- }
+
// Here's an interesting thing. The read request has the option of saying whether we need a response
// or not. What would it "mean" to receive a read request and NOT send a response back? That feels like
// a very strange read.
//
// We have to handle the case where the data we wish to send back to the client is greater than the maximum
-// packet size of 22 bytes. In this case, we become responsible for chunking the data into uints of 22 bytes.
-// The apparent algorithm is as follows.
+// packet size of 22 bytes. In this case, we become responsible for chunking the data into units of 22 bytes.
+// The apparent algorithm is as follows:
+//
// If the is_long flag is set then this is a follow on from an original read and we will already have sent at least 22 bytes.
// If the is_long flag is not set then we need to check how much data we are going to send. If we are sending LESS than
// 22 bytes, then we "just" send it and thats the end of the story.
@@ -348,12 +360,19 @@ void BLECharacteristic::handleGATTServerEvent(
// The following code has deliberately not been factored to make it fewer statements because this would cloud the
// the logic flow comprehension.
//
+ // TODO requires some more research to confirm that 512 is max PDU like in bluetooth specs
+ uint16_t maxOffset = BLEDevice::getMTU() - 1;
+ if (BLEDevice::getMTU() > 512) {
+ maxOffset = 512;
+ }
if (param->read.need_rsp) {
ESP_LOGD(LOG_TAG, "Sending a response (esp_ble_gatts_send_response)");
esp_gatt_rsp_t rsp;
- std::string value = m_value.getValue();
+
if (param->read.is_long) {
- if (value.length() - m_value.getReadOffset() < 22) {
+ std::string value = m_value.getValue();
+
+ if (value.length() - m_value.getReadOffset() < maxOffset) {
// This is the last in the chain
rsp.attr_value.len = value.length() - m_value.getReadOffset();
rsp.attr_value.offset = m_value.getReadOffset();
@@ -361,16 +380,23 @@ void BLECharacteristic::handleGATTServerEvent(
m_value.setReadOffset(0);
} else {
// There will be more to come.
- rsp.attr_value.len = 22;
+ rsp.attr_value.len = maxOffset;
rsp.attr_value.offset = m_value.getReadOffset();
memcpy(rsp.attr_value.value, value.data() + rsp.attr_value.offset, rsp.attr_value.len);
- m_value.setReadOffset(rsp.attr_value.offset + 22);
+ m_value.setReadOffset(rsp.attr_value.offset + maxOffset);
+ }
+ } else { // read.is_long == false
+
+ if (m_pCallbacks != nullptr) { // If is.long is false then this is the first (or only) request to read data, so invoke the callback
+ m_pCallbacks->onRead(this); // Invoke the read callback.
}
- } else {
- if (value.length() > 21) {
+
+ std::string value = m_value.getValue();
+
+ if (value.length()+1 > maxOffset) {
// Too big for a single shot entry.
- m_value.setReadOffset(22);
- rsp.attr_value.len = 22;
+ m_value.setReadOffset(maxOffset);
+ rsp.attr_value.len = maxOffset;
rsp.attr_value.offset = 0;
memcpy(rsp.attr_value.value, value.data(), rsp.attr_value.len);
} else {
@@ -400,6 +426,7 @@ void BLECharacteristic::handleGATTServerEvent(
break;
} // ESP_GATTS_READ_EVT
+
// ESP_GATTS_CONF_EVT
//
// conf:
@@ -411,6 +438,16 @@ void BLECharacteristic::handleGATTServerEvent(
break;
}
+ case ESP_GATTS_CONNECT_EVT: {
+ m_semaphoreConfEvt.give();
+ break;
+ }
+
+ case ESP_GATTS_DISCONNECT_EVT: {
+ m_semaphoreConfEvt.give();
+ break;
+ }
+
default: {
break;
} // default
@@ -421,7 +458,7 @@ void BLECharacteristic::handleGATTServerEvent(
// event.
m_descriptorMap.handleGATTServerEvent(event, gatts_if, param);
-
+ ESP_LOGD(LOG_TAG, "<< handleGATTServerEvent");
} // handleGATTServerEvent
@@ -454,14 +491,11 @@ void BLECharacteristic::indicate() {
return;
}
- if (m_value.getValue().length() > 20) {
- ESP_LOGD(LOG_TAG, "- Truncating to 20 bytes (maximum notify size)");
+ if (m_value.getValue().length() > (BLEDevice::getMTU() - 3)) {
+ ESP_LOGI(LOG_TAG, "- Truncating to %d bytes (maximum indicate size)", BLEDevice::getMTU() - 3);
}
size_t length = m_value.getValue().length();
- if (length > 20) {
- length = 20;
- }
m_semaphoreConfEvt.take("indicate");
@@ -510,14 +544,13 @@ void BLECharacteristic::notify() {
return;
}
- if (m_value.getValue().length() > 20) {
- ESP_LOGD(LOG_TAG, "- Truncating to 20 bytes (maximum notify size)");
+ if (m_value.getValue().length() > (BLEDevice::getMTU() - 3)) {
+ ESP_LOGI(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", BLEDevice::getMTU() - 3);
}
size_t length = m_value.getValue().length();
- if (length > 20) {
- length = 20;
- }
+
+ m_semaphoreConfEvt.take("notify");
esp_err_t errRc = ::esp_ble_gatts_send_indicate(
getService()->getServer()->getGattsIf(),
@@ -528,6 +561,8 @@ void BLECharacteristic::notify() {
return;
}
+ m_semaphoreConfEvt.wait("notify");
+
ESP_LOGD(LOG_TAG, "<< notify");
} // Notify
@@ -695,8 +730,10 @@ std::string BLECharacteristic::toString() {
return stringstream.str();
} // toString
+
BLECharacteristicCallbacks::~BLECharacteristicCallbacks() {}
+
/**
* @brief Callback function to support a read request.
* @param [in] pCharacteristic The characteristic that is the source of the event.