mirror of
https://github.com/h2zero/esp-nimble-cpp.git
synced 2024-11-22 05:00:55 +01:00
Replace semaphores with task notifications. (#9)
* Replace all semaphores with task notifications. * use critical sections to prevent concurrent data access. * Ensure scan stop has been called before connecting. * Optimize and cleanup * Add template casting to NimBLERemoteDescriptor::readValue() * Removed storage of the descriptor value read as it did not serve any purpose.
This commit is contained in:
parent
5bc9d59646
commit
f5541d18de
11 changed files with 368 additions and 401 deletions
|
@ -18,7 +18,6 @@
|
||||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLEClient.h"
|
#include "NimBLEClient.h"
|
||||||
#include "NimBLEUtils.h"
|
|
||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
|
@ -54,7 +53,10 @@ NimBLEClient::NimBLEClient()
|
||||||
m_pClientCallbacks = &defaultCallbacks;
|
m_pClientCallbacks = &defaultCallbacks;
|
||||||
m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
||||||
m_isConnected = false;
|
m_isConnected = false;
|
||||||
|
m_waitingToConnect = false;
|
||||||
m_connectTimeout = 30000;
|
m_connectTimeout = 30000;
|
||||||
|
m_deleteCallbacks = false;
|
||||||
|
m_pTaskData = nullptr;
|
||||||
|
|
||||||
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
|
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
|
||||||
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
|
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
|
||||||
|
@ -157,6 +159,10 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!NimBLEDevice::getScan()->stop()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
m_peerAddress = address;
|
m_peerAddress = address;
|
||||||
|
|
||||||
|
@ -164,7 +170,8 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
||||||
memcpy(&peerAddrt.val, address.getNative(),6);
|
memcpy(&peerAddrt.val, address.getNative(),6);
|
||||||
peerAddrt.type = type;
|
peerAddrt.type = type;
|
||||||
|
|
||||||
m_semaphoreOpenEvt.take("connect");
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||||
|
m_pTaskData = &taskData;
|
||||||
|
|
||||||
/** Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
|
/** Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
|
||||||
* timeout (default value of m_connectTimeout).
|
* timeout (default value of m_connectTimeout).
|
||||||
|
@ -174,7 +181,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
||||||
rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &peerAddrt, m_connectTimeout, &m_pConnParams,
|
rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &peerAddrt, m_connectTimeout, &m_pConnParams,
|
||||||
NimBLEClient::handleGapEvent, this);
|
NimBLEClient::handleGapEvent, this);
|
||||||
if(rc == BLE_HS_EBUSY) {
|
if(rc == BLE_HS_EBUSY) {
|
||||||
vTaskDelay(1);
|
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
}while(rc == BLE_HS_EBUSY);
|
}while(rc == BLE_HS_EBUSY);
|
||||||
|
|
||||||
|
@ -184,17 +191,17 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
||||||
type,
|
type,
|
||||||
m_peerAddress.toString().c_str(),
|
m_peerAddress.toString().c_str(),
|
||||||
rc, NimBLEUtils::returnCodeToString(rc));
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
m_pTaskData = nullptr;
|
||||||
m_semaphoreOpenEvt.give();
|
|
||||||
m_waitingToConnect = false;
|
m_waitingToConnect = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_waitingToConnect = true;
|
m_waitingToConnect = true;
|
||||||
|
|
||||||
rc = m_semaphoreOpenEvt.wait("connect"); // Wait for the connection to complete.
|
// Wait for the connection to complete.
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
if(rc != 0){
|
if(taskData.rc != 0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,17 +223,18 @@ bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refr
|
||||||
* @return True on success.
|
* @return True on success.
|
||||||
*/
|
*/
|
||||||
bool NimBLEClient::secureConnection() {
|
bool NimBLEClient::secureConnection() {
|
||||||
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||||
m_semeaphoreSecEvt.take("secureConnection");
|
m_pTaskData = &taskData;
|
||||||
|
|
||||||
int rc = NimBLEDevice::startSecurity(m_conn_id);
|
int rc = NimBLEDevice::startSecurity(m_conn_id);
|
||||||
if(rc != 0){
|
if(rc != 0){
|
||||||
m_semeaphoreSecEvt.give();
|
m_pTaskData = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = m_semeaphoreSecEvt.wait("secureConnection");
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
if(rc != 0){
|
|
||||||
|
if(taskData.rc != 0){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,30 +466,31 @@ bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveServices");
|
NIMBLE_LOGD(LOG_TAG, ">> retrieveServices");
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if(!m_isConnected){
|
if(!m_isConnected){
|
||||||
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting");
|
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve services -aborting");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_semaphoreSearchCmplEvt.take("retrieveServices");
|
int rc = 0;
|
||||||
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||||
|
|
||||||
if(uuid_filter == nullptr) {
|
if(uuid_filter == nullptr) {
|
||||||
rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this);
|
rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, &taskData);
|
||||||
} else {
|
} else {
|
||||||
rc = ble_gattc_disc_svc_by_uuid(m_conn_id, &uuid_filter->getNative()->u,
|
rc = ble_gattc_disc_svc_by_uuid(m_conn_id, &uuid_filter->getNative()->u,
|
||||||
NimBLEClient::serviceDiscoveredCB, this);
|
NimBLEClient::serviceDiscoveredCB, &taskData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_svcs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
m_semaphoreSearchCmplEvt.give();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until we have all the services
|
// wait until we have all the services
|
||||||
if(m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0){
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
|
if(taskData.rc == 0){
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveServices");
|
NIMBLE_LOGD(LOG_TAG, "<< retrieveServices");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -505,41 +514,34 @@ int NimBLEClient::serviceDiscoveredCB(
|
||||||
NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d",
|
NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d",
|
||||||
error->status, (error->status == 0) ? service->start_handle : -1);
|
error->status, (error->status == 0) ? service->start_handle : -1);
|
||||||
|
|
||||||
NimBLEClient *peer = (NimBLEClient*)arg;
|
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||||
int rc=0;
|
NimBLEClient *client = (NimBLEClient*)pTaskData->pATT;
|
||||||
|
|
||||||
// Make sure the service discovery is for this device
|
// Make sure the service discovery is for this device
|
||||||
if(peer->getConnId() != conn_handle){
|
if(client->getConnId() != conn_handle){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (error->status) {
|
if(error->status == 0) {
|
||||||
case 0: {
|
// Found a service - add it to the vector
|
||||||
// Found a service - add it to the vector
|
NimBLERemoteService* pRemoteService = new NimBLERemoteService(client, service);
|
||||||
NimBLERemoteService* pRemoteService = new NimBLERemoteService(peer, service);
|
client->m_servicesVector.push_back(pRemoteService);
|
||||||
peer->m_servicesVector.push_back(pRemoteService);
|
return 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BLE_HS_EDONE:{
|
|
||||||
// All services discovered; start discovering characteristics.
|
|
||||||
|
|
||||||
//NIMBLE_LOGD(LOG_TAG,"Giving search semaphore - completed");
|
|
||||||
peer->m_semaphoreSearchCmplEvt.give(0);
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// Error; abort discovery.
|
|
||||||
rc = error->status;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != 0) {
|
if(error->status == BLE_HS_EDONE) {
|
||||||
// pass non-zero to semaphore on error to indicate an error finding services
|
pTaskData->rc = 0;
|
||||||
peer->m_semaphoreSearchCmplEvt.give(1);
|
} else {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "characteristicDiscCB() rc=%d %s",
|
||||||
|
error->status,
|
||||||
|
NimBLEUtils::returnCodeToString(error->status));
|
||||||
|
pTaskData->rc = error->status;
|
||||||
}
|
}
|
||||||
NIMBLE_LOGD(LOG_TAG,"<< Service Discovered. status: %d", rc);
|
|
||||||
return rc;
|
xTaskNotifyGive(pTaskData->task);
|
||||||
|
|
||||||
|
NIMBLE_LOGD(LOG_TAG,"<< << Service Discovered");
|
||||||
|
return error->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -611,15 +613,11 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
* @param [in] arg = pointer to the client instance
|
* @param [in] arg = pointer to the client instance
|
||||||
*/
|
*/
|
||||||
/*STATIC*/ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
/*STATIC*/ int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||||
|
|
||||||
NimBLEClient* client = (NimBLEClient*)arg;
|
NimBLEClient* client = (NimBLEClient*)arg;
|
||||||
//struct ble_gap_conn_desc desc;
|
|
||||||
//struct ble_hs_adv_fields fields;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Got Client event %s", NimBLEUtils::gapEventToString(event->type));
|
NIMBLE_LOGD(LOG_TAG, "Got Client event %s", NimBLEUtils::gapEventToString(event->type));
|
||||||
|
|
||||||
// Execute handler code based on the type of event received.
|
|
||||||
switch(event->type) {
|
switch(event->type) {
|
||||||
|
|
||||||
case BLE_GAP_EVENT_DISCONNECT: {
|
case BLE_GAP_EVENT_DISCONNECT: {
|
||||||
|
@ -636,9 +634,6 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
|
|
||||||
NIMBLE_LOGI(LOG_TAG, "disconnect; reason=%d, %s", event->disconnect.reason,
|
NIMBLE_LOGI(LOG_TAG, "disconnect; reason=%d, %s", event->disconnect.reason,
|
||||||
NimBLEUtils::returnCodeToString(event->disconnect.reason));
|
NimBLEUtils::returnCodeToString(event->disconnect.reason));
|
||||||
//print_conn_desc(&event->disconnect.conn);
|
|
||||||
//MODLOG_DFLT(INFO, "\n");
|
|
||||||
|
|
||||||
|
|
||||||
// If Host reset tell the device now before returning to prevent
|
// If Host reset tell the device now before returning to prevent
|
||||||
// any errors caused by calling host functions before resyncing.
|
// any errors caused by calling host functions before resyncing.
|
||||||
|
@ -655,15 +650,9 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
//client->m_conn_id = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
|
||||||
// Indicate a non-success return value to any semaphores waiting
|
|
||||||
client->m_semaphoreOpenEvt.give(1);
|
|
||||||
client->m_semaphoreSearchCmplEvt.give(1);
|
|
||||||
client->m_semeaphoreSecEvt.give(1);
|
|
||||||
|
|
||||||
client->m_pClientCallbacks->onDisconnect(client);
|
client->m_pClientCallbacks->onDisconnect(client);
|
||||||
|
rc = event->disconnect.reason;
|
||||||
return 0;
|
break;
|
||||||
} // BLE_GAP_EVENT_DISCONNECT
|
} // BLE_GAP_EVENT_DISCONNECT
|
||||||
|
|
||||||
case BLE_GAP_EVENT_CONNECT: {
|
case BLE_GAP_EVENT_CONNECT: {
|
||||||
|
@ -683,31 +672,24 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
|
|
||||||
client->m_conn_id = event->connect.conn_handle;
|
client->m_conn_id = event->connect.conn_handle;
|
||||||
|
|
||||||
// rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
|
||||||
// assert(rc == 0);
|
|
||||||
// print_conn_desc(&desc);
|
|
||||||
// MODLOG_DFLT(INFO, "\n");
|
|
||||||
|
|
||||||
|
|
||||||
// In the case of a multiconnecting device we ignore this device when
|
|
||||||
// scanning since we are already connected to it
|
|
||||||
NimBLEDevice::addIgnored(client->m_peerAddress);
|
|
||||||
|
|
||||||
rc = ble_gattc_exchange_mtu(client->m_conn_id, NULL,NULL);
|
rc = ble_gattc_exchange_mtu(client->m_conn_id, NULL,NULL);
|
||||||
if(rc != 0) {
|
if(rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_exchange_mtu: rc=%d %s",rc,
|
NIMBLE_LOGE(LOG_TAG, "ble_gattc_exchange_mtu: rc=%d %s",rc,
|
||||||
NimBLEUtils::returnCodeToString(rc));
|
NimBLEUtils::returnCodeToString(rc));
|
||||||
// if error getting mtu indicate a connection error.
|
break;
|
||||||
client->m_semaphoreOpenEvt.give(rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In the case of a multiconnecting device we ignore this device when
|
||||||
|
// scanning since we are already connected to it
|
||||||
|
NimBLEDevice::addIgnored(client->m_peerAddress);
|
||||||
} else {
|
} else {
|
||||||
// Connection attempt failed
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "Error: Connection failed; status=%d %s",
|
NIMBLE_LOGE(LOG_TAG, "Error: Connection failed; status=%d %s",
|
||||||
event->connect.status,
|
event->connect.status,
|
||||||
NimBLEUtils::returnCodeToString(event->connect.status));
|
NimBLEUtils::returnCodeToString(event->connect.status));
|
||||||
|
|
||||||
client->m_isConnected = false;
|
client->m_isConnected = false;
|
||||||
client->m_semaphoreOpenEvt.give(event->connect.status);
|
rc = event->connect.status;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} // BLE_GAP_EVENT_CONNECT
|
} // BLE_GAP_EVENT_CONNECT
|
||||||
|
@ -719,7 +701,7 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Notify Recieved for handle: %d",event->notify_rx.attr_handle);
|
NIMBLE_LOGD(LOG_TAG, "Notify Recieved for handle: %d",event->notify_rx.attr_handle);
|
||||||
|
|
||||||
for(auto &it: client->m_servicesVector) {
|
for(auto &it: client->m_servicesVector) {
|
||||||
// Dont waste cycles searching services without this handle in their range
|
// Dont waste cycles searching services without this handle in its range
|
||||||
if(it->getEndHandle() < event->notify_rx.attr_handle) {
|
if(it->getEndHandle() < event->notify_rx.attr_handle) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -738,11 +720,10 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
if(characteristic != cVector->cend()) {
|
if(characteristic != cVector->cend()) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", (*characteristic)->toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", (*characteristic)->toString().c_str());
|
||||||
|
|
||||||
if((*characteristic)->m_semaphoreReadCharEvt.take(0, "notifyValue")) {
|
portENTER_CRITICAL(&(*characteristic)->m_valMux);
|
||||||
(*characteristic)->m_value = std::string((char *)event->notify_rx.om->om_data, event->notify_rx.om->om_len);
|
(*characteristic)->m_value = std::string((char *)event->notify_rx.om->om_data, event->notify_rx.om->om_len);
|
||||||
(*characteristic)->m_timestamp = time(nullptr);
|
(*characteristic)->m_timestamp = time(nullptr);
|
||||||
(*characteristic)->m_semaphoreReadCharEvt.give();
|
portEXIT_CRITICAL(&(*characteristic)->m_valMux);
|
||||||
}
|
|
||||||
|
|
||||||
if ((*characteristic)->m_notifyCallback != nullptr) {
|
if ((*characteristic)->m_notifyCallback != nullptr) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s",
|
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s",
|
||||||
|
@ -761,7 +742,7 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
case BLE_GAP_EVENT_CONN_UPDATE_REQ:
|
case BLE_GAP_EVENT_CONN_UPDATE_REQ:
|
||||||
case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: {
|
case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: {
|
||||||
if(client->m_conn_id != event->conn_update_req.conn_handle){
|
if(client->m_conn_id != event->conn_update_req.conn_handle){
|
||||||
return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE
|
return 0;
|
||||||
}
|
}
|
||||||
NIMBLE_LOGD(LOG_TAG, "Peer requesting to update connection parameters");
|
NIMBLE_LOGD(LOG_TAG, "Peer requesting to update connection parameters");
|
||||||
NIMBLE_LOGD(LOG_TAG, "MinInterval: %d, MaxInterval: %d, Latency: %d, Timeout: %d",
|
NIMBLE_LOGD(LOG_TAG, "MinInterval: %d, MaxInterval: %d, Latency: %d, Timeout: %d",
|
||||||
|
@ -787,7 +768,7 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
|
|
||||||
case BLE_GAP_EVENT_CONN_UPDATE: {
|
case BLE_GAP_EVENT_CONN_UPDATE: {
|
||||||
if(client->m_conn_id != event->conn_update.conn_handle){
|
if(client->m_conn_id != event->conn_update.conn_handle){
|
||||||
return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE
|
return 0;
|
||||||
}
|
}
|
||||||
if(event->conn_update.status == 0) {
|
if(event->conn_update.status == 0) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "Connection parameters updated.");
|
NIMBLE_LOGI(LOG_TAG, "Connection parameters updated.");
|
||||||
|
@ -799,7 +780,7 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
|
|
||||||
case BLE_GAP_EVENT_ENC_CHANGE: {
|
case BLE_GAP_EVENT_ENC_CHANGE: {
|
||||||
if(client->m_conn_id != event->enc_change.conn_handle){
|
if(client->m_conn_id != event->enc_change.conn_handle){
|
||||||
return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event->enc_change.status == 0) {
|
if(event->enc_change.status == 0) {
|
||||||
|
@ -814,23 +795,23 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client->m_semeaphoreSecEvt.give(event->enc_change.status);
|
rc = event->enc_change.status;
|
||||||
return 0;
|
break;
|
||||||
} //BLE_GAP_EVENT_ENC_CHANGE
|
} //BLE_GAP_EVENT_ENC_CHANGE
|
||||||
|
|
||||||
case BLE_GAP_EVENT_MTU: {
|
case BLE_GAP_EVENT_MTU: {
|
||||||
if(client->m_conn_id != event->mtu.conn_handle){
|
if(client->m_conn_id != event->mtu.conn_handle){
|
||||||
return 0; //BLE_HS_ENOTCONN BLE_ATT_ERR_INVALID_HANDLE
|
return 0;
|
||||||
}
|
}
|
||||||
NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d",
|
NIMBLE_LOGI(LOG_TAG, "mtu update event; conn_handle=%d mtu=%d",
|
||||||
event->mtu.conn_handle,
|
event->mtu.conn_handle,
|
||||||
event->mtu.value);
|
event->mtu.value);
|
||||||
client->m_semaphoreOpenEvt.give(0);
|
rc = 0;
|
||||||
return 0;
|
break;
|
||||||
} // BLE_GAP_EVENT_MTU
|
} // BLE_GAP_EVENT_MTU
|
||||||
|
|
||||||
case BLE_GAP_EVENT_PASSKEY_ACTION: {
|
case BLE_GAP_EVENT_PASSKEY_ACTION: {
|
||||||
struct ble_sm_io pkey = {0};
|
struct ble_sm_io pkey = {0,0};
|
||||||
|
|
||||||
if(client->m_conn_id != event->passkey.conn_handle)
|
if(client->m_conn_id != event->passkey.conn_handle)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -891,6 +872,14 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // Switch
|
} // Switch
|
||||||
|
|
||||||
|
if(client->m_pTaskData != nullptr) {
|
||||||
|
client->m_pTaskData->rc = rc;
|
||||||
|
xTaskNotifyGive(client->m_pTaskData->task);
|
||||||
|
client->m_pTaskData = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
} // handleGapEvent
|
} // handleGapEvent
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,13 @@
|
||||||
|
|
||||||
#include "NimBLEAddress.h"
|
#include "NimBLEAddress.h"
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLEAdvertisedDevice.h"
|
#include "NimBLEAdvertisedDevice.h"
|
||||||
#include "NimBLERemoteService.h"
|
#include "NimBLERemoteService.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const NimBLEUUID *uuid;
|
|
||||||
const void *attribute;
|
|
||||||
} disc_filter_t;
|
|
||||||
|
|
||||||
class NimBLERemoteService;
|
class NimBLERemoteService;
|
||||||
class NimBLEClientCallbacks;
|
class NimBLEClientCallbacks;
|
||||||
class NimBLEAdvertisedDevice;
|
class NimBLEAdvertisedDevice;
|
||||||
|
@ -89,14 +85,12 @@ private:
|
||||||
|
|
||||||
NimBLEAddress m_peerAddress = NimBLEAddress("");
|
NimBLEAddress m_peerAddress = NimBLEAddress("");
|
||||||
uint16_t m_conn_id;
|
uint16_t m_conn_id;
|
||||||
bool m_isConnected = false;
|
bool m_isConnected;
|
||||||
bool m_waitingToConnect =false;
|
bool m_waitingToConnect;
|
||||||
bool m_deleteCallbacks = true;
|
bool m_deleteCallbacks;
|
||||||
int32_t m_connectTimeout;
|
int32_t m_connectTimeout;
|
||||||
NimBLEClientCallbacks* m_pClientCallbacks = nullptr;
|
NimBLEClientCallbacks* m_pClientCallbacks;
|
||||||
FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt");
|
ble_task_data_t *m_pTaskData;
|
||||||
FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt");
|
|
||||||
FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security");
|
|
||||||
|
|
||||||
std::vector<NimBLERemoteService*> m_servicesVector;
|
std::vector<NimBLERemoteService*> m_servicesVector;
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
||||||
m_pRemoteService = pRemoteService;
|
m_pRemoteService = pRemoteService;
|
||||||
m_notifyCallback = nullptr;
|
m_notifyCallback = nullptr;
|
||||||
m_timestamp = 0;
|
m_timestamp = 0;
|
||||||
|
m_valMux = portMUX_INITIALIZER_UNLOCKED;
|
||||||
} // NimBLERemoteCharacteristic
|
} // NimBLERemoteCharacteristic
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
||||||
*@brief Destructor.
|
*@brief Destructor.
|
||||||
*/
|
*/
|
||||||
NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
|
NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
|
||||||
deleteDescriptors(); // Release resources for any descriptor information we may have allocated.
|
deleteDescriptors();
|
||||||
} // ~NimBLERemoteCharacteristic
|
} // ~NimBLERemoteCharacteristic
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -147,12 +148,12 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d",
|
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d",
|
||||||
error->status, (error->status == 0) ? dsc->handle : -1);
|
error->status, (error->status == 0) ? dsc->handle : -1);
|
||||||
|
|
||||||
disc_filter_t *filter = (disc_filter_t*)arg;
|
desc_filter_t *filter = (desc_filter_t*)arg;
|
||||||
NimBLEUUID *uuid_filter = (NimBLEUUID*)filter->uuid;
|
const NimBLEUUID *uuid_filter = filter->uuid;
|
||||||
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)filter->attribute;
|
ble_task_data_t *pTaskData = (ble_task_data_t*)filter->task_data;
|
||||||
|
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||||
int rc=0;
|
int rc=0;
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
|
||||||
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +173,7 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||||
rc = BLE_HS_EDONE;
|
rc = BLE_HS_EDONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Found a descriptor - add it to the vector
|
|
||||||
NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc);
|
NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc);
|
||||||
characteristic->m_descriptorVector.push_back(pNewRemoteDescriptor);
|
characteristic->m_descriptorVector.push_back(pNewRemoteDescriptor);
|
||||||
break;
|
break;
|
||||||
|
@ -182,18 +183,20 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If rc == BLE_HS_EDONE, release the semaphore with a success error code and stop the discovery process.
|
/** If rc == BLE_HS_EDONE, resume the task with a success error code and stop the discovery process.
|
||||||
* Else if rc == 0, just return 0 to continue the discovery until we get BLE_HS_EDONE.
|
* Else if rc == 0, just return 0 to continue the discovery until we get BLE_HS_EDONE.
|
||||||
* If we get any other error code tell the application to abort by returning non-zero in the semaphore rc.
|
* If we get any other error code tell the application to abort by returning non-zero in the rc.
|
||||||
*/
|
*/
|
||||||
if (rc == BLE_HS_EDONE) {
|
if (rc == BLE_HS_EDONE) {
|
||||||
characteristic->m_semaphoreGetDescEvt.give(0);
|
pTaskData->rc = 0;
|
||||||
|
xTaskNotifyGive(pTaskData->task);
|
||||||
} else if(rc != 0) {
|
} else if(rc != 0) {
|
||||||
/* Error; abort discovery. */
|
// Error; abort discovery.
|
||||||
// pass error code to semaphore waiting
|
pTaskData->rc = rc;
|
||||||
characteristic->m_semaphoreGetDescEvt.give(rc);
|
xTaskNotifyGive(pTaskData->task);
|
||||||
}
|
}
|
||||||
NIMBLE_LOGD(LOG_TAG,"<< Descriptor Discovered. status: %d", rc);
|
|
||||||
|
NIMBLE_LOGD(LOG_TAG,"<< Descriptor Discovered. status: %d", pTaskData->rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,11 +209,8 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> retrieveDescriptors() for characteristic: %s", getUUID().toString().c_str());
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
disc_filter_t filter;
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||||
filter.uuid = uuid_filter;
|
desc_filter_t filter = {uuid_filter, &taskData};
|
||||||
filter.attribute = this;
|
|
||||||
|
|
||||||
m_semaphoreGetDescEvt.take("retrieveDescriptors");
|
|
||||||
|
|
||||||
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
|
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
|
||||||
m_handle,
|
m_handle,
|
||||||
|
@ -219,11 +219,12 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt
|
||||||
&filter);
|
&filter);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
m_semaphoreGetDescEvt.give();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_semaphoreGetDescEvt.wait("retrieveDescriptors") != 0) {
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
|
if(taskData.rc != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,6 +338,22 @@ NimBLEUUID NimBLERemoteCharacteristic::getUUID() {
|
||||||
} // getUUID
|
} // getUUID
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the value of the remote characteristic.
|
||||||
|
* @return The value of the remote characteristic.
|
||||||
|
*/
|
||||||
|
std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) {
|
||||||
|
portENTER_CRITICAL(&m_valMux);
|
||||||
|
std::string value = m_value;
|
||||||
|
if(timestamp != nullptr) {
|
||||||
|
*timestamp = m_timestamp;
|
||||||
|
}
|
||||||
|
portEXIT_CRITICAL(&m_valMux);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an unsigned 16 bit value
|
* @brief Read an unsigned 16 bit value
|
||||||
* @return The unsigned 16 bit value.
|
* @return The unsigned 16 bit value.
|
||||||
|
@ -384,33 +401,31 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x",
|
NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x",
|
||||||
getUUID().toString().c_str(), getHandle(), getHandle());
|
getUUID().toString().c_str(), getHandle(), getHandle());
|
||||||
|
|
||||||
int rc = 0;
|
|
||||||
int retryCount = 1;
|
|
||||||
|
|
||||||
NimBLEClient* pClient = getRemoteService()->getClient();
|
NimBLEClient* pClient = getRemoteService()->getClient();
|
||||||
|
std::string value;
|
||||||
|
|
||||||
// Check to see that we are connected.
|
|
||||||
if (!pClient->isConnected()) {
|
if (!pClient->isConnected()) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Disconnected");
|
NIMBLE_LOGE(LOG_TAG, "Disconnected");
|
||||||
return "";
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
int rc = 0;
|
||||||
m_semaphoreReadCharEvt.take("readValue");
|
int retryCount = 1;
|
||||||
// Clear the value before reading.
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(),0, &value};
|
||||||
m_value = "";
|
|
||||||
|
|
||||||
|
do {
|
||||||
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
||||||
NimBLERemoteCharacteristic::onReadCB,
|
NimBLERemoteCharacteristic::onReadCB,
|
||||||
this);
|
&taskData);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d, %s",
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d, %s",
|
||||||
rc, NimBLEUtils::returnCodeToString(rc));
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
m_semaphoreReadCharEvt.give(0);
|
return value;
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = m_semaphoreReadCharEvt.wait("readValue");
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
rc = taskData.rc;
|
||||||
|
|
||||||
switch(rc){
|
switch(rc){
|
||||||
case 0:
|
case 0:
|
||||||
case BLE_HS_EDONE:
|
case BLE_HS_EDONE:
|
||||||
|
@ -428,39 +443,24 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
|
||||||
break;
|
break;
|
||||||
/* Else falls through. */
|
/* Else falls through. */
|
||||||
default:
|
default:
|
||||||
return "";
|
NIMBLE_LOGE(LOG_TAG, "<< readValue rc=%d", rc);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
} while(rc != 0 && retryCount--);
|
} while(rc != 0 && retryCount--);
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length());
|
portENTER_CRITICAL(&m_valMux);
|
||||||
|
m_value = value;
|
||||||
m_semaphoreReadCharEvt.take("returnValue");
|
m_timestamp = time(nullptr);
|
||||||
std::string value = m_value;
|
|
||||||
if(timestamp != nullptr) {
|
if(timestamp != nullptr) {
|
||||||
*timestamp = m_timestamp;
|
*timestamp = m_timestamp;
|
||||||
}
|
}
|
||||||
m_semaphoreReadCharEvt.give();
|
portEXIT_CRITICAL(&m_valMux);
|
||||||
|
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "<< readValue length: %d rc=%d", value.length(), rc);
|
||||||
return value;
|
return value;
|
||||||
} // readValue
|
} // readValue
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the value of the remote characteristic.
|
|
||||||
* @return The value of the remote characteristic.
|
|
||||||
*/
|
|
||||||
std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) {
|
|
||||||
m_semaphoreReadCharEvt.take("getValue");
|
|
||||||
std::string value = m_value;
|
|
||||||
if(timestamp != nullptr) {
|
|
||||||
*timestamp = m_timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_semaphoreReadCharEvt.give();
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Callback for characteristic read operation.
|
* @brief Callback for characteristic read operation.
|
||||||
* @return 0 or error code.
|
* @return 0 or error code.
|
||||||
|
@ -469,27 +469,35 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
|
||||||
const struct ble_gatt_error *error,
|
const struct ble_gatt_error *error,
|
||||||
struct ble_gatt_attr *attr, void *arg)
|
struct ble_gatt_attr *attr, void *arg)
|
||||||
{
|
{
|
||||||
NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg;
|
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||||
|
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||||
uint16_t conn_id = characteristic->getRemoteService()->getClient()->getConnId();
|
uint16_t conn_id = characteristic->getRemoteService()->getClient()->getConnId();
|
||||||
|
|
||||||
// Make sure the read is for this client
|
|
||||||
if(conn_id != conn_handle) {
|
if(conn_id != conn_handle) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGI(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
|
NIMBLE_LOGI(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||||
|
|
||||||
if(error->status == 0) {
|
std::string *strBuf = (std::string*)pTaskData->buf;
|
||||||
if(attr) {
|
int rc = error->status;
|
||||||
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
|
|
||||||
|
|
||||||
characteristic->m_value += std::string((char*) attr->om->om_data, attr->om->om_len);
|
if(rc == 0) {
|
||||||
characteristic->m_timestamp = time(nullptr);
|
if(attr) {
|
||||||
return 0;
|
if(((*strBuf).length() + attr->om->om_len) > BLE_ATT_ATTR_MAX_LEN) {
|
||||||
|
rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
|
} else {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
|
||||||
|
(*strBuf) += std::string((char*) attr->om->om_data, attr->om->om_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Read complete release semaphore and let the app can continue.
|
|
||||||
characteristic->m_semaphoreReadCharEvt.give(error->status);
|
pTaskData->rc = rc;
|
||||||
return 0;
|
xTaskNotifyGive(pTaskData->task);
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -509,7 +517,7 @@ bool NimBLERemoteCharacteristic::setNotify(uint16_t val, bool response, notify_c
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_notifyCallback = notifyCallback; // Save the notification callback.
|
m_notifyCallback = notifyCallback;
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< setNotify()");
|
NIMBLE_LOGD(LOG_TAG, "<< setNotify()");
|
||||||
|
|
||||||
|
@ -572,7 +580,7 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac
|
||||||
*/
|
*/
|
||||||
void NimBLERemoteCharacteristic::deleteDescriptors() {
|
void NimBLERemoteCharacteristic::deleteDescriptors() {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptors");
|
NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptors");
|
||||||
// Iterate through all the descriptors releasing their storage and erasing them from the vector.
|
|
||||||
for(auto &it: m_descriptorVector) {
|
for(auto &it: m_descriptorVector) {
|
||||||
delete it;
|
delete it;
|
||||||
}
|
}
|
||||||
|
@ -588,7 +596,7 @@ void NimBLERemoteCharacteristic::deleteDescriptors() {
|
||||||
*/
|
*/
|
||||||
size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID &uuid) {
|
size_t NimBLERemoteCharacteristic::deleteDescriptor(const NimBLEUUID &uuid) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptor");
|
NIMBLE_LOGD(LOG_TAG, ">> deleteDescriptor");
|
||||||
// Delete the requested descriptor.
|
|
||||||
for(auto it = m_descriptorVector.begin(); it != m_descriptorVector.end(); ++it) {
|
for(auto it = m_descriptorVector.begin(); it != m_descriptorVector.end(); ++it) {
|
||||||
if((*it)->getUUID() == uuid) {
|
if((*it)->getUUID() == uuid) {
|
||||||
delete *it;
|
delete *it;
|
||||||
|
@ -665,47 +673,45 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length,
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> writeValue(), length: %d", length);
|
NIMBLE_LOGD(LOG_TAG, ">> writeValue(), length: %d", length);
|
||||||
|
|
||||||
NimBLEClient* pClient = getRemoteService()->getClient();
|
NimBLEClient* pClient = getRemoteService()->getClient();
|
||||||
int rc = 0;
|
|
||||||
int retryCount = 1;
|
|
||||||
uint16_t mtu;
|
|
||||||
|
|
||||||
// Check to see that we are connected.
|
|
||||||
if (!pClient->isConnected()) {
|
if (!pClient->isConnected()) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Disconnected");
|
NIMBLE_LOGE(LOG_TAG, "Disconnected");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
int rc = 0;
|
||||||
|
int retryCount = 1;
|
||||||
|
uint16_t mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
||||||
|
|
||||||
// Check if the data length is longer than we can write in 1 connection event.
|
// Check if the data length is longer than we can write in one connection event.
|
||||||
// If so we must do a long write which requires a response.
|
// If so we must do a long write which requires a response.
|
||||||
if(length <= mtu && !response) {
|
if(length <= mtu && !response) {
|
||||||
rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length);
|
rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length);
|
||||||
return (rc==0);
|
return (rc==0);
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||||
m_semaphoreWriteCharEvt.take("writeValue");
|
|
||||||
|
|
||||||
|
do {
|
||||||
if(length > mtu) {
|
if(length > mtu) {
|
||||||
NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length);
|
NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length);
|
||||||
os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
|
os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
|
||||||
rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om,
|
rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om,
|
||||||
NimBLERemoteCharacteristic::onWriteCB,
|
NimBLERemoteCharacteristic::onWriteCB,
|
||||||
this);
|
&taskData);
|
||||||
} else {
|
} else {
|
||||||
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
|
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
|
||||||
data, length,
|
data, length,
|
||||||
NimBLERemoteCharacteristic::onWriteCB,
|
NimBLERemoteCharacteristic::onWriteCB,
|
||||||
this);
|
&taskData);
|
||||||
}
|
}
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to write characteristic; rc=%d", rc);
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to write characteristic; rc=%d", rc);
|
||||||
m_semaphoreWriteCharEvt.give();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = m_semaphoreWriteCharEvt.wait("writeValue");
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
rc = taskData.rc;
|
||||||
|
|
||||||
switch(rc){
|
switch(rc){
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -725,11 +731,12 @@ bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length,
|
||||||
break;
|
break;
|
||||||
/* Else falls through. */
|
/* Else falls through. */
|
||||||
default:
|
default:
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "<< writeValue, rc: %d", rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while(rc != 0 && retryCount--);
|
} while(rc != 0 && retryCount--);
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< writeValue, rc: %d",rc);
|
NIMBLE_LOGD(LOG_TAG, "<< writeValue, rc: %d", rc);
|
||||||
return (rc == 0);
|
return (rc == 0);
|
||||||
} // writeValue
|
} // writeValue
|
||||||
|
|
||||||
|
@ -742,29 +749,21 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
|
||||||
const struct ble_gatt_error *error,
|
const struct ble_gatt_error *error,
|
||||||
struct ble_gatt_attr *attr, void *arg)
|
struct ble_gatt_attr *attr, void *arg)
|
||||||
{
|
{
|
||||||
NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg;
|
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||||
|
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)pTaskData->pATT;
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
|
||||||
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
|
NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||||
|
|
||||||
characteristic->m_semaphoreWriteCharEvt.give(error->status);
|
pTaskData->rc = error->status;
|
||||||
|
xTaskNotifyGive(pTaskData->task);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NimBLERemoteCharacteristic::releaseSemaphores() {
|
|
||||||
for (auto &it: m_descriptorVector) {
|
|
||||||
it->releaseSemaphores();
|
|
||||||
}
|
|
||||||
m_semaphoreWriteCharEvt.give(1);
|
|
||||||
m_semaphoreGetDescEvt.give(1);
|
|
||||||
m_semaphoreReadCharEvt.give(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -32,6 +32,12 @@ class NimBLERemoteDescriptor;
|
||||||
typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic,
|
typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic,
|
||||||
uint8_t* pData, size_t length, bool isNotify);
|
uint8_t* pData, size_t length, bool isNotify);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const NimBLEUUID *uuid;
|
||||||
|
void *task_data;
|
||||||
|
} desc_filter_t;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A model of a remote %BLE characteristic.
|
* @brief A model of a remote %BLE characteristic.
|
||||||
*/
|
*/
|
||||||
|
@ -110,7 +116,6 @@ private:
|
||||||
struct ble_gatt_attr *attr, void *arg);
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||||
struct ble_gatt_attr *attr, void *arg);
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
void releaseSemaphores();
|
|
||||||
static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
static int descriptorDiscCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||||
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
|
uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc,
|
||||||
void *arg);
|
void *arg);
|
||||||
|
@ -121,12 +126,10 @@ private:
|
||||||
uint16_t m_handle;
|
uint16_t m_handle;
|
||||||
uint16_t m_defHandle;
|
uint16_t m_defHandle;
|
||||||
NimBLERemoteService* m_pRemoteService;
|
NimBLERemoteService* m_pRemoteService;
|
||||||
FreeRTOS::Semaphore m_semaphoreGetDescEvt = FreeRTOS::Semaphore("GetDescEvt");
|
|
||||||
FreeRTOS::Semaphore m_semaphoreReadCharEvt = FreeRTOS::Semaphore("ReadCharEvt");
|
|
||||||
FreeRTOS::Semaphore m_semaphoreWriteCharEvt = FreeRTOS::Semaphore("WriteCharEvt");
|
|
||||||
std::string m_value;
|
std::string m_value;
|
||||||
notify_callback m_notifyCallback;
|
notify_callback m_notifyCallback;
|
||||||
time_t m_timestamp;
|
time_t m_timestamp;
|
||||||
|
portMUX_TYPE m_valMux;
|
||||||
|
|
||||||
// We maintain a vector of descriptors owned by this characteristic.
|
// We maintain a vector of descriptors owned by this characteristic.
|
||||||
std::vector<NimBLERemoteDescriptor*> m_descriptorVector;
|
std::vector<NimBLERemoteDescriptor*> m_descriptorVector;
|
||||||
|
|
|
@ -45,9 +45,9 @@ NimBLERemoteDescriptor::NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemo
|
||||||
m_uuid = nullptr;
|
m_uuid = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_handle = dsc->handle;
|
m_handle = dsc->handle;
|
||||||
m_pRemoteCharacteristic = pRemoteCharacteristic;
|
m_pRemoteCharacteristic = pRemoteCharacteristic;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,96 +78,6 @@ NimBLEUUID NimBLERemoteDescriptor::getUUID() {
|
||||||
} // getUUID
|
} // getUUID
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Callback for Descriptor read operation.
|
|
||||||
* @return 0 or error code.
|
|
||||||
*/
|
|
||||||
int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
|
|
||||||
const struct ble_gatt_error *error,
|
|
||||||
struct ble_gatt_attr *attr, void *arg)
|
|
||||||
{
|
|
||||||
NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)arg;
|
|
||||||
uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId();
|
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
|
||||||
if(conn_id != conn_handle){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
|
|
||||||
|
|
||||||
if(error->status == 0){
|
|
||||||
if(attr){
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
|
|
||||||
|
|
||||||
desc->m_value += std::string((char*) attr->om->om_data, attr->om->om_len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read complete release semaphore and let the app can continue.
|
|
||||||
desc->m_semaphoreReadDescrEvt.give(error->status);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string NimBLERemoteDescriptor::readValue() {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str());
|
|
||||||
|
|
||||||
int rc = 0;
|
|
||||||
int retryCount = 1;
|
|
||||||
// Clear the value before reading.
|
|
||||||
m_value = "";
|
|
||||||
|
|
||||||
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
|
|
||||||
|
|
||||||
// Check to see that we are connected.
|
|
||||||
if (!pClient->isConnected()) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "Disconnected");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
m_semaphoreReadDescrEvt.take("ReadDescriptor");
|
|
||||||
|
|
||||||
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
|
||||||
NimBLERemoteDescriptor::onReadCB,
|
|
||||||
this);
|
|
||||||
if (rc != 0) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read descriptor; rc=%d, %s",
|
|
||||||
rc, NimBLEUtils::returnCodeToString(rc));
|
|
||||||
m_semaphoreReadDescrEvt.give(0);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = m_semaphoreReadDescrEvt.wait("ReadDescriptor");
|
|
||||||
|
|
||||||
switch(rc){
|
|
||||||
case 0:
|
|
||||||
case BLE_HS_EDONE:
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
// Descriptor is not long-readable, return with what we have.
|
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
|
|
||||||
NIMBLE_LOGI(LOG_TAG, "Attribute not long");
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
|
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
|
|
||||||
if (retryCount && pClient->secureConnection())
|
|
||||||
break;
|
|
||||||
/* Else falls through. */
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
} while(rc != 0 && retryCount--);
|
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %d", m_value.length());
|
|
||||||
return m_value;
|
|
||||||
} // readValue
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t NimBLERemoteDescriptor::readUInt8() {
|
uint8_t NimBLERemoteDescriptor::readUInt8() {
|
||||||
std::string value = readValue();
|
std::string value = readValue();
|
||||||
if (value.length() >= 1) {
|
if (value.length() >= 1) {
|
||||||
|
@ -195,6 +105,100 @@ uint32_t NimBLERemoteDescriptor::readUInt32() {
|
||||||
} // readUInt32
|
} // readUInt32
|
||||||
|
|
||||||
|
|
||||||
|
std::string NimBLERemoteDescriptor::readValue() {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str());
|
||||||
|
|
||||||
|
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
|
||||||
|
std::string value;
|
||||||
|
|
||||||
|
if (!pClient->isConnected()) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Disconnected");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = 0;
|
||||||
|
int retryCount = 1;
|
||||||
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(),0, &value};
|
||||||
|
|
||||||
|
do {
|
||||||
|
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
||||||
|
NimBLERemoteDescriptor::onReadCB,
|
||||||
|
&taskData);
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read descriptor; rc=%d, %s",
|
||||||
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
rc = taskData.rc;
|
||||||
|
|
||||||
|
switch(rc){
|
||||||
|
case 0:
|
||||||
|
case BLE_HS_EDONE:
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
// Descriptor is not long-readable, return with what we have.
|
||||||
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Attribute not long");
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
||||||
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR):
|
||||||
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
|
||||||
|
if (retryCount && pClient->secureConnection())
|
||||||
|
break;
|
||||||
|
/* Else falls through. */
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
} while(rc != 0 && retryCount--);
|
||||||
|
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %d rc=%d", value.length(), rc);
|
||||||
|
return value;
|
||||||
|
} // readValue
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback for Descriptor read operation.
|
||||||
|
* @return 0 or error code.
|
||||||
|
*/
|
||||||
|
int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
|
||||||
|
const struct ble_gatt_error *error,
|
||||||
|
struct ble_gatt_attr *attr, void *arg)
|
||||||
|
{
|
||||||
|
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||||
|
NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)pTaskData->pATT;
|
||||||
|
uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId();
|
||||||
|
|
||||||
|
if(conn_id != conn_handle){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||||
|
|
||||||
|
std::string *strBuf = (std::string*)pTaskData->buf;
|
||||||
|
int rc = error->status;
|
||||||
|
|
||||||
|
if(rc == 0) {
|
||||||
|
if(attr) {
|
||||||
|
if(((*strBuf).length() + attr->om->om_len) > BLE_ATT_ATTR_MAX_LEN) {
|
||||||
|
rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||||
|
} else {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
|
||||||
|
(*strBuf) += std::string((char*) attr->om->om_data, attr->om->om_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pTaskData->rc = rc;
|
||||||
|
xTaskNotifyGive(pTaskData->task);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return a string representation of this BLE Remote Descriptor.
|
* @brief Return a string representation of this BLE Remote Descriptor.
|
||||||
* @retun A string representation of this BLE Remote Descriptor.
|
* @retun A string representation of this BLE Remote Descriptor.
|
||||||
|
@ -218,16 +222,17 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
|
||||||
const struct ble_gatt_error *error,
|
const struct ble_gatt_error *error,
|
||||||
struct ble_gatt_attr *attr, void *arg)
|
struct ble_gatt_attr *attr, void *arg)
|
||||||
{
|
{
|
||||||
NimBLERemoteDescriptor* descriptor = (NimBLERemoteDescriptor*)arg;
|
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||||
|
NimBLERemoteDescriptor* descriptor = (NimBLERemoteDescriptor*)pTaskData->pATT;
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
|
||||||
if(descriptor->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){
|
if(descriptor->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
|
NIMBLE_LOGI(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||||
|
|
||||||
descriptor->m_semaphoreDescWrite.give(error->status);
|
pTaskData->rc = error->status;
|
||||||
|
xTaskNotifyGive(pTaskData->task);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -245,17 +250,15 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
|
||||||
|
|
||||||
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
|
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
|
||||||
|
|
||||||
int rc = 0;
|
|
||||||
int retryCount = 1;
|
|
||||||
uint16_t mtu;
|
|
||||||
|
|
||||||
// Check to see that we are connected.
|
// Check to see that we are connected.
|
||||||
if (!pClient->isConnected()) {
|
if (!pClient->isConnected()) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Disconnected");
|
NIMBLE_LOGE(LOG_TAG, "Disconnected");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
int rc = 0;
|
||||||
|
int retryCount = 1;
|
||||||
|
uint16_t mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
||||||
|
|
||||||
// Check if the data length is longer than we can write in 1 connection event.
|
// Check if the data length is longer than we can write in 1 connection event.
|
||||||
// If so we must do a long write which requires a response.
|
// If so we must do a long write which requires a response.
|
||||||
|
@ -264,31 +267,31 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
|
||||||
return (rc == 0);
|
return (rc == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||||
m_semaphoreDescWrite.take("WriteDescriptor");
|
|
||||||
|
|
||||||
|
do {
|
||||||
if(length > mtu) {
|
if(length > mtu) {
|
||||||
NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length);
|
NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length);
|
||||||
os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
|
os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
|
||||||
rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om,
|
rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om,
|
||||||
NimBLERemoteDescriptor::onWriteCB,
|
NimBLERemoteDescriptor::onWriteCB,
|
||||||
this);
|
&taskData);
|
||||||
} else {
|
} else {
|
||||||
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
|
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
|
||||||
data, length,
|
data, length,
|
||||||
NimBLERemoteDescriptor::onWriteCB,
|
NimBLERemoteDescriptor::onWriteCB,
|
||||||
this);
|
&taskData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to write descriptor; rc=%d", rc);
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to write descriptor; rc=%d", rc);
|
||||||
m_semaphoreDescWrite.give();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = m_semaphoreDescWrite.wait("WriteDescriptor");
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
rc = taskData.rc;
|
||||||
|
|
||||||
switch(rc){
|
switch(rc) {
|
||||||
case 0:
|
case 0:
|
||||||
case BLE_HS_EDONE:
|
case BLE_HS_EDONE:
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
@ -335,13 +338,5 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t newValue, bool response) {
|
||||||
} // writeValue
|
} // writeValue
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief In the event of an error this is called to make sure we don't block.
|
|
||||||
*/
|
|
||||||
void NimBLERemoteDescriptor::releaseSemaphores() {
|
|
||||||
m_semaphoreDescWrite.give(1);
|
|
||||||
m_semaphoreReadDescrEvt.give(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -31,16 +31,24 @@ public:
|
||||||
uint16_t getHandle();
|
uint16_t getHandle();
|
||||||
NimBLERemoteCharacteristic* getRemoteCharacteristic();
|
NimBLERemoteCharacteristic* getRemoteCharacteristic();
|
||||||
NimBLEUUID getUUID();
|
NimBLEUUID getUUID();
|
||||||
std::string readValue(void);
|
std::string readValue();
|
||||||
uint8_t readUInt8(void);
|
|
||||||
uint16_t readUInt16(void);
|
template<typename T>
|
||||||
uint32_t readUInt32(void);
|
T readValue(bool skipSizeCheck = false) {
|
||||||
|
std::string value = readValue();
|
||||||
|
if(!skipSizeCheck && value.size() < sizeof(T)) return T();
|
||||||
|
const char *pData = value.data();
|
||||||
|
return *((T *)pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t readUInt8() __attribute__ ((deprecated));
|
||||||
|
uint16_t readUInt16() __attribute__ ((deprecated));
|
||||||
|
uint32_t readUInt32() __attribute__ ((deprecated));
|
||||||
std::string toString(void);
|
std::string toString(void);
|
||||||
bool writeValue(const uint8_t* data, size_t length, bool response = false);
|
bool writeValue(const uint8_t* data, size_t length, bool response = false);
|
||||||
bool writeValue(const std::string &newValue, bool response = false);
|
bool writeValue(const std::string &newValue, bool response = false);
|
||||||
bool writeValue(uint8_t newValue, bool response = false);
|
bool writeValue(uint8_t newValue, bool response = false);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLERemoteCharacteristic;
|
friend class NimBLERemoteCharacteristic;
|
||||||
|
|
||||||
|
@ -50,16 +58,10 @@ private:
|
||||||
struct ble_gatt_attr *attr, void *arg);
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||||
struct ble_gatt_attr *attr, void *arg);
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
void releaseSemaphores();
|
|
||||||
|
|
||||||
uint16_t m_handle;
|
uint16_t m_handle;
|
||||||
NimBLEUUID m_uuid;
|
NimBLEUUID m_uuid;
|
||||||
std::string m_value;
|
|
||||||
NimBLERemoteCharacteristic* m_pRemoteCharacteristic;
|
NimBLERemoteCharacteristic* m_pRemoteCharacteristic;
|
||||||
FreeRTOS::Semaphore m_semaphoreReadDescrEvt = FreeRTOS::Semaphore("ReadDescrEvt");
|
|
||||||
FreeRTOS::Semaphore m_semaphoreDescWrite = FreeRTOS::Semaphore("WriteDescEvt");
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
|
@ -148,43 +148,34 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||||
NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d",
|
NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d",
|
||||||
error->status, (error->status == 0) ? chr->val_handle : -1);
|
error->status, (error->status == 0) ? chr->val_handle : -1);
|
||||||
|
|
||||||
NimBLERemoteService *service = (NimBLERemoteService*)arg;
|
ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
|
||||||
int rc=0;
|
NimBLERemoteService *service = (NimBLERemoteService*)pTaskData->pATT;
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
// Make sure the discovery is for this device
|
||||||
if(service->getClient()->getConnId() != conn_handle){
|
if(service->getClient()->getConnId() != conn_handle){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (error->status) {
|
if(error->status == 0) {
|
||||||
case 0: {
|
// Found a service - add it to the vector
|
||||||
// Found a service - add it to the vector
|
NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr);
|
||||||
NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr);
|
service->m_characteristicVector.push_back(pRemoteCharacteristic);
|
||||||
service->m_characteristicVector.push_back(pRemoteCharacteristic);
|
return 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BLE_HS_EDONE:{
|
|
||||||
/** All characteristics in this service discovered; start discovering
|
|
||||||
* characteristics in the next service.
|
|
||||||
*/
|
|
||||||
service->m_semaphoreGetCharEvt.give(0);
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
rc = error->status;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (rc != 0) {
|
|
||||||
/* Error; abort discovery. */
|
if(error->status == BLE_HS_EDONE) {
|
||||||
// pass non-zero to semaphore on error to indicate an error finding characteristics
|
pTaskData->rc = 0;
|
||||||
// release memory from any characteristics we created
|
} else {
|
||||||
//service->deleteCharacteristics(); --this will now be done when we clear services on returning with error
|
NIMBLE_LOGE(LOG_TAG, "characteristicDiscCB() rc=%d %s",
|
||||||
NIMBLE_LOGE(LOG_TAG, "characteristicDiscCB() rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
error->status,
|
||||||
service->m_semaphoreGetCharEvt.give(1);
|
NimBLEUtils::returnCodeToString(error->status));
|
||||||
|
pTaskData->rc = error->status;
|
||||||
}
|
}
|
||||||
NIMBLE_LOGD(LOG_TAG,"<< Characteristic Discovered. status: %d", rc);
|
|
||||||
return rc;
|
xTaskNotifyGive(pTaskData->task);
|
||||||
|
|
||||||
|
NIMBLE_LOGD(LOG_TAG,"<< Characteristic Discovered");
|
||||||
|
return error->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,32 +188,31 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> retrieveCharacteristics() for service: %s", getUUID().toString().c_str());
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
//deleteCharacteristics(); // Forget any previous characteristics.
|
ble_task_data_t taskData = {this, xTaskGetCurrentTaskHandle(), 0, nullptr};
|
||||||
|
|
||||||
m_semaphoreGetCharEvt.take("retrieveCharacteristics");
|
|
||||||
|
|
||||||
if(uuid_filter == nullptr) {
|
if(uuid_filter == nullptr) {
|
||||||
rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(),
|
rc = ble_gattc_disc_all_chrs(m_pClient->getConnId(),
|
||||||
m_startHandle,
|
m_startHandle,
|
||||||
m_endHandle,
|
m_endHandle,
|
||||||
NimBLERemoteService::characteristicDiscCB,
|
NimBLERemoteService::characteristicDiscCB,
|
||||||
this);
|
&taskData);
|
||||||
} else {
|
} else {
|
||||||
rc = ble_gattc_disc_chrs_by_uuid(m_pClient->getConnId(),
|
rc = ble_gattc_disc_chrs_by_uuid(m_pClient->getConnId(),
|
||||||
m_startHandle,
|
m_startHandle,
|
||||||
m_endHandle,
|
m_endHandle,
|
||||||
&uuid_filter->getNative()->u,
|
&uuid_filter->getNative()->u,
|
||||||
NimBLERemoteService::characteristicDiscCB,
|
NimBLERemoteService::characteristicDiscCB,
|
||||||
this);
|
&taskData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGE(LOG_TAG, "ble_gattc_disc_all_chrs: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
m_semaphoreGetCharEvt.give();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0){
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
|
if(taskData.rc == 0){
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -319,7 +309,7 @@ void NimBLERemoteService::deleteCharacteristics() {
|
||||||
for(auto &it: m_characteristicVector) {
|
for(auto &it: m_characteristicVector) {
|
||||||
delete it;
|
delete it;
|
||||||
}
|
}
|
||||||
m_characteristicVector.clear(); // Clear the vector
|
m_characteristicVector.clear();
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< deleteCharacteristics");
|
NIMBLE_LOGD(LOG_TAG, "<< deleteCharacteristics");
|
||||||
} // deleteCharacteristics
|
} // deleteCharacteristics
|
||||||
|
|
||||||
|
@ -331,7 +321,7 @@ void NimBLERemoteService::deleteCharacteristics() {
|
||||||
*/
|
*/
|
||||||
size_t NimBLERemoteService::deleteCharacteristic(const NimBLEUUID &uuid) {
|
size_t NimBLERemoteService::deleteCharacteristic(const NimBLEUUID &uuid) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> deleteCharacteristic");
|
NIMBLE_LOGD(LOG_TAG, ">> deleteCharacteristic");
|
||||||
// Delete the requested characteristic.
|
|
||||||
for(auto it = m_characteristicVector.begin(); it != m_characteristicVector.end(); ++it) {
|
for(auto it = m_characteristicVector.begin(); it != m_characteristicVector.end(); ++it) {
|
||||||
if((*it)->getUUID() == uuid) {
|
if((*it)->getUUID() == uuid) {
|
||||||
delete *it;
|
delete *it;
|
||||||
|
@ -374,16 +364,5 @@ std::string NimBLERemoteService::toString() {
|
||||||
} // toString
|
} // toString
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief called when an error occurrs and we need to release the semaphores to resume operations.
|
|
||||||
* Will release all characteristic and subsequently all descriptor semaphores for this service.
|
|
||||||
*/
|
|
||||||
void NimBLERemoteService::releaseSemaphores() {
|
|
||||||
for(auto &it: m_characteristicVector) {
|
|
||||||
it->releaseSemaphores();
|
|
||||||
}
|
|
||||||
m_semaphoreGetCharEvt.give(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
#include "NimBLEClient.h"
|
#include "NimBLEClient.h"
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
#include "FreeRTOS.h"
|
|
||||||
#include "NimBLERemoteCharacteristic.h"
|
#include "NimBLERemoteCharacteristic.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -79,7 +78,6 @@ private:
|
||||||
std::vector<NimBLERemoteCharacteristic*> m_characteristicVector;
|
std::vector<NimBLERemoteCharacteristic*> m_characteristicVector;
|
||||||
|
|
||||||
NimBLEClient* m_pClient;
|
NimBLEClient* m_pClient;
|
||||||
FreeRTOS::Semaphore m_semaphoreGetCharEvt = FreeRTOS::Semaphore("GetCharEvt");
|
|
||||||
NimBLEUUID m_uuid;
|
NimBLEUUID m_uuid;
|
||||||
uint16_t m_startHandle;
|
uint16_t m_startHandle;
|
||||||
uint16_t m_endHandle;
|
uint16_t m_endHandle;
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
#include "NimBLEScan.h"
|
#include "NimBLEScan.h"
|
||||||
#include "NimBLEUtils.h"
|
|
||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
|
@ -70,6 +69,7 @@ NimBLEScan::NimBLEScan() {
|
||||||
m_pAdvertisedDeviceCallbacks = nullptr;
|
m_pAdvertisedDeviceCallbacks = nullptr;
|
||||||
m_stopped = true;
|
m_stopped = true;
|
||||||
m_wantDuplicates = false;
|
m_wantDuplicates = false;
|
||||||
|
m_pTaskData = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,14 +101,6 @@ NimBLEScan::NimBLEScan() {
|
||||||
|
|
||||||
NimBLEAddress advertisedAddress(event->disc.addr);
|
NimBLEAddress advertisedAddress(event->disc.addr);
|
||||||
|
|
||||||
// Print advertisement data
|
|
||||||
// print_adv_fields(&fields);
|
|
||||||
|
|
||||||
// If we are not scanning, nothing to do with the extra results.
|
|
||||||
if (pScan->m_stopped) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Examine our list of ignored addresses and stop processing if we don't want to see it or are already connected
|
// Examine our list of ignored addresses and stop processing if we don't want to see it or are already connected
|
||||||
if(NimBLEDevice::isIgnored(advertisedAddress)) {
|
if(NimBLEDevice::isIgnored(advertisedAddress)) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "Ignoring device: address: %s", advertisedAddress.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "Ignoring device: address: %s", advertisedAddress.toString().c_str());
|
||||||
|
@ -131,7 +123,6 @@ NimBLEScan::NimBLEScan() {
|
||||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||||
advertisedDevice->setAddressType(event->disc.addr.type);
|
advertisedDevice->setAddressType(event->disc.addr.type);
|
||||||
advertisedDevice->setAddress(advertisedAddress);
|
advertisedDevice->setAddress(advertisedAddress);
|
||||||
//NIMBLE_LOGE(LOG_TAG, "advertisement type: %d, %s",event->disc.event_type, NimBLEUtils::advTypeToString(event->disc.event_type));
|
|
||||||
advertisedDevice->setAdvType(event->disc.event_type);
|
advertisedDevice->setAdvType(event->disc.event_type);
|
||||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||||
NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "NEW DEVICE FOUND: %s", advertisedAddress.toString().c_str());
|
||||||
|
@ -153,7 +144,6 @@ NimBLEScan::NimBLEScan() {
|
||||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||||
}
|
}
|
||||||
//m_pAdvertisedDeviceCallbacks->onResult(*advertisedDevice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -167,7 +157,11 @@ NimBLEScan::NimBLEScan() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pScan->m_stopped = true;
|
pScan->m_stopped = true;
|
||||||
pScan->m_semaphoreScanEnd.give();
|
if(pScan->m_pTaskData != nullptr) {
|
||||||
|
pScan->m_pTaskData->rc = event->disc_complete.reason;
|
||||||
|
xTaskNotifyGive(pScan->m_pTaskData->task);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +243,6 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stopped = false;
|
m_stopped = false;
|
||||||
m_semaphoreScanEnd.take("start");
|
|
||||||
|
|
||||||
// Save the callback to be invoked when the scan completes.
|
// Save the callback to be invoked when the scan completes.
|
||||||
m_scanCompleteCB = scanCompleteCB;
|
m_scanCompleteCB = scanCompleteCB;
|
||||||
|
@ -275,7 +268,7 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||||
rc = ble_gap_disc(m_own_addr_type, duration, &m_scan_params,
|
rc = ble_gap_disc(m_own_addr_type, duration, &m_scan_params,
|
||||||
NimBLEScan::handleGapEvent, this);
|
NimBLEScan::handleGapEvent, this);
|
||||||
if(rc == BLE_HS_EBUSY) {
|
if(rc == BLE_HS_EBUSY) {
|
||||||
vTaskDelay(2);
|
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
} while(rc == BLE_HS_EBUSY);
|
} while(rc == BLE_HS_EBUSY);
|
||||||
|
|
||||||
|
@ -283,7 +276,6 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||||
NIMBLE_LOGE(LOG_TAG, "Error initiating GAP discovery procedure; rc=%d, %s",
|
NIMBLE_LOGE(LOG_TAG, "Error initiating GAP discovery procedure; rc=%d, %s",
|
||||||
rc, NimBLEUtils::returnCodeToString(rc));
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
m_stopped = true;
|
m_stopped = true;
|
||||||
m_semaphoreScanEnd.give();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,9 +290,18 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||||
* @return The BLEScanResults.
|
* @return The BLEScanResults.
|
||||||
*/
|
*/
|
||||||
NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) {
|
NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) {
|
||||||
if(start(duration, nullptr, is_continue)) {
|
if(duration == 0) {
|
||||||
m_semaphoreScanEnd.wait("start"); // Wait for the semaphore to release.
|
NIMBLE_LOGW(LOG_TAG, "Blocking scan called with duration = forever");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ble_task_data_t taskData = {nullptr, xTaskGetCurrentTaskHandle(),0, nullptr};
|
||||||
|
m_pTaskData = &taskData;
|
||||||
|
|
||||||
|
if(start(duration, nullptr, is_continue)) {
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pTaskData = nullptr;
|
||||||
return m_scanResults;
|
return m_scanResults;
|
||||||
} // start
|
} // start
|
||||||
|
|
||||||
|
@ -309,13 +310,13 @@ NimBLEScanResults NimBLEScan::start(uint32_t duration, bool is_continue) {
|
||||||
* @brief Stop an in progress scan.
|
* @brief Stop an in progress scan.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::stop() {
|
bool NimBLEScan::stop() {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> stop()");
|
NIMBLE_LOGD(LOG_TAG, ">> stop()");
|
||||||
|
|
||||||
int rc = ble_gap_disc_cancel();
|
int rc = ble_gap_disc_cancel();
|
||||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d\n", rc);
|
NIMBLE_LOGE(LOG_TAG, "Failed to cancel scan; rc=%d\n", rc);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_stopped = true;
|
m_stopped = true;
|
||||||
|
@ -324,9 +325,12 @@ void NimBLEScan::stop() {
|
||||||
m_scanCompleteCB(m_scanResults);
|
m_scanCompleteCB(m_scanResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_semaphoreScanEnd.give();
|
if(m_pTaskData != nullptr) {
|
||||||
|
xTaskNotifyGive(m_pTaskData->task);
|
||||||
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< stop()");
|
NIMBLE_LOGD(LOG_TAG, "<< stop()");
|
||||||
|
return true;
|
||||||
} // stop
|
} // stop
|
||||||
|
|
||||||
|
|
||||||
|
@ -350,7 +354,6 @@ void NimBLEScan::erase(const NimBLEAddress &address) {
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::onHostReset() {
|
void NimBLEScan::onHostReset() {
|
||||||
m_stopped = true;
|
m_stopped = true;
|
||||||
m_semaphoreScanEnd.give();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
#include "NimBLEAdvertisedDevice.h"
|
#include "NimBLEAdvertisedDevice.h"
|
||||||
#include "FreeRTOS.h"
|
#include "NimBLEUtils.h"
|
||||||
|
|
||||||
#include "host/ble_gap.h"
|
#include "host/ble_gap.h"
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public:
|
||||||
void setActiveScan(bool active);
|
void setActiveScan(bool active);
|
||||||
void setInterval(uint16_t intervalMSecs);
|
void setInterval(uint16_t intervalMSecs);
|
||||||
void setWindow(uint16_t windowMSecs);
|
void setWindow(uint16_t windowMSecs);
|
||||||
void stop();
|
bool stop();
|
||||||
void clearResults();
|
void clearResults();
|
||||||
NimBLEScanResults getResults();
|
NimBLEScanResults getResults();
|
||||||
void erase(const NimBLEAddress &address);
|
void erase(const NimBLEAddress &address);
|
||||||
|
@ -85,8 +85,8 @@ private:
|
||||||
bool m_stopped;
|
bool m_stopped;
|
||||||
bool m_wantDuplicates;
|
bool m_wantDuplicates;
|
||||||
NimBLEScanResults m_scanResults;
|
NimBLEScanResults m_scanResults;
|
||||||
FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd");
|
|
||||||
uint32_t m_duration;
|
uint32_t m_duration;
|
||||||
|
ble_task_data_t *m_pTaskData;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
|
@ -502,8 +502,13 @@ void print_bytes(const uint8_t *bytes, int len)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
MODLOG_DFLT(DEBUG, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
|
MODLOG_DFLT(ERROR, "%s0x%02x", i != 0 ? ":" : "", bytes[i]);
|
||||||
|
if(i % 30 == 0){
|
||||||
|
MODLOG_DFLT(ERROR, "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODLOG_DFLT(ERROR, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_mbuf(const struct os_mbuf *om)
|
void print_mbuf(const struct os_mbuf *om)
|
||||||
|
|
Loading…
Reference in a new issue