mirror of https://github.com/arendst/Tasmota.git
update NimBLE-Arduino
This commit is contained in:
parent
9a7f252d88
commit
7064a82fbf
|
@ -100,7 +100,7 @@ The `BLEAdvertisedDeviceCallbacks` class `onResult()` method now receives a poin
|
||||||
Defined as:
|
Defined as:
|
||||||
```
|
```
|
||||||
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
||||||
bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_TYPE_PUBLIC, bool refreshServices = true);
|
bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_PUBLIC, bool refreshServices = true);
|
||||||
```
|
```
|
||||||
If set to false the client will use the services database it retrieved from the peripheral last time it connected.
|
If set to false the client will use the services database it retrieved from the peripheral last time it connected.
|
||||||
This allows for faster connections and power saving if the devices just dropped connection and want to reconnect.
|
This allows for faster connections and power saving if the devices just dropped connection and want to reconnect.
|
||||||
|
@ -111,6 +111,46 @@ NimBLERemoteCharacteristic::registerForNotify();
|
||||||
```
|
```
|
||||||
Now return true or false to indicate success or failure so you can choose to disconnect or try again.
|
Now return true or false to indicate success or failure so you can choose to disconnect or try again.
|
||||||
|
|
||||||
|
```
|
||||||
|
NimBLEClient::getServices()
|
||||||
|
NimBLERemoteService::getCharacteristics()
|
||||||
|
```
|
||||||
|
Now return a pointer to a `std::vector` of the respective object database instead of `std::map`.
|
||||||
|
|
||||||
|
`NimBLERemoteService::getCharacteristicsByHandle()`
|
||||||
|
Has been removed from the API as it is no longer maintained in the library.
|
||||||
|
|
||||||
|
The last two above changes reduce the heap usage significantly with minimal application code adjustments.
|
||||||
|
|
||||||
|
**NEW** on May 23, 2020
|
||||||
|
> ```
|
||||||
|
> NimBLEClient::getServices(bool refresh = false)
|
||||||
|
> NimBLERemoteService::getCharacteristics(bool refresh = false)
|
||||||
|
> NimBLERemoteCharacteristic::getDecriptors(bool refresh = false)
|
||||||
|
>```
|
||||||
|
> These methods now take an optional (bool) parameter.
|
||||||
|
If true it will clear the respective vector and retrieve all the respective attributes from the peripheral.
|
||||||
|
If false it will retrieve the attributes only if the vector is empty, otherwise the vector is returned
|
||||||
|
with the currently stored attributes.
|
||||||
|
|
||||||
|
> Removed the automatic discovery of all peripheral attributes as they consumed time and resources for data
|
||||||
|
the user may not be interested in.
|
||||||
|
|
||||||
|
> Added `NimBLEClient::discoverAtrributes()` for the user to discover all the peripheral attributes
|
||||||
|
to replace the the former functionality.
|
||||||
|
|
||||||
|
|
||||||
|
> ```
|
||||||
|
>getService(NimBLEUUID)
|
||||||
|
>getCharacteristic(NimBLEUUID)
|
||||||
|
>getDescriptor(NimBLEUUID)
|
||||||
|
>```
|
||||||
|
>These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only)
|
||||||
|
the specified attribute from the peripheral.
|
||||||
|
|
||||||
|
> These changes allow more control for the user to manage the resources used for the attributes.
|
||||||
|
|
||||||
|
|
||||||
#### Client Security:
|
#### Client Security:
|
||||||
The client will automatically initiate security when the peripheral responds that it's required.
|
The client will automatically initiate security when the peripheral responds that it's required.
|
||||||
The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
|
The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
# *** UPDATE ***
|
# *** UPDATE ***
|
||||||
Server now handles long reads and writes, still work to do on client.
|
**Breaking change:** Client and scan now use `std::vector` instead of `std::map` for storing the remote attribute database.
|
||||||
|
|
||||||
NEW Client callback created - ```bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params)```
|
This change will affect your application code if you use `NimBLEClient::getServices()` or `NimBLERemoteService::getCharacteristics()`
|
||||||
Called when the server wants to change the connection parameters, return true to accept them or false if not.
|
in your application as they now return a pointer to `std::vector` of the respective attributes.
|
||||||
Check NimBLE_Client.ino example for a demonstration.
|
|
||||||
|
|
||||||
|
In addition `NimBLERemoteService::getCharacteristicsByHandle()` has been removed as it is no longer maintained in the library.
|
||||||
|
|
||||||
|
These changes were necessary due to the amount of resources required to use `std::map`, it was not justifed by any benfit it provided.
|
||||||
|
|
||||||
|
It is expected that there will be minimal impact on most applications, if you need help adjusting your code please create an issue.
|
||||||
|
|
||||||
# NimBLE-Arduino
|
# NimBLE-Arduino
|
||||||
A fork of the NimBLE stack restructured for compilation in the Ardruino IDE with a CPP library for use with ESP32.
|
A fork of the NimBLE stack restructured for compilation in the Ardruino IDE with a CPP library for use with ESP32.
|
||||||
|
@ -59,10 +62,9 @@ Change the settings in the `nimconfig.h` file to customize NimBLE to your projec
|
||||||
|
|
||||||
# Continuing development:
|
# Continuing development:
|
||||||
|
|
||||||
This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@0a1604a.](https://github.com/espressif/esp-nimble)
|
This Library is tracking the esp-nimble repo, nimble-1.2.0-idf master branch, currently [@fead24e.](https://github.com/espressif/esp-nimble)
|
||||||
|
|
||||||
Also tracking the NimBLE related changes in esp-idf, master branch, currently [@48bd2d7.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
|
||||||
|
|
||||||
|
Also tracking the NimBLE related changes in esp-idf, master branch, currently [@2bc28bb.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
|
||||||
|
|
||||||
# Acknowledgments:
|
# Acknowledgments:
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,7 @@ class ServerCallbacks: public NimBLEServerCallbacks {
|
||||||
void onAuthenticationComplete(ble_gap_conn_desc* desc){
|
void onAuthenticationComplete(ble_gap_conn_desc* desc){
|
||||||
/** Check that encryption was successful, if not we disconnect the client */
|
/** Check that encryption was successful, if not we disconnect the client */
|
||||||
if(!desc->sec_state.encrypted) {
|
if(!desc->sec_state.encrypted) {
|
||||||
/** NOTE: createServer returns the current server reference unless one is not already created */
|
NimBLEDevice::getServer()->disconnect(desc->conn_handle);
|
||||||
NimBLEDevice::createServer()->disconnect(desc->conn_handle);
|
|
||||||
Serial.println("Encrypt connection failed - disconnecting client");
|
Serial.println("Encrypt connection failed - disconnecting client");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLE2902.h"
|
#include "NimBLE2902.h"
|
||||||
|
|
||||||
NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic)
|
NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic)
|
||||||
|
@ -72,4 +75,5 @@ void NimBLE2902::setNotifications(bool flag) {
|
||||||
else pValue[0] &= ~(1 << 0);
|
else pValue[0] &= ~(1 << 0);
|
||||||
} // setNotifications
|
} // setNotifications
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif
|
#endif
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEDescriptor.h"
|
#include "NimBLEDescriptor.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -46,5 +49,6 @@ private:
|
||||||
|
|
||||||
}; // NimBLE2902
|
}; // NimBLE2902
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* MAIN_NIMBLE2902_H_ */
|
#endif /* MAIN_NIMBLE2902_H_ */
|
|
@ -19,6 +19,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLE2904.h"
|
#include "NimBLE2904.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,4 +86,5 @@ void NimBLE2904::setUnit(uint16_t unit) {
|
||||||
setValue((uint8_t*) &m_data, sizeof(m_data));
|
setValue((uint8_t*) &m_data, sizeof(m_data));
|
||||||
} // setUnit
|
} // setUnit
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif
|
#endif
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEDescriptor.h"
|
#include "NimBLEDescriptor.h"
|
||||||
|
|
||||||
struct BLE2904_Data {
|
struct BLE2904_Data {
|
||||||
|
@ -78,5 +81,6 @@ private:
|
||||||
BLE2904_Data m_data;
|
BLE2904_Data m_data;
|
||||||
}; // BLE2904
|
}; // BLE2904
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* MAIN_NIMBLE2904_H_ */
|
#endif /* MAIN_NIMBLE2904_H_ */
|
|
@ -14,9 +14,13 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "NimBLEAddress.h"
|
#include "NimBLEAddress.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
|
static const char* LOG_TAG = "NimBLEAddress";
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
NOTE: NimBLE addresses are in INVERSE ORDER!
|
NOTE: NimBLE addresses are in INVERSE ORDER!
|
||||||
|
@ -43,26 +47,49 @@ NimBLEAddress::NimBLEAddress(ble_addr_t address) {
|
||||||
*
|
*
|
||||||
* @param [in] stringAddress The hex representation of the address.
|
* @param [in] stringAddress The hex representation of the address.
|
||||||
*/
|
*/
|
||||||
NimBLEAddress::NimBLEAddress(std::string stringAddress) {
|
NimBLEAddress::NimBLEAddress(const std::string &stringAddress) {
|
||||||
if (stringAddress.length() != 17) return;
|
if (stringAddress.length() == 0) {
|
||||||
|
memset(m_address, 0, 6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stringAddress.length() == 6) {
|
||||||
|
std::reverse_copy(stringAddress.data(), stringAddress.data() + 6, m_address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stringAddress.length() != 17) {
|
||||||
|
memset(m_address, 0, sizeof m_address); // "00:00:00:00:00:00" represents an invalid address
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "Invalid address '%s'", stringAddress.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int data[6];
|
int data[6];
|
||||||
sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[5], &data[4], &data[3], &data[2], &data[1], &data[0]);
|
if(sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[5], &data[4], &data[3], &data[2], &data[1], &data[0]) != 6) {
|
||||||
m_address[0] = (uint8_t) data[0];
|
memset(m_address, 0, sizeof m_address); // "00:00:00:00:00:00" represents an invalid address
|
||||||
m_address[1] = (uint8_t) data[1];
|
NIMBLE_LOGD(LOG_TAG, "Invalid address '%s'", stringAddress.c_str());
|
||||||
m_address[2] = (uint8_t) data[2];
|
}
|
||||||
m_address[3] = (uint8_t) data[3];
|
for(size_t index = 0; index < sizeof m_address; index++) {
|
||||||
m_address[4] = (uint8_t) data[4];
|
m_address[index] = data[index];
|
||||||
m_address[5] = (uint8_t) data[5];
|
}
|
||||||
} // BLEAddress
|
} // BLEAddress
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructor for compatibility with bluedrioid esp library.
|
* @brief Constructor for compatibility with bluedroid esp library.
|
||||||
* @param [in] esp_bd_addr_t struct containing the address.
|
* @param [in] uint8_t[6] or esp_bd_addr_t struct containing the address.
|
||||||
*/
|
*/
|
||||||
NimBLEAddress::NimBLEAddress(esp_bd_addr_t address) {
|
NimBLEAddress::NimBLEAddress(uint8_t address[6]) {
|
||||||
NimBLEUtils::memrcpy(m_address, address, 6);
|
std::reverse_copy(address, address + sizeof m_address, m_address);
|
||||||
|
} // NimBLEAddress
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor for address using a hex value. Use the same byte order, so use 0xa4c1385def16 for "a4:c1:38:5d:ef:16"
|
||||||
|
* @param [in] uint64_t containing the address.
|
||||||
|
*/
|
||||||
|
NimBLEAddress::NimBLEAddress(const uint64_t &address) {
|
||||||
|
memcpy(m_address, &address, sizeof m_address);
|
||||||
} // NimBLEAddress
|
} // NimBLEAddress
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,8 +98,8 @@ NimBLEAddress::NimBLEAddress(esp_bd_addr_t address) {
|
||||||
* @param [in] otherAddress The other address to compare against.
|
* @param [in] otherAddress The other address to compare against.
|
||||||
* @return True if the addresses are equal.
|
* @return True if the addresses are equal.
|
||||||
*/
|
*/
|
||||||
bool NimBLEAddress::equals(NimBLEAddress otherAddress) {
|
bool NimBLEAddress::equals(const NimBLEAddress &otherAddress) const {
|
||||||
return memcmp(otherAddress.getNative(), m_address, 6) == 0;
|
return *this == otherAddress;
|
||||||
} // equals
|
} // equals
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +107,7 @@ bool NimBLEAddress::equals(NimBLEAddress otherAddress) {
|
||||||
* @brief Return the native representation of the address.
|
* @brief Return the native representation of the address.
|
||||||
* @return The native representation of the address.
|
* @return The native representation of the address.
|
||||||
*/
|
*/
|
||||||
uint8_t *NimBLEAddress::getNative() {
|
const uint8_t *NimBLEAddress::getNative() const {
|
||||||
return m_address;
|
return m_address;
|
||||||
} // getNative
|
} // getNative
|
||||||
|
|
||||||
|
@ -96,13 +123,23 @@ uint8_t *NimBLEAddress::getNative() {
|
||||||
*
|
*
|
||||||
* @return The string representation of the address.
|
* @return The string representation of the address.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAddress::toString() {
|
std::string NimBLEAddress::toString() const {
|
||||||
auto size = 18;
|
return std::string(*this);
|
||||||
char *res = (char*)malloc(size);
|
|
||||||
snprintf(res, size, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[5], m_address[4], m_address[3], m_address[2], m_address[1], m_address[0]);
|
|
||||||
std::string ret(res);
|
|
||||||
free(res);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
} // toString
|
} // toString
|
||||||
|
|
||||||
|
|
||||||
|
bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const {
|
||||||
|
return memcmp(rhs.m_address, m_address, sizeof m_address) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NimBLEAddress::operator !=(const NimBLEAddress & rhs) const {
|
||||||
|
return !this->operator==(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
NimBLEAddress::operator std::string() const {
|
||||||
|
char buffer[18];
|
||||||
|
sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[5], m_address[4], m_address[3], m_address[2], m_address[1], m_address[0]);
|
||||||
|
return std::string(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,22 +24,7 @@
|
||||||
/**************************/
|
/**************************/
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
typedef enum {
|
|
||||||
BLE_ADDR_TYPE_PUBLIC = 0x00,
|
|
||||||
BLE_ADDR_TYPE_RANDOM = 0x01,
|
|
||||||
BLE_ADDR_TYPE_RPA_PUBLIC = 0x02,
|
|
||||||
BLE_ADDR_TYPE_RPA_RANDOM = 0x03,
|
|
||||||
} esp_nimble_addr_type_t;
|
|
||||||
|
|
||||||
typedef uint8_t esp_ble_addr_type_t ;
|
|
||||||
|
|
||||||
/// Bluetooth address length
|
|
||||||
#define ESP_BD_ADDR_LEN 6
|
|
||||||
|
|
||||||
/// Bluetooth device address
|
|
||||||
typedef uint8_t esp_bd_addr_t[ESP_BD_ADDR_LEN];
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A %BLE device address.
|
* @brief A %BLE device address.
|
||||||
|
@ -49,11 +34,16 @@ typedef uint8_t esp_bd_addr_t[ESP_BD_ADDR_LEN];
|
||||||
class NimBLEAddress {
|
class NimBLEAddress {
|
||||||
public:
|
public:
|
||||||
NimBLEAddress(ble_addr_t address);
|
NimBLEAddress(ble_addr_t address);
|
||||||
NimBLEAddress(esp_bd_addr_t address);
|
NimBLEAddress(uint8_t address[6]);
|
||||||
NimBLEAddress(std::string stringAddress);
|
NimBLEAddress(const std::string &stringAddress);
|
||||||
bool equals(NimBLEAddress otherAddress);
|
NimBLEAddress(const uint64_t &address);
|
||||||
uint8_t* getNative();
|
bool equals(const NimBLEAddress &otherAddress) const;
|
||||||
std::string toString();
|
const uint8_t* getNative() const;
|
||||||
|
std::string toString() const;
|
||||||
|
|
||||||
|
bool operator ==(const NimBLEAddress & rhs) const;
|
||||||
|
bool operator !=(const NimBLEAddress & rhs) const;
|
||||||
|
operator std::string() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t m_address[6];
|
uint8_t m_address[6];
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
#include "NimBLEAdvertisedDevice.h"
|
#include "NimBLEAdvertisedDevice.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
@ -141,7 +144,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID() { //TODO Remove it eventual
|
||||||
* @brief Check advertised serviced for existence required UUID
|
* @brief Check advertised serviced for existence required UUID
|
||||||
* @return Return true if service is advertised
|
* @return Return true if service is advertised
|
||||||
*/
|
*/
|
||||||
bool NimBLEAdvertisedDevice::isAdvertisingService(NimBLEUUID uuid){
|
bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid){
|
||||||
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "Comparing UUIDS: %s %s", m_serviceUUIDs[i].toString().c_str(), uuid.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "Comparing UUIDS: %s %s", m_serviceUUIDs[i].toString().c_str(), uuid.toString().c_str());
|
||||||
if (m_serviceUUIDs[i].equals(uuid)) return true;
|
if (m_serviceUUIDs[i].equals(uuid)) return true;
|
||||||
|
@ -441,6 +444,12 @@ void NimBLEAdvertisedDevice::setServiceUUID(const char* serviceUUID) {
|
||||||
* @param [in] serviceUUID The discovered serviceUUID
|
* @param [in] serviceUUID The discovered serviceUUID
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisedDevice::setServiceUUID(NimBLEUUID serviceUUID) {
|
void NimBLEAdvertisedDevice::setServiceUUID(NimBLEUUID serviceUUID) {
|
||||||
|
// Don't add duplicates
|
||||||
|
for (int i = 0; i < m_serviceUUIDs.size(); i++) {
|
||||||
|
if (m_serviceUUIDs[i].equals(serviceUUID)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
m_serviceUUIDs.push_back(serviceUUID);
|
m_serviceUUIDs.push_back(serviceUUID);
|
||||||
m_haveServiceUUID = true;
|
m_haveServiceUUID = true;
|
||||||
NIMBLE_LOGD(LOG_TAG,"- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG,"- addServiceUUID(): serviceUUID: %s", serviceUUID.toString().c_str());
|
||||||
|
@ -542,5 +551,6 @@ void NimBLEAdvertisedDevice::setAdvertisementResult(uint8_t* payload, uint8_t le
|
||||||
m_payloadLength = length;
|
m_payloadLength = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
#include "NimBLEAddress.h"
|
#include "NimBLEAddress.h"
|
||||||
#include "NimBLEScan.h"
|
#include "NimBLEScan.h"
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
|
@ -54,7 +57,7 @@ public:
|
||||||
void setAddressType(uint8_t type);
|
void setAddressType(uint8_t type);
|
||||||
|
|
||||||
|
|
||||||
bool isAdvertisingService(NimBLEUUID uuid);
|
bool isAdvertisingService(const NimBLEUUID &uuid);
|
||||||
bool haveAppearance();
|
bool haveAppearance();
|
||||||
bool haveManufacturerData();
|
bool haveManufacturerData();
|
||||||
bool haveName();
|
bool haveName();
|
||||||
|
@ -92,7 +95,7 @@ private:
|
||||||
bool m_haveTXPower;
|
bool m_haveTXPower;
|
||||||
|
|
||||||
|
|
||||||
NimBLEAddress m_address = NimBLEAddress("\0\0\0\0\0\0");
|
NimBLEAddress m_address = NimBLEAddress("");
|
||||||
uint8_t m_advType;
|
uint8_t m_advType;
|
||||||
uint16_t m_appearance;
|
uint16_t m_appearance;
|
||||||
int m_deviceType;
|
int m_deviceType;
|
||||||
|
@ -129,5 +132,6 @@ public:
|
||||||
virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0;
|
virtual void onResult(NimBLEAdvertisedDevice* advertisedDevice) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */
|
#endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
*/
|
*/
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
|
||||||
#include "services/gap/ble_svc_gap.h"
|
#include "services/gap/ble_svc_gap.h"
|
||||||
#include "NimBLEAdvertising.h"
|
#include "NimBLEAdvertising.h"
|
||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
|
@ -58,7 +62,7 @@ NimBLEAdvertising::NimBLEAdvertising() {
|
||||||
* @brief Add a service uuid to exposed list of services.
|
* @brief Add a service uuid to exposed list of services.
|
||||||
* @param [in] serviceUUID The UUID of the service to expose.
|
* @param [in] serviceUUID The UUID of the service to expose.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::addServiceUUID(NimBLEUUID serviceUUID) {
|
void NimBLEAdvertising::addServiceUUID(const NimBLEUUID &serviceUUID) {
|
||||||
m_serviceUUIDs.push_back(serviceUUID);
|
m_serviceUUIDs.push_back(serviceUUID);
|
||||||
} // addServiceUUID
|
} // addServiceUUID
|
||||||
|
|
||||||
|
@ -188,10 +192,17 @@ void NimBLEAdvertising::start() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(NimBLEDevice::createServer()->getConnectedCount() >= NIMBLE_MAX_CONNECTIONS) {
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
NimBLEServer* pServer = NimBLEDevice::getServer();
|
||||||
|
if(pServer != nullptr) {
|
||||||
|
if(!pServer->m_gattsStarted){
|
||||||
|
pServer->start();
|
||||||
|
} else if(pServer->getConnectedCount() >= NIMBLE_MAX_CONNECTIONS) {
|
||||||
NIMBLE_LOGW(LOG_TAG, "Max connections reached - not advertising");
|
NIMBLE_LOGW(LOG_TAG, "Max connections reached - not advertising");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int numServices = m_serviceUUIDs.size();
|
int numServices = m_serviceUUIDs.size();
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -203,11 +214,6 @@ void NimBLEAdvertising::start() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NimBLEServer* pServer = NimBLEDevice::createServer();
|
|
||||||
if(!pServer->m_gattsStarted){
|
|
||||||
pServer->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_customAdvData && !m_advSvcsSet && numServices > 0) {
|
if (!m_customAdvData && !m_advSvcsSet && numServices > 0) {
|
||||||
for (int i = 0; i < numServices; i++) {
|
for (int i = 0; i < numServices; i++) {
|
||||||
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_16) {
|
if(m_serviceUUIDs[i].getNative()->u.type == BLE_UUID_TYPE_16) {
|
||||||
|
@ -352,8 +358,15 @@ void NimBLEAdvertising::start() {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER,
|
rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER,
|
||||||
&m_advParams, NimBLEServer::handleGapEvent, NimBLEDevice::createServer()); //get a reference to the server (does not create a new one)
|
&m_advParams,
|
||||||
|
(pServer != nullptr) ? NimBLEServer::handleGapEvent : NULL,
|
||||||
|
pServer);
|
||||||
|
#else
|
||||||
|
rc = ble_gap_adv_start(addressType, NULL, BLE_HS_FOREVER,
|
||||||
|
&m_advParams, NULL,NULL);
|
||||||
|
#endif
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGC(LOG_TAG, "Error enabling advertising; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
NIMBLE_LOGC(LOG_TAG, "Error enabling advertising; rc=%d, %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
abort();
|
abort();
|
||||||
|
@ -393,7 +406,7 @@ void NimBLEAdvertising::onHostReset() {
|
||||||
* @brief Add data to the payload to be advertised.
|
* @brief Add data to the payload to be advertised.
|
||||||
* @param [in] data The data to be added to the payload.
|
* @param [in] data The data to be added to the payload.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::addData(std::string data) {
|
void NimBLEAdvertisementData::addData(const std::string &data) {
|
||||||
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -420,7 +433,7 @@ void NimBLEAdvertisementData::setAppearance(uint16_t appearance) {
|
||||||
* @brief Set the complete services.
|
* @brief Set the complete services.
|
||||||
* @param [in] uuid The single service to advertise.
|
* @param [in] uuid The single service to advertise.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setCompleteServices(NimBLEUUID uuid) {
|
void NimBLEAdvertisementData::setCompleteServices(const NimBLEUUID &uuid) {
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
switch (uuid.bitSize()) {
|
switch (uuid.bitSize()) {
|
||||||
case 16: {
|
case 16: {
|
||||||
|
@ -482,7 +495,7 @@ void NimBLEAdvertisementData::setFlags(uint8_t flag) {
|
||||||
* @brief Set manufacturer specific data.
|
* @brief Set manufacturer specific data.
|
||||||
* @param [in] data Manufacturer data.
|
* @param [in] data Manufacturer data.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setManufacturerData(std::string data) {
|
void NimBLEAdvertisementData::setManufacturerData(const std::string &data) {
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData");
|
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setManufacturerData");
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
cdata[0] = data.length() + 1;
|
cdata[0] = data.length() + 1;
|
||||||
|
@ -496,7 +509,7 @@ void NimBLEAdvertisementData::setManufacturerData(std::string data) {
|
||||||
* @brief Set the name.
|
* @brief Set the name.
|
||||||
* @param [in] The complete name of the device.
|
* @param [in] The complete name of the device.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setName(std::string name) {
|
void NimBLEAdvertisementData::setName(const std::string &name) {
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str());
|
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setName: %s", name.c_str());
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
cdata[0] = name.length() + 1;
|
cdata[0] = name.length() + 1;
|
||||||
|
@ -510,7 +523,7 @@ void NimBLEAdvertisementData::setName(std::string name) {
|
||||||
* @brief Set the partial services.
|
* @brief Set the partial services.
|
||||||
* @param [in] uuid The single service to advertise.
|
* @param [in] uuid The single service to advertise.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setPartialServices(NimBLEUUID uuid) {
|
void NimBLEAdvertisementData::setPartialServices(const NimBLEUUID &uuid) {
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
switch (uuid.bitSize()) {
|
switch (uuid.bitSize()) {
|
||||||
case 16: {
|
case 16: {
|
||||||
|
@ -548,7 +561,7 @@ void NimBLEAdvertisementData::setPartialServices(NimBLEUUID uuid) {
|
||||||
* @param [in] uuid The UUID to set with the service data. Size of UUID will be used.
|
* @param [in] uuid The UUID to set with the service data. Size of UUID will be used.
|
||||||
* @param [in] data The data to be associated with the service data advert.
|
* @param [in] data The data to be associated with the service data advert.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setServiceData(NimBLEUUID uuid, std::string data) {
|
void NimBLEAdvertisementData::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
switch (uuid.bitSize()) {
|
switch (uuid.bitSize()) {
|
||||||
case 16: {
|
case 16: {
|
||||||
|
@ -585,7 +598,7 @@ void NimBLEAdvertisementData::setServiceData(NimBLEUUID uuid, std::string data)
|
||||||
* @brief Set the short name.
|
* @brief Set the short name.
|
||||||
* @param [in] The short name of the device.
|
* @param [in] The short name of the device.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisementData::setShortName(std::string name) {
|
void NimBLEAdvertisementData::setShortName(const std::string &name) {
|
||||||
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str());
|
NIMBLE_LOGD("NimBLEAdvertisementData", ">> setShortName: %s", name.c_str());
|
||||||
char cdata[2];
|
char cdata[2];
|
||||||
cdata[0] = name.length() + 1;
|
cdata[0] = name.length() + 1;
|
||||||
|
@ -603,4 +616,5 @@ std::string NimBLEAdvertisementData::getPayload() {
|
||||||
return m_payload;
|
return m_payload;
|
||||||
} // getPayload
|
} // getPayload
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
|
||||||
#include "host/ble_gap.h"
|
#include "host/ble_gap.h"
|
||||||
/**** FIX COMPILATION ****/
|
/**** FIX COMPILATION ****/
|
||||||
#undef min
|
#undef min
|
||||||
|
@ -47,14 +50,14 @@ class NimBLEAdvertisementData {
|
||||||
//
|
//
|
||||||
public:
|
public:
|
||||||
void setAppearance(uint16_t appearance);
|
void setAppearance(uint16_t appearance);
|
||||||
void setCompleteServices(NimBLEUUID uuid);
|
void setCompleteServices(const NimBLEUUID &uuid);
|
||||||
void setFlags(uint8_t);
|
void setFlags(uint8_t);
|
||||||
void setManufacturerData(std::string data);
|
void setManufacturerData(const std::string &data);
|
||||||
void setName(std::string name);
|
void setName(const std::string &name);
|
||||||
void setPartialServices(NimBLEUUID uuid);
|
void setPartialServices(const NimBLEUUID &uuid);
|
||||||
void setServiceData(NimBLEUUID uuid, std::string data);
|
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||||
void setShortName(std::string name);
|
void setShortName(const std::string &name);
|
||||||
void addData(std::string data); // Add data to the payload.
|
void addData(const std::string &data); // Add data to the payload.
|
||||||
std::string getPayload(); // Retrieve the current advert payload.
|
std::string getPayload(); // Retrieve the current advert payload.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -71,7 +74,7 @@ private:
|
||||||
class NimBLEAdvertising {
|
class NimBLEAdvertising {
|
||||||
public:
|
public:
|
||||||
NimBLEAdvertising();
|
NimBLEAdvertising();
|
||||||
void addServiceUUID(NimBLEUUID serviceUUID);
|
void addServiceUUID(const NimBLEUUID &serviceUUID);
|
||||||
void addServiceUUID(const char* serviceUUID);
|
void addServiceUUID(const char* serviceUUID);
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
@ -90,7 +93,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEDevice;
|
friend class NimBLEDevice;
|
||||||
|
|
||||||
void onHostReset();
|
void onHostReset();
|
||||||
|
|
||||||
ble_hs_adv_fields m_advData;
|
ble_hs_adv_fields m_advData;
|
||||||
ble_hs_adv_fields m_scanData;
|
ble_hs_adv_fields m_scanData;
|
||||||
ble_gap_adv_params m_advParams;
|
ble_gap_adv_params m_advParams;
|
||||||
|
@ -101,5 +106,7 @@ private:
|
||||||
bool m_advSvcsSet = false;
|
bool m_advSvcsSet = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* MAIN_BLEADVERTISING_H_ */
|
#endif /* MAIN_BLEADVERTISING_H_ */
|
|
@ -13,6 +13,7 @@
|
||||||
*/
|
*/
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "NimBLEBeacon.h"
|
#include "NimBLEBeacon.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
@ -58,7 +59,7 @@ int8_t NimBLEBeacon::getSignalPower() {
|
||||||
/**
|
/**
|
||||||
* Set the raw data for the beacon record.
|
* Set the raw data for the beacon record.
|
||||||
*/
|
*/
|
||||||
void NimBLEBeacon::setData(std::string data) {
|
void NimBLEBeacon::setData(const std::string &data) {
|
||||||
if (data.length() != sizeof(m_beaconData)) {
|
if (data.length() != sizeof(m_beaconData)) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
|
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
|
||||||
data.length(), sizeof(m_beaconData));
|
data.length(), sizeof(m_beaconData));
|
||||||
|
@ -79,14 +80,14 @@ void NimBLEBeacon::setMinor(uint16_t minor) {
|
||||||
m_beaconData.minor = ENDIAN_CHANGE_U16(minor);
|
m_beaconData.minor = ENDIAN_CHANGE_U16(minor);
|
||||||
} // setMinior
|
} // setMinior
|
||||||
|
|
||||||
void NimBLEBeacon::setProximityUUID(NimBLEUUID uuid) {
|
void NimBLEBeacon::setProximityUUID(const NimBLEUUID &uuid) {
|
||||||
uuid = uuid.to128();
|
NimBLEUUID temp_uuid = uuid;
|
||||||
memcpy(m_beaconData.proximityUUID, uuid.getNative()->u128.value, 16);
|
temp_uuid.to128();
|
||||||
|
memcpy(m_beaconData.proximityUUID, temp_uuid.getNative()->u128.value, 16);
|
||||||
} // setProximityUUID
|
} // setProximityUUID
|
||||||
|
|
||||||
void NimBLEBeacon::setSignalPower(int8_t signalPower) {
|
void NimBLEBeacon::setSignalPower(int8_t signalPower) {
|
||||||
m_beaconData.signalPower = signalPower;
|
m_beaconData.signalPower = signalPower;
|
||||||
} // setSignalPower
|
} // setSignalPower
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#ifndef MAIN_NIMBLEBEACON_H_
|
#ifndef MAIN_NIMBLEBEACON_H_
|
||||||
#define MAIN_NIMBLEBEACON_H_
|
#define MAIN_NIMBLEBEACON_H_
|
||||||
|
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
/**
|
/**
|
||||||
* @brief Representation of a beacon.
|
* @brief Representation of a beacon.
|
||||||
|
@ -39,11 +40,11 @@ public:
|
||||||
uint16_t getManufacturerId();
|
uint16_t getManufacturerId();
|
||||||
NimBLEUUID getProximityUUID();
|
NimBLEUUID getProximityUUID();
|
||||||
int8_t getSignalPower();
|
int8_t getSignalPower();
|
||||||
void setData(std::string data);
|
void setData(const std::string &data);
|
||||||
void setMajor(uint16_t major);
|
void setMajor(uint16_t major);
|
||||||
void setMinor(uint16_t minor);
|
void setMinor(uint16_t minor);
|
||||||
void setManufacturerId(uint16_t manufacturerId);
|
void setManufacturerId(uint16_t manufacturerId);
|
||||||
void setProximityUUID(NimBLEUUID uuid);
|
void setProximityUUID(const NimBLEUUID &uuid);
|
||||||
void setSignalPower(int8_t signalPower);
|
void setSignalPower(int8_t signalPower);
|
||||||
}; // NimBLEBeacon
|
}; // NimBLEBeacon
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLECharacteristic.h"
|
#include "NimBLECharacteristic.h"
|
||||||
#include "NimBLE2902.h"
|
#include "NimBLE2902.h"
|
||||||
#include "NimBLE2904.h"
|
#include "NimBLE2904.h"
|
||||||
|
@ -41,7 +44,7 @@ NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties
|
||||||
* @param [in] uuid - UUID for the characteristic.
|
* @param [in] uuid - UUID for the characteristic.
|
||||||
* @param [in] properties - Properties for the characteristic.
|
* @param [in] properties - Properties for the characteristic.
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic::NimBLECharacteristic(NimBLEUUID uuid, uint16_t properties, NimBLEService* pService) {
|
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) {
|
||||||
m_uuid = uuid;
|
m_uuid = uuid;
|
||||||
m_handle = NULL_HANDLE;
|
m_handle = NULL_HANDLE;
|
||||||
m_properties = properties;
|
m_properties = properties;
|
||||||
|
@ -99,7 +102,7 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3
|
||||||
* @param [in] properties - The properties of the descriptor.
|
* @param [in] properties - The properties of the descriptor.
|
||||||
* @return The new BLE descriptor.
|
* @return The new BLE descriptor.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(NimBLEUUID uuid, uint32_t properties, uint16_t max_len) {
|
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
|
||||||
NimBLEDescriptor* pDescriptor = nullptr;
|
NimBLEDescriptor* pDescriptor = nullptr;
|
||||||
if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) {
|
if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) {
|
||||||
if(!(m_properties & BLE_GATT_CHR_F_NOTIFY) && !(m_properties & BLE_GATT_CHR_F_INDICATE)) {
|
if(!(m_properties & BLE_GATT_CHR_F_NOTIFY) && !(m_properties & BLE_GATT_CHR_F_INDICATE)) {
|
||||||
|
@ -139,7 +142,7 @@ NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const char* descript
|
||||||
* @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
|
* @param [in] descriptorUUID The UUID of the descriptor that we wish to retrieve.
|
||||||
* @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
* @return The BLE Descriptor. If no such descriptor is associated with the characteristic, nullptr is returned.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(NimBLEUUID descriptorUUID) {
|
NimBLEDescriptor* NimBLECharacteristic::getDescriptorByUUID(const NimBLEUUID &descriptorUUID) {
|
||||||
return m_descriptorMap.getByUUID(descriptorUUID);
|
return m_descriptorMap.getByUUID(descriptorUUID);
|
||||||
} // getDescriptorByUUID
|
} // getDescriptorByUUID
|
||||||
|
|
||||||
|
@ -198,6 +201,15 @@ uint8_t* NimBLECharacteristic::getData() {
|
||||||
} // getData
|
} // getData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve the the current data length of the characteristic.
|
||||||
|
* @return The length of the current characteristic data.
|
||||||
|
*/
|
||||||
|
size_t NimBLECharacteristic:: getDataLength() {
|
||||||
|
return m_value.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
|
||||||
struct ble_gatt_access_ctxt *ctxt,
|
struct ble_gatt_access_ctxt *ctxt,
|
||||||
void *arg)
|
void *arg)
|
||||||
|
@ -509,7 +521,7 @@ void NimBLECharacteristic::setWriteProperty(bool value) {
|
||||||
* @param [in] data The data to set for the characteristic.
|
* @param [in] data The data to set for the characteristic.
|
||||||
* @param [in] length The length of the data in bytes.
|
* @param [in] length The length of the data in bytes.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristic::setValue(uint8_t* data, size_t length) {
|
void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) {
|
||||||
char* pHex = NimBLEUtils::buildHexData(nullptr, data, length);
|
char* pHex = NimBLEUtils::buildHexData(nullptr, data, length);
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> setValue: length=%d, data=%s, characteristic UUID=%s", length, pHex, getUUID().toString().c_str());
|
||||||
free(pHex);
|
free(pHex);
|
||||||
|
@ -537,7 +549,7 @@ void NimBLECharacteristic::setValue(uint8_t* data, size_t length) {
|
||||||
* @param [in] Set the value of the characteristic.
|
* @param [in] Set the value of the characteristic.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristic::setValue(std::string value) {
|
void NimBLECharacteristic::setValue(const std::string &value) {
|
||||||
setValue((uint8_t*)(value.data()), value.length());
|
setValue((uint8_t*)(value.data()), value.length());
|
||||||
} // setValue
|
} // setValue
|
||||||
|
|
||||||
|
@ -637,4 +649,5 @@ void NimBLECharacteristicCallbacks::onStatus(NimBLECharacteristic* pCharacterist
|
||||||
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
|
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onStatus: default");
|
||||||
} // onStatus
|
} // onStatus
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
|
@ -16,6 +16,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "host/ble_hs.h"
|
#include "host/ble_hs.h"
|
||||||
/**** FIX COMPILATION ****/
|
/**** FIX COMPILATION ****/
|
||||||
#undef min
|
#undef min
|
||||||
|
@ -58,10 +61,10 @@ class NimBLECharacteristicCallbacks;
|
||||||
class NimBLEDescriptorMap {
|
class NimBLEDescriptorMap {
|
||||||
public:
|
public:
|
||||||
void setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor);
|
void setByUUID(const char* uuid, NimBLEDescriptor* pDescriptor);
|
||||||
void setByUUID(NimBLEUUID uuid, NimBLEDescriptor* pDescriptor);
|
void setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor);
|
||||||
// void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor);
|
// void setByHandle(uint16_t handle, NimBLEDescriptor* pDescriptor);
|
||||||
NimBLEDescriptor* getByUUID(const char* uuid);
|
NimBLEDescriptor* getByUUID(const char* uuid);
|
||||||
NimBLEDescriptor* getByUUID(NimBLEUUID uuid);
|
NimBLEDescriptor* getByUUID(const NimBLEUUID &uuid);
|
||||||
// NimBLEDescriptor* getByHandle(uint16_t handle);
|
// NimBLEDescriptor* getByHandle(uint16_t handle);
|
||||||
std::string toString();
|
std::string toString();
|
||||||
NimBLEDescriptor* getFirst();
|
NimBLEDescriptor* getFirst();
|
||||||
|
@ -87,16 +90,17 @@ public:
|
||||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||||
NIMBLE_PROPERTY::WRITE,
|
NIMBLE_PROPERTY::WRITE,
|
||||||
uint16_t max_len = 100);
|
uint16_t max_len = 100);
|
||||||
NimBLEDescriptor* createDescriptor(NimBLEUUID uuid,
|
NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid,
|
||||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||||
NIMBLE_PROPERTY::WRITE,
|
NIMBLE_PROPERTY::WRITE,
|
||||||
uint16_t max_len = 100);
|
uint16_t max_len = 100);
|
||||||
|
|
||||||
NimBLEDescriptor* getDescriptorByUUID(const char* descriptorUUID);
|
NimBLEDescriptor* getDescriptorByUUID(const char* descriptorUUID);
|
||||||
NimBLEDescriptor* getDescriptorByUUID(NimBLEUUID descriptorUUID);
|
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &descriptorUUID);
|
||||||
NimBLEUUID getUUID();
|
NimBLEUUID getUUID();
|
||||||
std::string getValue();
|
std::string getValue();
|
||||||
uint8_t* getData();
|
uint8_t* getData();
|
||||||
|
size_t getDataLength();
|
||||||
|
|
||||||
void indicate();
|
void indicate();
|
||||||
void notify(bool is_notification = true);
|
void notify(bool is_notification = true);
|
||||||
|
@ -109,8 +113,8 @@ public:
|
||||||
void setWriteProperty(bool value);
|
void setWriteProperty(bool value);
|
||||||
void setWriteNoResponseProperty(bool value);
|
void setWriteNoResponseProperty(bool value);
|
||||||
//////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////
|
||||||
void setValue(uint8_t* data, size_t size);
|
void setValue(const uint8_t* data, size_t size);
|
||||||
void setValue(std::string value);
|
void setValue(const std::string &value);
|
||||||
void setValue(uint16_t& data16);
|
void setValue(uint16_t& data16);
|
||||||
void setValue(uint32_t& data32);
|
void setValue(uint32_t& data32);
|
||||||
void setValue(int& data32);
|
void setValue(int& data32);
|
||||||
|
@ -140,7 +144,7 @@ private:
|
||||||
|
|
||||||
NimBLECharacteristic(const char* uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
NimBLECharacteristic(const char* uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||||
NimBLEService* pService = nullptr);
|
NimBLEService* pService = nullptr);
|
||||||
NimBLECharacteristic(NimBLEUUID uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
||||||
NimBLEService* pService = nullptr);
|
NimBLEService* pService = nullptr);
|
||||||
virtual ~NimBLECharacteristic();
|
virtual ~NimBLECharacteristic();
|
||||||
|
|
||||||
|
@ -190,5 +194,7 @@ public:
|
||||||
virtual void onNotify(NimBLECharacteristic* pCharacteristic);
|
virtual void onNotify(NimBLECharacteristic* pCharacteristic);
|
||||||
virtual void onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code);
|
virtual void onStatus(NimBLECharacteristic* pCharacteristic, Status s, int code);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /*MAIN_NIMBLECHARACTERISTIC_H_*/
|
#endif /*MAIN_NIMBLECHARACTERISTIC_H_*/
|
|
@ -12,6 +12,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEService.h"
|
#include "NimBLEService.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
|
@ -41,7 +44,7 @@ NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const char* uuid) {
|
||||||
* @param [in] UUID The UUID to look up the characteristic.
|
* @param [in] UUID The UUID to look up the characteristic.
|
||||||
* @return The characteristic.
|
* @return The characteristic.
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(NimBLEUUID uuid) {
|
NimBLECharacteristic* NimBLECharacteristicMap::getByUUID(const NimBLEUUID &uuid) {
|
||||||
for (auto &myPair : m_uuidMap) {
|
for (auto &myPair : m_uuidMap) {
|
||||||
if (myPair.first->getUUID().equals(uuid)) {
|
if (myPair.first->getUUID().equals(uuid)) {
|
||||||
return myPair.first;
|
return myPair.first;
|
||||||
|
@ -100,7 +103,7 @@ void NimBLECharacteristicMap::setByHandle(uint16_t handle, NimBLECharacteristic*
|
||||||
* @param [in] characteristic The characteristic to cache.
|
* @param [in] characteristic The characteristic to cache.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, NimBLEUUID uuid) {
|
void NimBLECharacteristicMap::setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid) {
|
||||||
m_uuidMap.insert(std::pair<NimBLECharacteristic*, std::string>(pCharacteristic, uuid.toString()));
|
m_uuidMap.insert(std::pair<NimBLECharacteristic*, std::string>(pCharacteristic, uuid.toString()));
|
||||||
} // setByUUID
|
} // setByUUID
|
||||||
|
|
||||||
|
@ -125,4 +128,5 @@ std::string NimBLECharacteristicMap::toString() {
|
||||||
} // toString
|
} // toString
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
|
@ -14,6 +14,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLEClient.h"
|
#include "NimBLEClient.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
|
@ -40,8 +43,8 @@ static NimBLEClientCallbacks defaultCallbacks;
|
||||||
* Since there is a hierarchical relationship here, we will have the idea that from a NimBLERemoteService will own
|
* Since there is a hierarchical relationship here, we will have the idea that from a NimBLERemoteService will own
|
||||||
* zero or more remote characteristics and a NimBLERemoteCharacteristic will own zero or more remote NimBLEDescriptors.
|
* zero or more remote characteristics and a NimBLERemoteCharacteristic will own zero or more remote NimBLEDescriptors.
|
||||||
*
|
*
|
||||||
* We will assume that a NimBLERemoteService contains a map that maps NimBLEUUIDs to the set of owned characteristics
|
* We will assume that a NimBLERemoteService contains a vector of owned characteristics
|
||||||
* and that a NimBLECharacteristic contains a map that maps NimBLEUUIDs to the set of owned descriptors.
|
* and that a NimBLECharacteristic contains a vector of owned descriptors.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -50,7 +53,6 @@ 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_haveServices = false;
|
|
||||||
m_isConnected = false;
|
m_isConnected = false;
|
||||||
m_connectTimeout = 30000;
|
m_connectTimeout = 30000;
|
||||||
|
|
||||||
|
@ -74,7 +76,7 @@ NimBLEClient::~NimBLEClient() {
|
||||||
// Before we are finished with the client, we must release resources.
|
// Before we are finished with the client, we must release resources.
|
||||||
clearServices();
|
clearServices();
|
||||||
|
|
||||||
if(m_deleteCallbacks) {
|
if(m_deleteCallbacks && m_pClientCallbacks != &defaultCallbacks) {
|
||||||
delete m_pClientCallbacks;
|
delete m_pClientCallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,11 +89,11 @@ NimBLEClient::~NimBLEClient() {
|
||||||
void NimBLEClient::clearServices() {
|
void NimBLEClient::clearServices() {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> clearServices");
|
NIMBLE_LOGD(LOG_TAG, ">> clearServices");
|
||||||
// Delete all the services.
|
// Delete all the services.
|
||||||
for (auto &myPair : m_servicesMap) {
|
for(auto &it: m_servicesVector) {
|
||||||
delete myPair.second;
|
delete it;
|
||||||
}
|
}
|
||||||
m_servicesMap.clear();
|
m_servicesVector.clear();
|
||||||
m_haveServices = false;
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< clearServices");
|
NIMBLE_LOGD(LOG_TAG, "<< clearServices");
|
||||||
} // clearServices
|
} // clearServices
|
||||||
|
|
||||||
|
@ -120,7 +122,7 @@ bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool refreshServices)
|
||||||
* @param [in] address The address of the partner.
|
* @param [in] address The address of the partner.
|
||||||
* @return True on success.
|
* @return True on success.
|
||||||
*/
|
*/
|
||||||
bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServices) {
|
bool NimBLEClient::connect(const NimBLEAddress &address, uint8_t type, bool refreshServices) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
|
||||||
|
|
||||||
if(!NimBLEDevice::m_synced) {
|
if(!NimBLEDevice::m_synced) {
|
||||||
|
@ -179,18 +181,6 @@ bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServ
|
||||||
clearServices();
|
clearServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_haveServices) {
|
|
||||||
if (!retrieveServices()) {
|
|
||||||
// error getting services, make sure we disconnect and release any resources before returning
|
|
||||||
disconnect();
|
|
||||||
clearServices();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Found %d services", getServices()->size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pClientCallbacks->onConnect(this);
|
m_pClientCallbacks->onConnect(this);
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< connect()");
|
NIMBLE_LOGD(LOG_TAG, "<< connect()");
|
||||||
|
@ -344,6 +334,24 @@ int NimBLEClient::getRssi() {
|
||||||
} // getRssi
|
} // getRssi
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get iterator to the beginning of the vector of remote service pointers.
|
||||||
|
* @return An iterator to the beginning of the vector of remote service pointers.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLERemoteService*>::iterator NimBLEClient::begin() {
|
||||||
|
return m_servicesVector.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get iterator to the end of the vector of remote service pointers.
|
||||||
|
* @return An iterator to the end of the vector of remote service pointers.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLERemoteService*>::iterator NimBLEClient::end() {
|
||||||
|
return m_servicesVector.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the service BLE Remote Service instance corresponding to the uuid.
|
* @brief Get the service BLE Remote Service instance corresponding to the uuid.
|
||||||
* @param [in] uuid The UUID of the service being sought.
|
* @param [in] uuid The UUID of the service being sought.
|
||||||
|
@ -359,29 +367,62 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) {
|
||||||
* @param [in] uuid The UUID of the service being sought.
|
* @param [in] uuid The UUID of the service being sought.
|
||||||
* @return A reference to the Service or nullptr if don't know about it.
|
* @return A reference to the Service or nullptr if don't know about it.
|
||||||
*/
|
*/
|
||||||
NimBLERemoteService* NimBLEClient::getService(NimBLEUUID uuid) {
|
NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str());
|
||||||
|
|
||||||
if (!m_haveServices) {
|
for(auto &it: m_servicesVector) {
|
||||||
return nullptr;
|
if(it->getUUID() == uuid) {
|
||||||
}
|
|
||||||
std::string uuidStr = uuid.toString();
|
|
||||||
for (auto &myPair : m_servicesMap) {
|
|
||||||
if (myPair.first == uuidStr) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str());
|
||||||
return myPair.second;
|
return it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t prev_size = m_servicesVector.size();
|
||||||
|
if(retrieveServices(&uuid)) {
|
||||||
|
if(m_servicesVector.size() > prev_size) {
|
||||||
|
return m_servicesVector.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< getService: not found");
|
NIMBLE_LOGD(LOG_TAG, "<< getService: not found");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getService
|
} // getService
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Get a pointer to the map of found services.
|
* @Get a pointer to the vector of found services.
|
||||||
|
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||||
|
* subsequently all services retrieved from the peripheral.
|
||||||
|
* If false the vector will be returned with the currently stored services,
|
||||||
|
* if vector is empty it will retrieve all services from the peripheral.
|
||||||
|
* @return a pointer to the vector of available services.
|
||||||
*/
|
*/
|
||||||
std::map<std::string, NimBLERemoteService*>* NimBLEClient::getServices() {
|
std::vector<NimBLERemoteService*>* NimBLEClient::getServices(bool refresh) {
|
||||||
return &m_servicesMap;
|
if(refresh) {
|
||||||
|
clearServices();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_servicesVector.empty()) {
|
||||||
|
if (!retrieveServices()) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to get services");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Found %d services", m_servicesVector.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &m_servicesVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ Retrieves the full database of attributes that the peripheral has available.
|
||||||
|
*/
|
||||||
|
void NimBLEClient::discoverAttributes() {
|
||||||
|
for(auto svc: *getServices(true)) {
|
||||||
|
for(auto chr: *svc->getCharacteristics(true)) {
|
||||||
|
chr->getDescriptors(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -392,7 +433,7 @@ std::map<std::string, NimBLERemoteService*>* NimBLEClient::getServices() {
|
||||||
* We then ask for the characteristics for each service found and their desciptors.
|
* We then ask for the characteristics for each service found and their desciptors.
|
||||||
* @return true on success otherwise false if an error occurred
|
* @return true on success otherwise false if an error occurred
|
||||||
*/
|
*/
|
||||||
bool NimBLEClient::retrieveServices() {
|
bool NimBLEClient::retrieveServices(const NimBLEUUID *uuid_filter) {
|
||||||
/**
|
/**
|
||||||
* Design
|
* Design
|
||||||
* ------
|
* ------
|
||||||
|
@ -401,6 +442,7 @@ bool NimBLEClient::retrieveServices() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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");
|
||||||
|
@ -409,26 +451,21 @@ bool NimBLEClient::retrieveServices() {
|
||||||
|
|
||||||
m_semaphoreSearchCmplEvt.take("retrieveServices");
|
m_semaphoreSearchCmplEvt.take("retrieveServices");
|
||||||
|
|
||||||
int rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this);
|
if(uuid_filter == nullptr) {
|
||||||
|
rc = ble_gattc_disc_all_svcs(m_conn_id, NimBLEClient::serviceDiscoveredCB, this);
|
||||||
|
} else {
|
||||||
|
rc = ble_gattc_disc_svc_by_uuid(m_conn_id, &uuid_filter->getNative()->u,
|
||||||
|
NimBLEClient::serviceDiscoveredCB, this);
|
||||||
|
}
|
||||||
|
|
||||||
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_haveServices = false;
|
|
||||||
m_semaphoreSearchCmplEvt.give();
|
m_semaphoreSearchCmplEvt.give();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until we have all the services
|
// wait until we have all the services
|
||||||
// If sucessful, remember that we now have services.
|
if(m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0){
|
||||||
m_haveServices = (m_semaphoreSearchCmplEvt.wait("retrieveServices") == 0);
|
|
||||||
if(m_haveServices){
|
|
||||||
for (auto &myPair : m_servicesMap) {
|
|
||||||
if(!m_isConnected || !myPair.second->retrieveCharacteristics()) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "Disconnected, could not retrieve characteristics -aborting");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveServices");
|
NIMBLE_LOGD(LOG_TAG, "<< retrieveServices");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -449,7 +486,9 @@ int NimBLEClient::serviceDiscoveredCB(
|
||||||
const struct ble_gatt_error *error,
|
const struct ble_gatt_error *error,
|
||||||
const struct ble_gatt_svc *service, void *arg)
|
const struct ble_gatt_svc *service, void *arg)
|
||||||
{
|
{
|
||||||
NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d", error->status, conn_handle);
|
NIMBLE_LOGD(LOG_TAG,"Service Discovered >> status: %d handle: %d",
|
||||||
|
error->status, (error->status == 0) ? service->start_handle : -1);
|
||||||
|
|
||||||
NimBLEClient *peer = (NimBLEClient*)arg;
|
NimBLEClient *peer = (NimBLEClient*)arg;
|
||||||
int rc=0;
|
int rc=0;
|
||||||
|
|
||||||
|
@ -460,9 +499,9 @@ int NimBLEClient::serviceDiscoveredCB(
|
||||||
|
|
||||||
switch (error->status) {
|
switch (error->status) {
|
||||||
case 0: {
|
case 0: {
|
||||||
// Found a service - add it to the map
|
// Found a service - add it to the vector
|
||||||
NimBLERemoteService* pRemoteService = new NimBLERemoteService(peer, service);
|
NimBLERemoteService* pRemoteService = new NimBLERemoteService(peer, service);
|
||||||
peer->m_servicesMap.insert(std::pair<std::string, NimBLERemoteService*>(pRemoteService->getUUID().toString(), pRemoteService));
|
peer->m_servicesVector.push_back(pRemoteService);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BLE_HS_EDONE:{
|
case BLE_HS_EDONE:{
|
||||||
|
@ -494,8 +533,9 @@ int NimBLEClient::serviceDiscoveredCB(
|
||||||
* @param [in] characteristicUUID The characteristic whose value we wish to read.
|
* @param [in] characteristicUUID The characteristic whose value we wish to read.
|
||||||
* @returns characteristic value or an empty string if not found
|
* @returns characteristic value or an empty string if not found
|
||||||
*/
|
*/
|
||||||
std::string NimBLEClient::getValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID) {
|
std::string NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s",
|
||||||
|
serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
|
||||||
|
|
||||||
std::string ret = "";
|
std::string ret = "";
|
||||||
NimBLERemoteService* pService = getService(serviceUUID);
|
NimBLERemoteService* pService = getService(serviceUUID);
|
||||||
|
@ -518,8 +558,11 @@ std::string NimBLEClient::getValue(NimBLEUUID serviceUUID, NimBLEUUID characteri
|
||||||
* @param [in] characteristicUUID The characteristic whose value we wish to write.
|
* @param [in] characteristicUUID The characteristic whose value we wish to write.
|
||||||
* @returns true if successful otherwise false
|
* @returns true if successful otherwise false
|
||||||
*/
|
*/
|
||||||
bool NimBLEClient::setValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID, std::string value) {
|
bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID,
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
|
const std::string &value)
|
||||||
|
{
|
||||||
|
NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s",
|
||||||
|
serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
NimBLERemoteService* pService = getService(serviceUUID);
|
NimBLERemoteService* pService = getService(serviceUUID);
|
||||||
|
@ -656,23 +699,33 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
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);
|
||||||
if(!client->m_haveServices)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for(auto &sPair : client->m_servicesMap){
|
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 their range
|
||||||
if(sPair.second->getEndHandle() < event->notify_rx.attr_handle) {
|
if(it->getEndHandle() < event->notify_rx.attr_handle) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto cMap = sPair.second->getCharacteristicsByHandle();
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d", sPair.second->getUUID().toString().c_str(),event->notify_rx.attr_handle);
|
|
||||||
auto characteristic = cMap->find(event->notify_rx.attr_handle);
|
|
||||||
if(characteristic != cMap->end()) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", characteristic->second->toString().c_str());
|
|
||||||
|
|
||||||
if (characteristic->second->m_notifyCallback != nullptr) {
|
auto cVector = &it->m_characteristicVector;
|
||||||
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", characteristic->second->toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, "checking service %s for handle: %d",
|
||||||
characteristic->second->m_notifyCallback(characteristic->second, event->notify_rx.om->om_data, event->notify_rx.om->om_len, !event->notify_rx.indication);
|
it->getUUID().toString().c_str(),
|
||||||
|
event->notify_rx.attr_handle);
|
||||||
|
|
||||||
|
auto characteristic = cVector->cbegin();
|
||||||
|
for(; characteristic != cVector->cend(); ++characteristic) {
|
||||||
|
if((*characteristic)->m_handle == event->notify_rx.attr_handle)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(characteristic != cVector->cend()) {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", (*characteristic)->toString().c_str());
|
||||||
|
|
||||||
|
if ((*characteristic)->m_notifyCallback != nullptr) {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s",
|
||||||
|
(*characteristic)->toString().c_str());
|
||||||
|
(*characteristic)->m_notifyCallback(*characteristic, event->notify_rx.om->om_data,
|
||||||
|
event->notify_rx.om->om_len,
|
||||||
|
!event->notify_rx.indication);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -750,7 +803,6 @@ uint16_t NimBLEClient::getMTU() {
|
||||||
event->mtu.conn_handle,
|
event->mtu.conn_handle,
|
||||||
event->mtu.value);
|
event->mtu.value);
|
||||||
client->m_semaphoreOpenEvt.give(0);
|
client->m_semaphoreOpenEvt.give(0);
|
||||||
//client->m_mtu = event->mtu.value;
|
|
||||||
return 0;
|
return 0;
|
||||||
} // BLE_GAP_EVENT_MTU
|
} // BLE_GAP_EVENT_MTU
|
||||||
|
|
||||||
|
@ -848,8 +900,9 @@ void NimBLEClient::setClientCallbacks(NimBLEClientCallbacks* pClientCallbacks, b
|
||||||
std::string NimBLEClient::toString() {
|
std::string NimBLEClient::toString() {
|
||||||
std::string res = "peer address: " + m_peerAddress.toString();
|
std::string res = "peer address: " + m_peerAddress.toString();
|
||||||
res += "\nServices:\n";
|
res += "\nServices:\n";
|
||||||
for (auto &myPair : m_servicesMap) {
|
|
||||||
res += myPair.second->toString() + "\n";
|
for(auto &it: m_servicesVector) {
|
||||||
|
res += it->toString() + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -890,4 +943,5 @@ bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
|
|
|
@ -14,16 +14,24 @@
|
||||||
#ifndef MAIN_NIMBLECLIENT_H_
|
#ifndef MAIN_NIMBLECLIENT_H_
|
||||||
#define MAIN_NIMBLECLIENT_H_
|
#define MAIN_NIMBLECLIENT_H_
|
||||||
|
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLEAddress.h"
|
#include "NimBLEAddress.h"
|
||||||
#include "NimBLEAdvertisedDevice.h"
|
#include "NimBLEAdvertisedDevice.h"
|
||||||
#include "NimBLERemoteService.h"
|
#include "NimBLERemoteService.h"
|
||||||
|
|
||||||
#include <map>
|
#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;
|
||||||
|
@ -34,57 +42,61 @@ class NimBLEAdvertisedDevice;
|
||||||
class NimBLEClient {
|
class NimBLEClient {
|
||||||
public:
|
public:
|
||||||
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
bool connect(NimBLEAdvertisedDevice* device, bool refreshServices = true);
|
||||||
bool connect(NimBLEAddress address, uint8_t type = BLE_ADDR_TYPE_PUBLIC, bool refreshServices = true); // Connect to the remote BLE Server
|
bool connect(const NimBLEAddress &address, uint8_t type = BLE_ADDR_PUBLIC,
|
||||||
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM); // Disconnect from the remote BLE Server
|
bool refreshServices = true);
|
||||||
NimBLEAddress getPeerAddress(); // Get the address of the remote BLE Server
|
int disconnect(uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||||
int getRssi(); // Get the RSSI of the remote BLE Server
|
NimBLEAddress getPeerAddress();
|
||||||
std::map<std::string, NimBLERemoteService*>* getServices(); // Get a map of the services offered by the remote BLE Server
|
int getRssi();
|
||||||
NimBLERemoteService* getService(const char* uuid); // Get a reference to a specified service offered by the remote BLE server.
|
std::vector<NimBLERemoteService*>* getServices(bool refresh = false);
|
||||||
NimBLERemoteService* getService(NimBLEUUID uuid); // Get a reference to a specified service offered by the remote BLE server.
|
std::vector<NimBLERemoteService*>::iterator begin();
|
||||||
std::string getValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID); // Get the value of a given characteristic at a given service.
|
std::vector<NimBLERemoteService*>::iterator end();
|
||||||
bool setValue(NimBLEUUID serviceUUID, NimBLEUUID characteristicUUID, std::string value); // Set the value of a given characteristic at a given service.
|
NimBLERemoteService* getService(const char* uuid);
|
||||||
bool isConnected(); // Return true if we are connected.
|
NimBLERemoteService* getService(const NimBLEUUID &uuid);
|
||||||
void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks, bool deleteCallbacks = true);
|
std::string getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID);
|
||||||
std::string toString(); // Return a string representation of this client.
|
bool setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID,
|
||||||
|
const std::string &value);
|
||||||
|
bool isConnected();
|
||||||
|
void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks,
|
||||||
|
bool deleteCallbacks = true);
|
||||||
|
std::string toString();
|
||||||
uint16_t getConnId();
|
uint16_t getConnId();
|
||||||
uint16_t getMTU();
|
uint16_t getMTU();
|
||||||
bool secureConnection();
|
bool secureConnection();
|
||||||
void setConnectTimeout(uint8_t timeout);
|
void setConnectTimeout(uint8_t timeout);
|
||||||
void setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
|
void setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
|
||||||
uint16_t latency, uint16_t timeout,
|
uint16_t latency, uint16_t timeout,
|
||||||
uint16_t scanInterval=16, uint16_t scanWindow=16); // NimBLE default scan settings
|
uint16_t scanInterval=16, uint16_t scanWindow=16);
|
||||||
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
|
||||||
uint16_t latency, uint16_t timeout);
|
uint16_t latency, uint16_t timeout);
|
||||||
|
void discoverAttributes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NimBLEClient();
|
NimBLEClient();
|
||||||
~NimBLEClient();
|
~NimBLEClient();
|
||||||
|
|
||||||
friend class NimBLEDevice;
|
friend class NimBLEDevice;
|
||||||
friend class NimBLERemoteService;
|
friend class NimBLERemoteService;
|
||||||
|
|
||||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||||
static int serviceDiscoveredCB(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg);
|
static int serviceDiscoveredCB(uint16_t conn_handle,
|
||||||
void clearServices(); // Clear any existing services.
|
const struct ble_gatt_error *error,
|
||||||
bool retrieveServices(); //Retrieve services from the server
|
const struct ble_gatt_svc *service,
|
||||||
// void onHostReset();
|
void *arg);
|
||||||
|
void clearServices();
|
||||||
|
bool retrieveServices(const NimBLEUUID *uuid_filter = nullptr);
|
||||||
|
|
||||||
NimBLEAddress m_peerAddress = NimBLEAddress("\0\0\0\0\0\0"); // The BD address of the remote server.
|
NimBLEAddress m_peerAddress = NimBLEAddress("");
|
||||||
uint16_t m_conn_id;
|
uint16_t m_conn_id;
|
||||||
bool m_haveServices = false; // Have we previously obtain the set of services from the remote server.
|
bool m_isConnected = false;
|
||||||
bool m_isConnected = false; // Are we currently connected.
|
|
||||||
bool m_waitingToConnect =false;
|
bool m_waitingToConnect =false;
|
||||||
bool m_deleteCallbacks = true;
|
bool m_deleteCallbacks = true;
|
||||||
int32_t m_connectTimeout;
|
int32_t m_connectTimeout;
|
||||||
//uint16_t m_mtu = 23;
|
|
||||||
|
|
||||||
NimBLEClientCallbacks* m_pClientCallbacks = nullptr;
|
NimBLEClientCallbacks* m_pClientCallbacks = nullptr;
|
||||||
|
|
||||||
FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt");
|
FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt");
|
||||||
FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt");
|
FreeRTOS::Semaphore m_semaphoreSearchCmplEvt = FreeRTOS::Semaphore("SearchCmplEvt");
|
||||||
FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security");
|
FreeRTOS::Semaphore m_semeaphoreSecEvt = FreeRTOS::Semaphore("Security");
|
||||||
|
|
||||||
std::map<std::string, NimBLERemoteService*> m_servicesMap;
|
std::vector<NimBLERemoteService*> m_servicesVector;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEClientCallbacks;
|
friend class NimBLEClientCallbacks;
|
||||||
|
@ -109,5 +121,6 @@ public:
|
||||||
virtual bool onConfirmPIN(uint32_t pin);
|
virtual bool onConfirmPIN(uint32_t pin);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
#endif /* MAIN_NIMBLECLIENT_H_ */
|
#endif /* MAIN_NIMBLECLIENT_H_ */
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEService.h"
|
#include "NimBLEService.h"
|
||||||
#include "NimBLEDescriptor.h"
|
#include "NimBLEDescriptor.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
@ -187,7 +190,7 @@ void NimBLEDescriptor::setHandle(uint16_t handle) {
|
||||||
* @param [in] data The data to set for the descriptor.
|
* @param [in] data The data to set for the descriptor.
|
||||||
* @param [in] length The length of the data in bytes.
|
* @param [in] length The length of the data in bytes.
|
||||||
*/
|
*/
|
||||||
void NimBLEDescriptor::setValue(uint8_t* data, size_t length) {
|
void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) {
|
||||||
if (length > BLE_ATT_ATTR_MAX_LEN) {
|
if (length > BLE_ATT_ATTR_MAX_LEN) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
|
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
|
||||||
return;
|
return;
|
||||||
|
@ -201,7 +204,7 @@ void NimBLEDescriptor::setValue(uint8_t* data, size_t length) {
|
||||||
* @brief Set the value of the descriptor.
|
* @brief Set the value of the descriptor.
|
||||||
* @param [in] value The value of the descriptor in string form.
|
* @param [in] value The value of the descriptor in string form.
|
||||||
*/
|
*/
|
||||||
void NimBLEDescriptor::setValue(std::string value) {
|
void NimBLEDescriptor::setValue(const std::string &value) {
|
||||||
setValue((uint8_t*) value.data(), value.length());
|
setValue((uint8_t*) value.data(), value.length());
|
||||||
} // setValue
|
} // setValue
|
||||||
|
|
||||||
|
@ -244,5 +247,5 @@ void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) {
|
||||||
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default");
|
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default");
|
||||||
} // onWrite
|
} // onWrite
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLECharacteristic.h"
|
#include "NimBLECharacteristic.h"
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
|
@ -50,8 +53,8 @@ public:
|
||||||
uint8_t* getValue(); // Get a pointer to the value of the descriptor.
|
uint8_t* getValue(); // Get a pointer to the value of the descriptor.
|
||||||
// void setAccessPermissions(uint8_t perm); // Set the permissions of the descriptor.
|
// void setAccessPermissions(uint8_t perm); // Set the permissions of the descriptor.
|
||||||
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks); // Set callbacks to be invoked for the descriptor.
|
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks); // Set callbacks to be invoked for the descriptor.
|
||||||
void setValue(uint8_t* data, size_t size); // Set the value of the descriptor as a pointer to data.
|
void setValue(const uint8_t* data, size_t size); // Set the value of the descriptor as a pointer to data.
|
||||||
void setValue(std::string value); // Set the value of the descriptor as a data buffer.
|
void setValue(const std::string &value); // Set the value of the descriptor as a data buffer.
|
||||||
|
|
||||||
std::string toString(); // Convert the descriptor to a string representation.
|
std::string toString(); // Convert the descriptor to a string representation.
|
||||||
|
|
||||||
|
@ -97,5 +100,7 @@ public:
|
||||||
virtual void onRead(NimBLEDescriptor* pDescriptor);
|
virtual void onRead(NimBLEDescriptor* pDescriptor);
|
||||||
virtual void onWrite(NimBLEDescriptor* pDescriptor);
|
virtual void onWrite(NimBLEDescriptor* pDescriptor);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* MAIN_NIMBLEDESCRIPTOR_H_ */
|
#endif /* MAIN_NIMBLEDESCRIPTOR_H_ */
|
|
@ -13,6 +13,10 @@
|
||||||
*/
|
*/
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLECharacteristic.h"
|
#include "NimBLECharacteristic.h"
|
||||||
#include "NimBLEDescriptor.h"
|
#include "NimBLEDescriptor.h"
|
||||||
|
|
||||||
|
@ -32,7 +36,7 @@ NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const char* uuid) {
|
||||||
* @param [in] UUID The UUID to look up the descriptor.
|
* @param [in] UUID The UUID to look up the descriptor.
|
||||||
* @return The descriptor. If not present, then nullptr is returned.
|
* @return The descriptor. If not present, then nullptr is returned.
|
||||||
*/
|
*/
|
||||||
NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(NimBLEUUID uuid) {
|
NimBLEDescriptor* NimBLEDescriptorMap::getByUUID(const NimBLEUUID &uuid) {
|
||||||
for (auto &myPair : m_uuidMap) {
|
for (auto &myPair : m_uuidMap) {
|
||||||
if (myPair.first->getUUID().equals(uuid)) {
|
if (myPair.first->getUUID().equals(uuid)) {
|
||||||
return myPair.first;
|
return myPair.first;
|
||||||
|
@ -71,7 +75,7 @@ void NimBLEDescriptorMap::setByUUID(const char* uuid, NimBLEDescriptor* pDescrip
|
||||||
* @param [in] characteristic The descriptor to cache.
|
* @param [in] characteristic The descriptor to cache.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLEDescriptorMap::setByUUID(NimBLEUUID uuid, NimBLEDescriptor* pDescriptor) {
|
void NimBLEDescriptorMap::setByUUID(const NimBLEUUID &uuid, NimBLEDescriptor* pDescriptor) {
|
||||||
m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid.toString()));
|
m_uuidMap.insert(std::pair<NimBLEDescriptor*, std::string>(pDescriptor, uuid.toString()));
|
||||||
} // setByUUID
|
} // setByUUID
|
||||||
|
|
||||||
|
@ -140,4 +144,6 @@ NimBLEDescriptor* NimBLEDescriptorMap::getNext() {
|
||||||
m_iterator++;
|
m_iterator++;
|
||||||
return pRet;
|
return pRet;
|
||||||
} // getNext
|
} // getNext
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
|
@ -14,6 +14,7 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
|
|
||||||
|
@ -39,35 +40,34 @@ static const char* LOG_TAG = "NimBLEDevice";
|
||||||
/**
|
/**
|
||||||
* Singletons for the NimBLEDevice.
|
* Singletons for the NimBLEDevice.
|
||||||
*/
|
*/
|
||||||
bool NimBLEDevice_initialized = false;
|
bool initialized = false;
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
NimBLEScan* NimBLEDevice::m_pScan = nullptr;
|
NimBLEScan* NimBLEDevice::m_pScan = nullptr;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
NimBLEServer* NimBLEDevice::m_pServer = nullptr;
|
NimBLEServer* NimBLEDevice::m_pServer = nullptr;
|
||||||
|
#endif
|
||||||
uint32_t NimBLEDevice::m_passkey = 123456;
|
uint32_t NimBLEDevice::m_passkey = 123456;
|
||||||
bool NimBLEDevice::m_synced = false;
|
bool NimBLEDevice::m_synced = false;
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
gap_event_handler NimBLEDevice::m_customGapHandler = nullptr;
|
gap_event_handler NimBLEDevice::m_customGapHandler = nullptr;
|
||||||
ble_gap_event_listener NimBLEDevice::m_listener;
|
ble_gap_event_listener NimBLEDevice::m_listener;
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
std::list <NimBLEClient*> NimBLEDevice::m_cList;
|
std::list <NimBLEClient*> NimBLEDevice::m_cList;
|
||||||
|
#endif
|
||||||
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
|
||||||
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
||||||
|
|
||||||
//std::map<uint16_t, conn_status_t> BLEDevice::m_connectedClientsMap;
|
|
||||||
|
|
||||||
//gattc_event_handler BLEDevice::m_customGattcHandler = nullptr;
|
|
||||||
//gatts_event_handler BLEDevice::m_customGattsHandler = nullptr;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new instance of a server.
|
* @brief Create a new instance of a server.
|
||||||
* @return A new instance of the server.
|
* @return A new instance of the server.
|
||||||
*/
|
*/
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
/* STATIC */ NimBLEServer* NimBLEDevice::createServer() {
|
/* STATIC */ NimBLEServer* NimBLEDevice::createServer() {
|
||||||
/*#ifndef CONFIG_GATTS_ENABLE // Check that BLE GATTS is enabled in make menuconfig
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "BLE GATTS is not enabled - CONFIG_GATTS_ENABLE not defined");
|
|
||||||
abort();
|
|
||||||
#endif // CONFIG_GATTS_ENABLE
|
|
||||||
*/
|
|
||||||
if(NimBLEDevice::m_pServer == nullptr) {
|
if(NimBLEDevice::m_pServer == nullptr) {
|
||||||
NimBLEDevice::m_pServer = new NimBLEServer();
|
NimBLEDevice::m_pServer = new NimBLEServer();
|
||||||
ble_gatts_reset();
|
ble_gatts_reset();
|
||||||
|
@ -79,6 +79,17 @@ NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
|
||||||
} // createServer
|
} // createServer
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the instance of the server.
|
||||||
|
* @return A pointer to the server instance.
|
||||||
|
*/
|
||||||
|
/* STATIC */ NimBLEServer* NimBLEDevice::getServer() {
|
||||||
|
return m_pServer;
|
||||||
|
} // getServer
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
NimBLEAdvertising* NimBLEDevice::getAdvertising() {
|
NimBLEAdvertising* NimBLEDevice::getAdvertising() {
|
||||||
if(m_bleAdvertising == nullptr) {
|
if(m_bleAdvertising == nullptr) {
|
||||||
m_bleAdvertising = new NimBLEAdvertising();
|
m_bleAdvertising = new NimBLEAdvertising();
|
||||||
|
@ -95,6 +106,7 @@ void NimBLEDevice::startAdvertising() {
|
||||||
void NimBLEDevice::stopAdvertising() {
|
void NimBLEDevice::stopAdvertising() {
|
||||||
getAdvertising()->stop();
|
getAdvertising()->stop();
|
||||||
} // stopAdvertising
|
} // stopAdvertising
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,19 +114,21 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
* @return The scanning object reference. This is a singleton object. The caller should not
|
* @return The scanning object reference. This is a singleton object. The caller should not
|
||||||
* try and release/delete it.
|
* try and release/delete it.
|
||||||
*/
|
*/
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
/* STATIC */ NimBLEScan* NimBLEDevice::getScan() {
|
/* STATIC */ NimBLEScan* NimBLEDevice::getScan() {
|
||||||
if (m_pScan == nullptr) {
|
if (m_pScan == nullptr) {
|
||||||
m_pScan = new NimBLEScan();
|
m_pScan = new NimBLEScan();
|
||||||
}
|
}
|
||||||
return m_pScan;
|
return m_pScan;
|
||||||
} // getScan
|
} // getScan
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new client object and maintains a list of all client objects
|
* @brief Creates a new client object and maintains a list of all client objects
|
||||||
* each client can connect to 1 peripheral device.
|
* each client can connect to 1 peripheral device.
|
||||||
* @return A reference to the new client object.
|
* @return A reference to the new client object.
|
||||||
*/
|
*/
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
/* STATIC */ NimBLEClient* NimBLEDevice::createClient() {
|
/* STATIC */ NimBLEClient* NimBLEDevice::createClient() {
|
||||||
if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) {
|
if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) {
|
||||||
NIMBLE_LOGW("Number of clients exceeds Max connections. Max=(%d)",
|
NIMBLE_LOGW("Number of clients exceeds Max connections. Max=(%d)",
|
||||||
|
@ -202,7 +216,7 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
* @param [in] a NimBLEAddress of the peer to search for.
|
* @param [in] a NimBLEAddress of the peer to search for.
|
||||||
* @return A reference pointer to the client with the peer address.
|
* @return A reference pointer to the client with the peer address.
|
||||||
*/
|
*/
|
||||||
/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(NimBLEAddress peer_addr) {
|
/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(const NimBLEAddress &peer_addr) {
|
||||||
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
|
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
|
||||||
if((*it)->getPeerAddress().equals(peer_addr)) {
|
if((*it)->getPeerAddress().equals(peer_addr)) {
|
||||||
return (*it);
|
return (*it);
|
||||||
|
@ -225,6 +239,8 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getDisconnectedClient
|
} // getDisconnectedClient
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the transmission power.
|
* @brief Set the transmission power.
|
||||||
|
@ -340,9 +356,12 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
|
|
||||||
m_synced = false;
|
m_synced = false;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
if(m_pScan != nullptr) {
|
if(m_pScan != nullptr) {
|
||||||
m_pScan->onHostReset();
|
m_pScan->onHostReset();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Not needed
|
/* Not needed
|
||||||
if(m_pServer != nullptr) {
|
if(m_pServer != nullptr) {
|
||||||
m_pServer->onHostReset();
|
m_pServer->onHostReset();
|
||||||
|
@ -352,9 +371,12 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
(*it)->onHostReset();
|
(*it)->onHostReset();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
if(m_bleAdvertising != nullptr) {
|
if(m_bleAdvertising != nullptr) {
|
||||||
m_bleAdvertising->onHostReset();
|
m_bleAdvertising->onHostReset();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason,
|
NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason,
|
||||||
NimBLEUtils::returnCodeToString(reason));
|
NimBLEUtils::returnCodeToString(reason));
|
||||||
|
@ -379,15 +401,21 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
|
|
||||||
m_synced = true;
|
m_synced = true;
|
||||||
|
|
||||||
|
if(initialized) {
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
if(m_pScan != nullptr) {
|
if(m_pScan != nullptr) {
|
||||||
// Restart scanning with the last values sent, allow to clear results.
|
// Restart scanning with the last values sent, allow to clear results.
|
||||||
m_pScan->start(m_pScan->m_duration, m_pScan->m_scanCompleteCB);
|
m_pScan->start(m_pScan->m_duration, m_pScan->m_scanCompleteCB);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
if(m_bleAdvertising != nullptr) {
|
if(m_bleAdvertising != nullptr) {
|
||||||
// Restart advertisng, parameters should already be set.
|
// Restart advertisng, parameters should already be set.
|
||||||
m_bleAdvertising->start();
|
m_bleAdvertising->start();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
} // onSync
|
} // onSync
|
||||||
|
|
||||||
|
|
||||||
|
@ -408,10 +436,8 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
* @brief Initialize the %BLE environment.
|
* @brief Initialize the %BLE environment.
|
||||||
* @param deviceName The device name of the device.
|
* @param deviceName The device name of the device.
|
||||||
*/
|
*/
|
||||||
/* STATIC */ void NimBLEDevice::init(std::string deviceName) {
|
/* STATIC */ void NimBLEDevice::init(const std::string &deviceName) {
|
||||||
if(!NimBLEDevice_initialized){
|
if(!initialized){
|
||||||
NimBLEDevice_initialized = true; // Set the initialization flag to ensure we are only initialized once.
|
|
||||||
|
|
||||||
int rc=0;
|
int rc=0;
|
||||||
esp_err_t errRc = ESP_OK;
|
esp_err_t errRc = ESP_OK;
|
||||||
|
|
||||||
|
@ -459,7 +485,8 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
while(!m_synced){
|
while(!m_synced){
|
||||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
//vTaskDelay(200 / portTICK_PERIOD_MS); // Delay for 200 msecs as a workaround to an apparent Arduino environment issue.
|
|
||||||
|
initialized = true; // Set the initialization flag to ensure we are only initialized once.
|
||||||
} // init
|
} // init
|
||||||
|
|
||||||
|
|
||||||
|
@ -476,7 +503,8 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
|
NIMBLE_LOGE(LOG_TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
NimBLEDevice_initialized = false;
|
initialized = false;
|
||||||
|
m_synced = false;
|
||||||
}
|
}
|
||||||
} // deinit
|
} // deinit
|
||||||
|
|
||||||
|
@ -485,7 +513,7 @@ void NimBLEDevice::stopAdvertising() {
|
||||||
* @brief Check if the initialization is complete.
|
* @brief Check if the initialization is complete.
|
||||||
*/
|
*/
|
||||||
bool NimBLEDevice::getInitialized() {
|
bool NimBLEDevice::getInitialized() {
|
||||||
return NimBLEDevice_initialized;
|
return initialized;
|
||||||
} // getInitialized
|
} // getInitialized
|
||||||
|
|
||||||
|
|
||||||
|
@ -610,7 +638,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
||||||
* @brief Check if the device address is on our ignore list.
|
* @brief Check if the device address is on our ignore list.
|
||||||
* @return True if ignoring.
|
* @return True if ignoring.
|
||||||
*/
|
*/
|
||||||
/*STATIC*/ bool NimBLEDevice::isIgnored(NimBLEAddress address) {
|
/*STATIC*/ bool NimBLEDevice::isIgnored(const NimBLEAddress &address) {
|
||||||
for(auto &it : m_ignoreList) {
|
for(auto &it : m_ignoreList) {
|
||||||
if(it.equals(address)){
|
if(it.equals(address)){
|
||||||
return true;
|
return true;
|
||||||
|
@ -625,7 +653,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
||||||
* @brief Add a device to the ignore list.
|
* @brief Add a device to the ignore list.
|
||||||
* @param Address of the device we want to ignore.
|
* @param Address of the device we want to ignore.
|
||||||
*/
|
*/
|
||||||
/*STATIC*/ void NimBLEDevice::addIgnored(NimBLEAddress address) {
|
/*STATIC*/ void NimBLEDevice::addIgnored(const NimBLEAddress &address) {
|
||||||
m_ignoreList.push_back(address);
|
m_ignoreList.push_back(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,7 +662,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
|
||||||
* @brief Remove a device from the ignore list.
|
* @brief Remove a device from the ignore list.
|
||||||
* @param Address of the device we want to remove from the list.
|
* @param Address of the device we want to remove from the list.
|
||||||
*/
|
*/
|
||||||
/*STATIC*/void NimBLEDevice::removeIgnored(NimBLEAddress address) {
|
/*STATIC*/void NimBLEDevice::removeIgnored(const NimBLEAddress &address) {
|
||||||
for(auto it = m_ignoreList.begin(); it != m_ignoreList.end(); ++it) {
|
for(auto it = m_ignoreList.begin(); it != m_ignoreList.end(); ++it) {
|
||||||
if((*it).equals(address)){
|
if((*it).equals(address)){
|
||||||
m_ignoreList.erase(it);
|
m_ignoreList.erase(it);
|
||||||
|
@ -659,20 +687,4 @@ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) {
|
||||||
} // setCustomGapHandler
|
} // setCustomGapHandler
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Backward compatibility for bluedroid gatt events.
|
|
||||||
* NimBLe does not send GATT events
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
void BLEDevice::setCustomGattcHandler(gattc_event_handler handler) {
|
|
||||||
setCustomGapHandler(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BLEDevice::setCustomGattsHandler(gatts_event_handler handler) {
|
|
||||||
setCustomGapHandler(handler);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/**********************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
|
|
|
@ -17,11 +17,27 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
#include "NimBLEScan.h"
|
#include "NimBLEScan.h"
|
||||||
#include "NimBLEUtils.h"
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
#include "NimBLEAdvertising.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#include "NimBLEClient.h"
|
#include "NimBLEClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#include "NimBLEServer.h"
|
#include "NimBLEServer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLESecurity.h"
|
#include "NimBLESecurity.h"
|
||||||
|
#include "NimBLEAddress.h"
|
||||||
|
|
||||||
#include "esp_bt.h"
|
#include "esp_bt.h"
|
||||||
|
|
||||||
|
@ -69,22 +85,26 @@
|
||||||
* @brief BLE functions.
|
* @brief BLE functions.
|
||||||
*/
|
*/
|
||||||
typedef int (*gap_event_handler)(ble_gap_event *event, void *arg);
|
typedef int (*gap_event_handler)(ble_gap_event *event, void *arg);
|
||||||
//typedef void (*gattc_event_handler)(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t* param);
|
|
||||||
//typedef void (*gatts_event_handler)(esp_gatts_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gatts_cb_param_t* param);
|
|
||||||
|
|
||||||
extern "C" void ble_store_config_init(void);
|
extern "C" void ble_store_config_init(void);
|
||||||
|
|
||||||
class NimBLEDevice {
|
class NimBLEDevice {
|
||||||
public:
|
public:
|
||||||
static void init(std::string deviceName); // Initialize the local BLE environment.
|
static void init(const std::string &deviceName);
|
||||||
static void deinit();
|
static void deinit();
|
||||||
static bool getInitialized();
|
static bool getInitialized();
|
||||||
static NimBLEAddress getAddress();
|
static NimBLEAddress getAddress();
|
||||||
static std::string toString();
|
static std::string toString();
|
||||||
static NimBLEScan* getScan(); // Get the scan object
|
|
||||||
static NimBLEClient* createClient();
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
static NimBLEScan* getScan();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
static NimBLEServer* createServer();
|
static NimBLEServer* createServer();
|
||||||
static bool deleteClient(NimBLEClient* pClient);
|
static NimBLEServer* getServer();
|
||||||
|
#endif
|
||||||
|
|
||||||
static void setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
|
static void setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
|
||||||
static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
|
static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
|
||||||
static void setCustomGapHandler(gap_event_handler handler);
|
static void setCustomGapHandler(gap_event_handler handler);
|
||||||
|
@ -98,39 +118,69 @@ public:
|
||||||
static void setSecurityCallbacks(NimBLESecurityCallbacks* pCallbacks);
|
static void setSecurityCallbacks(NimBLESecurityCallbacks* pCallbacks);
|
||||||
static int setMTU(uint16_t mtu);
|
static int setMTU(uint16_t mtu);
|
||||||
static uint16_t getMTU();
|
static uint16_t getMTU();
|
||||||
static bool isIgnored(NimBLEAddress address);
|
static bool isIgnored(const NimBLEAddress &address);
|
||||||
static void addIgnored(NimBLEAddress address);
|
static void addIgnored(const NimBLEAddress &address);
|
||||||
static void removeIgnored(NimBLEAddress address);
|
static void removeIgnored(const NimBLEAddress &address);
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
static NimBLEAdvertising* getAdvertising();
|
static NimBLEAdvertising* getAdvertising();
|
||||||
static void startAdvertising();
|
static void startAdvertising();
|
||||||
static void stopAdvertising();
|
static void stopAdvertising();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
static NimBLEClient* createClient();
|
||||||
|
static bool deleteClient(NimBLEClient* pClient);
|
||||||
static NimBLEClient* getClientByID(uint16_t conn_id);
|
static NimBLEClient* getClientByID(uint16_t conn_id);
|
||||||
static NimBLEClient* getClientByPeerAddress(NimBLEAddress peer_addr);
|
static NimBLEClient* getClientByPeerAddress(const NimBLEAddress &peer_addr);
|
||||||
static NimBLEClient* getDisconnectedClient();
|
static NimBLEClient* getDisconnectedClient();
|
||||||
static size_t getClientListSize();
|
static size_t getClientListSize();
|
||||||
static std::list<NimBLEClient*>* getClientList();
|
static std::list<NimBLEClient*>* getClientList();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEServer;
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
friend class NimBLEClient;
|
friend class NimBLEClient;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
friend class NimBLEScan;
|
friend class NimBLEScan;
|
||||||
friend class NimBLEAdvertising;
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
friend class NimBLEServer;
|
||||||
friend class NimBLECharacteristic;
|
friend class NimBLECharacteristic;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
friend class NimBLEAdvertising;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void onReset(int reason);
|
static void onReset(int reason);
|
||||||
static void onSync(void);
|
static void onSync(void);
|
||||||
static void host_task(void *param);
|
static void host_task(void *param);
|
||||||
static int startSecurity(uint16_t conn_id);
|
static int startSecurity(uint16_t conn_id);
|
||||||
|
|
||||||
static bool m_synced;
|
static bool m_synced;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
static NimBLEScan* m_pScan;
|
static NimBLEScan* m_pScan;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
static NimBLEServer* m_pServer;
|
static NimBLEServer* m_pServer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
static NimBLEAdvertising* m_bleAdvertising;
|
static NimBLEAdvertising* m_bleAdvertising;
|
||||||
static ble_gap_event_listener m_listener;
|
#endif
|
||||||
static uint32_t m_passkey;
|
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
static std::list <NimBLEClient*> m_cList;
|
static std::list <NimBLEClient*> m_cList;
|
||||||
|
#endif
|
||||||
static std::list <NimBLEAddress> m_ignoreList;
|
static std::list <NimBLEAddress> m_ignoreList;
|
||||||
static NimBLESecurityCallbacks* m_securityCallbacks;
|
static NimBLESecurityCallbacks* m_securityCallbacks;
|
||||||
|
static uint32_t m_passkey;
|
||||||
|
static ble_gap_event_listener m_listener;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static gap_event_handler m_customGapHandler;
|
static gap_event_handler m_customGapHandler;
|
||||||
|
|
|
@ -116,7 +116,7 @@ std::string NimBLEEddystoneTLM::toString() {
|
||||||
/**
|
/**
|
||||||
* Set the raw data for the beacon record.
|
* Set the raw data for the beacon record.
|
||||||
*/
|
*/
|
||||||
void NimBLEEddystoneTLM::setData(std::string data) {
|
void NimBLEEddystoneTLM::setData(const std::string &data) {
|
||||||
if (data.length() != sizeof(m_eddystoneData)) {
|
if (data.length() != sizeof(m_eddystoneData)) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
|
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and expected %d",
|
||||||
data.length(), sizeof(m_eddystoneData));
|
data.length(), sizeof(m_eddystoneData));
|
||||||
|
@ -125,7 +125,7 @@ void NimBLEEddystoneTLM::setData(std::string data) {
|
||||||
memcpy(&m_eddystoneData, data.data(), data.length());
|
memcpy(&m_eddystoneData, data.data(), data.length());
|
||||||
} // setData
|
} // setData
|
||||||
|
|
||||||
void NimBLEEddystoneTLM::setUUID(NimBLEUUID l_uuid) {
|
void NimBLEEddystoneTLM::setUUID(const NimBLEUUID &l_uuid) {
|
||||||
beaconUUID = l_uuid.getNative()->u16.value;
|
beaconUUID = l_uuid.getNative()->u16.value;
|
||||||
} // setUUID
|
} // setUUID
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ public:
|
||||||
uint32_t getCount();
|
uint32_t getCount();
|
||||||
uint32_t getTime();
|
uint32_t getTime();
|
||||||
std::string toString();
|
std::string toString();
|
||||||
void setData(std::string data);
|
void setData(const std::string &data);
|
||||||
void setUUID(NimBLEUUID l_uuid);
|
void setUUID(const NimBLEUUID &l_uuid);
|
||||||
void setVersion(uint8_t version);
|
void setVersion(uint8_t version);
|
||||||
void setVolt(uint16_t volt);
|
void setVolt(uint16_t volt);
|
||||||
void setTemp(float temp);
|
void setTemp(float temp);
|
||||||
|
|
|
@ -125,7 +125,7 @@ std::string NimBLEEddystoneURL::getDecodedURL() {
|
||||||
/**
|
/**
|
||||||
* Set the raw data for the beacon record.
|
* Set the raw data for the beacon record.
|
||||||
*/
|
*/
|
||||||
void NimBLEEddystoneURL::setData(std::string data) {
|
void NimBLEEddystoneURL::setData(const std::string &data) {
|
||||||
if (data.length() > sizeof(m_eddystoneData)) {
|
if (data.length() > sizeof(m_eddystoneData)) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and max expected %d",
|
NIMBLE_LOGE(LOG_TAG, "Unable to set the data ... length passed in was %d and max expected %d",
|
||||||
data.length(), sizeof(m_eddystoneData));
|
data.length(), sizeof(m_eddystoneData));
|
||||||
|
@ -136,7 +136,7 @@ void NimBLEEddystoneURL::setData(std::string data) {
|
||||||
lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url));
|
lengthURL = data.length() - (sizeof(m_eddystoneData) - sizeof(m_eddystoneData.url));
|
||||||
} // setData
|
} // setData
|
||||||
|
|
||||||
void NimBLEEddystoneURL::setUUID(NimBLEUUID l_uuid) {
|
void NimBLEEddystoneURL::setUUID(const NimBLEUUID &l_uuid) {
|
||||||
beaconUUID = l_uuid.getNative()->u16.value;
|
beaconUUID = l_uuid.getNative()->u16.value;
|
||||||
} // setUUID
|
} // setUUID
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ void NimBLEEddystoneURL::setPower(int8_t advertisedTxPower) {
|
||||||
m_eddystoneData.advertisedTxPower = advertisedTxPower;
|
m_eddystoneData.advertisedTxPower = advertisedTxPower;
|
||||||
} // setPower
|
} // setPower
|
||||||
|
|
||||||
void NimBLEEddystoneURL::setURL(std::string url) {
|
void NimBLEEddystoneURL::setURL(const std::string &url) {
|
||||||
if (url.length() > sizeof(m_eddystoneData.url)) {
|
if (url.length() > sizeof(m_eddystoneData.url)) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Unable to set the url ... length passed in was %d and max expected %d",
|
NIMBLE_LOGE(LOG_TAG, "Unable to set the url ... length passed in was %d and max expected %d",
|
||||||
url.length(), sizeof(m_eddystoneData.url));
|
url.length(), sizeof(m_eddystoneData.url));
|
||||||
|
|
|
@ -33,10 +33,10 @@ public:
|
||||||
int8_t getPower();
|
int8_t getPower();
|
||||||
std::string getURL();
|
std::string getURL();
|
||||||
std::string getDecodedURL();
|
std::string getDecodedURL();
|
||||||
void setData(std::string data);
|
void setData(const std::string &data);
|
||||||
void setUUID(NimBLEUUID l_uuid);
|
void setUUID(const NimBLEUUID &l_uuid);
|
||||||
void setPower(int8_t advertisedTxPower);
|
void setPower(int8_t advertisedTxPower);
|
||||||
void setURL(std::string url);
|
void setURL(const std::string &url);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t beaconUUID;
|
uint16_t beaconUUID;
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLERemoteCharacteristic.h"
|
#include "NimBLERemoteCharacteristic.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
@ -32,7 +35,9 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
||||||
* ble_uuid_any_t uuid;
|
* ble_uuid_any_t uuid;
|
||||||
* };
|
* };
|
||||||
*/
|
*/
|
||||||
NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService, const struct ble_gatt_chr *chr) {
|
NimBLERemoteCharacteristic::NimBLERemoteCharacteristic(NimBLERemoteService *pRemoteService,
|
||||||
|
const struct ble_gatt_chr *chr)
|
||||||
|
{
|
||||||
|
|
||||||
switch (chr->uuid.u.type) {
|
switch (chr->uuid.u.type) {
|
||||||
case BLE_UUID_TYPE_16:
|
case BLE_UUID_TYPE_16:
|
||||||
|
@ -53,6 +58,8 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
||||||
m_charProp = chr->properties;
|
m_charProp = chr->properties;
|
||||||
m_pRemoteService = pRemoteService;
|
m_pRemoteService = pRemoteService;
|
||||||
m_notifyCallback = nullptr;
|
m_notifyCallback = nullptr;
|
||||||
|
m_rawData = nullptr;
|
||||||
|
m_dataLen = 0;
|
||||||
} // NimBLERemoteCharacteristic
|
} // NimBLERemoteCharacteristic
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +68,9 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
|
||||||
*/
|
*/
|
||||||
NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
|
NimBLERemoteCharacteristic::~NimBLERemoteCharacteristic() {
|
||||||
removeDescriptors(); // Release resources for any descriptor information we may have allocated.
|
removeDescriptors(); // Release resources for any descriptor information we may have allocated.
|
||||||
if(m_rawData != nullptr) free(m_rawData);
|
if(m_rawData != nullptr) {
|
||||||
|
free(m_rawData);
|
||||||
|
}
|
||||||
} // ~NimBLERemoteCharacteristic
|
} // ~NimBLERemoteCharacteristic
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -138,9 +147,12 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||||
const struct ble_gatt_dsc *dsc,
|
const struct ble_gatt_dsc *dsc,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d", error->status, conn_handle);
|
NIMBLE_LOGD(LOG_TAG,"Descriptor Discovered >> status: %d handle: %d",
|
||||||
|
error->status, (error->status == 0) ? dsc->handle : -1);
|
||||||
|
|
||||||
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)arg;
|
disc_filter_t *filter = (disc_filter_t*)arg;
|
||||||
|
NimBLEUUID *uuid_filter = (NimBLEUUID*)filter->uuid;
|
||||||
|
NimBLERemoteCharacteristic *characteristic = (NimBLERemoteCharacteristic*)filter->attribute;
|
||||||
int rc=0;
|
int rc=0;
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
// Make sure the discovery is for this device
|
||||||
|
@ -150,73 +162,149 @@ int NimBLERemoteCharacteristic::descriptorDiscCB(uint16_t conn_handle,
|
||||||
|
|
||||||
switch (error->status) {
|
switch (error->status) {
|
||||||
case 0: {
|
case 0: {
|
||||||
// Found a descriptor - add it to the map
|
if(dsc->uuid.u.type == BLE_UUID_TYPE_16 && dsc->uuid.u16.value == uint16_t(0x2803)) {
|
||||||
NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc);
|
NIMBLE_LOGD(LOG_TAG,"Descriptor NOT found - end of Characteristic definintion");
|
||||||
characteristic->m_descriptorMap.insert(std::pair<std::string, NimBLERemoteDescriptor*>(pNewRemoteDescriptor->getUUID().toString(), pNewRemoteDescriptor));
|
rc = BLE_HS_EDONE;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BLE_HS_EDONE:{
|
if(uuid_filter != nullptr) {
|
||||||
/* All descriptors in this characteristic discovered; */
|
if(ble_uuid_cmp(&uuid_filter->getNative()->u, &dsc->uuid.u) != 0) {
|
||||||
characteristic->m_semaphoreGetDescEvt.give(0);
|
return 0;
|
||||||
rc = 0;
|
} else {
|
||||||
|
NIMBLE_LOGD(LOG_TAG,"Descriptor Found");
|
||||||
|
rc = BLE_HS_EDONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Found a descriptor - add it to the vector
|
||||||
|
NimBLERemoteDescriptor* pNewRemoteDescriptor = new NimBLERemoteDescriptor(characteristic, dsc);
|
||||||
|
characteristic->m_descriptorVector.push_back(pNewRemoteDescriptor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
rc = error->status;
|
rc = error->status;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (rc != 0) {
|
|
||||||
|
/** If rc == BLE_HS_EDONE, release the semaphore 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.
|
||||||
|
* If we get any other error code tell the application to abort by returning non-zero in the semaphore rc.
|
||||||
|
*/
|
||||||
|
if (rc == BLE_HS_EDONE) {
|
||||||
|
characteristic->m_semaphoreGetDescEvt.give(0);
|
||||||
|
} else if(rc != 0) {
|
||||||
/* Error; abort discovery. */
|
/* Error; abort discovery. */
|
||||||
// pass non-zero to semaphore on error to indicate an error finding descriptors
|
// pass error code to semaphore waiting
|
||||||
characteristic->m_semaphoreGetDescEvt.give(1);
|
characteristic->m_semaphoreGetDescEvt.give(rc);
|
||||||
}
|
}
|
||||||
NIMBLE_LOGD(LOG_TAG,"<< Descriptor Discovered. status: %d", rc);
|
NIMBLE_LOGD(LOG_TAG,"<< Descriptor Discovered. status: %d", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Populate the descriptors (if any) for this characteristic.
|
* @brief Populate the descriptors (if any) for this characteristic.
|
||||||
* @param [in] the end handle of the characteristic, or the service, whichever comes first.
|
* @param [in] the end handle of the characteristic, or the service, whichever comes first.
|
||||||
*/
|
*/
|
||||||
bool NimBLERemoteCharacteristic::retrieveDescriptors(uint16_t endHdl) {
|
bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filter) {
|
||||||
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;
|
||||||
//removeDescriptors(); // Remove any existing descriptors.
|
disc_filter_t filter;
|
||||||
|
filter.uuid = uuid_filter;
|
||||||
|
filter.attribute = this;
|
||||||
|
|
||||||
m_semaphoreGetDescEvt.take("retrieveDescriptors");
|
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,
|
||||||
endHdl,
|
getRemoteService()->getEndHandle(),
|
||||||
NimBLERemoteCharacteristic::descriptorDiscCB,
|
NimBLERemoteCharacteristic::descriptorDiscCB,
|
||||||
this);
|
&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();
|
m_semaphoreGetDescEvt.give();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_semaphoreGetDescEvt.wait("retrieveCharacteristics") != 0) {
|
if(m_semaphoreGetDescEvt.wait("retrieveDescriptors") != 0) {
|
||||||
// if there was an error release the resources
|
|
||||||
//removeDescriptors();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorMap.size());
|
NIMBLE_LOGD(LOG_TAG, "<< retrieveDescriptors(): Found %d descriptors.", m_descriptorVector.size());
|
||||||
} // getDescriptors
|
} // getDescriptors
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the map of descriptors keyed by UUID.
|
* @brief Get the descriptor instance with the given UUID that belongs to this characteristic.
|
||||||
|
* @param [in] uuid The UUID of the descriptor to find.
|
||||||
|
* @return The Remote descriptor (if present) or null if not present.
|
||||||
*/
|
*/
|
||||||
std::map<std::string, NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors() {
|
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID &uuid) {
|
||||||
return &m_descriptorMap;
|
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
||||||
|
|
||||||
|
for(auto &it: m_descriptorVector) {
|
||||||
|
if(it->getUUID() == uuid) {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found");
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t prev_size = m_descriptorVector.size();
|
||||||
|
if(retrieveDescriptors(&uuid)) {
|
||||||
|
if(m_descriptorVector.size() > prev_size) {
|
||||||
|
return m_descriptorVector.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found");
|
||||||
|
return nullptr;
|
||||||
|
} // getDescriptor
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get a pointer to the vector of found descriptors.
|
||||||
|
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||||
|
* subsequently all descriptors for this characteristic retrieved from the peripheral.
|
||||||
|
* If false the vector will be returned with the currently stored descriptors,
|
||||||
|
* if the vector is empty it will retrieve all descriptors for this characteristic
|
||||||
|
* from the peripheral.
|
||||||
|
* @return a pointer to the vector of descriptors for this characteristic.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLERemoteDescriptor*>* NimBLERemoteCharacteristic::getDescriptors(bool refresh) {
|
||||||
|
if(refresh) {
|
||||||
|
removeDescriptors();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_descriptorVector.empty()) {
|
||||||
|
if (!retrieveDescriptors()) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to get descriptors");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Found %d descriptor(s)", m_descriptorVector.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &m_descriptorVector;
|
||||||
} // getDescriptors
|
} // getDescriptors
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get iterator to the beginning of the vector of remote descriptor pointers.
|
||||||
|
* @return An iterator to the beginning of the vector of remote descriptor pointers.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLERemoteDescriptor*>::iterator NimBLERemoteCharacteristic::begin() {
|
||||||
|
return m_descriptorVector.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get iterator to the end of the vector of remote descriptor pointers.
|
||||||
|
* @return An iterator to the end of the vector of remote descriptor pointers.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLERemoteDescriptor*>::iterator NimBLERemoteCharacteristic::end() {
|
||||||
|
return m_descriptorVector.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the handle for this characteristic.
|
* @brief Get the handle for this characteristic.
|
||||||
* @return The handle for this characteristic.
|
* @return The handle for this characteristic.
|
||||||
|
@ -234,25 +322,6 @@ uint16_t NimBLERemoteCharacteristic::getDefHandle() {
|
||||||
} // getDefHandle
|
} // getDefHandle
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the descriptor instance with the given UUID that belongs to this characteristic.
|
|
||||||
* @param [in] uuid The UUID of the descriptor to find.
|
|
||||||
* @return The Remote descriptor (if present) or null if not present.
|
|
||||||
*/
|
|
||||||
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(NimBLEUUID uuid) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
|
|
||||||
std::string v = uuid.toString();
|
|
||||||
for (auto &myPair : m_descriptorMap) {
|
|
||||||
if (myPair.first == v) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: found");
|
|
||||||
return myPair.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< getDescriptor: Not found");
|
|
||||||
return nullptr;
|
|
||||||
} // getDescriptor
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the remote service associated with this characteristic.
|
* @brief Get the remote service associated with this characteristic.
|
||||||
* @return The remote service associated with this characteristic.
|
* @return The remote service associated with this characteristic.
|
||||||
|
@ -315,10 +384,13 @@ uint8_t NimBLERemoteCharacteristic::readUInt8() {
|
||||||
* @return The value of the remote characteristic.
|
* @return The value of the remote characteristic.
|
||||||
*/
|
*/
|
||||||
std::string NimBLERemoteCharacteristic::readValue() {
|
std::string NimBLERemoteCharacteristic::readValue() {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x", getUUID().toString().c_str(), getHandle(), getHandle());
|
NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x",
|
||||||
|
getUUID().toString().c_str(), getHandle(), getHandle());
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int retryCount = 1;
|
int retryCount = 1;
|
||||||
|
// Clear the value before reading.
|
||||||
|
m_value = "";
|
||||||
|
|
||||||
NimBLEClient* pClient = getRemoteService()->getClient();
|
NimBLEClient* pClient = getRemoteService()->getClient();
|
||||||
|
|
||||||
|
@ -331,24 +403,27 @@ std::string NimBLERemoteCharacteristic::readValue() {
|
||||||
do {
|
do {
|
||||||
m_semaphoreReadCharEvt.take("readValue");
|
m_semaphoreReadCharEvt.take("readValue");
|
||||||
|
|
||||||
rc = ble_gattc_read(pClient->getConnId(), m_handle,
|
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
||||||
NimBLERemoteCharacteristic::onReadCB, this);
|
NimBLERemoteCharacteristic::onReadCB,
|
||||||
|
this);
|
||||||
// long read experiment
|
|
||||||
/* rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
|
||||||
NimBLERemoteCharacteristic::onReadCB, this);
|
|
||||||
*/
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d", rc);
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d, %s",
|
||||||
m_semaphoreReadCharEvt.give();
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
m_semaphoreReadCharEvt.give(0);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = m_semaphoreReadCharEvt.wait("readValue");
|
rc = m_semaphoreReadCharEvt.wait("readValue");
|
||||||
switch(rc){
|
switch(rc){
|
||||||
case 0:
|
case 0:
|
||||||
|
case BLE_HS_EDONE:
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
// Characteristic 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;
|
break;
|
||||||
|
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
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_AUTHOR):
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
|
||||||
|
@ -361,7 +436,7 @@ std::string NimBLERemoteCharacteristic::readValue() {
|
||||||
} while(rc != 0 && retryCount--);
|
} while(rc != 0 && retryCount--);
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length());
|
NIMBLE_LOGD(LOG_TAG, "<< readValue(): length: %d", m_value.length());
|
||||||
return (rc == 0) ? m_value : "";
|
return m_value;
|
||||||
} // readValue
|
} // readValue
|
||||||
|
|
||||||
|
|
||||||
|
@ -374,36 +449,25 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
|
||||||
struct ble_gatt_attr *attr, void *arg)
|
struct ble_gatt_attr *attr, void *arg)
|
||||||
{
|
{
|
||||||
NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg;
|
NimBLERemoteCharacteristic* characteristic = (NimBLERemoteCharacteristic*)arg;
|
||||||
|
uint16_t conn_id = characteristic->getRemoteService()->getClient()->getConnId();
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
// Make sure the read is for this client
|
||||||
if(characteristic->getRemoteService()->getClient()->getConnId() != 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);
|
||||||
// long read experiment
|
|
||||||
/* if(attr && (attr->om->om_len >= (ble_att_mtu(characteristic->getRemoteService()->getClient()->getConnId()) - 1))){
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(characteristic->m_rawData != nullptr) {
|
|
||||||
free(characteristic->m_rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(error->status == 0) {
|
if(error->status == 0) {
|
||||||
characteristic->m_value = std::string((char*) attr->om->om_data, attr->om->om_len);
|
if(attr) {
|
||||||
characteristic->m_rawData = (uint8_t*) calloc(attr->om->om_len, sizeof(uint8_t));
|
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
|
||||||
memcpy(characteristic->m_rawData, attr->om->om_data, attr->om->om_len);
|
|
||||||
characteristic->m_semaphoreReadCharEvt.give(0);
|
|
||||||
} else {
|
|
||||||
characteristic->m_rawData = nullptr;
|
|
||||||
characteristic->m_value = "";
|
|
||||||
characteristic->m_semaphoreReadCharEvt.give(error->status);
|
|
||||||
}
|
|
||||||
|
|
||||||
// characteristic->m_semaphoreReadCharEvt.give(error->status);
|
characteristic->m_value += std::string((char*) attr->om->om_data, attr->om->om_len);
|
||||||
return 0; //1
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Read complete release semaphore and let the app can continue.
|
||||||
|
characteristic->m_semaphoreReadCharEvt.give(error->status);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -443,19 +507,18 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Delete the descriptors in the descriptor map.
|
* @brief Delete the descriptors in the descriptor vector.
|
||||||
* We maintain a map called m_descriptorMap that contains pointers to BLERemoteDescriptors
|
* We maintain a vector called m_descriptorVector that contains pointers to BLERemoteDescriptors
|
||||||
* object references. Since we allocated these in this class, we are also responsible for deleteing
|
* object references. Since we allocated these in this class, we are also responsible for deleteing
|
||||||
* them. This method does just that.
|
* them. This method does just that.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLERemoteCharacteristic::removeDescriptors() {
|
void NimBLERemoteCharacteristic::removeDescriptors() {
|
||||||
// Iterate through all the descriptors releasing their storage and erasing them from the map.
|
// Iterate through all the descriptors releasing their storage and erasing them from the vector.
|
||||||
for (auto &myPair : m_descriptorMap) {
|
for(auto &it: m_descriptorVector) {
|
||||||
m_descriptorMap.erase(myPair.first);
|
delete it;
|
||||||
delete myPair.second;
|
|
||||||
}
|
}
|
||||||
m_descriptorMap.clear(); // Technically not neeeded, but just to be sure.
|
m_descriptorVector.clear();
|
||||||
} // removeCharacteristics
|
} // removeCharacteristics
|
||||||
|
|
||||||
|
|
||||||
|
@ -477,8 +540,8 @@ std::string NimBLERemoteCharacteristic::toString() {
|
||||||
snprintf(val, sizeof(val), "%02x", m_charProp);
|
snprintf(val, sizeof(val), "%02x", m_charProp);
|
||||||
res += val;
|
res += val;
|
||||||
|
|
||||||
for (auto &myPair : m_descriptorMap) {
|
for(auto &it: m_descriptorVector) {
|
||||||
res += "\n" + myPair.second->toString();
|
res += "\n" + it->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -491,7 +554,7 @@ std::string NimBLERemoteCharacteristic::toString() {
|
||||||
* @param [in] response Do we expect a response?
|
* @param [in] response Do we expect a response?
|
||||||
* @return false if not connected or cant perform write for some reason.
|
* @return false if not connected or cant perform write for some reason.
|
||||||
*/
|
*/
|
||||||
bool NimBLERemoteCharacteristic::writeValue(std::string newValue, bool response) {
|
bool NimBLERemoteCharacteristic::writeValue(const std::string &newValue, bool response) {
|
||||||
return writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response);
|
return writeValue((uint8_t*)newValue.c_str(), strlen(newValue.c_str()), response);
|
||||||
} // writeValue
|
} // writeValue
|
||||||
|
|
||||||
|
@ -516,14 +579,14 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t newValue, bool response) {
|
||||||
* @param [in] response Whether we require a response from the write.
|
* @param [in] response Whether we require a response from the write.
|
||||||
* @return false if not connected or cant perform write for some reason.
|
* @return false if not connected or cant perform write for some reason.
|
||||||
*/
|
*/
|
||||||
bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool response) {
|
bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) {
|
||||||
|
|
||||||
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 rc = 0;
|
||||||
int retryCount = 1;
|
int retryCount = 1;
|
||||||
// uint16_t mtu;
|
uint16_t mtu;
|
||||||
|
|
||||||
// Check to see that we are connected.
|
// Check to see that we are connected.
|
||||||
if (!pClient->isConnected()) {
|
if (!pClient->isConnected()) {
|
||||||
|
@ -531,29 +594,30 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool r
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
||||||
|
|
||||||
if(/*!length > mtu &&*/ !response) {
|
// 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(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 {
|
do {
|
||||||
m_semaphoreWriteCharEvt.take("writeValue");
|
m_semaphoreWriteCharEvt.take("writeValue");
|
||||||
// long write experiment
|
|
||||||
/* if(length > mtu) {
|
if(length > mtu) {
|
||||||
NIMBLE_LOGD(LOG_TAG,"long write");
|
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);
|
this);
|
||||||
} 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);
|
this);
|
||||||
// }
|
}
|
||||||
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();
|
m_semaphoreWriteCharEvt.give();
|
||||||
|
@ -564,6 +628,13 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool r
|
||||||
|
|
||||||
switch(rc){
|
switch(rc){
|
||||||
case 0:
|
case 0:
|
||||||
|
case BLE_HS_EDONE:
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Long write not supported by peer; Truncating length to %d", mtu);
|
||||||
|
retryCount++;
|
||||||
|
length = mtu;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
||||||
|
@ -599,13 +670,7 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
if (error->status == 0) {
|
|
||||||
|
|
||||||
characteristic->m_semaphoreWriteCharEvt.give(0);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
characteristic->m_semaphoreWriteCharEvt.give(error->status);
|
characteristic->m_semaphoreWriteCharEvt.give(error->status);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -613,19 +678,42 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read raw data from remote characteristic as hex bytes
|
* @brief Read raw data from remote characteristic as hex bytes
|
||||||
* @return return pointer data read
|
* @return uint8_t pointer to the data read.
|
||||||
*/
|
*/
|
||||||
uint8_t* NimBLERemoteCharacteristic::readRawData() {
|
uint8_t* NimBLERemoteCharacteristic::readRawData() {
|
||||||
|
if(m_rawData != nullptr) {
|
||||||
|
free(m_rawData);
|
||||||
|
m_rawData = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dataLen = m_value.length();
|
||||||
|
// If we have data copy it to rawData
|
||||||
|
if(m_dataLen) {
|
||||||
|
m_rawData = (uint8_t*) calloc(m_dataLen, sizeof(uint8_t));
|
||||||
|
memcpy(m_rawData, m_value.data(), m_dataLen);
|
||||||
|
}
|
||||||
|
|
||||||
return m_rawData;
|
return m_rawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the length of the data read from the remote characteristic.
|
||||||
|
* @return size_t length of the data in bytes.
|
||||||
|
*/
|
||||||
|
size_t NimBLERemoteCharacteristic::getDataLength() {
|
||||||
|
return m_value.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void NimBLERemoteCharacteristic::releaseSemaphores() {
|
void NimBLERemoteCharacteristic::releaseSemaphores() {
|
||||||
for (auto &dPair : m_descriptorMap) {
|
for (auto &it: m_descriptorVector) {
|
||||||
dPair.second->releaseSemaphores();
|
it->releaseSemaphores();
|
||||||
}
|
}
|
||||||
m_semaphoreWriteCharEvt.give(1);
|
m_semaphoreWriteCharEvt.give(1);
|
||||||
m_semaphoreGetDescEvt.give(1);
|
m_semaphoreGetDescEvt.give(1);
|
||||||
m_semaphoreReadCharEvt.give(1);
|
m_semaphoreReadCharEvt.give(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -17,19 +17,20 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
//#include "NimBLEUUID.h"
|
#include "nimconfig.h"
|
||||||
//#include "FreeRTOS.h"
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLERemoteService.h"
|
#include "NimBLERemoteService.h"
|
||||||
#include "NimBLERemoteDescriptor.h"
|
#include "NimBLERemoteDescriptor.h"
|
||||||
|
|
||||||
//#include <string>
|
#include <vector>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
class NimBLERemoteService;
|
class NimBLERemoteService;
|
||||||
class NimBLERemoteDescriptor;
|
class NimBLERemoteDescriptor;
|
||||||
|
|
||||||
|
|
||||||
typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify);
|
typedef void (*notify_callback)(NimBLERemoteCharacteristic* pBLERemoteCharacteristic,
|
||||||
|
uint8_t* pData, size_t length, bool isNotify);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A model of a remote %BLE characteristic.
|
* @brief A model of a remote %BLE characteristic.
|
||||||
|
@ -45,8 +46,10 @@ public:
|
||||||
bool canRead();
|
bool canRead();
|
||||||
bool canWrite();
|
bool canWrite();
|
||||||
bool canWriteNoResponse();
|
bool canWriteNoResponse();
|
||||||
NimBLERemoteDescriptor* getDescriptor(NimBLEUUID uuid);
|
std::vector<NimBLERemoteDescriptor*>::iterator begin();
|
||||||
std::map<std::string, NimBLERemoteDescriptor*>* getDescriptors();
|
std::vector<NimBLERemoteDescriptor*>::iterator end();
|
||||||
|
NimBLERemoteDescriptor* getDescriptor(const NimBLEUUID &uuid);
|
||||||
|
std::vector<NimBLERemoteDescriptor*>* getDescriptors(bool refresh = false);
|
||||||
uint16_t getHandle();
|
uint16_t getHandle();
|
||||||
uint16_t getDefHandle();
|
uint16_t getDefHandle();
|
||||||
NimBLEUUID getUUID();
|
NimBLEUUID getUUID();
|
||||||
|
@ -54,12 +57,19 @@ public:
|
||||||
uint8_t readUInt8();
|
uint8_t readUInt8();
|
||||||
uint16_t readUInt16();
|
uint16_t readUInt16();
|
||||||
uint32_t readUInt32();
|
uint32_t readUInt32();
|
||||||
bool registerForNotify(notify_callback _callback, bool notifications = true, bool response = true);
|
bool registerForNotify(notify_callback _callback,
|
||||||
bool writeValue(uint8_t* data, size_t length, bool response = false);
|
bool notifications = true,
|
||||||
bool writeValue(std::string newValue, bool response = false);
|
bool response = true);
|
||||||
bool writeValue(uint8_t newValue, 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(uint8_t newValue,
|
||||||
|
bool response = false);
|
||||||
std::string toString();
|
std::string toString();
|
||||||
uint8_t* readRawData();
|
uint8_t* readRawData();
|
||||||
|
size_t getDataLength();
|
||||||
NimBLERemoteService* getRemoteService();
|
NimBLERemoteService* getRemoteService();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -72,9 +82,11 @@ private:
|
||||||
|
|
||||||
// Private member functions
|
// Private member functions
|
||||||
void removeDescriptors();
|
void removeDescriptors();
|
||||||
bool retrieveDescriptors(uint16_t endHdl);
|
bool retrieveDescriptors(const NimBLEUUID *uuid_filter = nullptr);
|
||||||
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg);
|
static int onReadCB(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);
|
||||||
|
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||||
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
void releaseSemaphores();
|
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,
|
||||||
|
@ -90,11 +102,14 @@ private:
|
||||||
FreeRTOS::Semaphore m_semaphoreReadCharEvt = FreeRTOS::Semaphore("ReadCharEvt");
|
FreeRTOS::Semaphore m_semaphoreReadCharEvt = FreeRTOS::Semaphore("ReadCharEvt");
|
||||||
FreeRTOS::Semaphore m_semaphoreWriteCharEvt = FreeRTOS::Semaphore("WriteCharEvt");
|
FreeRTOS::Semaphore m_semaphoreWriteCharEvt = FreeRTOS::Semaphore("WriteCharEvt");
|
||||||
std::string m_value;
|
std::string m_value;
|
||||||
uint8_t* m_rawData = nullptr;
|
uint8_t* m_rawData;
|
||||||
|
size_t m_dataLen;
|
||||||
notify_callback m_notifyCallback;
|
notify_callback m_notifyCallback;
|
||||||
|
|
||||||
// We maintain a map of descriptors owned by this characteristic keyed by a string representation of the UUID.
|
// We maintain a vector of descriptors owned by this characteristic.
|
||||||
std::map<std::string, NimBLERemoteDescriptor*> m_descriptorMap;
|
std::vector<NimBLERemoteDescriptor*> m_descriptorVector;
|
||||||
}; // BLERemoteCharacteristic
|
}; // NimBLERemoteCharacteristic
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */
|
#endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */
|
||||||
|
|
|
@ -14,7 +14,11 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLERemoteDescriptor.h"
|
#include "NimBLERemoteDescriptor.h"
|
||||||
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
static const char* LOG_TAG = "NimBLERemoteDescriptor";
|
static const char* LOG_TAG = "NimBLERemoteDescriptor";
|
||||||
|
@ -83,22 +87,26 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
|
||||||
struct ble_gatt_attr *attr, void *arg)
|
struct ble_gatt_attr *attr, void *arg)
|
||||||
{
|
{
|
||||||
NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)arg;
|
NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)arg;
|
||||||
|
uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId();
|
||||||
|
|
||||||
// Make sure the discovery is for this device
|
// Make sure the discovery is for this device
|
||||||
if(desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId() != conn_handle){
|
if(conn_id != conn_handle){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
|
NIMBLE_LOGD(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||||
|
|
||||||
if(error->status == 0){
|
if(error->status == 0){
|
||||||
desc->m_value = std::string((char*) attr->om->om_data, attr->om->om_len);
|
if(attr){
|
||||||
desc->m_semaphoreReadDescrEvt.give(0);
|
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len);
|
||||||
} else {
|
|
||||||
desc->m_value = "";
|
desc->m_value += std::string((char*) attr->om->om_data, attr->om->om_len);
|
||||||
desc->m_semaphoreReadDescrEvt.give(error->status);
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read complete release semaphore and let the app can continue.
|
||||||
|
desc->m_semaphoreReadDescrEvt.give(error->status);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,10 +114,12 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
|
||||||
std::string NimBLERemoteDescriptor::readValue() {
|
std::string NimBLERemoteDescriptor::readValue() {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> Descriptor readValue: %s", toString().c_str());
|
||||||
|
|
||||||
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
|
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int retryCount = 1;
|
int retryCount = 1;
|
||||||
|
// Clear the value before reading.
|
||||||
|
m_value = "";
|
||||||
|
|
||||||
|
NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
|
||||||
|
|
||||||
// Check to see that we are connected.
|
// Check to see that we are connected.
|
||||||
if (!pClient->isConnected()) {
|
if (!pClient->isConnected()) {
|
||||||
|
@ -120,12 +130,13 @@ std::string NimBLERemoteDescriptor::readValue() {
|
||||||
do {
|
do {
|
||||||
m_semaphoreReadDescrEvt.take("ReadDescriptor");
|
m_semaphoreReadDescrEvt.take("ReadDescriptor");
|
||||||
|
|
||||||
rc = ble_gattc_read(pClient->getConnId(), m_handle,
|
rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
|
||||||
NimBLERemoteDescriptor::onReadCB, this);
|
NimBLERemoteDescriptor::onReadCB,
|
||||||
|
this);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "Descriptor read failed, code: %d", rc);
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read descriptor; rc=%d, %s",
|
||||||
m_semaphoreReadDescrEvt.give();
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
m_semaphoreReadDescrEvt.give(0);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,8 +144,14 @@ std::string NimBLERemoteDescriptor::readValue() {
|
||||||
|
|
||||||
switch(rc){
|
switch(rc){
|
||||||
case 0:
|
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;
|
break;
|
||||||
|
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
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_AUTHOR):
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC):
|
||||||
|
@ -146,9 +163,8 @@ std::string NimBLERemoteDescriptor::readValue() {
|
||||||
}
|
}
|
||||||
} while(rc != 0 && retryCount--);
|
} while(rc != 0 && retryCount--);
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %d, rc: %d", m_value.length(), rc);
|
NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %d", m_value.length());
|
||||||
|
return m_value;
|
||||||
return (rc == 0) ? m_value : "";
|
|
||||||
} // readValue
|
} // readValue
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,11 +227,7 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
|
NIMBLE_LOGD(LOG_TAG, "Write complete; status=%d conn_handle=%d", error->status, conn_handle);
|
||||||
|
|
||||||
if (error->status == 0) {
|
|
||||||
descriptor->m_semaphoreDescWrite.give(0);
|
|
||||||
} else {
|
|
||||||
descriptor->m_semaphoreDescWrite.give(error->status);
|
descriptor->m_semaphoreDescWrite.give(error->status);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -227,7 +239,7 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
|
||||||
* @param [in] length The length of the data to send.
|
* @param [in] length The length of the data to send.
|
||||||
* @param [in] response True if we expect a response.
|
* @param [in] response True if we expect a response.
|
||||||
*/
|
*/
|
||||||
bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool response) {
|
bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) {
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> Descriptor writeValue: %s", toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> Descriptor writeValue: %s", toString().c_str());
|
||||||
|
|
||||||
|
@ -235,6 +247,7 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
||||||
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int retryCount = 1;
|
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()) {
|
||||||
|
@ -242,7 +255,11 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!response) {
|
mtu = ble_att_mtu(pClient->getConnId()) - 3;
|
||||||
|
|
||||||
|
// 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(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);
|
||||||
}
|
}
|
||||||
|
@ -250,10 +267,19 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
||||||
do {
|
do {
|
||||||
m_semaphoreDescWrite.take("WriteDescriptor");
|
m_semaphoreDescWrite.take("WriteDescriptor");
|
||||||
|
|
||||||
|
if(length > mtu) {
|
||||||
|
NIMBLE_LOGI(LOG_TAG,"long write %d bytes", length);
|
||||||
|
os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
|
||||||
|
rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om,
|
||||||
|
NimBLERemoteDescriptor::onWriteCB,
|
||||||
|
this);
|
||||||
|
} 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);
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
m_semaphoreDescWrite.give();
|
||||||
|
@ -264,6 +290,13 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
||||||
|
|
||||||
switch(rc){
|
switch(rc){
|
||||||
case 0:
|
case 0:
|
||||||
|
case BLE_HS_EDONE:
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_ATTR_NOT_LONG):
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Long write not supported by peer; Truncating length to %d", mtu);
|
||||||
|
retryCount++;
|
||||||
|
length = mtu;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN):
|
||||||
|
@ -278,7 +311,7 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
||||||
} while(rc != 0 && retryCount--);
|
} while(rc != 0 && retryCount--);
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< Descriptor writeValue, rc: %d",rc);
|
NIMBLE_LOGD(LOG_TAG, "<< Descriptor writeValue, rc: %d",rc);
|
||||||
return (rc == 0); //true;
|
return (rc == 0);
|
||||||
} // writeValue
|
} // writeValue
|
||||||
|
|
||||||
|
|
||||||
|
@ -287,7 +320,7 @@ bool NimBLERemoteDescriptor::writeValue(uint8_t* data, size_t length, bool respo
|
||||||
* @param [in] newValue The data to send to the remote descriptor.
|
* @param [in] newValue The data to send to the remote descriptor.
|
||||||
* @param [in] response True if we expect a response.
|
* @param [in] response True if we expect a response.
|
||||||
*/
|
*/
|
||||||
bool NimBLERemoteDescriptor::writeValue(std::string newValue, bool response) {
|
bool NimBLERemoteDescriptor::writeValue(const std::string &newValue, bool response) {
|
||||||
return writeValue((uint8_t*) newValue.data(), newValue.length(), response);
|
return writeValue((uint8_t*) newValue.data(), newValue.length(), response);
|
||||||
} // writeValue
|
} // writeValue
|
||||||
|
|
||||||
|
@ -309,4 +342,6 @@ void NimBLERemoteDescriptor::releaseSemaphores() {
|
||||||
m_semaphoreDescWrite.give(1);
|
m_semaphoreDescWrite.give(1);
|
||||||
m_semaphoreReadDescrEvt.give(1);
|
m_semaphoreReadDescrEvt.give(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLERemoteCharacteristic.h"
|
#include "NimBLERemoteCharacteristic.h"
|
||||||
|
|
||||||
class NimBLERemoteCharacteristic;
|
class NimBLERemoteCharacteristic;
|
||||||
|
@ -33,26 +36,32 @@ public:
|
||||||
uint16_t readUInt16(void);
|
uint16_t readUInt16(void);
|
||||||
uint32_t readUInt32(void);
|
uint32_t readUInt32(void);
|
||||||
std::string toString(void);
|
std::string toString(void);
|
||||||
bool writeValue(uint8_t* data, size_t length, bool response = false);
|
bool writeValue(const uint8_t* data, size_t length, bool response = false);
|
||||||
bool writeValue(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;
|
||||||
NimBLERemoteDescriptor(NimBLERemoteCharacteristic* pRemoteCharacteristic, const struct ble_gatt_dsc *dsc);
|
|
||||||
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg);
|
NimBLERemoteDescriptor (NimBLERemoteCharacteristic* pRemoteCharacteristic,
|
||||||
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg);
|
const struct ble_gatt_dsc *dsc);
|
||||||
|
static int onWriteCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||||
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
|
static int onReadCB(uint16_t conn_handle, const struct ble_gatt_error *error,
|
||||||
|
struct ble_gatt_attr *attr, void *arg);
|
||||||
void releaseSemaphores();
|
void releaseSemaphores();
|
||||||
|
|
||||||
uint16_t m_handle; // Server handle of this descriptor.
|
uint16_t m_handle;
|
||||||
NimBLEUUID m_uuid; // UUID of this descriptor.
|
NimBLEUUID m_uuid;
|
||||||
std::string m_value; // Last received value of the descriptor.
|
std::string m_value;
|
||||||
NimBLERemoteCharacteristic* m_pRemoteCharacteristic; // Reference to the Remote characteristic of which this descriptor is associated.
|
NimBLERemoteCharacteristic* m_pRemoteCharacteristic;
|
||||||
FreeRTOS::Semaphore m_semaphoreReadDescrEvt = FreeRTOS::Semaphore("ReadDescrEvt");
|
FreeRTOS::Semaphore m_semaphoreReadDescrEvt = FreeRTOS::Semaphore("ReadDescrEvt");
|
||||||
FreeRTOS::Semaphore m_semaphoreDescWrite = FreeRTOS::Semaphore("WriteDescEvt");
|
FreeRTOS::Semaphore m_semaphoreDescWrite = FreeRTOS::Semaphore("WriteDescEvt");
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */
|
#endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLERemoteService.h"
|
#include "NimBLERemoteService.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
|
@ -28,7 +31,7 @@ static const char* LOG_TAG = "NimBLERemoteService";
|
||||||
*/
|
*/
|
||||||
NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service) {
|
NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble_gatt_svc* service) {
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> BLERemoteService()");
|
NIMBLE_LOGD(LOG_TAG, ">> NimBLERemoteService()");
|
||||||
m_pClient = pClient;
|
m_pClient = pClient;
|
||||||
switch (service->uuid.u.type) {
|
switch (service->uuid.u.type) {
|
||||||
case BLE_UUID_TYPE_16:
|
case BLE_UUID_TYPE_16:
|
||||||
|
@ -46,9 +49,7 @@ NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const struct ble
|
||||||
}
|
}
|
||||||
m_startHandle = service->start_handle;
|
m_startHandle = service->start_handle;
|
||||||
m_endHandle = service->end_handle;
|
m_endHandle = service->end_handle;
|
||||||
m_haveCharacteristics = false;
|
NIMBLE_LOGD(LOG_TAG, "<< NimBLERemoteService()");
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< BLERemoteService()");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +62,24 @@ NimBLERemoteService::~NimBLERemoteService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get iterator to the beginning of the vector of remote characteristic pointers.
|
||||||
|
* @return An iterator to the beginning of the vector of remote characteristic pointers.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLERemoteCharacteristic*>::iterator NimBLERemoteService::begin() {
|
||||||
|
return m_characteristicVector.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get iterator to the end of the vector of remote characteristic pointers.
|
||||||
|
* @return An iterator to the end of the vector of remote characteristic pointers.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLERemoteCharacteristic*>::iterator NimBLERemoteService::end() {
|
||||||
|
return m_characteristicVector.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the remote characteristic object for the characteristic UUID.
|
* @brief Get the remote characteristic object for the characteristic UUID.
|
||||||
* @param [in] uuid Remote characteristic uuid.
|
* @param [in] uuid Remote characteristic uuid.
|
||||||
|
@ -76,20 +95,51 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u
|
||||||
* @param [in] uuid Characteristic uuid.
|
* @param [in] uuid Characteristic uuid.
|
||||||
* @return Reference to the characteristic object, or nullptr if not found.
|
* @return Reference to the characteristic object, or nullptr if not found.
|
||||||
*/
|
*/
|
||||||
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(NimBLEUUID uuid) {
|
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||||
if (m_haveCharacteristics) {
|
for(auto &it: m_characteristicVector) {
|
||||||
std::string v = uuid.toString();
|
if(it->getUUID() == uuid) {
|
||||||
for (auto &myPair : m_characteristicMap) {
|
return it;
|
||||||
if (myPair.first == v) {
|
|
||||||
return myPair.second;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t prev_size = m_characteristicVector.size();
|
||||||
|
if(retrieveCharacteristics(&uuid)) {
|
||||||
|
if(m_characteristicVector.size() > prev_size) {
|
||||||
|
return m_characteristicVector.back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} // getCharacteristic
|
} // getCharacteristic
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Get a pointer to the vector of found characteristics.
|
||||||
|
* @param [in] bool value to indicate if the current vector should be cleared and
|
||||||
|
* subsequently all characteristics for this service retrieved from the peripheral.
|
||||||
|
* If false the vector will be returned with the currently stored characteristics,
|
||||||
|
* if the vector is empty it will retrieve all characteristics of this service
|
||||||
|
* from the peripheral.
|
||||||
|
* @return a pointer to the vector of descriptors for this characteristic.
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::vector<NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristics(bool refresh) {
|
||||||
|
if(refresh) {
|
||||||
|
removeCharacteristics();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_characteristicVector.empty()) {
|
||||||
|
if (!retrieveCharacteristics()) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Error: Failed to get characteristics");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Found %d characteristics", m_characteristicVector.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &m_characteristicVector;
|
||||||
|
} // getCharacteristics
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Callback for Characterisic discovery.
|
* @brief Callback for Characterisic discovery.
|
||||||
*/
|
*/
|
||||||
|
@ -97,7 +147,8 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||||
const struct ble_gatt_error *error,
|
const struct ble_gatt_error *error,
|
||||||
const struct ble_gatt_chr *chr, void *arg)
|
const struct ble_gatt_chr *chr, void *arg)
|
||||||
{
|
{
|
||||||
NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d", error->status, conn_handle);
|
NIMBLE_LOGD(LOG_TAG,"Characteristic Discovered >> status: %d handle: %d",
|
||||||
|
error->status, (error->status == 0) ? chr->val_handle : -1);
|
||||||
|
|
||||||
NimBLERemoteService *service = (NimBLERemoteService*)arg;
|
NimBLERemoteService *service = (NimBLERemoteService*)arg;
|
||||||
int rc=0;
|
int rc=0;
|
||||||
|
@ -109,10 +160,9 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||||
|
|
||||||
switch (error->status) {
|
switch (error->status) {
|
||||||
case 0: {
|
case 0: {
|
||||||
// Found a service - add it to the map
|
// Found a service - add it to the vector
|
||||||
NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr);
|
NimBLERemoteCharacteristic* pRemoteCharacteristic = new NimBLERemoteCharacteristic(service, chr);
|
||||||
service->m_characteristicMap.insert(std::pair<std::string, NimBLERemoteCharacteristic*>(pRemoteCharacteristic->getUUID().toString(), pRemoteCharacteristic));
|
service->m_characteristicVector.push_back(pRemoteCharacteristic);
|
||||||
service->m_characteristicMapByHandle.insert(std::pair<uint16_t, NimBLERemoteCharacteristic*>(chr->val_handle, pRemoteCharacteristic));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BLE_HS_EDONE:{
|
case BLE_HS_EDONE:{
|
||||||
|
@ -145,7 +195,7 @@ int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
|
||||||
* This function will not return until we have all the characteristics.
|
* This function will not return until we have all the characteristics.
|
||||||
* @return N/A
|
* @return N/A
|
||||||
*/
|
*/
|
||||||
bool NimBLERemoteService::retrieveCharacteristics() {
|
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;
|
||||||
|
@ -153,48 +203,28 @@ bool NimBLERemoteService::retrieveCharacteristics() {
|
||||||
|
|
||||||
m_semaphoreGetCharEvt.take("retrieveCharacteristics");
|
m_semaphoreGetCharEvt.take("retrieveCharacteristics");
|
||||||
|
|
||||||
|
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);
|
this);
|
||||||
|
} else {
|
||||||
|
rc = ble_gattc_disc_chrs_by_uuid(m_pClient->getConnId(),
|
||||||
|
m_startHandle,
|
||||||
|
m_endHandle,
|
||||||
|
&uuid_filter->getNative()->u,
|
||||||
|
NimBLERemoteService::characteristicDiscCB,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
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_haveCharacteristics = false;
|
|
||||||
m_semaphoreGetCharEvt.give();
|
m_semaphoreGetCharEvt.give();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_haveCharacteristics = (m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0);
|
if(m_semaphoreGetCharEvt.wait("retrieveCharacteristics") == 0){
|
||||||
if(m_haveCharacteristics){
|
|
||||||
uint16_t endHdl = 0xFFFF;
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics", m_characteristicMapByHandle.size());
|
|
||||||
for (auto it = m_characteristicMapByHandle.cbegin(); it != m_characteristicMapByHandle.cend(); ++it) {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Found UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(), (*it).second->getDefHandle());
|
|
||||||
// The descriptor handle is between this characteristic val_handle and the next ones def_handle
|
|
||||||
// so make the end of the scan at the handle before the next characteristic def_handle
|
|
||||||
|
|
||||||
// Make sure we don't go past the service end handle
|
|
||||||
if(++it != m_characteristicMapByHandle.cend()){
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Next UUID: %s Handle: %d Def Handle: %d", (*it).second->getUUID().toString().c_str(), (*it).second->getHandle(),(*it).second->getDefHandle());
|
|
||||||
|
|
||||||
endHdl = (*it).second->getDefHandle()-1;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "END CHARS");
|
|
||||||
endHdl = m_endHandle;
|
|
||||||
}
|
|
||||||
--it;
|
|
||||||
|
|
||||||
//If there is no handles between this characteristic and the next there is no descriptor so skip to the next
|
|
||||||
if((*it).second->getHandle() != endHdl){
|
|
||||||
if(!m_pClient->m_isConnected || !(*it).second->retrieveDescriptors(endHdl)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//NIMBLE_LOGD(LOG_TAG, "Found %d Characteristics in service UUID: %s", chars->size(), myPair.first.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -205,24 +235,6 @@ bool NimBLERemoteService::retrieveCharacteristics() {
|
||||||
} // retrieveCharacteristics
|
} // retrieveCharacteristics
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Retrieve a map of all the characteristics of this service.
|
|
||||||
* @return A map of all the characteristics of this service.
|
|
||||||
*/
|
|
||||||
std::map<std::string, NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristics() {
|
|
||||||
return &m_characteristicMap;
|
|
||||||
} // getCharacteristics
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Retrieve a map of all the characteristics of this service.
|
|
||||||
* @return A map of all the characteristics of this service.
|
|
||||||
*/
|
|
||||||
std::map<uint16_t, NimBLERemoteCharacteristic*>* NimBLERemoteService::getCharacteristicsByHandle() {
|
|
||||||
return &m_characteristicMapByHandle;
|
|
||||||
} // getCharacteristicsByHandle
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the client associated with this service.
|
* @brief Get the client associated with this service.
|
||||||
* @return A reference to the client associated with this service.
|
* @return A reference to the client associated with this service.
|
||||||
|
@ -261,7 +273,7 @@ NimBLEUUID NimBLERemoteService::getUUID() {
|
||||||
* @param [in] characteristicUuid The characteristic to read.
|
* @param [in] characteristicUuid The characteristic to read.
|
||||||
* @returns a string containing the value or an empty string if not found or error.
|
* @returns a string containing the value or an empty string if not found or error.
|
||||||
*/
|
*/
|
||||||
std::string NimBLERemoteService::getValue(NimBLEUUID characteristicUuid) {
|
std::string NimBLERemoteService::getValue(const NimBLEUUID &characteristicUuid) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> readValue: uuid: %s", characteristicUuid.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> readValue: uuid: %s", characteristicUuid.toString().c_str());
|
||||||
|
|
||||||
std::string ret = "";
|
std::string ret = "";
|
||||||
|
@ -282,7 +294,7 @@ std::string NimBLERemoteService::getValue(NimBLEUUID characteristicUuid) {
|
||||||
* @param [in] value The value to set.
|
* @param [in] value The value to set.
|
||||||
* @returns true on success, false if not found or error
|
* @returns true on success, false if not found or error
|
||||||
*/
|
*/
|
||||||
bool NimBLERemoteService::setValue(NimBLEUUID characteristicUuid, std::string value) {
|
bool NimBLERemoteService::setValue(const NimBLEUUID &characteristicUuid, const std::string &value) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> setValue: uuid: %s", characteristicUuid.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> setValue: uuid: %s", characteristicUuid.toString().c_str());
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
@ -298,20 +310,17 @@ bool NimBLERemoteService::setValue(NimBLEUUID characteristicUuid, std::string va
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Delete the characteristics in the characteristics map.
|
* @brief Delete the characteristics in the characteristics vector.
|
||||||
* We maintain a map called m_characteristicsMap that contains pointers to BLERemoteCharacteristic
|
* We maintain a vector called m_characteristicsVector that contains pointers to BLERemoteCharacteristic
|
||||||
* object references. Since we allocated these in this class, we are also responsible for deleteing
|
* object references. Since we allocated these in this class, we are also responsible for deleting
|
||||||
* them. This method does just that.
|
* them. This method does just that.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLERemoteService::removeCharacteristics() {
|
void NimBLERemoteService::removeCharacteristics() {
|
||||||
m_characteristicMap.clear(); // Clear the map
|
for(auto &it: m_characteristicVector) {
|
||||||
|
delete it;
|
||||||
for (auto &myPair : m_characteristicMapByHandle) {
|
|
||||||
delete myPair.second;
|
|
||||||
}
|
}
|
||||||
m_characteristicMapByHandle.clear(); // Clear the map
|
m_characteristicVector.clear(); // Clear the vector
|
||||||
|
|
||||||
} // removeCharacteristics
|
} // removeCharacteristics
|
||||||
|
|
||||||
|
|
||||||
|
@ -335,8 +344,8 @@ std::string NimBLERemoteService::toString() {
|
||||||
res += " 0x";
|
res += " 0x";
|
||||||
res += val;
|
res += val;
|
||||||
|
|
||||||
for (auto &myPair : m_characteristicMap) {
|
for (auto &it: m_characteristicVector) {
|
||||||
res += "\n" + myPair.second->toString();
|
res += "\n" + it->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -348,10 +357,11 @@ std::string NimBLERemoteService::toString() {
|
||||||
* Will release all characteristic and subsequently all descriptor semaphores for this service.
|
* Will release all characteristic and subsequently all descriptor semaphores for this service.
|
||||||
*/
|
*/
|
||||||
void NimBLERemoteService::releaseSemaphores() {
|
void NimBLERemoteService::releaseSemaphores() {
|
||||||
for (auto &cPair : m_characteristicMapByHandle) {
|
for(auto &it: m_characteristicVector) {
|
||||||
cPair.second->releaseSemaphores();
|
it->releaseSemaphores();
|
||||||
}
|
}
|
||||||
m_semaphoreGetCharEvt.give(1);
|
m_semaphoreGetCharEvt.give(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -17,12 +17,15 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|
||||||
#include "NimBLEClient.h"
|
#include "NimBLEClient.h"
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "NimBLERemoteCharacteristic.h"
|
#include "NimBLERemoteCharacteristic.h"
|
||||||
|
|
||||||
#include <map>
|
#include <vector>
|
||||||
|
|
||||||
class NimBLEClient;
|
class NimBLEClient;
|
||||||
class NimBLERemoteCharacteristic;
|
class NimBLERemoteCharacteristic;
|
||||||
|
@ -36,19 +39,18 @@ public:
|
||||||
virtual ~NimBLERemoteService();
|
virtual ~NimBLERemoteService();
|
||||||
|
|
||||||
// Public methods
|
// Public methods
|
||||||
NimBLERemoteCharacteristic* getCharacteristic(const char* uuid); // Get the specified characteristic reference.
|
std::vector<NimBLERemoteCharacteristic*>::iterator begin();
|
||||||
NimBLERemoteCharacteristic* getCharacteristic(NimBLEUUID uuid); // Get the specified characteristic reference.
|
std::vector<NimBLERemoteCharacteristic*>::iterator end();
|
||||||
// BLERemoteCharacteristic* getCharacteristic(uint16_t uuid); // Get the specified characteristic reference.
|
NimBLERemoteCharacteristic* getCharacteristic(const char* uuid);
|
||||||
std::map<std::string, NimBLERemoteCharacteristic*>* getCharacteristics();
|
NimBLERemoteCharacteristic* getCharacteristic(const NimBLEUUID &uuid);
|
||||||
std::map<uint16_t, NimBLERemoteCharacteristic*>* getCharacteristicsByHandle(); // Get the characteristics map.
|
NimBLEClient* getClient(void);
|
||||||
// void getCharacteristics(std::map<uint16_t, BLERemoteCharacteristic*>* pCharacteristicMap);
|
uint16_t getHandle();
|
||||||
|
NimBLEUUID getUUID(void);
|
||||||
NimBLEClient* getClient(void); // Get a reference to the client associated with this service.
|
std::string getValue(const NimBLEUUID &characteristicUuid);
|
||||||
uint16_t getHandle(); // Get the handle of this service.
|
bool setValue(const NimBLEUUID &characteristicUuid,
|
||||||
NimBLEUUID getUUID(void); // Get the UUID of this service.
|
const std::string &value);
|
||||||
std::string getValue(NimBLEUUID characteristicUuid); // Get the value of a characteristic.
|
|
||||||
bool setValue(NimBLEUUID characteristicUuid, std::string value); // Set the value of a characteristic.
|
|
||||||
std::string toString(void);
|
std::string toString(void);
|
||||||
|
std::vector<NimBLERemoteCharacteristic*>* getCharacteristics(bool refresh = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Private constructor ... never meant to be created by a user application.
|
// Private constructor ... never meant to be created by a user application.
|
||||||
|
@ -59,31 +61,29 @@ private:
|
||||||
friend class NimBLERemoteCharacteristic;
|
friend class NimBLERemoteCharacteristic;
|
||||||
|
|
||||||
// Private methods
|
// Private methods
|
||||||
bool retrieveCharacteristics(void); // Retrieve the characteristics from the BLE Server.
|
bool retrieveCharacteristics(const NimBLEUUID *uuid_filter = nullptr);
|
||||||
static int characteristicDiscCB(uint16_t conn_handle,
|
static int characteristicDiscCB(uint16_t conn_handle,
|
||||||
const struct ble_gatt_error *error,
|
const struct ble_gatt_error *error,
|
||||||
const struct ble_gatt_chr *chr, void *arg);
|
const struct ble_gatt_chr *chr,
|
||||||
|
void *arg);
|
||||||
|
|
||||||
uint16_t getStartHandle(); // Get the start handle for this service.
|
uint16_t getStartHandle();
|
||||||
uint16_t getEndHandle(); // Get the end handle for this service.
|
uint16_t getEndHandle();
|
||||||
void releaseSemaphores();
|
void releaseSemaphores();
|
||||||
void removeCharacteristics();
|
void removeCharacteristics();
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
|
|
||||||
// We maintain a map of characteristics owned by this service keyed by a string representation of the UUID.
|
// We maintain a vector of characteristics owned by this service.
|
||||||
std::map<std::string, NimBLERemoteCharacteristic*> m_characteristicMap;
|
std::vector<NimBLERemoteCharacteristic*> m_characteristicVector;
|
||||||
|
|
||||||
// We maintain a map of characteristics owned by this service keyed by a handle.
|
|
||||||
std::map<uint16_t, NimBLERemoteCharacteristic*> m_characteristicMapByHandle;
|
|
||||||
|
|
||||||
bool m_haveCharacteristics; // Have we previously obtained the characteristics.
|
|
||||||
NimBLEClient* m_pClient;
|
NimBLEClient* m_pClient;
|
||||||
FreeRTOS::Semaphore m_semaphoreGetCharEvt = FreeRTOS::Semaphore("GetCharEvt");
|
FreeRTOS::Semaphore m_semaphoreGetCharEvt = FreeRTOS::Semaphore("GetCharEvt");
|
||||||
NimBLEUUID m_uuid; // The UUID of this service.
|
NimBLEUUID m_uuid;
|
||||||
uint16_t m_startHandle; // The starting handle of this service.
|
uint16_t m_startHandle;
|
||||||
uint16_t m_endHandle; // The ending handle of this service.
|
uint16_t m_endHandle;
|
||||||
}; // BLERemoteService
|
}; // NimBLERemoteService
|
||||||
|
|
||||||
|
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */
|
#endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
#include "NimBLEScan.h"
|
#include "NimBLEScan.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLEDevice.h"
|
#include "NimBLEDevice.h"
|
||||||
|
@ -63,7 +66,7 @@ NimBLEScan::NimBLEScan() {
|
||||||
m_scan_params.itvl = 0; // This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. (units=0.625 msec)
|
m_scan_params.itvl = 0; // This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. (units=0.625 msec)
|
||||||
m_scan_params.window = 0; // The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval (units=0.625 msec)
|
m_scan_params.window = 0; // The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval (units=0.625 msec)
|
||||||
m_scan_params.limited = 0; // If set, only discover devices in limited discoverable mode.
|
m_scan_params.limited = 0; // If set, only discover devices in limited discoverable mode.
|
||||||
m_scan_params.filter_duplicates = 1; // If set, the controller ignores all but the first advertisement from each device.
|
m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device.
|
||||||
m_pAdvertisedDeviceCallbacks = nullptr;
|
m_pAdvertisedDeviceCallbacks = nullptr;
|
||||||
m_stopped = true;
|
m_stopped = true;
|
||||||
m_wantDuplicates = false;
|
m_wantDuplicates = false;
|
||||||
|
@ -114,13 +117,15 @@ NimBLEScan::NimBLEScan() {
|
||||||
|
|
||||||
NimBLEAdvertisedDevice* advertisedDevice = nullptr;
|
NimBLEAdvertisedDevice* advertisedDevice = nullptr;
|
||||||
|
|
||||||
// If we've seen this device before get a pointer to it from the map
|
// If we've seen this device before get a pointer to it from the vector
|
||||||
auto it = pScan->m_scanResults.m_advertisedDevicesMap.find(advertisedAddress.toString());
|
for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||||
if(it != pScan->m_scanResults.m_advertisedDevicesMap.cend()) {
|
if(it->getAddress() == advertisedAddress) {
|
||||||
advertisedDevice = (*it).second;
|
advertisedDevice = it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we haven't seen this device before; create a new instance and insert it in the map.
|
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
||||||
// Otherwise just update the relevant parameters of the already known device.
|
// Otherwise just update the relevant parameters of the already known device.
|
||||||
if(advertisedDevice == nullptr){
|
if(advertisedDevice == nullptr){
|
||||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||||
|
@ -128,7 +133,7 @@ NimBLEScan::NimBLEScan() {
|
||||||
advertisedDevice->setAddress(advertisedAddress);
|
advertisedDevice->setAddress(advertisedAddress);
|
||||||
//NIMBLE_LOGE(LOG_TAG, "advertisement type: %d, %s",event->disc.event_type, NimBLEUtils::advTypeToString(event->disc.event_type));
|
//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_advertisedDevicesMap.insert(std::pair<std::string, NimBLEAdvertisedDevice*>(advertisedAddress.toString(), 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());
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
@ -141,7 +146,7 @@ NimBLEScan::NimBLEScan() {
|
||||||
|
|
||||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||||
// If not active scanning report the result to the listener.
|
// If not active scanning report the result to the listener.
|
||||||
if(pScan->m_scan_params.passive) {
|
if(pScan->m_scan_params.passive || event->disc.event_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
|
||||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||||
// Otherwise wait for the scan response so we can report all of the data at once.
|
// Otherwise wait for the scan response so we can report all of the data at once.
|
||||||
} 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) {
|
||||||
|
@ -259,7 +264,7 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are connecting to devices that are advertising even after being connected, multiconnecting peripherals
|
// if we are connecting to devices that are advertising even after being connected, multiconnecting peripherals
|
||||||
// then we should not clear map or we will connect the same device few times
|
// then we should not clear vector or we will connect the same device few times
|
||||||
if(!is_continue) {
|
if(!is_continue) {
|
||||||
clearResults();
|
clearResults();
|
||||||
}
|
}
|
||||||
|
@ -325,11 +330,16 @@ void NimBLEScan::stop() {
|
||||||
|
|
||||||
|
|
||||||
// delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address
|
// delete peer device from cache after disconnecting, it is required in case we are connecting to devices with not public address
|
||||||
void NimBLEScan::erase(NimBLEAddress address) {
|
void NimBLEScan::erase(const NimBLEAddress &address) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "erase device: %s", address.toString().c_str());
|
||||||
NimBLEAdvertisedDevice *advertisedDevice = m_scanResults.m_advertisedDevicesMap.find(address.toString())->second;
|
|
||||||
m_scanResults.m_advertisedDevicesMap.erase(address.toString());
|
for(auto it = m_scanResults.m_advertisedDevicesVector.begin(); it != m_scanResults.m_advertisedDevicesVector.end(); ++it) {
|
||||||
delete advertisedDevice;
|
if((*it)->getAddress() == address) {
|
||||||
|
delete *it;
|
||||||
|
m_scanResults.m_advertisedDevicesVector.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -356,10 +366,10 @@ NimBLEScanResults NimBLEScan::getResults() {
|
||||||
* @brief Clear the results of the scan.
|
* @brief Clear the results of the scan.
|
||||||
*/
|
*/
|
||||||
void NimBLEScan::clearResults() {
|
void NimBLEScan::clearResults() {
|
||||||
for(auto _dev : m_scanResults.m_advertisedDevicesMap){
|
for(auto &it: m_scanResults.m_advertisedDevicesVector) {
|
||||||
delete _dev.second;
|
delete it;
|
||||||
}
|
}
|
||||||
m_scanResults.m_advertisedDevicesMap.clear();
|
m_scanResults.m_advertisedDevicesVector.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -379,7 +389,7 @@ void NimBLEScanResults::dump() {
|
||||||
* @return The number of devices found in the last scan.
|
* @return The number of devices found in the last scan.
|
||||||
*/
|
*/
|
||||||
int NimBLEScanResults::getCount() {
|
int NimBLEScanResults::getCount() {
|
||||||
return m_advertisedDevicesMap.size();
|
return m_advertisedDevicesVector.size();
|
||||||
} // getCount
|
} // getCount
|
||||||
|
|
||||||
|
|
||||||
|
@ -390,14 +400,43 @@ int NimBLEScanResults::getCount() {
|
||||||
* @return The device at the specified index.
|
* @return The device at the specified index.
|
||||||
*/
|
*/
|
||||||
NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) {
|
NimBLEAdvertisedDevice NimBLEScanResults::getDevice(uint32_t i) {
|
||||||
uint32_t x = 0;
|
return *m_advertisedDevicesVector[i];
|
||||||
NimBLEAdvertisedDevice dev = *m_advertisedDevicesMap.begin()->second;
|
|
||||||
for (auto it = m_advertisedDevicesMap.begin(); it != m_advertisedDevicesMap.end(); it++) {
|
|
||||||
dev = *it->second;
|
|
||||||
if (x==i) break;
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
return dev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get iterator to the beginning of the vector of advertised device pointers.
|
||||||
|
* @return An iterator to the beginning of the vector of advertised device pointers.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLEAdvertisedDevice*>::iterator NimBLEScanResults::begin() {
|
||||||
|
return m_advertisedDevicesVector.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get iterator to the end of the vector of advertised device pointers.
|
||||||
|
* @return An iterator to the end of the vector of advertised device pointers.
|
||||||
|
*/
|
||||||
|
std::vector<NimBLEAdvertisedDevice*>::iterator NimBLEScanResults::end() {
|
||||||
|
return m_advertisedDevicesVector.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return a pointer to the specified device at the given address.
|
||||||
|
* If the address is not found a nullptr is returned.
|
||||||
|
* @param [in] address The address of the device.
|
||||||
|
* @return A pointer to the device at the specified address.
|
||||||
|
*/
|
||||||
|
NimBLEAdvertisedDevice *NimBLEScanResults::getDevice(const NimBLEAddress &address) {
|
||||||
|
for(size_t index = 0; index < m_advertisedDevicesVector.size(); index++) {
|
||||||
|
if(m_advertisedDevicesVector[index]->getAddress() == address) {
|
||||||
|
return m_advertisedDevicesVector[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -16,17 +16,21 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
|
||||||
#include "NimBLEAdvertisedDevice.h"
|
#include "NimBLEAdvertisedDevice.h"
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
|
|
||||||
#include "host/ble_gap.h"
|
#include "host/ble_gap.h"
|
||||||
|
|
||||||
#include <map>
|
#include <vector>
|
||||||
|
|
||||||
class NimBLEDevice;
|
class NimBLEDevice;
|
||||||
class NimBLEScan;
|
class NimBLEScan;
|
||||||
class NimBLEAdvertisedDevice;
|
class NimBLEAdvertisedDevice;
|
||||||
class NimBLEAdvertisedDeviceCallbacks;
|
class NimBLEAdvertisedDeviceCallbacks;
|
||||||
|
class NimBLEAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The result of having performed a scan.
|
* @brief The result of having performed a scan.
|
||||||
|
@ -40,10 +44,13 @@ public:
|
||||||
void dump();
|
void dump();
|
||||||
int getCount();
|
int getCount();
|
||||||
NimBLEAdvertisedDevice getDevice(uint32_t i);
|
NimBLEAdvertisedDevice getDevice(uint32_t i);
|
||||||
|
std::vector<NimBLEAdvertisedDevice*>::iterator begin();
|
||||||
|
std::vector<NimBLEAdvertisedDevice*>::iterator end();
|
||||||
|
NimBLEAdvertisedDevice *getDevice(const NimBLEAddress &address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend NimBLEScan;
|
friend NimBLEScan;
|
||||||
std::map<std::string, NimBLEAdvertisedDevice*> m_advertisedDevicesMap;
|
std::vector<NimBLEAdvertisedDevice*> m_advertisedDevicesVector;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,7 +69,7 @@ public:
|
||||||
void stop();
|
void stop();
|
||||||
void clearResults();
|
void clearResults();
|
||||||
NimBLEScanResults getResults();
|
NimBLEScanResults getResults();
|
||||||
void erase(NimBLEAddress address);
|
void erase(const NimBLEAddress &address);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -82,6 +89,6 @@ private:
|
||||||
uint32_t m_duration;
|
uint32_t m_duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* COMPONENTS_NIMBLE_SCAN_H_ */
|
#endif /* COMPONENTS_NIMBLE_SCAN_H_ */
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEServer.h"
|
#include "NimBLEServer.h"
|
||||||
#include "NimBLE2902.h"
|
#include "NimBLE2902.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
|
@ -62,7 +65,7 @@ NimBLEService* NimBLEServer::createService(const char* uuid) {
|
||||||
* @param [in] inst_id With multiple services with the same UUID we need to provide inst_id value different for each service.
|
* @param [in] inst_id With multiple services with the same UUID we need to provide inst_id value different for each service.
|
||||||
* @return A reference to the new service object.
|
* @return A reference to the new service object.
|
||||||
*/
|
*/
|
||||||
NimBLEService* NimBLEServer::createService(NimBLEUUID uuid, uint32_t numHandles, uint8_t inst_id) {
|
NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid, uint32_t numHandles, uint8_t inst_id) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
|
NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
|
||||||
|
|
||||||
// Check that a service with the supplied UUID does not already exist.
|
// Check that a service with the supplied UUID does not already exist.
|
||||||
|
@ -95,7 +98,7 @@ NimBLEService* NimBLEServer::getServiceByUUID(const char* uuid) {
|
||||||
* @param [in] uuid The UUID of the new service.
|
* @param [in] uuid The UUID of the new service.
|
||||||
* @return A reference to the service object.
|
* @return A reference to the service object.
|
||||||
*/
|
*/
|
||||||
NimBLEService* NimBLEServer::getServiceByUUID(NimBLEUUID uuid) {
|
NimBLEService* NimBLEServer::getServiceByUUID(const NimBLEUUID &uuid) {
|
||||||
return m_serviceMap.getByUUID(uuid);
|
return m_serviceMap.getByUUID(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,4 +608,6 @@ void NimBLEServer::onHostReset() {
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEAddress.h"
|
#include "NimBLEAddress.h"
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
#include "NimBLEAdvertising.h"
|
#include "NimBLEAdvertising.h"
|
||||||
|
@ -24,7 +27,6 @@
|
||||||
#include "NimBLESecurity.h"
|
#include "NimBLESecurity.h"
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class NimBLEService;
|
class NimBLEService;
|
||||||
|
@ -46,10 +48,10 @@ class NimBLEServiceMap {
|
||||||
public:
|
public:
|
||||||
// NimBLEService* getByHandle(uint16_t handle);
|
// NimBLEService* getByHandle(uint16_t handle);
|
||||||
NimBLEService* getByUUID(const char* uuid);
|
NimBLEService* getByUUID(const char* uuid);
|
||||||
NimBLEService* getByUUID(NimBLEUUID uuid, uint8_t inst_id = 0);
|
NimBLEService* getByUUID(const NimBLEUUID &uuid, uint8_t inst_id = 0);
|
||||||
// void setByHandle(uint16_t handle, NimBLEService* service);
|
// void setByHandle(uint16_t handle, NimBLEService* service);
|
||||||
void setByUUID(const char* uuid, NimBLEService* service);
|
void setByUUID(const char* uuid, NimBLEService* service);
|
||||||
void setByUUID(NimBLEUUID uuid, NimBLEService* service);
|
void setByUUID(const NimBLEUUID &uuid, NimBLEService* service);
|
||||||
std::string toString();
|
std::string toString();
|
||||||
NimBLEService* getFirst();
|
NimBLEService* getFirst();
|
||||||
NimBLEService* getNext();
|
NimBLEService* getNext();
|
||||||
|
@ -70,7 +72,7 @@ class NimBLEServer {
|
||||||
public:
|
public:
|
||||||
uint32_t getConnectedCount();
|
uint32_t getConnectedCount();
|
||||||
NimBLEService* createService(const char* uuid);
|
NimBLEService* createService(const char* uuid);
|
||||||
NimBLEService* createService(NimBLEUUID uuid, uint32_t numHandles=15, uint8_t inst_id=0);
|
NimBLEService* createService(const NimBLEUUID &uuid, uint32_t numHandles=15, uint8_t inst_id=0);
|
||||||
NimBLEAdvertising* getAdvertising();
|
NimBLEAdvertising* getAdvertising();
|
||||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks);
|
void setCallbacks(NimBLEServerCallbacks* pCallbacks);
|
||||||
void startAdvertising();
|
void startAdvertising();
|
||||||
|
@ -78,7 +80,7 @@ public:
|
||||||
void start();
|
void start();
|
||||||
// void removeService(BLEService* service);
|
// void removeService(BLEService* service);
|
||||||
NimBLEService* getServiceByUUID(const char* uuid);
|
NimBLEService* getServiceByUUID(const char* uuid);
|
||||||
NimBLEService* getServiceByUUID(NimBLEUUID uuid);
|
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid);
|
||||||
int disconnect(uint16_t connID, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
int disconnect(uint16_t connID, uint8_t reason = BLE_ERR_REM_USER_CONN_TERM);
|
||||||
// bool connect(BLEAddress address);
|
// bool connect(BLEAddress address);
|
||||||
void updateConnParams(uint16_t conn_handle,
|
void updateConnParams(uint16_t conn_handle,
|
||||||
|
@ -150,5 +152,6 @@ public:
|
||||||
}; // BLEServerCallbacks
|
}; // BLEServerCallbacks
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
#endif /* MAIN_NIMBLESERVER_H_ */
|
#endif /* MAIN_NIMBLESERVER_H_ */
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEService.h"
|
#include "NimBLEService.h"
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
@ -43,7 +46,7 @@ NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer
|
||||||
* @param [in] uuid The UUID of the service.
|
* @param [in] uuid The UUID of the service.
|
||||||
* @param [in] numHandles The maximum number of handles associated with the service.
|
* @param [in] numHandles The maximum number of handles associated with the service.
|
||||||
*/
|
*/
|
||||||
NimBLEService::NimBLEService(NimBLEUUID uuid, uint16_t numHandles, NimBLEServer* pServer) {
|
NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) {
|
||||||
m_uuid = uuid;
|
m_uuid = uuid;
|
||||||
m_handle = NULL_HANDLE;
|
m_handle = NULL_HANDLE;
|
||||||
m_pServer = pServer;
|
m_pServer = pServer;
|
||||||
|
@ -111,8 +114,9 @@ bool NimBLEService::start() {
|
||||||
if(numDscs) {
|
if(numDscs) {
|
||||||
// skip 2902 as it's automatically created by NimBLE
|
// skip 2902 as it's automatically created by NimBLE
|
||||||
// if Indicate or Notify flags are set
|
// if Indicate or Notify flags are set
|
||||||
if((pCharacteristic->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
if(((pCharacteristic->m_properties & BLE_GATT_CHR_F_INDICATE) ||
|
||||||
(pCharacteristic->m_properties & BLE_GATT_CHR_F_NOTIFY)) {
|
(pCharacteristic->m_properties & BLE_GATT_CHR_F_NOTIFY)) &&
|
||||||
|
pCharacteristic->getDescriptorByUUID("2902") != nullptr) {
|
||||||
numDscs--;
|
numDscs--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +251,7 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
|
||||||
* @param [in] properties - The properties of the characteristic.
|
* @param [in] properties - The properties of the characteristic.
|
||||||
* @return The new BLE characteristic.
|
* @return The new BLE characteristic.
|
||||||
*/
|
*/
|
||||||
NimBLECharacteristic* NimBLEService::createCharacteristic(NimBLEUUID uuid, uint32_t properties) {
|
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) {
|
||||||
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this);
|
||||||
addCharacteristic(pCharacteristic);
|
addCharacteristic(pCharacteristic);
|
||||||
//pCharacteristic->executeCreate(this);
|
//pCharacteristic->executeCreate(this);
|
||||||
|
@ -260,7 +264,7 @@ NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NimBLECharacteristic* NimBLEService::getCharacteristic(NimBLEUUID uuid) {
|
NimBLECharacteristic* NimBLEService::getCharacteristic(const NimBLEUUID &uuid) {
|
||||||
return m_characteristicMap.getByUUID(uuid);
|
return m_characteristicMap.getByUUID(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,4 +294,5 @@ NimBLEServer* NimBLEService::getServer() {
|
||||||
return m_pServer;
|
return m_pServer;
|
||||||
} // getServer
|
} // getServer
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
|
@ -17,6 +17,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLECharacteristic.h"
|
#include "NimBLECharacteristic.h"
|
||||||
#include "NimBLEServer.h"
|
#include "NimBLEServer.h"
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
|
@ -32,10 +35,10 @@ class NimBLECharacteristic;
|
||||||
class NimBLECharacteristicMap {
|
class NimBLECharacteristicMap {
|
||||||
public:
|
public:
|
||||||
void setByUUID(NimBLECharacteristic* pCharacteristic, const char* uuid);
|
void setByUUID(NimBLECharacteristic* pCharacteristic, const char* uuid);
|
||||||
void setByUUID(NimBLECharacteristic* pCharacteristic, NimBLEUUID uuid);
|
void setByUUID(NimBLECharacteristic* pCharacteristic, const NimBLEUUID &uuid);
|
||||||
void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic);
|
void setByHandle(uint16_t handle, NimBLECharacteristic* pCharacteristic);
|
||||||
NimBLECharacteristic* getByUUID(const char* uuid);
|
NimBLECharacteristic* getByUUID(const char* uuid);
|
||||||
NimBLECharacteristic* getByUUID(NimBLEUUID uuid);
|
NimBLECharacteristic* getByUUID(const NimBLEUUID &uuid);
|
||||||
NimBLECharacteristic* getByHandle(uint16_t handle);
|
NimBLECharacteristic* getByHandle(uint16_t handle);
|
||||||
NimBLECharacteristic* getFirst();
|
NimBLECharacteristic* getFirst();
|
||||||
NimBLECharacteristic* getNext();
|
NimBLECharacteristic* getNext();
|
||||||
|
@ -59,13 +62,13 @@ public:
|
||||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||||
NIMBLE_PROPERTY::WRITE);
|
NIMBLE_PROPERTY::WRITE);
|
||||||
|
|
||||||
NimBLECharacteristic* createCharacteristic(NimBLEUUID uuid,
|
NimBLECharacteristic* createCharacteristic(const NimBLEUUID &uuid,
|
||||||
uint32_t properties = NIMBLE_PROPERTY::READ |
|
uint32_t properties = NIMBLE_PROPERTY::READ |
|
||||||
NIMBLE_PROPERTY::WRITE);
|
NIMBLE_PROPERTY::WRITE);
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
NimBLECharacteristic* getCharacteristic(const char* uuid);
|
NimBLECharacteristic* getCharacteristic(const char* uuid);
|
||||||
NimBLECharacteristic* getCharacteristic(NimBLEUUID uuid);
|
NimBLECharacteristic* getCharacteristic(const NimBLEUUID &uuid);
|
||||||
NimBLEUUID getUUID();
|
NimBLEUUID getUUID();
|
||||||
NimBLEServer* getServer();
|
NimBLEServer* getServer();
|
||||||
bool start();
|
bool start();
|
||||||
|
@ -76,7 +79,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||||
NimBLEService(NimBLEUUID uuid, uint16_t numHandles, NimBLEServer* pServer);
|
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer);
|
||||||
friend class NimBLEServer;
|
friend class NimBLEServer;
|
||||||
friend class NimBLEDevice;
|
friend class NimBLEDevice;
|
||||||
|
|
||||||
|
@ -92,5 +95,6 @@ private:
|
||||||
}; // BLEService
|
}; // BLEService
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
#endif /* MAIN_NIMBLESERVICE_H_ */
|
#endif /* MAIN_NIMBLESERVICE_H_ */
|
|
@ -14,6 +14,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEService.h"
|
#include "NimBLEService.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,7 +34,7 @@ NimBLEService* NimBLEServiceMap::getByUUID(const char* uuid) {
|
||||||
* @param [in] UUID The UUID to look up the service.
|
* @param [in] UUID The UUID to look up the service.
|
||||||
* @return The characteristic.
|
* @return The characteristic.
|
||||||
*/
|
*/
|
||||||
NimBLEService* NimBLEServiceMap::getByUUID(NimBLEUUID uuid, uint8_t inst_id) {
|
NimBLEService* NimBLEServiceMap::getByUUID(const NimBLEUUID &uuid, uint8_t inst_id) {
|
||||||
for (auto &myPair : m_uuidMap) {
|
for (auto &myPair : m_uuidMap) {
|
||||||
if (myPair.first->getUUID().equals(uuid)) {
|
if (myPair.first->getUUID().equals(uuid)) {
|
||||||
return myPair.first;
|
return myPair.first;
|
||||||
|
@ -59,7 +62,7 @@ NimBLEService* NimBLEServiceMap::getByHandle(uint16_t handle) {
|
||||||
* @param [in] characteristic The service to cache.
|
* @param [in] characteristic The service to cache.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
*/
|
*/
|
||||||
void NimBLEServiceMap::setByUUID(NimBLEUUID uuid, NimBLEService* service) {
|
void NimBLEServiceMap::setByUUID(const NimBLEUUID &uuid, NimBLEService* service) {
|
||||||
m_uuidMap.insert(std::pair<NimBLEService*, std::string>(service, uuid.toString()));
|
m_uuidMap.insert(std::pair<NimBLEService*, std::string>(service, uuid.toString()));
|
||||||
} // setByUUID
|
} // setByUUID
|
||||||
|
|
||||||
|
@ -105,6 +108,7 @@ NimBLEService* NimBLEServiceMap::getFirst() {
|
||||||
return pRet;
|
return pRet;
|
||||||
} // getFirst
|
} // getFirst
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the next service in the map.
|
* @brief Get the next service in the map.
|
||||||
* @return The next service in the map.
|
* @return The next service in the map.
|
||||||
|
@ -116,6 +120,7 @@ NimBLEService* NimBLEServiceMap::getNext() {
|
||||||
return pRet;
|
return pRet;
|
||||||
} // getNext
|
} // getNext
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Removes service from maps.
|
* @brief Removes service from maps.
|
||||||
* @return N/A.
|
* @return N/A.
|
||||||
|
@ -125,6 +130,7 @@ void NimBLEServiceMap::removeService(NimBLEService* service) {
|
||||||
m_uuidMap.erase(service);
|
m_uuidMap.erase(service);
|
||||||
} // removeService
|
} // removeService
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the amount of registered services
|
* @brief Returns the amount of registered services
|
||||||
* @return amount of registered services
|
* @return amount of registered services
|
||||||
|
@ -134,4 +140,6 @@ int NimBLEServiceMap::getRegisteredServiceCount(){
|
||||||
return m_uuidMap.size();
|
return m_uuidMap.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
|
@ -18,6 +18,8 @@
|
||||||
#include "NimBLEUUID.h"
|
#include "NimBLEUUID.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
static const char* LOG_TAG = "NimBLEUUID";
|
static const char* LOG_TAG = "NimBLEUUID";
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,54 +40,29 @@ static const char* LOG_TAG = "NimBLEUUID";
|
||||||
*
|
*
|
||||||
* @param [in] value The string to build a UUID from.
|
* @param [in] value The string to build a UUID from.
|
||||||
*/
|
*/
|
||||||
NimBLEUUID::NimBLEUUID(std::string value) {
|
NimBLEUUID::NimBLEUUID(const std::string &value) {
|
||||||
m_valueSet = true;
|
m_valueSet = true;
|
||||||
if (value.length() == 4) {
|
if (value.length() == 4) {
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_16;
|
m_uuid.u.type = BLE_UUID_TYPE_16;
|
||||||
m_uuid.u16.value = 0;
|
m_uuid.u16.value = strtoul(value.c_str(), NULL, 16);
|
||||||
for(int i=0;i<value.length();){
|
|
||||||
uint8_t MSB = value.c_str()[i];
|
|
||||||
uint8_t LSB = value.c_str()[i+1];
|
|
||||||
|
|
||||||
if(MSB > '9') MSB -= 7;
|
|
||||||
if(LSB > '9') LSB -= 7;
|
|
||||||
m_uuid.u16.value += (((MSB&0x0F) <<4) | (LSB & 0x0F))<<(2-i)*4;
|
|
||||||
i+=2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (value.length() == 8) {
|
else if (value.length() == 8) {
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_32;
|
m_uuid.u.type = BLE_UUID_TYPE_32;
|
||||||
m_uuid.u32.value = 0;
|
m_uuid.u32.value = strtoul(value.c_str(), NULL, 16);
|
||||||
for(int i=0;i<value.length();){
|
|
||||||
uint8_t MSB = value.c_str()[i];
|
|
||||||
uint8_t LSB = value.c_str()[i+1];
|
|
||||||
|
|
||||||
if(MSB > '9') MSB -= 7;
|
|
||||||
if(LSB > '9') LSB -= 7;
|
|
||||||
m_uuid.u32.value += (((MSB&0x0F) <<4) | (LSB & 0x0F))<<(6-i)*4;
|
|
||||||
i+=2;
|
|
||||||
}
|
}
|
||||||
}
|
else if (value.length() == 16) {
|
||||||
else if (value.length() == 16) { // how we can have 16 byte length string reprezenting 128 bit uuid??? needs to be investigated (lack of time)
|
*this = NimBLEUUID((uint8_t*)value.data(), 16, true);
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
|
||||||
NimBLEUtils::memrcpy(m_uuid.u128.value, (uint8_t*)value.data(), 16);
|
|
||||||
}
|
}
|
||||||
else if (value.length() == 36) {
|
else if (value.length() == 36) {
|
||||||
// If the length of the string is 36 bytes then we will assume it is a long hex string in
|
// If the length of the string is 36 bytes then we will assume it is a long hex string in
|
||||||
// UUID format.
|
// UUID format.
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
char * position = const_cast<char *>(value.c_str());
|
||||||
int n = 0;
|
uint32_t first = strtoul(position, &position, 16);
|
||||||
for(int i=0;i<value.length();){
|
uint16_t second = strtoul(position + 1, &position, 16);
|
||||||
if(value.c_str()[i] == '-')
|
uint16_t third = strtoul(position + 1, &position, 16);
|
||||||
i++;
|
uint16_t fourth = strtoul(position + 1, &position, 16);
|
||||||
uint8_t MSB = value.c_str()[i];
|
uint64_t fifth = strtoull(position + 1, NULL, 16);
|
||||||
uint8_t LSB = value.c_str()[i+1];
|
*this = NimBLEUUID(first, second, third, (uint64_t(fourth) << 48) + fifth);
|
||||||
|
|
||||||
if(MSB > '9') MSB -= 7;
|
|
||||||
if(LSB > '9') LSB -= 7;
|
|
||||||
m_uuid.u128.value[15-n++] = ((MSB&0x0F) <<4) | (LSB & 0x0F);
|
|
||||||
i+=2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID value not 2, 4, 16 or 36 bytes");
|
NIMBLE_LOGE(LOG_TAG,"ERROR: UUID value not 2, 4, 16 or 36 bytes");
|
||||||
|
@ -101,7 +78,7 @@ static const char* LOG_TAG = "NimBLEUUID";
|
||||||
* @param [in] size The size of the data.
|
* @param [in] size The size of the data.
|
||||||
* @param [in] msbFirst Is the MSB first in pData memory?
|
* @param [in] msbFirst Is the MSB first in pData memory?
|
||||||
*/
|
*/
|
||||||
NimBLEUUID::NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst) {
|
NimBLEUUID::NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst) {
|
||||||
/*** TODO: change this to use the Nimble function for various lenght UUIDs:
|
/*** TODO: change this to use the Nimble function for various lenght UUIDs:
|
||||||
int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len);
|
int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len);
|
||||||
***/
|
***/
|
||||||
|
@ -110,8 +87,9 @@ NimBLEUUID::NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||||
|
|
||||||
if (msbFirst) {
|
if (msbFirst) {
|
||||||
NimBLEUtils::memrcpy(m_uuid.u128.value, pData, 16);
|
std::reverse_copy(pData, pData + 16, m_uuid.u128.value);
|
||||||
} else {
|
} else {
|
||||||
memcpy(m_uuid.u128.value, pData, 16);
|
memcpy(m_uuid.u128.value, pData, 16);
|
||||||
}
|
}
|
||||||
|
@ -148,14 +126,33 @@ NimBLEUUID::NimBLEUUID(uint32_t uuid) {
|
||||||
*
|
*
|
||||||
* @param [in] uuid The native UUID.
|
* @param [in] uuid The native UUID.
|
||||||
*/
|
*/
|
||||||
|
NimBLEUUID::NimBLEUUID(const ble_uuid128_t* uuid) {
|
||||||
NimBLEUUID::NimBLEUUID(ble_uuid128_t* uuid) {
|
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||||
memcpy(m_uuid.u128.value, uuid->value, 16);
|
memcpy(m_uuid.u128.value, uuid->value, 16);
|
||||||
m_valueSet = true;
|
m_valueSet = true;
|
||||||
} // NimBLEUUID
|
} // NimBLEUUID
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a UUID from the 128bit value using hex parts instead of string,
|
||||||
|
* instead of BLEUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6"), it becomes
|
||||||
|
* BLEUUID(0xebe0ccb0, 0x7a0a, 0x4b0c, 0x8a1a6ff2997da3a6)
|
||||||
|
*
|
||||||
|
* @param [in] first The first 32bit of the UUID.
|
||||||
|
* @param [in] second The next 16bit of the UUID.
|
||||||
|
* @param [in] third The next 16bit of the UUID.
|
||||||
|
* @param [in] fourth The last 64bit of the UUID, combining the last 2 parts of the string equivalent
|
||||||
|
*/
|
||||||
|
NimBLEUUID::NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth) {
|
||||||
|
m_uuid.u.type = BLE_UUID_TYPE_128;
|
||||||
|
memcpy(m_uuid.u128.value + 12, &first, 4);
|
||||||
|
memcpy(m_uuid.u128.value + 10, &second, 2);
|
||||||
|
memcpy(m_uuid.u128.value + 8, &third, 2);
|
||||||
|
memcpy(m_uuid.u128.value, &fourth, 8);
|
||||||
|
m_valueSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NimBLEUUID::NimBLEUUID() {
|
NimBLEUUID::NimBLEUUID() {
|
||||||
m_valueSet = false;
|
m_valueSet = false;
|
||||||
} // NimBLEUUID
|
} // NimBLEUUID
|
||||||
|
@ -165,7 +162,7 @@ NimBLEUUID::NimBLEUUID() {
|
||||||
* @brief Get the number of bits in this uuid.
|
* @brief Get the number of bits in this uuid.
|
||||||
* @return The number of bits in the UUID. One of 16, 32 or 128.
|
* @return The number of bits in the UUID. One of 16, 32 or 128.
|
||||||
*/
|
*/
|
||||||
uint8_t NimBLEUUID::bitSize() {
|
uint8_t NimBLEUUID::bitSize() const {
|
||||||
if (!m_valueSet) return 0;
|
if (!m_valueSet) return 0;
|
||||||
return m_uuid.u.type;
|
return m_uuid.u.type;
|
||||||
} // bitSize
|
} // bitSize
|
||||||
|
@ -177,11 +174,8 @@ uint8_t NimBLEUUID::bitSize() {
|
||||||
* @param [in] uuid The UUID to compare against.
|
* @param [in] uuid The UUID to compare against.
|
||||||
* @return True if the UUIDs are equal and false otherwise.
|
* @return True if the UUIDs are equal and false otherwise.
|
||||||
*/
|
*/
|
||||||
bool NimBLEUUID::equals(NimBLEUUID uuid) {
|
bool NimBLEUUID::equals(const NimBLEUUID &uuid) const {
|
||||||
if(ble_uuid_cmp(&m_uuid.u, &uuid.getNative()->u) == 0){
|
return *this == uuid;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,8 +188,7 @@ bool NimBLEUUID::equals(NimBLEUUID uuid) {
|
||||||
* NNNNNNNN
|
* NNNNNNNN
|
||||||
* <UUID>
|
* <UUID>
|
||||||
*/
|
*/
|
||||||
|
NimBLEUUID NimBLEUUID::fromString(const std::string &_uuid) {
|
||||||
NimBLEUUID NimBLEUUID::fromString(std::string _uuid) {
|
|
||||||
uint8_t start = 0;
|
uint8_t start = 0;
|
||||||
if (strstr(_uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters.
|
if (strstr(_uuid.c_str(), "0x") != nullptr) { // If the string starts with 0x, skip those characters.
|
||||||
start = 2;
|
start = 2;
|
||||||
|
@ -220,7 +213,7 @@ NimBLEUUID NimBLEUUID::fromString(std::string _uuid) {
|
||||||
*
|
*
|
||||||
* @return The native UUID value or NULL if not set.
|
* @return The native UUID value or NULL if not set.
|
||||||
*/
|
*/
|
||||||
ble_uuid_any_t* NimBLEUUID::getNative() {
|
const ble_uuid_any_t* NimBLEUUID::getNative() const {
|
||||||
if (m_valueSet == false) {
|
if (m_valueSet == false) {
|
||||||
NIMBLE_LOGD(LOG_TAG,"<< Return of un-initialized UUID!");
|
NIMBLE_LOGD(LOG_TAG,"<< Return of un-initialized UUID!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -235,47 +228,20 @@ ble_uuid_any_t* NimBLEUUID::getNative() {
|
||||||
* A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method
|
* A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method
|
||||||
* will convert 16 or 32 bit representations to the full 128bit.
|
* will convert 16 or 32 bit representations to the full 128bit.
|
||||||
*/
|
*/
|
||||||
NimBLEUUID NimBLEUUID::to128() {
|
const NimBLEUUID &NimBLEUUID::to128() {
|
||||||
// If we either don't have a value or are already a 128 bit UUID, nothing further to do.
|
// If we either don't have a value or are already a 128 bit UUID, nothing further to do.
|
||||||
if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_128) {
|
if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_128) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are 16 bit or 32 bit, then set the 4 bytes of the variable part of the UUID.
|
// If we are 16 bit or 32 bit, then set the other bytes of the UUID.
|
||||||
if (m_uuid.u.type == BLE_UUID_TYPE_16) {
|
if (m_uuid.u.type == BLE_UUID_TYPE_16) {
|
||||||
uint16_t temp = m_uuid.u16.value;
|
*this = NimBLEUUID(m_uuid.u16.value, 0x0000, 0x1000, 0x800000805f9b34fb);
|
||||||
m_uuid.u128.value[15] = 0;
|
|
||||||
m_uuid.u128.value[14] = 0;
|
|
||||||
m_uuid.u128.value[13] = (temp >> 8) & 0xff;
|
|
||||||
m_uuid.u128.value[12] = temp & 0xff;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (m_uuid.u.type == BLE_UUID_TYPE_32) {
|
else if (m_uuid.u.type == BLE_UUID_TYPE_32) {
|
||||||
uint32_t temp = m_uuid.u32.value;
|
*this = NimBLEUUID(m_uuid.u32.value, 0x0000, 0x1000, 0x800000805f9b34fb);
|
||||||
m_uuid.u128.value[15] = (temp >> 24) & 0xff;
|
|
||||||
m_uuid.u128.value[14] = (temp >> 16) & 0xff;
|
|
||||||
m_uuid.u128.value[13] = (temp >> 8) & 0xff;
|
|
||||||
m_uuid.u128.value[12] = temp & 0xff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the fixed parts of the UUID.
|
|
||||||
m_uuid.u128.value[11] = 0x00;
|
|
||||||
m_uuid.u128.value[10] = 0x00;
|
|
||||||
|
|
||||||
m_uuid.u128.value[9] = 0x10;
|
|
||||||
m_uuid.u128.value[8] = 0x00;
|
|
||||||
|
|
||||||
m_uuid.u128.value[7] = 0x80;
|
|
||||||
m_uuid.u128.value[6] = 0x00;
|
|
||||||
|
|
||||||
m_uuid.u128.value[5] = 0x00;
|
|
||||||
m_uuid.u128.value[4] = 0x80;
|
|
||||||
m_uuid.u128.value[3] = 0x5f;
|
|
||||||
m_uuid.u128.value[2] = 0x9b;
|
|
||||||
m_uuid.u128.value[1] = 0x34;
|
|
||||||
m_uuid.u128.value[0] = 0xfb;
|
|
||||||
|
|
||||||
m_uuid.u.type = BLE_UUID_TYPE_128;
|
|
||||||
return *this;
|
return *this;
|
||||||
} // to128
|
} // to128
|
||||||
|
|
||||||
|
@ -290,12 +256,32 @@ NimBLEUUID NimBLEUUID::to128() {
|
||||||
*
|
*
|
||||||
* @return A string representation of the UUID.
|
* @return A string representation of the UUID.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEUUID::toString() {
|
std::string NimBLEUUID::toString() const {
|
||||||
if (!m_valueSet) return "<NULL>"; // If we have no value, nothing to format.
|
return std::string(*this);
|
||||||
|
} // toString
|
||||||
|
|
||||||
|
|
||||||
|
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
|
||||||
|
if(m_valueSet && rhs.m_valueSet) {
|
||||||
|
return ble_uuid_cmp(&m_uuid.u, &rhs.m_uuid.u) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_valueSet == rhs.m_valueSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
|
||||||
|
return !this->operator==(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NimBLEUUID::operator std::string() const {
|
||||||
|
if (!m_valueSet) return std::string(); // If we have no value, nothing to format.
|
||||||
|
|
||||||
char buf[BLE_UUID_STR_LEN];
|
char buf[BLE_UUID_STR_LEN];
|
||||||
|
|
||||||
return ble_uuid_to_str(&m_uuid.u, buf);
|
return ble_uuid_to_str(&m_uuid.u, buf);
|
||||||
} // toString
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED */
|
#endif /* CONFIG_BT_ENABLED */
|
||||||
|
|
|
@ -30,18 +30,23 @@
|
||||||
*/
|
*/
|
||||||
class NimBLEUUID {
|
class NimBLEUUID {
|
||||||
public:
|
public:
|
||||||
NimBLEUUID(std::string uuid);
|
NimBLEUUID(const std::string &uuid);
|
||||||
NimBLEUUID(uint16_t uuid);
|
NimBLEUUID(uint16_t uuid);
|
||||||
NimBLEUUID(uint32_t uuid);
|
NimBLEUUID(uint32_t uuid);
|
||||||
NimBLEUUID(ble_uuid128_t* uuid);
|
NimBLEUUID(const ble_uuid128_t* uuid);
|
||||||
NimBLEUUID(uint8_t* pData, size_t size, bool msbFirst);
|
NimBLEUUID(const uint8_t* pData, size_t size, bool msbFirst);
|
||||||
|
NimBLEUUID(uint32_t first, uint16_t second, uint16_t third, uint64_t fourth);
|
||||||
NimBLEUUID();
|
NimBLEUUID();
|
||||||
uint8_t bitSize(); // Get the number of bits in this uuid.
|
uint8_t bitSize() const; // Get the number of bits in this uuid.
|
||||||
bool equals(NimBLEUUID uuid);
|
bool equals(const NimBLEUUID &uuid) const;
|
||||||
ble_uuid_any_t* getNative();
|
const ble_uuid_any_t* getNative() const;
|
||||||
NimBLEUUID to128();
|
const NimBLEUUID & to128();
|
||||||
std::string toString();
|
std::string toString() const;
|
||||||
static NimBLEUUID fromString(std::string uuid); // Create a NimBLEUUID from a string
|
static NimBLEUUID fromString(const std::string &uuid); // Create a NimBLEUUID from a string
|
||||||
|
|
||||||
|
bool operator ==(const NimBLEUUID & rhs) const;
|
||||||
|
bool operator !=(const NimBLEUUID & rhs) const;
|
||||||
|
operator std::string() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ble_uuid_any_t m_uuid; // The underlying UUID structure that this class wraps.
|
ble_uuid_any_t m_uuid; // The underlying UUID structure that this class wraps.
|
||||||
|
|
|
@ -11,38 +11,10 @@
|
||||||
|
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
#include "nimconfig.h"
|
||||||
|
|
||||||
static const char* LOG_TAG = "NimBLEUtils";
|
static const char* LOG_TAG = "NimBLEUtils";
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Copy memory from source to target but in reverse order.
|
|
||||||
*
|
|
||||||
* When we move memory from one location it is normally:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* [0][1][2]...[n] -> [0][1][2]...[n]
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* with this function, it is:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* [0][1][2]...[n] -> [n][n-1][n-2]...[0]
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @param [in] target The target of the copy
|
|
||||||
* @param [in] source The source of the copy
|
|
||||||
* @param [in] size The number of bytes to copy
|
|
||||||
*/
|
|
||||||
void NimBLEUtils::memrcpy(uint8_t* target, uint8_t* source, uint32_t size) {
|
|
||||||
assert(size > 0);
|
|
||||||
target += (size - 1); // Point target to the last byte of the target data
|
|
||||||
while (size > 0) {
|
|
||||||
*target = *source;
|
|
||||||
target--;
|
|
||||||
source++;
|
|
||||||
size--;
|
|
||||||
}
|
|
||||||
} // memrcpy
|
|
||||||
|
|
||||||
int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
|
int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
|
||||||
/* Check connection interval min */
|
/* Check connection interval min */
|
||||||
|
@ -78,6 +50,7 @@ int NimBLEUtils::checkConnParams(ble_gap_conn_params* params) {
|
||||||
|
|
||||||
|
|
||||||
const char* NimBLEUtils::returnCodeToString(int rc) {
|
const char* NimBLEUtils::returnCodeToString(int rc) {
|
||||||
|
#if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||||
switch(rc) {
|
switch(rc) {
|
||||||
case 0:
|
case 0:
|
||||||
return "SUCCESS";
|
return "SUCCESS";
|
||||||
|
@ -355,19 +328,22 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
|
||||||
return "Pairing over the LE transport failed - Pairing Request sent over the BR/EDR transport in process.";
|
return "Pairing over the LE transport failed - Pairing Request sent over the BR/EDR transport in process.";
|
||||||
case (0x0500+BLE_SM_ERR_CROSS_TRANS ):
|
case (0x0500+BLE_SM_ERR_CROSS_TRANS ):
|
||||||
return "BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.";
|
return "BR/EDR Link Key generated on the BR/EDR transport cannot be used to derive and distribute keys for the LE transport.";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||||
|
return "";
|
||||||
|
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert the BLE Advertising Data flags to a string.
|
* @brief Convert the BLE Advertising Data flags to a string.
|
||||||
* @param adFlags The flags to convert
|
* @param adFlags The flags to convert
|
||||||
* @return std::string A string representation of the advertising flags.
|
* @return std::string A string representation of the advertising flags.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
||||||
|
#if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||||
switch(advType) {
|
switch(advType) {
|
||||||
case BLE_HCI_ADV_TYPE_ADV_IND : //0
|
case BLE_HCI_ADV_TYPE_ADV_IND : //0
|
||||||
return "Undirected - Connectable / Scannable";
|
return "Undirected - Connectable / Scannable";
|
||||||
|
@ -382,7 +358,9 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
||||||
default:
|
default:
|
||||||
return "Unknown flag";
|
return "Unknown flag";
|
||||||
}
|
}
|
||||||
|
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||||
|
return "";
|
||||||
|
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
|
||||||
} // adFlagsToString
|
} // adFlagsToString
|
||||||
|
|
||||||
|
|
||||||
|
@ -394,7 +372,7 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
|
||||||
* @param [in] length The length of the data to convert.
|
* @param [in] length The length of the data to convert.
|
||||||
* @return A pointer to the formatted buffer.
|
* @return A pointer to the formatted buffer.
|
||||||
*/
|
*/
|
||||||
char* NimBLEUtils::buildHexData(uint8_t* target, uint8_t* source, uint8_t length) {
|
char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t length) {
|
||||||
// Guard against too much data.
|
// Guard against too much data.
|
||||||
if (length > 100) length = 100;
|
if (length > 100) length = 100;
|
||||||
|
|
||||||
|
@ -422,17 +400,20 @@ char* NimBLEUtils::buildHexData(uint8_t* target, uint8_t* source, uint8_t length
|
||||||
} // buildHexData
|
} // buildHexData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){
|
void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){
|
||||||
|
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||||
NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type));
|
NIMBLE_LOGD(LOG_TAG, "Received a GAP event: %s", gapEventToString(event->type));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert a BT GAP event type to a string representation.
|
* @brief Convert a BT GAP event type to a string representation.
|
||||||
* @param [in] eventType The type of event.
|
* @param [in] eventType The type of event.
|
||||||
* @return A string representation of the event type.
|
* @return A string representation of the event type.
|
||||||
*/
|
*/
|
||||||
const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
||||||
|
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case BLE_GAP_EVENT_CONNECT : //0
|
case BLE_GAP_EVENT_CONNECT : //0
|
||||||
return "BLE_GAP_EVENT_CONNECT ";
|
return "BLE_GAP_EVENT_CONNECT ";
|
||||||
|
@ -507,6 +488,9 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
|
||||||
NIMBLE_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType);
|
NIMBLE_LOGD(LOG_TAG, "gapEventToString: Unknown event type %d 0x%.2x", eventType, eventType);
|
||||||
return "Unknown event type";
|
return "Unknown event type";
|
||||||
}
|
}
|
||||||
|
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||||
|
return "";
|
||||||
|
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
|
||||||
} // gapEventToString
|
} // gapEventToString
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,9 @@ class NimBLEUtils {
|
||||||
public:
|
public:
|
||||||
static void dumpGapEvent(ble_gap_event *event, void *arg);
|
static void dumpGapEvent(ble_gap_event *event, void *arg);
|
||||||
static const char* gapEventToString(uint8_t eventType);
|
static const char* gapEventToString(uint8_t eventType);
|
||||||
static char* buildHexData(uint8_t* target, uint8_t* source, uint8_t length);
|
static char* buildHexData(uint8_t* target, const uint8_t* source, uint8_t length);
|
||||||
static const char* advTypeToString(uint8_t advType);
|
static const char* advTypeToString(uint8_t advType);
|
||||||
static const char* returnCodeToString(int rc);
|
static const char* returnCodeToString(int rc);
|
||||||
static void memrcpy(uint8_t* target, uint8_t* source, uint32_t size);
|
|
||||||
static int checkConnParams(ble_gap_conn_params* params);
|
static int checkConnParams(ble_gap_conn_params* params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include "NimBLEValue.h"
|
#include "NimBLEValue.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
|
@ -31,7 +34,7 @@ NimBLEValue::NimBLEValue() {
|
||||||
* The accumulation is a growing set of data that is added to until a commit or cancel.
|
* The accumulation is a growing set of data that is added to until a commit or cancel.
|
||||||
* @param [in] part A message part being added.
|
* @param [in] part A message part being added.
|
||||||
*/
|
*/
|
||||||
void NimBLEValue::addPart(std::string part) {
|
void NimBLEValue::addPart(const std::string &part) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length());
|
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", part.length());
|
||||||
m_accumulation += part;
|
m_accumulation += part;
|
||||||
} // addPart
|
} // addPart
|
||||||
|
@ -43,7 +46,7 @@ void NimBLEValue::addPart(std::string part) {
|
||||||
* @param [in] pData A message part being added.
|
* @param [in] pData A message part being added.
|
||||||
* @param [in] length The number of bytes being added.
|
* @param [in] length The number of bytes being added.
|
||||||
*/
|
*/
|
||||||
void NimBLEValue::addPart(uint8_t* pData, size_t length) {
|
void NimBLEValue::addPart(const uint8_t* pData, size_t length) {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length);
|
NIMBLE_LOGD(LOG_TAG, ">> addPart: length=%d", length);
|
||||||
m_accumulation += std::string((char*) pData, length);
|
m_accumulation += std::string((char*) pData, length);
|
||||||
} // addPart
|
} // addPart
|
||||||
|
@ -122,7 +125,7 @@ void NimBLEValue::setReadOffset(uint16_t readOffset) {
|
||||||
/**
|
/**
|
||||||
* @brief Set the current value.
|
* @brief Set the current value.
|
||||||
*/
|
*/
|
||||||
void NimBLEValue::setValue(std::string value) {
|
void NimBLEValue::setValue(const std::string &value) {
|
||||||
m_value = value;
|
m_value = value;
|
||||||
} // setValue
|
} // setValue
|
||||||
|
|
||||||
|
@ -132,9 +135,9 @@ void NimBLEValue::setValue(std::string value) {
|
||||||
* @param [in] pData The data for the current value.
|
* @param [in] pData The data for the current value.
|
||||||
* @param [in] The length of the new current value.
|
* @param [in] The length of the new current value.
|
||||||
*/
|
*/
|
||||||
void NimBLEValue::setValue(uint8_t* pData, size_t length) {
|
void NimBLEValue::setValue(const uint8_t* pData, size_t length) {
|
||||||
m_value = std::string((char*) pData, length);
|
m_value = std::string((char*) pData, length);
|
||||||
} // setValue
|
} // setValue
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
|
@ -16,6 +16,10 @@
|
||||||
#define MAIN_BLEVALUE_H_
|
#define MAIN_BLEVALUE_H_
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED)
|
#if defined(CONFIG_BT_ENABLED)
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,8 +28,8 @@
|
||||||
class NimBLEValue {
|
class NimBLEValue {
|
||||||
public:
|
public:
|
||||||
NimBLEValue();
|
NimBLEValue();
|
||||||
void addPart(std::string part);
|
void addPart(const std::string &part);
|
||||||
void addPart(uint8_t* pData, size_t length);
|
void addPart(const uint8_t* pData, size_t length);
|
||||||
void cancel();
|
void cancel();
|
||||||
void commit();
|
void commit();
|
||||||
uint8_t* getData();
|
uint8_t* getData();
|
||||||
|
@ -33,8 +37,8 @@ public:
|
||||||
uint16_t getReadOffset();
|
uint16_t getReadOffset();
|
||||||
std::string getValue();
|
std::string getValue();
|
||||||
void setReadOffset(uint16_t readOffset);
|
void setReadOffset(uint16_t readOffset);
|
||||||
void setValue(std::string value);
|
void setValue(const std::string &value);
|
||||||
void setValue(uint8_t* pData, size_t length);
|
void setValue(const uint8_t* pData, size_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_accumulation;
|
std::string m_accumulation;
|
||||||
|
@ -42,5 +46,7 @@ private:
|
||||||
std::string m_value;
|
std::string m_value;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
#endif // CONFIG_BT_ENABLED
|
#endif // CONFIG_BT_ENABLED
|
||||||
#endif /* MAIN_BLEVALUE_H_ */
|
#endif /* MAIN_BLEVALUE_H_ */
|
|
@ -1,6 +1,4 @@
|
||||||
|
|
||||||
/* Modifications copyright (C) 2020 Ryan Powell */
|
|
||||||
|
|
||||||
#ifndef __ESP_NIMBLE_CFG__
|
#ifndef __ESP_NIMBLE_CFG__
|
||||||
#define __ESP_NIMBLE_CFG__
|
#define __ESP_NIMBLE_CFG__
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
|
@ -470,7 +468,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT
|
#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT
|
||||||
#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT CONFIG_BT_NIMBLE_FLOW_CTRL_TX_ON_DISCONNECT
|
#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS
|
#ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
*
|
*
|
||||||
|
|
|
@ -98,8 +98,8 @@ struct hci_conn_update;
|
||||||
|
|
||||||
#define BLE_GAP_INITIAL_CONN_LATENCY 0
|
#define BLE_GAP_INITIAL_CONN_LATENCY 0
|
||||||
#define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100
|
#define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100
|
||||||
#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0010
|
#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0000
|
||||||
#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0300
|
#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0000
|
||||||
|
|
||||||
#define BLE_GAP_ROLE_MASTER 0
|
#define BLE_GAP_ROLE_MASTER 0
|
||||||
#define BLE_GAP_ROLE_SLAVE 1
|
#define BLE_GAP_ROLE_SLAVE 1
|
||||||
|
@ -1783,6 +1783,20 @@ int ble_gap_unpair(const ble_addr_t *peer_addr);
|
||||||
*/
|
*/
|
||||||
int ble_gap_unpair_oldest_peer(void);
|
int ble_gap_unpair_oldest_peer(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that the
|
||||||
|
* peer received in input parameters is not deleted.
|
||||||
|
*
|
||||||
|
* @param peer_addr Address of the peer (not to be deleted)
|
||||||
|
*
|
||||||
|
* @return 0 on success;
|
||||||
|
* A BLE host HCI return code if the controller
|
||||||
|
* rejected the request;
|
||||||
|
* A BLE host core return code on unexpected
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr);
|
||||||
|
|
||||||
#define BLE_GAP_PRIVATE_MODE_NETWORK 0
|
#define BLE_GAP_PRIVATE_MODE_NETWORK 0
|
||||||
#define BLE_GAP_PRIVATE_MODE_DEVICE 1
|
#define BLE_GAP_PRIVATE_MODE_DEVICE 1
|
||||||
|
|
||||||
|
@ -1886,20 +1900,6 @@ struct ble_gap_event_listener {
|
||||||
SLIST_ENTRY(ble_gap_event_listener) link;
|
SLIST_ENTRY(ble_gap_event_listener) link;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that current
|
|
||||||
* peer is not deleted.
|
|
||||||
*
|
|
||||||
* @param peer_addr Address of the current peer (not to be deleted)
|
|
||||||
*
|
|
||||||
* @return 0 on success;
|
|
||||||
* A BLE host HCI return code if the controller
|
|
||||||
* rejected the request;
|
|
||||||
* A BLE host core return code on unexpected
|
|
||||||
* error.
|
|
||||||
*/
|
|
||||||
int ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers listener for GAP events
|
* Registers listener for GAP events
|
||||||
*
|
*
|
||||||
|
|
|
@ -288,8 +288,6 @@ int ble_store_clear(void);
|
||||||
|
|
||||||
/*** Utility functions. */
|
/*** Utility functions. */
|
||||||
|
|
||||||
int ble_store_clean_old_cccds(const ble_addr_t *curr_peer);
|
|
||||||
|
|
||||||
int ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs,
|
int ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs,
|
||||||
int *out_num_peers,
|
int *out_num_peers,
|
||||||
int max_peers);
|
int max_peers);
|
||||||
|
|
|
@ -330,11 +330,8 @@ static inline void net_buf_simple_restore(struct os_mbuf *buf,
|
||||||
buf->om_len = state->len;
|
buf->om_len = state->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sys_memcpy_swap(void *destination, const void *source, size_t length)
|
static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
|
||||||
{
|
{
|
||||||
u8_t *dst = destination;
|
|
||||||
const u8_t *src = source;
|
|
||||||
|
|
||||||
__ASSERT(((src < dst && (src + length) <= dst) ||
|
__ASSERT(((src < dst && (src + length) <= dst) ||
|
||||||
(src > dst && (dst + length) <= src)),
|
(src > dst && (dst + length) <= src)),
|
||||||
"Source and destination buffers must not overlap");
|
"Source and destination buffers must not overlap");
|
||||||
|
@ -342,7 +339,7 @@ static inline void sys_memcpy_swap(void *destination, const void *source, size_t
|
||||||
src += length - 1;
|
src += length - 1;
|
||||||
|
|
||||||
for (; length > 0; length--) {
|
for (; length > 0; length--) {
|
||||||
*dst++ = *src--;
|
*((u8_t *)dst++) = *((u8_t *)src--);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,31 +41,43 @@ modlog_dummy(const char *msg, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
/// Uncomment these and comment out the 3 defines below to see NimBLE messages in Arduino.
|
#define MODLOG_ESP_LOCAL(level, ml_msg_, ...) do { \
|
||||||
/*
|
if (LOG_LOCAL_LEVEL >= level) esp_log_write(level, "NimBLE", ml_msg_, ##__VA_ARGS__); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_BT_NIMBLE_DEBUG)
|
||||||
|
|
||||||
#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
|
#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
|
||||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
|
#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
|
||||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
|
#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
|
||||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||||
*/
|
|
||||||
|
#else
|
||||||
|
|
||||||
#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
|
#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
|
||||||
esp_log_write(ESP_LOG_DEBUG, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
MODLOG_ESP_LOCAL(ESP_LOG_DEBUG, ml_msg_, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
|
#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
|
||||||
esp_log_write(ESP_LOG_INFO, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
MODLOG_ESP_LOCAL(ESP_LOG_INFO, ml_msg_, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
|
#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
|
||||||
esp_log_write(ESP_LOG_WARN, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
MODLOG_ESP_LOCAL(ESP_LOG_WARN, ml_msg_, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \
|
#define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \
|
||||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \
|
#define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \
|
||||||
esp_log_write(ESP_LOG_ERROR, "NimBLE",ml_msg_, ##__VA_ARGS__)
|
MODLOG_ESP_LOCAL(ESP_LOG_ERROR, ml_msg_, ##__VA_ARGS__)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,7 @@ void ble_gap_preempt(void);
|
||||||
void ble_gap_preempt_done(void);
|
void ble_gap_preempt_done(void);
|
||||||
|
|
||||||
void ble_gap_conn_broken(uint16_t conn_handle, int reason);
|
void ble_gap_conn_broken(uint16_t conn_handle, int reason);
|
||||||
|
void ble_gap_reset_state(int reason);
|
||||||
int32_t ble_gap_timer(void);
|
int32_t ble_gap_timer(void);
|
||||||
|
|
||||||
int ble_gap_init(void);
|
int ble_gap_init(void);
|
||||||
|
|
|
@ -33,6 +33,10 @@ int ble_hs_id_use_addr(uint8_t addr_type);
|
||||||
void ble_hs_id_reset(void);
|
void ble_hs_id_reset(void);
|
||||||
void ble_hs_id_rnd_reset(void);
|
void ble_hs_id_rnd_reset(void);
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||||
|
bool ble_hs_is_rpa(uint8_t *addr, uint8_t addr_type);
|
||||||
|
int ble_hs_id_set_pseudo_rnd(const uint8_t *);
|
||||||
|
#endif
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,6 +35,9 @@ int ble_hs_pvcy_add_entry(const uint8_t *addr, uint8_t addrtype,
|
||||||
const uint8_t *irk);
|
const uint8_t *irk);
|
||||||
int ble_hs_pvcy_ensure_started(void);
|
int ble_hs_pvcy_ensure_started(void);
|
||||||
int ble_hs_pvcy_set_mode(const ble_addr_t *addr, uint8_t priv_mode);
|
int ble_hs_pvcy_set_mode(const ble_addr_t *addr, uint8_t priv_mode);
|
||||||
|
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||||
|
bool ble_hs_pvcy_enabled(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||||
|
/*
|
||||||
|
* An entry in the resolving list.
|
||||||
|
*/
|
||||||
|
struct ble_hs_resolv_entry {
|
||||||
|
uint8_t rl_addr_type;
|
||||||
|
uint8_t rl_local_irk[16];
|
||||||
|
uint8_t rl_peer_irk[16];
|
||||||
|
uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN];
|
||||||
|
uint8_t rl_pseudo_id[BLE_DEV_ADDR_LEN];
|
||||||
|
uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN];
|
||||||
|
uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST)
|
||||||
|
/* Persist peer records in NVS. XXX Need to handle this in `store` module */
|
||||||
|
int ble_store_persist_peer_records(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ble_hs_peer_sec {
|
||||||
|
ble_addr_t peer_addr;
|
||||||
|
uint8_t irk[16];
|
||||||
|
uint8_t irk_present: 1;
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* BLE host peer device record, this helps in storing peer RPA before bond is
|
||||||
|
* created and IRKs are exchanged.
|
||||||
|
*/
|
||||||
|
struct ble_hs_dev_records {
|
||||||
|
bool rec_used;
|
||||||
|
uint8_t pseudo_addr[BLE_DEV_ADDR_LEN];
|
||||||
|
uint8_t rand_addr[BLE_DEV_ADDR_LEN];
|
||||||
|
uint8_t identity_addr[BLE_DEV_ADDR_LEN];
|
||||||
|
struct ble_hs_peer_sec peer_sec;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Add a device to the resolving list */
|
||||||
|
int ble_hs_resolv_list_add(uint8_t *cmdbuf);
|
||||||
|
int ble_hs_gen_own_rpa_random(void);
|
||||||
|
uint8_t *ble_hs_get_rpa_local(void);
|
||||||
|
|
||||||
|
/* Remove a device from the resolving list */
|
||||||
|
int ble_hs_resolv_list_rmv(uint8_t, uint8_t *);
|
||||||
|
/* Clear the resolving list and peer dev record */
|
||||||
|
void ble_hs_resolv_list_clear_all(void);
|
||||||
|
|
||||||
|
/* Address resolution enable command */
|
||||||
|
void ble_hs_resolv_enable(bool);
|
||||||
|
|
||||||
|
/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */
|
||||||
|
struct ble_hs_resolv_entry *
|
||||||
|
ble_hs_resolv_list_find(uint8_t *addr);
|
||||||
|
|
||||||
|
/* Returns true if host based RPA (privacy) is enabled */
|
||||||
|
bool ble_host_rpa_enabled(void);
|
||||||
|
|
||||||
|
/* Searches peer device records (RPA) and fetches matching RL, peer_address
|
||||||
|
* into input parameters if RL is found */
|
||||||
|
void
|
||||||
|
ble_rpa_replace_peer_params_with_rl(uint8_t *, uint8_t *, struct ble_hs_resolv_entry **);
|
||||||
|
|
||||||
|
int ble_rpa_resolv_add_peer_rec(uint8_t *);
|
||||||
|
|
||||||
|
struct ble_hs_dev_records *ble_rpa_get_peer_dev_records(void);
|
||||||
|
int ble_rpa_get_num_peer_dev_records(void);
|
||||||
|
void ble_rpa_set_num_peer_dev_records(int);
|
||||||
|
int ble_rpa_remove_peer_dev_rec(struct ble_hs_dev_records *);
|
||||||
|
struct ble_hs_dev_records *ble_rpa_find_peer_dev_rec(uint8_t *);
|
||||||
|
|
||||||
|
/* Set the resolvable private address timeout */
|
||||||
|
int ble_hs_resolv_set_rpa_tmo(uint16_t);
|
||||||
|
|
||||||
|
/* Resolve a resolvable private address */
|
||||||
|
int ble_hs_resolv_rpa(uint8_t *rpa, uint8_t *irk);
|
||||||
|
|
||||||
|
/* Initialize resolv*/
|
||||||
|
void ble_hs_resolv_init(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -399,6 +399,7 @@ int ble_sm_slave_initiate(uint16_t conn_handle);
|
||||||
int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size,
|
int ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size,
|
||||||
const uint8_t *ltk, uint16_t ediv,
|
const uint8_t *ltk, uint16_t ediv,
|
||||||
uint64_t rand_val, int auth);
|
uint64_t rand_val, int auth);
|
||||||
|
int ble_sm_alg_encrypt(uint8_t *key, uint8_t *plaintext, uint8_t *enc_data);
|
||||||
int ble_sm_init(void);
|
int ble_sm_init(void);
|
||||||
|
|
||||||
#define BLE_SM_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \
|
#define BLE_SM_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \
|
||||||
|
@ -419,6 +420,9 @@ int ble_sm_init(void);
|
||||||
|
|
||||||
#define ble_sm_init() 0
|
#define ble_sm_init() 0
|
||||||
|
|
||||||
|
#define ble_sm_alg_encrypt(key, plaintext, enc_data) \
|
||||||
|
BLE_HS_ENOTSUP
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle);
|
struct ble_l2cap_chan *ble_sm_create_chan(uint16_t handle);
|
||||||
|
|
|
@ -66,11 +66,10 @@ ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom)
|
||||||
|
|
||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
|
|
||||||
ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn,
|
rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn,
|
||||||
&chan);
|
&chan);
|
||||||
if (chan == NULL) {
|
if (rc != 0) {
|
||||||
os_mbuf_free_chain(txom);
|
os_mbuf_free_chain(txom);
|
||||||
rc = BLE_HS_ENOTCONN;
|
|
||||||
} else {
|
} else {
|
||||||
ble_att_truncate_to_mtu(chan, txom);
|
ble_att_truncate_to_mtu(chan, txom);
|
||||||
rc = ble_l2cap_tx(conn, chan, txom);
|
rc = ble_l2cap_tx(conn, chan, txom);
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Modifications copyright (C) 2020 Ryan Powell */
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -1855,7 +1853,6 @@ ble_gap_update_timer(void)
|
||||||
ble_hs_unlock();
|
ble_hs_unlock();
|
||||||
|
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
ble_gap_update_notify(conn_handle, BLE_HS_ETIMEOUT);
|
|
||||||
ble_gap_update_entry_free(entry);
|
ble_gap_update_entry_free(entry);
|
||||||
}
|
}
|
||||||
} while (entry != NULL);
|
} while (entry != NULL);
|
||||||
|
@ -5303,8 +5300,7 @@ ble_gap_unpair_oldest_peer(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_peers == 0) {
|
if (num_peers == 0) {
|
||||||
return BLE_HS_ENOENT;
|
return 0;
|
||||||
//return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ble_gap_unpair(&oldest_peer_id_addr);
|
rc = ble_gap_unpair(&oldest_peer_id_addr);
|
||||||
|
@ -5316,14 +5312,14 @@ ble_gap_unpair_oldest_peer(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer)
|
ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr)
|
||||||
{
|
{
|
||||||
ble_addr_t oldest_peer_id_addr[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
||||||
int num_peers;
|
int num_peers;
|
||||||
int rc, i;
|
int rc, i;
|
||||||
|
|
||||||
rc = ble_store_util_bonded_peers(
|
rc = ble_store_util_bonded_peers(
|
||||||
&oldest_peer_id_addr[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
&peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -5333,21 +5329,16 @@ ble_gap_unpair_oldest_except_curr(const ble_addr_t *curr_peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_peers; i++) {
|
for (i = 0; i < num_peers; i++) {
|
||||||
if (memcmp(curr_peer, &oldest_peer_id_addr[i], sizeof (ble_addr_t)) != 0) {
|
if (ble_addr_cmp(peer_addr, &peer_id_addrs[i]) != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < num_peers) {
|
if (i >= num_peers) {
|
||||||
rc = ble_gap_unpair(&oldest_peer_id_addr[i]);
|
|
||||||
if (rc != 0) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return BLE_HS_ENOMEM;
|
return BLE_HS_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return ble_gap_unpair(&peer_id_addrs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -5371,7 +5362,8 @@ ble_gap_passkey_event(uint16_t conn_handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
|
ble_gap_enc_event(uint16_t conn_handle, int status,
|
||||||
|
int security_restored, int bonded)
|
||||||
{
|
{
|
||||||
#if !NIMBLE_BLE_SM
|
#if !NIMBLE_BLE_SM
|
||||||
return;
|
return;
|
||||||
|
@ -5387,17 +5379,24 @@ ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
|
||||||
ble_gap_event_listener_call(&event);
|
ble_gap_event_listener_call(&event);
|
||||||
ble_gap_call_conn_event_cb(&event, conn_handle);
|
ble_gap_call_conn_event_cb(&event, conn_handle);
|
||||||
|
|
||||||
/* H2zero mod
|
if (status != 0) {
|
||||||
If bonding is not enabled don't store cccd data
|
return;
|
||||||
if (status == 0) {
|
}
|
||||||
|
|
||||||
|
/* If encryption succeded and encryption has been restored for bonded device,
|
||||||
|
* notify gatt server so it has chance to send notification/indication if needed.
|
||||||
*/
|
*/
|
||||||
if (status == 0 && ble_hs_cfg.sm_bonding) {
|
|
||||||
/* End mod */
|
|
||||||
if (security_restored) {
|
if (security_restored) {
|
||||||
ble_gatts_bonding_restored(conn_handle);
|
ble_gatts_bonding_restored(conn_handle);
|
||||||
} else {
|
return;
|
||||||
ble_gatts_bonding_established(conn_handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If this is fresh pairing and bonding has been established,
|
||||||
|
* notify gatt server about that so previous subscriptions (before bonding)
|
||||||
|
* can be stored.
|
||||||
|
*/
|
||||||
|
if (bonded) {
|
||||||
|
ble_gatts_bonding_established(conn_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ int ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
|
||||||
struct ble_gap_upd_params *params);
|
struct ble_gap_upd_params *params);
|
||||||
void ble_gap_rx_phy_update_complete(struct hci_le_phy_upd_complete *evt);
|
void ble_gap_rx_phy_update_complete(struct hci_le_phy_upd_complete *evt);
|
||||||
void ble_gap_enc_event(uint16_t conn_handle, int status,
|
void ble_gap_enc_event(uint16_t conn_handle, int status,
|
||||||
int security_restored);
|
int security_restored, int bonded);
|
||||||
void ble_gap_passkey_event(uint16_t conn_handle,
|
void ble_gap_passkey_event(uint16_t conn_handle,
|
||||||
struct ble_gap_passkey_params *passkey_params);
|
struct ble_gap_passkey_params *passkey_params);
|
||||||
void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
|
void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
|
||||||
|
|
|
@ -1689,8 +1689,8 @@ ble_gatts_bonding_established(uint16_t conn_handle)
|
||||||
|
|
||||||
conn = ble_hs_conn_find(conn_handle);
|
conn = ble_hs_conn_find(conn_handle);
|
||||||
BLE_HS_DBG_ASSERT(conn != NULL);
|
BLE_HS_DBG_ASSERT(conn != NULL);
|
||||||
|
BLE_HS_DBG_ASSERT(conn->bhc_sec_state.bonded);
|
||||||
|
|
||||||
if (conn->bhc_sec_state.bonded) {
|
|
||||||
cccd_value.peer_addr = conn->bhc_peer_addr;
|
cccd_value.peer_addr = conn->bhc_peer_addr;
|
||||||
gatt_srv = &conn->bhc_gatt_svr;
|
gatt_srv = &conn->bhc_gatt_svr;
|
||||||
|
|
||||||
|
@ -1714,7 +1714,6 @@ ble_gatts_bonding_established(uint16_t conn_handle)
|
||||||
BLE_HS_DBG_ASSERT(conn != NULL);
|
BLE_HS_DBG_ASSERT(conn != NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ble_hs_unlock();
|
ble_hs_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -410,15 +410,13 @@ ble_hs_conn_addrs(const struct ble_hs_conn *conn,
|
||||||
|
|
||||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||||
/* RPA: Override peer address information. */
|
/* RPA: Override peer address information. */
|
||||||
struct ble_hs_resolv_entry *rl = NULL;
|
|
||||||
|
|
||||||
ble_addr_t bhc_peer_addr;
|
ble_addr_t bhc_peer_addr;
|
||||||
bhc_peer_addr.type = conn->bhc_peer_addr.type;
|
bhc_peer_addr.type = conn->bhc_peer_addr.type;
|
||||||
memcpy(bhc_peer_addr.val, conn->bhc_peer_addr.val, BLE_DEV_ADDR_LEN);
|
memcpy(bhc_peer_addr.val, conn->bhc_peer_addr.val, BLE_DEV_ADDR_LEN);
|
||||||
|
|
||||||
|
struct ble_hs_resolv_entry *rl = NULL;
|
||||||
rl = ble_hs_resolv_list_find(bhc_peer_addr.val);
|
rl = ble_hs_resolv_list_find(bhc_peer_addr.val);
|
||||||
if (rl != NULL) {
|
if (rl != NULL) {
|
||||||
addrs->peer_ota_addr = conn->bhc_peer_rpa_addr;
|
|
||||||
memcpy(addrs->peer_id_addr.val, rl->rl_identity_addr, BLE_DEV_ADDR_LEN);
|
memcpy(addrs->peer_id_addr.val, rl->rl_identity_addr, BLE_DEV_ADDR_LEN);
|
||||||
addrs->peer_id_addr.type = rl->rl_addr_type;
|
addrs->peer_id_addr.type = rl->rl_addr_type;
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,7 @@ ble_hs_hci_process_ack(uint16_t expected_opcode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
if (params_buf == NULL) {
|
if (params_buf == NULL || out_ack->bha_params == NULL) {
|
||||||
out_ack->bha_params_len = 0;
|
out_ack->bha_params_len = 0;
|
||||||
} else {
|
} else {
|
||||||
if (out_ack->bha_params_len > params_buf_len) {
|
if (out_ack->bha_params_len > params_buf_len) {
|
||||||
|
|
|
@ -337,14 +337,6 @@ ble_hs_hci_evt_le_conn_complete(uint8_t subevent, uint8_t *data, int len)
|
||||||
struct ble_hs_resolv_entry *rl = NULL;
|
struct ble_hs_resolv_entry *rl = NULL;
|
||||||
ble_rpa_replace_peer_params_with_rl(evt.peer_addr,
|
ble_rpa_replace_peer_params_with_rl(evt.peer_addr,
|
||||||
&evt.peer_addr_type, &rl);
|
&evt.peer_addr_type, &rl);
|
||||||
if (rl == NULL) {
|
|
||||||
if (ble_rpa_resolv_add_peer_rec(evt.peer_addr) != 0) {
|
|
||||||
BLE_HS_LOG(DEBUG, "Memory unavailable for new peer record\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Set the correct RPA for logging */
|
|
||||||
memcpy(evt.peer_rpa, data + 6, BLE_DEV_ADDR_LEN);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
memset(evt.local_rpa, 0, BLE_DEV_ADDR_LEN);
|
memset(evt.local_rpa, 0, BLE_DEV_ADDR_LEN);
|
||||||
|
@ -441,14 +433,6 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, uint8_t *data, int len)
|
||||||
memcpy(desc.addr.val, data + off, 6);
|
memcpy(desc.addr.val, data + off, 6);
|
||||||
off += 6;
|
off += 6;
|
||||||
|
|
||||||
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
|
||||||
if (ble_host_rpa_enabled()) {
|
|
||||||
/* Now RPA to be resolved here, since controller is unaware of the
|
|
||||||
* address is RPA */
|
|
||||||
ble_rpa_replace_peer_params_with_rl(desc.addr.val,
|
|
||||||
&desc.addr.type, NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
desc.length_data = data[off];
|
desc.length_data = data[off];
|
||||||
++off;
|
++off;
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
||||||
struct ble_hs_conn **out_conn,
|
struct ble_hs_conn **out_conn,
|
||||||
struct ble_l2cap_chan **out_chan)
|
struct ble_l2cap_chan **out_chan)
|
||||||
|
@ -66,7 +66,9 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = ble_hs_misc_conn_chan_find(conn_handle, cid, &conn, &chan);
|
rc = ble_hs_misc_conn_chan_find(conn_handle, cid, &conn, &chan);
|
||||||
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
if (out_conn != NULL) {
|
if (out_conn != NULL) {
|
||||||
*out_conn = conn;
|
*out_conn = conn;
|
||||||
|
@ -74,6 +76,8 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
||||||
if (out_chan != NULL) {
|
if (out_chan != NULL) {
|
||||||
*out_chan = chan;
|
*out_chan = chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
|
|
|
@ -115,7 +115,7 @@ int ble_hs_hci_evt_acl_process(struct os_mbuf *om);
|
||||||
int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
|
int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
|
||||||
struct ble_hs_conn **out_conn,
|
struct ble_hs_conn **out_conn,
|
||||||
struct ble_l2cap_chan **out_chan);
|
struct ble_l2cap_chan **out_chan);
|
||||||
void ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
|
||||||
struct ble_hs_conn **out_conn,
|
struct ble_hs_conn **out_conn,
|
||||||
struct ble_l2cap_chan **out_chan);
|
struct ble_l2cap_chan **out_chan);
|
||||||
uint8_t ble_hs_misc_addr_type_to_id(uint8_t addr_type);
|
uint8_t ble_hs_misc_addr_type_to_id(uint8_t addr_type);
|
||||||
|
|
|
@ -473,8 +473,13 @@ ble_l2cap_sig_update(uint16_t conn_handle,
|
||||||
STATS_INC(ble_l2cap_stats, update_init);
|
STATS_INC(ble_l2cap_stats, update_init);
|
||||||
|
|
||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
|
rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
|
||||||
&conn, &chan);
|
&conn, &chan);
|
||||||
|
if (rc != 0) {
|
||||||
|
ble_hs_unlock();
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
master = conn->bhc_flags & BLE_HS_CONN_F_MASTER;
|
master = conn->bhc_flags & BLE_HS_CONN_F_MASTER;
|
||||||
ble_hs_unlock();
|
ble_hs_unlock();
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,11 @@ ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
|
rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
|
||||||
&conn, &chan);
|
&conn, &chan);
|
||||||
|
if (rc == 0) {
|
||||||
rc = ble_l2cap_tx(conn, chan, txom);
|
rc = ble_l2cap_tx(conn, chan, txom);
|
||||||
|
}
|
||||||
ble_hs_unlock();
|
ble_hs_unlock();
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -538,6 +538,11 @@ ble_sm_persist_keys(struct ble_sm_proc *proc)
|
||||||
case BLE_ADDR_PUBLIC:
|
case BLE_ADDR_PUBLIC:
|
||||||
case BLE_ADDR_PUBLIC_ID:
|
case BLE_ADDR_PUBLIC_ID:
|
||||||
conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID;
|
conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID;
|
||||||
|
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||||
|
/* In case of Host based privacy, we should not be changing
|
||||||
|
* peer address type to BLE_ADDR_PUBLIC_ID */
|
||||||
|
conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLE_ADDR_RANDOM:
|
case BLE_ADDR_RANDOM:
|
||||||
|
@ -944,7 +949,7 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res)
|
||||||
|
|
||||||
if (res->enc_cb) {
|
if (res->enc_cb) {
|
||||||
BLE_HS_DBG_ASSERT(proc == NULL || rm);
|
BLE_HS_DBG_ASSERT(proc == NULL || rm);
|
||||||
ble_gap_enc_event(conn_handle, res->app_status, res->restore);
|
ble_gap_enc_event(conn_handle, res->app_status, res->restore, res->bonded);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res->app_status == 0 &&
|
if (res->app_status == 0 &&
|
||||||
|
@ -1198,6 +1203,7 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
|
||||||
|
|
||||||
ble_hs_unlock();
|
ble_hs_unlock();
|
||||||
|
|
||||||
|
res.bonded = bonded;
|
||||||
ble_sm_process_result(conn_handle, &res);
|
ble_sm_process_result(conn_handle, &res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1793,8 +1799,21 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||||
*/
|
*/
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, &prev);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, &prev);
|
||||||
if (proc != NULL) {
|
if (proc != NULL) {
|
||||||
/* Pairing already in progress; abort old procedure and start new. */
|
/* Fail if procedure is in progress unless we sent a slave security
|
||||||
/* XXX: Check the spec on this. */
|
* request to peer.
|
||||||
|
*/
|
||||||
|
if (proc->state != BLE_SM_PROC_STATE_SEC_REQ) {
|
||||||
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED);
|
||||||
|
ble_hs_unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the procedure because it was allocated when
|
||||||
|
* sending the Slave Security Request and it will be allocated
|
||||||
|
* again later in this method. We should probably refactor this
|
||||||
|
* in the future.
|
||||||
|
*/
|
||||||
ble_sm_proc_remove(proc, prev);
|
ble_sm_proc_remove(proc, prev);
|
||||||
ble_sm_proc_free(proc);
|
ble_sm_proc_free(proc);
|
||||||
}
|
}
|
||||||
|
@ -2459,7 +2478,7 @@ ble_sm_timer(void)
|
||||||
* procedures without reconnect.
|
* procedures without reconnect.
|
||||||
*/
|
*/
|
||||||
while ((proc = STAILQ_FIRST(&exp_list)) != NULL) {
|
while ((proc = STAILQ_FIRST(&exp_list)) != NULL) {
|
||||||
ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0);
|
ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0, 0);
|
||||||
|
|
||||||
STAILQ_REMOVE_HEAD(&exp_list, next);
|
STAILQ_REMOVE_HEAD(&exp_list, next);
|
||||||
ble_sm_proc_free(proc);
|
ble_sm_proc_free(proc);
|
||||||
|
|
|
@ -52,14 +52,19 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
|
||||||
{
|
{
|
||||||
struct ble_l2cap_chan *chan;
|
struct ble_l2cap_chan *chan;
|
||||||
struct ble_hs_conn *conn;
|
struct ble_hs_conn *conn;
|
||||||
|
int rc;
|
||||||
|
|
||||||
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
|
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
|
||||||
|
|
||||||
STATS_INC(ble_l2cap_stats, sm_tx);
|
STATS_INC(ble_l2cap_stats, sm_tx);
|
||||||
|
|
||||||
ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
|
rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
|
||||||
&conn, &chan);
|
&conn, &chan);
|
||||||
return ble_l2cap_tx(conn, chan, txom);
|
if (rc == 0) {
|
||||||
|
rc = ble_l2cap_tx(conn, chan, txom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NIMBLE_BLE_SM
|
#if NIMBLE_BLE_SM
|
||||||
|
|
|
@ -279,7 +279,7 @@ struct ble_sm_result {
|
||||||
void *state_arg;
|
void *state_arg;
|
||||||
unsigned execute : 1;
|
unsigned execute : 1;
|
||||||
unsigned enc_cb : 1;
|
unsigned enc_cb : 1;
|
||||||
unsigned persist_keys:1;
|
unsigned bonded : 1;
|
||||||
unsigned restore : 1;
|
unsigned restore : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "host/ble_store.h"
|
#include "host/ble_store.h"
|
||||||
#include "ble_hs_priv.h"
|
#include "ble_hs_priv.h"
|
||||||
|
#include "ble_hs_resolv_priv.h"
|
||||||
|
|
||||||
struct ble_store_util_peer_set {
|
struct ble_store_util_peer_set {
|
||||||
ble_addr_t *peer_id_addrs;
|
ble_addr_t *peer_id_addrs;
|
||||||
|
@ -27,12 +28,6 @@ struct ble_store_util_peer_set {
|
||||||
int status;
|
int status;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ble_store_util_peer_cccd_set {
|
|
||||||
struct ble_store_util_peer_set peer_set;
|
|
||||||
ble_addr_t *curr_peer_addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ble_store_util_iter_unique_peer(int obj_type,
|
ble_store_util_iter_unique_peer(int obj_type,
|
||||||
union ble_store_value *val,
|
union ble_store_value *val,
|
||||||
|
@ -65,42 +60,6 @@ ble_store_util_iter_unique_peer(int obj_type,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
ble_store_util_iter_peer_cccd(int obj_type,
|
|
||||||
union ble_store_value *val,
|
|
||||||
void *arg)
|
|
||||||
{
|
|
||||||
struct ble_store_util_peer_cccd_set *set;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
set = arg;
|
|
||||||
|
|
||||||
/* Do nothing if this peer is a duplicate or current peer */
|
|
||||||
for (i = 0; i < set->peer_set.num_peers; i++) {
|
|
||||||
if (ble_addr_cmp(set->peer_set.peer_id_addrs + i, &val->cccd.peer_addr) == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set->curr_peer_addr != NULL) {
|
|
||||||
if (ble_addr_cmp(set->curr_peer_addr, &val->cccd.peer_addr) == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set->peer_set.num_peers >= set->peer_set.max_peers) {
|
|
||||||
/* Overflow; abort the iterate procedure. */
|
|
||||||
set->peer_set.status = BLE_HS_ENOMEM;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
set->peer_set.peer_id_addrs[set->peer_set.num_peers] = val->cccd.peer_addr;
|
|
||||||
set->peer_set.num_peers++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the set of peer addresses for which a bond has been established.
|
* Retrieves the set of peer addresses for which a bond has been established.
|
||||||
*
|
*
|
||||||
|
@ -141,51 +100,6 @@ ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the set of peer addresses for which CCCDs are subscribed.
|
|
||||||
*
|
|
||||||
* @param out_peer_id_addrs On success, the set of peer addresses
|
|
||||||
* gets written here.
|
|
||||||
* @param out_num_peers On success, the number of peer addresses gets written
|
|
||||||
* here.
|
|
||||||
* @param max_peers The capacity of the destination buffer.
|
|
||||||
*
|
|
||||||
* @param curr_peer_addrs Current peer's address, ignore if NULL
|
|
||||||
*
|
|
||||||
* @return 0 on success;
|
|
||||||
* BLE_HS_ENOMEM if the destination buffer is too
|
|
||||||
* small;
|
|
||||||
* Other nonzero on error.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
ble_store_util_subscribed_cccds(ble_addr_t *out_peer_id_addrs, int *out_num_peers,
|
|
||||||
int max_peers, ble_addr_t *curr_peer_addr)
|
|
||||||
{
|
|
||||||
struct ble_store_util_peer_cccd_set set = {
|
|
||||||
.peer_set = {
|
|
||||||
.peer_id_addrs = out_peer_id_addrs,
|
|
||||||
.num_peers = 0,
|
|
||||||
.max_peers = max_peers,
|
|
||||||
.status = 0,
|
|
||||||
},
|
|
||||||
.curr_peer_addr = curr_peer_addr,
|
|
||||||
};
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = ble_store_iterate(BLE_STORE_OBJ_TYPE_CCCD,
|
|
||||||
ble_store_util_iter_peer_cccd,
|
|
||||||
&set);
|
|
||||||
if (rc != 0) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
if (set.peer_set.status != 0) {
|
|
||||||
return set.peer_set.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_num_peers = set.peer_set.num_peers;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all entries from the store that are attached to the specified peer
|
* Deletes all entries from the store that are attached to the specified peer
|
||||||
* address. This function deletes security entries and CCCD records.
|
* address. This function deletes security entries and CCCD records.
|
||||||
|
@ -222,6 +136,25 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY)
|
||||||
|
struct ble_hs_dev_records *peer_rec =
|
||||||
|
ble_rpa_find_peer_dev_rec(key.sec.peer_addr.val);
|
||||||
|
|
||||||
|
if (peer_rec != NULL) {
|
||||||
|
rc = ble_hs_resolv_list_rmv(peer_rec->peer_sec.peer_addr.type,
|
||||||
|
peer_rec->peer_sec.peer_addr.val);
|
||||||
|
if (rc != 0) {
|
||||||
|
/* We can't do anything much here, continue with removing from peer_record */
|
||||||
|
BLE_HS_LOG(DEBUG, "Peer Device was not removed from RL \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ble_rpa_remove_peer_dev_rec(peer_rec);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,63 +238,6 @@ ble_store_util_delete_oldest_peer(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete CCCDs of unbonded devices.
|
|
||||||
*
|
|
||||||
* @param curr_peer Current peer's address (not to delete), ignore
|
|
||||||
* ignore if NULL
|
|
||||||
*
|
|
||||||
* @return 0 on success;
|
|
||||||
* nonzero on error.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
ble_store_clean_old_cccds(const ble_addr_t *curr_peer)
|
|
||||||
{
|
|
||||||
ble_addr_t peer_cccd_addrs[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
|
|
||||||
ble_addr_t peer_bonded_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
|
|
||||||
int num_bonded_peers, num_cccd_peers;
|
|
||||||
int i, j, rc;
|
|
||||||
|
|
||||||
rc = ble_store_util_subscribed_cccds(&peer_cccd_addrs[0], &num_cccd_peers,
|
|
||||||
MYNEWT_VAL(BLE_STORE_MAX_CCCDS),
|
|
||||||
(void *) curr_peer);
|
|
||||||
if (rc != 0) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ble_store_util_bonded_peers(&peer_bonded_addrs[0], &num_bonded_peers,
|
|
||||||
MYNEWT_VAL(BLE_STORE_MAX_BONDS));
|
|
||||||
if (rc != 0) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
union ble_store_key key = {0};
|
|
||||||
/* Init rc to BLE_HS_ENOENT to indicate no CCCD is deleted */
|
|
||||||
rc = BLE_HS_ENOENT;
|
|
||||||
|
|
||||||
for (i = 0; i < num_cccd_peers; i++) {
|
|
||||||
key.cccd.peer_addr = peer_cccd_addrs[i];
|
|
||||||
|
|
||||||
for (j = 0; j < num_bonded_peers; j++) {
|
|
||||||
if (memcmp(&peer_cccd_addrs[i], &peer_bonded_addrs[j],
|
|
||||||
sizeof(ble_addr_t)) == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j < num_bonded_peers) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_CCCD, &key);
|
|
||||||
if (rc != 0) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Round-robin status callback. If a there is insufficient storage capacity
|
* Round-robin status callback. If a there is insufficient storage capacity
|
||||||
* for a new record, delete the oldest bond and proceed with the persist
|
* for a new record, delete the oldest bond and proceed with the persist
|
||||||
|
@ -374,7 +250,6 @@ ble_store_clean_old_cccds(const ble_addr_t *curr_peer)
|
||||||
int
|
int
|
||||||
ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
|
ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
|
||||||
{
|
{
|
||||||
int rc = BLE_HS_EUNKNOWN;
|
|
||||||
switch (event->event_code) {
|
switch (event->event_code) {
|
||||||
case BLE_STORE_EVENT_OVERFLOW:
|
case BLE_STORE_EVENT_OVERFLOW:
|
||||||
switch (event->overflow.obj_type) {
|
switch (event->overflow.obj_type) {
|
||||||
|
@ -382,25 +257,11 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
|
||||||
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
||||||
return ble_gap_unpair_oldest_peer();
|
return ble_gap_unpair_oldest_peer();
|
||||||
case BLE_STORE_OBJ_TYPE_CCCD:
|
case BLE_STORE_OBJ_TYPE_CCCD:
|
||||||
/* Try to remove unbonded CCCDs first */
|
/* Try unpairing oldest peer except current peer */
|
||||||
if ((rc = ble_store_clean_old_cccds((void *) &event->overflow.value->cccd.peer_addr)) == BLE_HS_ENOENT) {
|
return ble_gap_unpair_oldest_except(&event->overflow.value->cccd.peer_addr);
|
||||||
/* No unbonded CCCDs found to delete, try unpairing oldest peer
|
|
||||||
* except current peer */
|
|
||||||
return ble_gap_unpair_oldest_except_curr((void *) &event->overflow.value->cccd.peer_addr);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return BLE_HS_EUNKNOWN;
|
return BLE_HS_EUNKNOWN;
|
||||||
|
|
||||||
/* case BLE_STORE_OBJ_TYPE_OUR_SEC:
|
|
||||||
case BLE_STORE_OBJ_TYPE_PEER_SEC:
|
|
||||||
case BLE_STORE_OBJ_TYPE_CCCD:
|
|
||||||
return ble_gap_unpair_oldest_peer();
|
|
||||||
|
|
||||||
default:
|
|
||||||
return BLE_HS_EUNKNOWN;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case BLE_STORE_EVENT_FULL:
|
case BLE_STORE_EVENT_FULL:
|
||||||
|
|
|
@ -210,11 +210,11 @@ get_nvs_db_attribute(int obj_type, bool empty, void *value, int num_value)
|
||||||
err = get_nvs_matching_index(&p_dev_rec, value, num_value,
|
err = get_nvs_matching_index(&p_dev_rec, value, num_value,
|
||||||
sizeof(struct ble_hs_dev_records));
|
sizeof(struct ble_hs_dev_records));
|
||||||
} else {
|
} else {
|
||||||
if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) {
|
if (obj_type != BLE_STORE_OBJ_TYPE_CCCD) {
|
||||||
err = get_nvs_matching_index(&cur.sec, value, num_value,
|
err = get_nvs_matching_index(&cur.sec, value, num_value,
|
||||||
sizeof(struct ble_store_value_sec));
|
sizeof(struct ble_store_value_sec));
|
||||||
} else {
|
} else {
|
||||||
err = get_nvs_matching_index(&cur.sec, value, num_value,
|
err = get_nvs_matching_index(&cur.cccd, value, num_value,
|
||||||
sizeof(struct ble_store_value_cccd));
|
sizeof(struct ble_store_value_cccd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Modifications copyright (C) 2020 Ryan Powell*/
|
|
||||||
|
|
||||||
#ifndef _NIMBLE_NPL_H_
|
#ifndef _NIMBLE_NPL_H_
|
||||||
#define _NIMBLE_NPL_H_
|
#define _NIMBLE_NPL_H_
|
||||||
|
|
||||||
|
@ -26,6 +24,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Modifications copyright (C) 2020 Ryan Powell */
|
|
||||||
#ifndef _NIMBLE_PORT_H
|
#ifndef _NIMBLE_PORT_H
|
||||||
#define _NIMBLE_PORT_H
|
#define _NIMBLE_PORT_H
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,100 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1
|
|
||||||
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
#include "sdkconfig.h"
|
||||||
#define CONFIG_BT_NIMBLE_MAX_BONDS 3
|
/** For ESP-IDF compatibility
|
||||||
#define CONFIG_BT_NIMBLE_MAX_CCCDS 8
|
*
|
||||||
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
* Some versions of ESP-IDF used the config name format "CONFIG_NIMBLE_".
|
||||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE_0 1
|
* This converts them to "CONFIG_BT_NIMBLE_" format used in the latest IDF.
|
||||||
|
*/
|
||||||
|
/* Detect if using ESP-IDF or Arduino (Arduino won't have these defines in sdkconfig)*/
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
||||||
|
|
||||||
|
#if defined(CONFIG_NIMBLE_ENABLED)
|
||||||
|
#define CONFIG_BT_NIMBLE_ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_NIMBLE_ROLE_OBSERVER)
|
||||||
|
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_NIMBLE_ROLE_CENTRAL)
|
||||||
|
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_NIMBLE_DEBUG)
|
||||||
|
#define CONFIG_BT_NIMBLE_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else // Using Arduino
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
* Arduino config options
|
||||||
|
**********************************************/
|
||||||
|
|
||||||
|
/** Comment out if not using NimBLE Client functions
|
||||||
|
* Reduces flash size by approx. 7kB.
|
||||||
|
*/
|
||||||
|
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL
|
||||||
|
|
||||||
|
/** Comment out if not using NimBLE Scan functions
|
||||||
|
* Reduces flash size by approx. 26kB.
|
||||||
|
*/
|
||||||
|
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||||
|
|
||||||
|
/** Comment out if not using NimBLE Server functions
|
||||||
|
* Reduces flash size by approx. 16kB.
|
||||||
|
*/
|
||||||
|
// #define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL // Tasmota
|
||||||
|
|
||||||
|
/** Comment out if not using NimBLE Advertising functions
|
||||||
|
* Reduces flash size by approx. 5kB.
|
||||||
|
*/
|
||||||
|
// #define CONFIG_BT_NIMBLE_ROLE_BROADCASTER // Tasmota
|
||||||
|
|
||||||
|
/** Uncomment to see debug log messages from the NimBLE host
|
||||||
|
* Uses approx. 32kB of flash memory.
|
||||||
|
*/
|
||||||
|
// #define CONFIG_BT_NIMBLE_DEBUG
|
||||||
|
|
||||||
|
/** Uncomment to see NimBLE host return codes as text debug log messages.
|
||||||
|
* Uses approx. 7kB of flash memory.
|
||||||
|
*/
|
||||||
|
// #define CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
|
||||||
|
|
||||||
|
/** Uncomment to see GAP event codes as text in debug log messages.
|
||||||
|
* Uses approx. 1kB of flash memory.
|
||||||
|
*/
|
||||||
|
// #define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
|
||||||
|
|
||||||
|
/** Uncomment to see advertisment types as text while scanning in debug log messages.
|
||||||
|
* Uses approx. 250 bytes of flash memory.
|
||||||
|
*/
|
||||||
|
// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
|
||||||
|
|
||||||
|
/** Sets the core NimBLE host runs on */
|
||||||
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
|
||||||
|
|
||||||
|
/** Sets the stack size for the NimBLE host task */
|
||||||
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
|
||||||
#define CONFIG_BT_NIMBLE_ROLE_CENTRAL 1
|
|
||||||
#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL 1
|
/** Sets the number of simultaneous connections (esp controller max is 9) */
|
||||||
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER 1
|
#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3
|
||||||
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER 1
|
|
||||||
#define CONFIG_BT_NIMBLE_NVS_PERSIST 1
|
/** Sets the number of devices allowed to store/bond with */
|
||||||
|
#define CONFIG_BT_NIMBLE_MAX_BONDS 3 // Tasmota
|
||||||
|
|
||||||
|
/** Sets the number of CCCD's to store per bonded device */
|
||||||
|
#define CONFIG_BT_NIMBLE_MAX_CCCDS 3 // Tasmota
|
||||||
|
|
||||||
|
#define CONFIG_BT_NIMBLE_NVS_PERSIST 0 // Tasmota
|
||||||
#define CONFIG_BT_NIMBLE_SM_LEGACY 1
|
#define CONFIG_BT_NIMBLE_SM_LEGACY 1
|
||||||
#define CONFIG_BT_NIMBLE_SM_SC 1
|
#define CONFIG_BT_NIMBLE_SM_SC 1
|
||||||
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble"
|
||||||
|
@ -29,6 +112,23 @@
|
||||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
|
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2
|
||||||
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT 1
|
#define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT 1
|
||||||
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900
|
||||||
#define CONFIG_BT_ENABLED 1
|
#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0
|
||||||
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY 1
|
|
||||||
#define CONFIG_BT_NIMBLE_DEBUG 0
|
/** Do not comment out */
|
||||||
|
#ifndef CONFIG_BT_ENABLED
|
||||||
|
#define CONFIG_BT_ENABLED
|
||||||
|
#endif
|
||||||
|
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
|
||||||
|
#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
|
||||||
|
|
||||||
|
#endif // #if defined(CONFIG_BT_NIMBLE_TASK_STACK_SIZE) || defined(CONFIG_NIMBLE_TASK_STACK_SIZE)
|
||||||
|
|
||||||
|
/** Cannot use client without scan */
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) && !defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
|
||||||
|
#define CONFIG_BT_NIMBLE_ROLE_OBSERVER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Cannot use server without advertise */
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) && !defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER
|
||||||
|
#endif
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Modifications copyright (C) 2020 Ryan Powell */
|
|
||||||
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
|
@ -32,6 +30,8 @@ IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
|
||||||
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
|
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
|
||||||
|
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
|
||||||
|
return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||||
#else
|
#else
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,6 +43,8 @@ IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
|
||||||
return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||||
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
|
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
|
||||||
|
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
|
||||||
|
return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||||
#else
|
#else
|
||||||
return calloc(n, size);
|
return calloc(n, size);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue