diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 0ffa9fb..23ca8ba 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -52,7 +52,6 @@ NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t prop m_pService = pService; m_value = ""; m_valMux = portMUX_INITIALIZER_UNLOCKED; - m_pTaskData = nullptr; m_timestamp = 0; } // NimBLECharacteristic @@ -301,14 +300,12 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) { subVal |= NIMBLE_SUB_INDICATE; } - if(m_pTaskData != nullptr) { - m_pTaskData->rc = (subVal & NIMBLE_SUB_INDICATE) ? 0 : - NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_DISABLED; - xTaskNotifyGive(m_pTaskData->task); - } - NIMBLE_LOGI(LOG_TAG, "New subscribe value for conn: %d val: %d", - event->subscribe.conn_handle, subVal); + event->subscribe.conn_handle, subVal); + + if(!event->subscribe.cur_indicate && event->subscribe.prev_indicate) { + NimBLEDevice::getServer()->clearIndicateWait(event->subscribe.conn_handle); + } m_pCallbacks->onSubscribe(this, &desc, subVal); @@ -329,9 +326,7 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) { } else if(it != m_subscribedVec.end()) { m_subscribedVec.erase(it); - m_subscribedVec.shrink_to_fit(); } - } @@ -416,40 +411,20 @@ void NimBLECharacteristic::notify(bool is_notification) { // We also must create it in each loop iteration because it is consumed with each host call. os_mbuf *om = ble_hs_mbuf_from_flat((uint8_t*)value.data(), length); - NimBLECharacteristicCallbacks::Status statusRC; - if(!is_notification && (m_properties & NIMBLE_PROPERTY::INDICATE)) { - ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr}; - m_pTaskData = &taskData; + if(!NimBLEDevice::getServer()->setIndicateWait(it.first)) { + NIMBLE_LOGE(LOG_TAG, "prior Indication in progress"); + os_mbuf_free_chain(om); + return; + } rc = ble_gattc_indicate_custom(it.first, m_handle, om); if(rc != 0){ - statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT; - } else { - ulTaskNotifyTake(pdTRUE, portMAX_DELAY); - rc = m_pTaskData->rc; - } - - m_pTaskData = nullptr; - - if(rc == BLE_HS_EDONE) { - rc = 0; - statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_INDICATE; - } else if(rc == BLE_HS_ETIMEOUT) { - statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT; - } else { - statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE; + NimBLEDevice::getServer()->clearIndicateWait(it.first); } } else { - rc = ble_gattc_notify_custom(it.first, m_handle, om); - if(rc == 0) { - statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY; - } else { - statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT; - } + ble_gattc_notify_custom(it.first, m_handle, om); } - - m_pCallbacks->onStatus(this, statusRC, rc); } NIMBLE_LOGD(LOG_TAG, "<< notify"); diff --git a/src/NimBLECharacteristic.h b/src/NimBLECharacteristic.h index 9bb9d07..22670df 100644 --- a/src/NimBLECharacteristic.h +++ b/src/NimBLECharacteristic.h @@ -150,7 +150,6 @@ private: NimBLEService* m_pService; std::string m_value; std::vector m_dscVec; - ble_task_data_t *m_pTaskData; portMUX_TYPE m_valMux; time_t m_timestamp; diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index 139e7e0..1b88503 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -37,6 +37,7 @@ static NimBLEServerCallbacks defaultCallbacks; * the NimBLEDevice class. */ NimBLEServer::NimBLEServer() { + memset(m_indWait, BLE_HS_CONN_HANDLE_NONE, sizeof(m_indWait)); // m_svcChgChrHdl = 0xffff; // Future Use m_pServerCallbacks = &defaultCallbacks; m_gattsStarted = false; @@ -419,18 +420,44 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) { } // BLE_GAP_EVENT_MTU case BLE_GAP_EVENT_NOTIFY_TX: { - if(event->notify_tx.indication && event->notify_tx.status != 0) { - for(auto &it : server->m_notifyChrVec) { - if(it->getHandle() == event->notify_tx.attr_handle) { - if(it->m_pTaskData != nullptr) { - it->m_pTaskData->rc = event->notify_tx.status; - xTaskNotifyGive(it->m_pTaskData->task); - } - break; - } + NimBLECharacteristic *pChar = nullptr; + + for(auto &it : server->m_notifyChrVec) { + if(it->getHandle() == event->notify_tx.attr_handle) { + pChar = it; } } + if(pChar == nullptr) { + return 0; + } + + NimBLECharacteristicCallbacks::Status statusRC; + + if(event->notify_tx.indication) { + if(event->notify_tx.status != 0) { + if(event->notify_tx.status == BLE_HS_EDONE) { + statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_INDICATE; + } else if(rc == BLE_HS_ETIMEOUT) { + statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_TIMEOUT; + } else { + statusRC = NimBLECharacteristicCallbacks::Status::ERROR_INDICATE_FAILURE; + } + } else { + return 0; + } + + server->clearIndicateWait(event->notify_tx.conn_handle); + } else { + if(event->notify_tx.status == 0) { + statusRC = NimBLECharacteristicCallbacks::Status::SUCCESS_NOTIFY; + } else { + statusRC = NimBLECharacteristicCallbacks::Status::ERROR_GATT; + } + } + + pChar->m_pCallbacks->onStatus(pChar, statusRC, event->notify_tx.status); + return 0; } // BLE_GAP_EVENT_NOTIFY_TX @@ -732,6 +759,27 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle, }// updateConnParams +bool NimBLEServer::setIndicateWait(uint16_t conn_handle) { + for(auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { + if(m_indWait[i] == conn_handle) { + return false; + } + } + + return true; +} + + +void NimBLEServer::clearIndicateWait(uint16_t conn_handle) { + for(auto i = 0; i < CONFIG_BT_NIMBLE_MAX_CONNECTIONS; i++) { + if(m_indWait[i] == conn_handle) { + m_indWait[i] = BLE_HS_CONN_HANDLE_NONE; + return; + } + } +} + + /** Default callback handlers */ void NimBLEServerCallbacks::onConnect(NimBLEServer* pServer) { diff --git a/src/NimBLEServer.h b/src/NimBLEServer.h index 47309e1..8259b8e 100644 --- a/src/NimBLEServer.h +++ b/src/NimBLEServer.h @@ -77,6 +77,7 @@ private: bool m_svcChanged; NimBLEServerCallbacks* m_pServerCallbacks; bool m_deleteCallbacks; + uint16_t m_indWait[CONFIG_BT_NIMBLE_MAX_CONNECTIONS]; std::vector m_connectedPeersVec; // uint16_t m_svcChgChrHdl; // Future use @@ -86,6 +87,8 @@ private: static int handleGapEvent(struct ble_gap_event *event, void *arg); void resetGATT(); + bool setIndicateWait(uint16_t conn_handle); + void clearIndicateWait(uint16_t conn_handle); }; // NimBLEServer