Skip to content

Commit

Permalink
Fixing BLE GATT Characteristic notification and Characteristic Descri…
Browse files Browse the repository at this point in the history
…ptor read (#4464)

* BLERemoteChar: fix descriptor 2902 write for characteristic notifications

When registering a notification on a characteristic, the 2902 descriptor
(CCCD) value is set to 1 (or 2 for indication).
According to the BLUETOOTH CORE SPECIFICATION Version 5.2, Revision Date
2019-12-31, section 4.12.3 "Write Characteristic Descriptors" (page 1588),
the characteristic descriptor write must expect a response.
Currently, the descriptor write is performed without expecting a reponse,
which prevents the notification to be functional with some BLE stacks.
This commit modify the write to expect the response.

Signed-off-by: Jimmy Durand Wesolowski <[email protected]>

* BLERemoteChar: forward GATT client event to characteristic descriptors

This commits prevents a permanent wait when calling BLERemoteDescriptor
readValue function, on the m_semaphoreReadDescrEvt semaphore.

ESP32 BLE stack calls to remote characteristic
- notification,
- value read
- value write
and remote characteristic descriptor
- value read
are asynchronous.

When such a call is performed by this library, a semaphore is taken prior
to the BLE stack read or write operation, and waited on after it.

Releasing the semaphore is done by the characteristic event handling
function (gattClientEventHandler), when the appropriate event is received.

However, the characteristic descriptor events are discarded, and the
value read semaphore is never released.

This commits forwards the GATT client events from the remote
characteristic down to their remote characteristic descriptor, and
implements their event handling.

Adding a semaphore for the remote characteristic descriptor value write
will be done in a separate commit.

Signed-off-by: Jimmy Durand Wesolowski <[email protected]>

* BLERemoteDescriptor: add semaphore to characteristic descriptor write

This adds a semaphore to characteristic descriptor value write, to mimic
the value read function, and to ensure completion of the operation before
we carry on.

Signed-off-by: Jimmy Durand Wesolowski <[email protected]>

Co-authored-by: Jimmy Durand Wesolowski <[email protected]>
  • Loading branch information
JimmyDurandWesolowski and Jimmy Durand Wesolowski authored Nov 2, 2020
1 parent 57145ad commit 360e04f
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 deletions.
11 changes: 9 additions & 2 deletions libraries/BLE/src/BLERemoteCharacteristic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ void BLERemoteCharacteristic::gattClientEventHandler(esp_gattc_cb_event_t event,
break;
} // ESP_GATTC_WRITE_CHAR_EVT

case ESP_GATTC_READ_DESCR_EVT:
case ESP_GATTC_WRITE_DESCR_EVT:
for (auto &myPair : m_descriptorMap) {
myPair.second->gattClientEventHandler(
event, gattc_if, evtParam);
}
break;

default:
break;
Expand Down Expand Up @@ -468,7 +475,7 @@ void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback,
if(!notifications) val[0] = 0x02;
BLERemoteDescriptor* desc = getDescriptor(BLEUUID((uint16_t)0x2902));
if (desc != nullptr)
desc->writeValue(val, 2);
desc->writeValue(val, 2, true);
} // End Register
else { // If we weren't passed a callback function, then this is an unregistration.
esp_err_t errRc = ::esp_ble_gattc_unregister_for_notify(
Expand All @@ -484,7 +491,7 @@ void BLERemoteCharacteristic::registerForNotify(notify_callback notifyCallback,
uint8_t val[] = {0x00, 0x00};
BLERemoteDescriptor* desc = getDescriptor((uint16_t)0x2902);
if (desc != nullptr)
desc->writeValue(val, 2);
desc->writeValue(val, 2, true);
} // End Unregister

m_semaphoreRegForNotifyEvt.wait("registerForNotify");
Expand Down
21 changes: 21 additions & 0 deletions libraries/BLE/src/BLERemoteDescriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ BLEUUID BLERemoteDescriptor::getUUID() {
return m_uuid;
} // getUUID

void BLERemoteDescriptor::gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam) {
switch(event) {
case ESP_GATTC_READ_DESCR_EVT:
if (evtParam->read.handle != getHandle())
break;
m_semaphoreReadDescrEvt.give();
break;

case ESP_GATTC_WRITE_DESCR_EVT:
if (evtParam->write.handle != getHandle())
break;
m_semaphoreWriteDescrEvt.give();
break;
default:
break;
}
}

std::string BLERemoteDescriptor::readValue() {
log_v(">> readValue: %s", toString().c_str());
Expand Down Expand Up @@ -137,6 +154,8 @@ void BLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool response
return;
}

m_semaphoreWriteDescrEvt.take("writeValue");

esp_err_t errRc = ::esp_ble_gattc_write_char_descr(
m_pRemoteCharacteristic->getRemoteService()->getClient()->getGattcIf(),
m_pRemoteCharacteristic->getRemoteService()->getClient()->getConnId(),
Expand All @@ -149,6 +168,8 @@ void BLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool response
if (errRc != ESP_OK) {
log_e("esp_ble_gattc_write_char_descr: %d", errRc);
}

m_semaphoreWriteDescrEvt.wait("writeValue");
log_v("<< writeValue");
} // writeValue

Expand Down
3 changes: 2 additions & 1 deletion libraries/BLE/src/BLERemoteDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class BLERemoteDescriptor {
void writeValue(std::string newValue, bool response = false);
void writeValue(uint8_t newValue, bool response = false);
void setAuth(esp_gatt_auth_req_t auth);

void gattClientEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* evtParam);

private:
friend class BLERemoteCharacteristic;
Expand All @@ -49,6 +49,7 @@ class BLERemoteDescriptor {
std::string m_value; // Last received value of the descriptor.
BLERemoteCharacteristic* m_pRemoteCharacteristic; // Reference to the Remote characteristic of which this descriptor is associated.
FreeRTOS::Semaphore m_semaphoreReadDescrEvt = FreeRTOS::Semaphore("ReadDescrEvt");
FreeRTOS::Semaphore m_semaphoreWriteDescrEvt = FreeRTOS::Semaphore("WriteDescrEvt");
esp_gatt_auth_req_t m_auth;


Expand Down

0 comments on commit 360e04f

Please sign in to comment.