diff --git a/libraries/CurieBLE/src/internal/BLECallbacks.cpp b/libraries/CurieBLE/src/internal/BLECallbacks.cpp index 328c196b..5818c427 100644 --- a/libraries/CurieBLE/src/internal/BLECallbacks.cpp +++ b/libraries/CurieBLE/src/internal/BLECallbacks.cpp @@ -27,6 +27,11 @@ #include "BLEDeviceManager.h" #include "BLEProfileManager.h" +#include "BLECallbacks.h" + +#include +#include "../src/services/ble/conn_internal.h" + // GATT Server Only ssize_t profile_read_process(bt_conn_t *conn, const bt_gatt_attr_t *attr, @@ -237,6 +242,60 @@ void bleConnectEventHandler(bt_conn_t *conn, p->handleConnectEvent(conn, err); } +static uint8_t ble_gatt_disconnected_cb(const struct bt_gatt_attr *attr, void *user_data) +{ + struct bt_conn *conn = (struct bt_conn *)user_data; + struct _bt_gatt_ccc *ccc; + size_t i; + + /* Check attribute user_data must be of type struct _bt_gatt_ccc */ + if (attr->write != profile_gatt_attr_write_ccc) { + return BT_GATT_ITER_CONTINUE; + } + + ccc = (struct _bt_gatt_ccc *)attr->user_data; + /* If already disabled skip */ + if (!ccc->value) { + return BT_GATT_ITER_CONTINUE; + } + + for (i = 0; i < ccc->cfg_len; i++) + { + /* Ignore configurations with disabled value */ + if (!ccc->cfg[i].value) + { + continue; + } + + if (bt_addr_le_cmp(&conn->le.dst, &ccc->cfg[i].peer)) + { + struct bt_conn *tmp; + + /* Skip if there is another peer connected */ + tmp = bt_conn_lookup_addr_le(&ccc->cfg[i].peer); + if (tmp) { + if (tmp->state == BT_CONN_CONNECTED) { + bt_conn_unref(tmp); + return BT_GATT_ITER_CONTINUE; + } + + bt_conn_unref(tmp); + } + } + } + + /* Reset value while disconnected */ + memset(&ccc->value, 0, sizeof(ccc->value)); + + if (ccc->cfg_changed) { + ccc->cfg_changed(ccc->value); + } + + pr_debug(LOG_MODULE_BLE, "ccc %p reseted", ccc); + + return BT_GATT_ITER_CONTINUE; +} + void bleDisconnectEventHandler(bt_conn_t *conn, uint8_t reason, @@ -245,6 +304,7 @@ void bleDisconnectEventHandler(bt_conn_t *conn, BLEDeviceManager* p = (BLEDeviceManager*)param; pr_info(LOG_MODULE_BLE, "Connect lost. Reason: %d", reason); + bt_gatt_foreach_attr(0x0001, 0xffff, ble_gatt_disconnected_cb, conn); p->handleDisconnectEvent(conn, reason); } @@ -283,3 +343,29 @@ void ble_on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, BLECharacteristicImp::writeResponseReceived(conn, err, data); } +ssize_t profile_gatt_attr_write_ccc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, + uint16_t len, + uint16_t offset) +{ + struct _bt_gatt_ccc *ccc = (struct _bt_gatt_ccc *)attr->user_data; + const uint16_t *data = (const uint16_t *)buf; + bool cccdChanged = (ccc->value != *data); + ssize_t retValue = bt_gatt_attr_write_ccc(conn, attr, buf, len, offset); + if (cccdChanged) + { + // Find characteristic and do notification + const struct bt_gatt_attr *attrChrc = attr - 1; + BLEAttribute *bleattr = (BLEAttribute *)attrChrc->user_data; + BLEAttributeType type = bleattr->type(); + pr_debug(LOG_MODULE_BLE, "The Attribute type:%d", type); + if (BLETypeCharacteristic == type) + { + BLECharacteristicImp *blecharacteritic = (BLECharacteristicImp*)bleattr; + blecharacteritic->cccdValueChanged(); + } + } + return retValue; +} + diff --git a/libraries/CurieBLE/src/internal/BLECallbacks.h b/libraries/CurieBLE/src/internal/BLECallbacks.h index deffe92a..5d877ad3 100644 --- a/libraries/CurieBLE/src/internal/BLECallbacks.h +++ b/libraries/CurieBLE/src/internal/BLECallbacks.h @@ -89,5 +89,11 @@ uint8_t profile_characteristic_read_rsp_process(bt_conn_t *conn, const void *data, uint16_t length); +ssize_t profile_gatt_attr_write_ccc(struct bt_conn *conn, + const struct bt_gatt_attr *attr, + const void *buf, + uint16_t len, + uint16_t offset); + #endif diff --git a/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp b/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp index a7098e96..4ad8021d 100644 --- a/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp +++ b/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp @@ -802,7 +802,7 @@ int BLECharacteristicImp::updateProfile(bt_gatt_attr_t *attr_start, int& index) start->uuid = this->getClientCharacteristicConfigUuid(); start->perm = BT_GATT_PERM_READ | BT_GATT_PERM_WRITE; start->read = bt_gatt_attr_read_ccc; - start->write = bt_gatt_attr_write_ccc; + start->write = profile_gatt_attr_write_ccc; start->user_data = this->getCccCfg(); pr_info(LOG_MODULE_BLE, "cccd-%p", start); @@ -1070,4 +1070,26 @@ uint8_t BLECharacteristicImp::discoverResponseProc(bt_conn_t *conn, return retVal; } +void BLECharacteristicImp::cccdValueChanged() +{ + + enum BLECharacteristicEvent event = BLEUnsubscribed; + if (subscribed()) + { + event = BLESubscribed; + } + + if (_event_handlers[event]) + { + BLECharacteristic chrcTmp(this, &_ble_device); + _event_handlers[event](_ble_device, chrcTmp); + } + + if (_oldevent_handlers[event]) + { + BLECharacteristic chrcTmp(this, &_ble_device); + BLECentral central(_ble_device); + _oldevent_handlers[event](central, chrcTmp); + } +} diff --git a/libraries/CurieBLE/src/internal/BLECharacteristicImp.h b/libraries/CurieBLE/src/internal/BLECharacteristicImp.h index af5e9839..320cf980 100644 --- a/libraries/CurieBLE/src/internal/BLECharacteristicImp.h +++ b/libraries/CurieBLE/src/internal/BLECharacteristicImp.h @@ -172,7 +172,7 @@ class BLECharacteristicImp: public BLEAttribute{ static void writeResponseReceived(struct bt_conn *conn, uint8_t err, const void *data); - + void cccdValueChanged(); int descriptorCount() const; uint8_t discoverResponseProc(bt_conn_t *conn, const bt_gatt_attr_t *attr,