NimBLE v1.36 (#14744)

This commit is contained in:
Jason2866 2022-02-12 20:01:12 +01:00 committed by GitHub
parent 33a779f105
commit 5a70ca1562
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
434 changed files with 47577 additions and 7020 deletions

View File

@ -2,6 +2,17 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [1.3.6] - 2022-01-18
### Changed
- When retrieving attributes from a server fails with a 128bit UUID containing the ble base UUID another attempt will be made with the 16bit version of the UUID.
### Fixed
- Memory leak when services are changed on server devices.
- Rare crashing that occurs when BLE commands are sent from ISR context using IPC.
- Crashing caused by uninitialized disconnect timer in client.
- Potential crash due to unintialized advertising callback pointer.
## [1.3.5] - 2022-01-14 ## [1.3.5] - 2022-01-14
### Added ### Added

View File

@ -6,6 +6,24 @@ Sets the number of simultaneous connections (esp controller max is 9)
- Default value is 3 - Default value is 3
<br/> <br/>
`CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED`
Enable/disable storing the timestamp when an attribute value is updated
This allows for checking the last update time using getTimeStamp() or getValue(time_t*)
If disabled, the timestamp returned from these functions will be 0.
Disabling timestamps will reduce the memory used for each value.
1 = Enabled, 0 = Disabled; Default = Disabled
<br/>
`CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH`
Set the default allocation size (bytes) for each attribute.
If not specified when the constructor is called. This is also the size used when a remote
characteristic or descriptor is constructed before a value is read/notifed.
Increasing this will reduce reallocations but increase memory footprint.
Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
<br/>
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU` `CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
Sets the default MTU size. Sets the default MTU size.
@ -24,6 +42,13 @@ If defined, enables debug log messages from the NimBLE host
- Uses approx. 32kB of flash memory. - Uses approx. 32kB of flash memory.
<br/> <br/>
`CONFIG_NIMBLE_CPP_LOG_LEVEL`
Define to set the debug log message level from the NimBLE CPP Wrapper.
If not defined it will use the same value as the Arduino core debug level.
Values: 0 = NONE, 1 = ERROR, 2 = WARNING, 3 = INFO, 4+ = DEBUG
<br/>
`CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT` `CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT`
If defined, NimBLE host return codes will be printed as text in debug log messages. If defined, NimBLE host return codes will be printed as text in debug log messages.

View File

@ -69,7 +69,9 @@ Now takes 2 optional parameters, the first is the duration to advertise for (in
that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API). that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
This provides an opportunity to update the advertisment data if desired. This provides an opportunity to update the advertisment data if desired.
<br/>
Also now returns a bool value to indicate if advertising successfully started or not.
<br/>
<a name="client"></a> <a name="client"></a>
# Client # Client
@ -100,8 +102,18 @@ Has been **deprecated** as now the internally stored characteristic value is upd
`NimBLERemoteCharacteristic::subscribe` and `NimBLERemoteCharacteristic::unsubscribe` have been implemented to replace it. `NimBLERemoteCharacteristic::subscribe` and `NimBLERemoteCharacteristic::unsubscribe` have been implemented to replace it.
A callback is no longer requred to get the most recent value unless timing is important. Instead, the application can call `NimBLERemoteCharacteristic::getValue` to A callback is no longer requred to get the most recent value unless timing is important. Instead, the application can call `NimBLERemoteCharacteristic::getValue` to
get the last updated value any time. get the last updated value any time.
<br/>
In addition `NimBLERemoteCharacteristic::readValue` and `NimBLERemoteCharacteristic::getValue` take an optional timestamp parameter which will update it's value with The `notifiy_callback` function is now defined as a `std::function` to take advantage of using `std::bind` to specifiy a class member function for the callback.
Example:
```
using namespace std::placeholders;
notify_callback callback = std::bind(&<ClassName>::<memberFunctionCallbackName>, this, _1, _2, _3, _4);
<remoteCharacteristicInstance>->subscribe(true, callback);
```
`NimBLERemoteCharacteristic::readValue` and `NimBLERemoteCharacteristic::getValue` take an optional timestamp parameter which will update it's value with
the time the last value was recieved. the time the last value was recieved.
> NimBLEClient::getService > NimBLEClient::getService

View File

@ -127,7 +127,7 @@ class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
/** Handler class for descriptor actions */ /** Handler class for descriptor actions */
class DescriptorCallbacks : public NimBLEDescriptorCallbacks { class DescriptorCallbacks : public NimBLEDescriptorCallbacks {
void onWrite(NimBLEDescriptor* pDescriptor) { void onWrite(NimBLEDescriptor* pDescriptor) {
std::string dscVal((char*)pDescriptor->getValue(), pDescriptor->getLength()); std::string dscVal = pDescriptor->getValue();
Serial.print("Descriptor witten value:"); Serial.print("Descriptor witten value:");
Serial.println(dscVal.c_str()); Serial.println(dscVal.c_str());
}; };

View File

@ -2,7 +2,7 @@
"name": "NimBLE-Arduino", "name": "NimBLE-Arduino",
"keywords": "esp32, bluetooth", "keywords": "esp32, bluetooth",
"description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE", "description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE",
"version": "1.3.5", "version": "1.3.6",
"frameworks": "arduino", "frameworks": "arduino",
"platforms": "espressif32" "platforms": "espressif32"
} }

View File

@ -1,5 +1,5 @@
name=NimBLE-Arduino name=NimBLE-Arduino
version=1.3.5 version=1.3.6
author=h2zero author=h2zero
maintainer=h2zero <powellperalta@gmail.com> maintainer=h2zero <powellperalta@gmail.com>
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE. sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.

View File

@ -45,13 +45,8 @@
/* of data as per HID Class standard */ /* of data as per HID Class standard */
/* Main items */ /* Main items */
#ifdef ARDUINO_ARCH_ESP32 #define HIDINPUT(size) (0x80 | size)
#define HIDINPUT(size) (0x80 | size) #define HIDOUTPUT(size) (0x90 | size)
#define HIDOUTPUT(size) (0x90 | size)
#else
#define INPUT(size) (0x80 | size)
#define OUTPUT(size) (0x90 | size)
#endif
#define FEATURE(size) (0xb0 | size) #define FEATURE(size) (0xb0 | size)
#define COLLECTION(size) (0xa0 | size) #define COLLECTION(size) (0xa0 | size)
#define END_COLLECTION(size) (0xc0 | size) #define END_COLLECTION(size) (0xc0 | size)

View File

@ -16,11 +16,8 @@
* See also: * See also:
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLE2904.h" #include "NimBLE2904.h"
@ -86,5 +83,4 @@ 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 /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif

View File

@ -14,11 +14,8 @@
#ifndef MAIN_NIMBLE2904_H_ #ifndef MAIN_NIMBLE2904_H_
#define MAIN_NIMBLE2904_H_ #define MAIN_NIMBLE2904_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEDescriptor.h" #include "NimBLEDescriptor.h"
@ -82,6 +79,5 @@ private:
BLE2904_Data m_data; BLE2904_Data m_data;
}; // BLE2904 }; // BLE2904
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_NIMBLE2904_H_ */ #endif /* MAIN_NIMBLE2904_H_ */

View File

@ -11,7 +11,7 @@
* Created on: Jul 2, 2017 * Created on: Jul 2, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include <algorithm> #include <algorithm>

View File

@ -14,10 +14,15 @@
#ifndef COMPONENTS_NIMBLEADDRESS_H_ #ifndef COMPONENTS_NIMBLEADDRESS_H_
#define COMPONENTS_NIMBLEADDRESS_H_ #define COMPONENTS_NIMBLEADDRESS_H_
#include "sdkconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "nimble/ble.h" #include "nimble/ble.h"
#else
#include "nimble/nimble/include/nimble/ble.h"
#endif
/**** FIX COMPILATION ****/ /**** FIX COMPILATION ****/
#undef min #undef min
#undef max #undef max

View File

@ -11,11 +11,9 @@
* Created on: Jul 3, 2017 * Created on: Jul 3, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
#include "NimBLEAdvertisedDevice.h" #include "NimBLEAdvertisedDevice.h"
@ -783,7 +781,5 @@ size_t NimBLEAdvertisedDevice::getPayloadLength() {
return m_payload.size(); return m_payload.size();
} // getPayloadLength } // getPayloadLength
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */

View File

@ -14,20 +14,22 @@
#ifndef COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ #ifndef COMPONENTS_NIMBLEADVERTISEDDEVICE_H_
#define COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ #define COMPONENTS_NIMBLEADVERTISEDDEVICE_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEAddress.h" #include "NimBLEAddress.h"
#include "NimBLEScan.h" #include "NimBLEScan.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_hs_adv.h" #include "host/ble_hs_adv.h"
#else
#include "nimble/nimble/host/include/host/ble_hs_adv.h"
#endif
#include <map> #include <map>
#include <vector> #include <vector>
#include <time.h>
class NimBLEScan; class NimBLEScan;
@ -171,6 +173,5 @@ 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 && CONFIG_BT_NIMBLE_ROLE_OBSERVER */
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */ #endif /* COMPONENTS_NIMBLEADVERTISEDDEVICE_H_ */

View File

@ -13,13 +13,14 @@
* Author: kolban * Author: kolban
* *
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "services/gap/ble_svc_gap.h" #include "services/gap/ble_svc_gap.h"
#else
#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
#endif
#include "NimBLEAdvertising.h" #include "NimBLEAdvertising.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
#include "NimBLEServer.h" #include "NimBLEServer.h"
@ -68,6 +69,7 @@ void NimBLEAdvertising::reset() {
m_advDataSet = false; m_advDataSet = false;
// Set this to non-zero to prevent auto start if host reset before started by app. // Set this to non-zero to prevent auto start if host reset before started by app.
m_duration = BLE_HS_FOREVER; m_duration = BLE_HS_FOREVER;
m_advCompCB = nullptr;
} // reset } // reset
@ -653,12 +655,8 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
break; break;
} }
if(rc != 0) {
return false;
}
NIMBLE_LOGD(LOG_TAG, "<< Advertising start"); NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
return true; return (rc == 0);
} // start } // start
@ -1028,5 +1026,4 @@ std::string NimBLEAdvertisementData::getPayload() {
return m_payload; return m_payload;
} // getPayload } // getPayload
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
#endif /* CONFIG_BT_ENABLED */

View File

@ -14,13 +14,15 @@
#ifndef MAIN_BLEADVERTISING_H_ #ifndef MAIN_BLEADVERTISING_H_
#define MAIN_BLEADVERTISING_H_ #define MAIN_BLEADVERTISING_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_gap.h" #include "host/ble_gap.h"
#else
#include "nimble/nimble/host/include/host/ble_gap.h"
#endif
/**** FIX COMPILATION ****/ /**** FIX COMPILATION ****/
#undef min #undef min
#undef max #undef max
@ -132,6 +134,5 @@ private:
std::vector<uint8_t> m_uri; std::vector<uint8_t> m_uri;
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
#endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_BLEADVERTISING_H_ */ #endif /* MAIN_BLEADVERTISING_H_ */

View File

@ -0,0 +1,447 @@
/*
* NimBLEAttValue.h
*
* Created: on March 18, 2021
* Author H2zero
*
*/
#ifndef MAIN_NIMBLEATTVALUE_H_
#define MAIN_NIMBLEATTVALUE_H_
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
#include <Arduino.h>
#endif
#include "NimBLELog.h"
/**** FIX COMPILATION ****/
#undef min
#undef max
/**************************/
#include <string>
#include <vector>
#ifndef CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# define CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED 0
#endif
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
# include <time.h>
#endif
#if !defined(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH)
# define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
#elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH > BLE_ATT_ATTR_MAX_LEN
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be larger than 512 (BLE_ATT_ATTR_MAX_LEN)
#elif CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH < 1
# error CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH cannot be less than 1; Range = 1 : 512
#endif
/* Used to determine if the type passed to a template has a c_str() and length() method. */
template <typename T, typename = void, typename = void>
struct Has_c_str_len : std::false_type {};
template <typename T>
struct Has_c_str_len<T, decltype(void(std::declval<T &>().c_str())),
decltype(void(std::declval<T &>().length()))> : std::true_type {};
/**
* @brief A specialized container class to hold BLE attribute values.
* @details This class is designed to be more memory efficient than using\n
* standard container types for value storage, while being convertable to\n
* many different container classes.
*/
class NimBLEAttValue
{
uint8_t* m_attr_value = nullptr;
uint16_t m_attr_max_len = 0;
uint16_t m_attr_len = 0;
uint16_t m_capacity = 0;
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
time_t m_timestamp = 0;
#endif
void deepCopy(const NimBLEAttValue & source);
public:
/**
* @brief Default constructor.
* @param[in] init_len The initial size in bytes.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(uint16_t init_len = CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
/**
* @brief Construct with an initial value from a buffer.
* @param value A pointer to the initial value to set.
* @param[in] len The size in bytes of the value to set.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(const uint8_t *value, uint16_t len,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
/**
* @brief Construct with an initializer list.
* @param list An initializer list containing the initial value to set.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(std::initializer_list<uint8_t> list,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
:NimBLEAttValue(list.begin(), (uint16_t)list.size(), max_len){}
/**
* @brief Construct with an initial value from a const char string.
* @param value A pointer to the initial value to set.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(const char *value, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
:NimBLEAttValue((uint8_t*)value, (uint16_t)strlen(value), max_len){}
/**
* @brief Construct with an initial value from a std::string.
* @param str A std::string containing to the initial value to set.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(const std::string str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
:NimBLEAttValue((uint8_t*)str.data(), (uint16_t)str.length(), max_len){}
/**
* @brief Construct with an initial value from a std::vector<uint8_t>.
* @param vec A std::vector<uint8_t> containing to the initial value to set.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(const std::vector<uint8_t> vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
:NimBLEAttValue(&vec[0], (uint16_t)vec.size(), max_len){}
#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
/**
* @brief Construct with an initial value from an Arduino String.
* @param str An Arduino String containing to the initial value to set.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(const String str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
:NimBLEAttValue((uint8_t*)str.c_str(), str.length(), max_len){}
#endif
/** @brief Copy constructor */
NimBLEAttValue(const NimBLEAttValue & source) { deepCopy(source); }
/** @brief Move constructor */
NimBLEAttValue(NimBLEAttValue && source) { *this = std::move(source); }
/** @brief Destructor */
~NimBLEAttValue();
/** @brief Returns the max size in bytes */
uint16_t max_size() const { return m_attr_max_len; }
/** @brief Returns the currently allocated capacity in bytes */
uint16_t capacity() const { return m_capacity; }
/** @brief Returns the current length of the value in bytes */
uint16_t length() const { return m_attr_len; }
/** @brief Returns the current size of the value in bytes */
uint16_t size() const { return m_attr_len; }
/** @brief Returns a pointer to the internal buffer of the value */
const uint8_t* data() const { return m_attr_value; }
/** @brief Returns a pointer to the internal buffer of the value as a const char* */
const char* c_str() const { return (const char*)m_attr_value; }
/** @brief Iterator begin */
const uint8_t* begin() const { return m_attr_value; }
/** @brief Iterator end */
const uint8_t* end() const { return m_attr_value + m_attr_len; }
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
/** @brief Returns a timestamp of when the value was last updated */
time_t getTimeStamp() const { return m_timestamp; }
/** @brief Set the timestamp to the current time */
void setTimeStamp() { m_timestamp = time(nullptr); }
/**
* @brief Set the timestamp to the specified time
* @param[in] t The timestamp value to set
*/
void setTimeStamp(time_t t) { m_timestamp = t; }
#else
time_t getTimeStamp() const { return 0; }
void setTimeStamp() { }
void setTimeStamp(time_t t) { }
#endif
/**
* @brief Set the value from a buffer
* @param[in] value A ponter to a buffer containing the value.
* @param[in] len The length of the value in bytes.
* @returns True if successful.
*/
bool setValue(const uint8_t *value, uint16_t len);
/**
* @brief Set value to the value of const char*.
* @param [in] s A ponter to a const char value to set.
*/
bool setValue(const char* s) {
return setValue((uint8_t*)s, (uint16_t)strlen(s)); }
/**
* @brief Get a pointer to the value buffer with timestamp.
* @param[in] timestamp A ponter to a time_t variable to store the timestamp.
* @returns A pointer to the internal value buffer.
*/
const uint8_t* getValue(time_t *timestamp);
/**
* @brief Append data to the value.
* @param[in] value A ponter to a data buffer with the value to append.
* @param[in] len The length of the value to append in bytes.
* @returns A reference to the appended NimBLEAttValue.
*/
NimBLEAttValue& append(const uint8_t *value, uint16_t len);
/*********************** Template Functions ************************/
/**
* @brief Template to set value to the value of <type\>val.
* @param [in] s The <type\>value to set.
* @details Only used for types without a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
bool
#else
typename std::enable_if<!Has_c_str_len<T>::value, bool>::type
#endif
setValue(const T &s) {
return setValue((uint8_t*)&s, sizeof(T));
}
/**
* @brief Template to set value to the value of <type\>val.
* @param [in] s The <type\>value to set.
* @details Only used if the <type\> has a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
bool
#else
typename std::enable_if<Has_c_str_len<T>::value, bool>::type
#endif
setValue(const T & s) {
return setValue((uint8_t*)s.c_str(), (uint16_t)s.length());
}
/**
* @brief Template to return the value as a <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than\n
* <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is\n
* less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
if(!skipSizeCheck && size() < sizeof(T)) {
return T();
}
return *((T *)getValue(timestamp));
}
/*********************** Operators ************************/
/** @brief Subscript operator */
uint8_t operator [](int pos) const {
assert(pos < m_attr_len && "out of range"); return m_attr_value[pos]; }
/** @brief Operator; Get the value as a std::vector<uint8_t>. */
operator std::vector<uint8_t>() const {
return std::vector<uint8_t>(m_attr_value, m_attr_value + m_attr_len); }
/** @brief Operator; Get the value as a std::string. */
operator std::string() const {
return std::string((char*)m_attr_value, m_attr_len); }
/** @brief Operator; Get the value as a const uint8_t*. */
operator const uint8_t*() const { return m_attr_value; }
/** @brief Operator; Append another NimBLEAttValue. */
NimBLEAttValue& operator +=(const NimBLEAttValue & source) {
return append(source.data(), source.size()); }
/** @brief Operator; Set the value from a std::string source. */
NimBLEAttValue& operator =(const std::string & source) {
setValue((uint8_t*)source.data(), (uint16_t)source.size()); return *this; }
/** @brief Move assignment operator */
NimBLEAttValue& operator =(NimBLEAttValue && source);
/** @brief Copy assignment operator */
NimBLEAttValue& operator =(const NimBLEAttValue & source);
/** @brief Equality operator */
bool operator ==(const NimBLEAttValue & source) {
return (m_attr_len == source.size()) ?
memcmp(m_attr_value, source.data(), m_attr_len) == 0 : false; }
/** @brief Inequality operator */
bool operator !=(const NimBLEAttValue & source){ return !(*this == source); }
#ifdef NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
/** @brief Operator; Get the value as an Arduino String value. */
operator String() const { return String((char*)m_attr_value); }
#endif
};
inline NimBLEAttValue::NimBLEAttValue(uint16_t init_len, uint16_t max_len) {
m_attr_value = (uint8_t*)calloc(init_len + 1, 1);
assert(m_attr_value && "No Mem");
m_attr_max_len = std::min(BLE_ATT_ATTR_MAX_LEN, (int)max_len);
m_attr_len = 0;
m_capacity = init_len;
setTimeStamp(0);
}
inline NimBLEAttValue::NimBLEAttValue(const uint8_t *value, uint16_t len, uint16_t max_len)
: NimBLEAttValue(len, max_len) {
memcpy(m_attr_value, value, len);
m_attr_value[len] = '\0';
m_attr_len = len;
}
inline NimBLEAttValue::~NimBLEAttValue() {
if(m_attr_value != nullptr) {
free(m_attr_value);
}
}
inline NimBLEAttValue& NimBLEAttValue::operator =(NimBLEAttValue && source) {
if (this != &source){
free(m_attr_value);
m_attr_value = source.m_attr_value;
m_attr_max_len = source.m_attr_max_len;
m_attr_len = source.m_attr_len;
m_capacity = source.m_capacity;
setTimeStamp(source.getTimeStamp());
source.m_attr_value = nullptr;
}
return *this;
}
inline NimBLEAttValue& NimBLEAttValue::operator =(const NimBLEAttValue & source) {
if (this != &source) {
deepCopy(source);
}
return *this;
}
inline void NimBLEAttValue::deepCopy(const NimBLEAttValue & source) {
uint8_t* res = (uint8_t*)realloc( m_attr_value, source.m_capacity + 1);
assert(res && "deepCopy: realloc failed");
ble_npl_hw_enter_critical();
m_attr_value = res;
m_attr_max_len = source.m_attr_max_len;
m_attr_len = source.m_attr_len;
m_capacity = source.m_capacity;
setTimeStamp(source.getTimeStamp());
memcpy(m_attr_value, source.m_attr_value, m_attr_len + 1);
ble_npl_hw_exit_critical(0);
}
inline const uint8_t* NimBLEAttValue::getValue(time_t *timestamp) {
if(timestamp != nullptr) {
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
*timestamp = m_timestamp;
#else
*timestamp = 0;
#endif
}
return m_attr_value;
}
inline bool NimBLEAttValue::setValue(const uint8_t *value, uint16_t len) {
if (len > m_attr_max_len) {
NIMBLE_LOGE("NimBLEAttValue", "value exceeds max, len=%u, max=%u",
len, m_attr_max_len);
return false;
}
uint8_t *res = m_attr_value;
if (len > m_capacity) {
res = (uint8_t*)realloc(m_attr_value, (len + 1));
m_capacity = len;
}
assert(res && "setValue: realloc failed");
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
time_t t = time(nullptr);
#else
time_t t = 0;
#endif
ble_npl_hw_enter_critical();
m_attr_value = res;
memcpy(m_attr_value, value, len);
m_attr_value[len] = '\0';
m_attr_len = len;
setTimeStamp(t);
ble_npl_hw_exit_critical(0);
return true;
}
inline NimBLEAttValue& NimBLEAttValue::append(const uint8_t *value, uint16_t len) {
if (len < 1) {
return *this;
}
if ((m_attr_len + len) > m_attr_max_len) {
NIMBLE_LOGE("NimBLEAttValue", "val > max, len=%u, max=%u",
len, m_attr_max_len);
return *this;
}
uint8_t* res = m_attr_value;
uint16_t new_len = m_attr_len + len;
if (new_len > m_capacity) {
res = (uint8_t*)realloc(m_attr_value, (new_len + 1));
m_capacity = new_len;
}
assert(res && "append: realloc failed");
#if CONFIG_NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED
time_t t = time(nullptr);
#else
time_t t = 0;
#endif
ble_npl_hw_enter_critical();
m_attr_value = res;
memcpy(m_attr_value + m_attr_len, value, len);
m_attr_len = new_len;
m_attr_value[m_attr_len] = '\0';
setTimeStamp(t);
ble_npl_hw_exit_critical(0);
return *this;
}
#endif /*(CONFIG_BT_ENABLED) */
#endif /* MAIN_NIMBLEATTVALUE_H_ */

View File

@ -11,7 +11,7 @@
* Created on: Jan 4, 2018 * Created on: Jan 4, 2018
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include <string.h> #include <string.h>

View File

@ -9,11 +9,9 @@
* Created on: Jun 22, 2017 * Created on: Jun 22, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLECharacteristic.h" #include "NimBLECharacteristic.h"
#include "NimBLE2904.h" #include "NimBLE2904.h"
@ -32,27 +30,29 @@ static const char* LOG_TAG = "NimBLECharacteristic";
* @brief Construct a characteristic * @brief Construct a characteristic
* @param [in] uuid - UUID (const char*) for the characteristic. * @param [in] uuid - UUID (const char*) for the characteristic.
* @param [in] properties - Properties for the characteristic. * @param [in] properties - Properties for the characteristic.
* @param [in] max_len - The maximum length in bytes that the characteristic value can hold. (Default: 512 bytes for esp32, 20 for all others).
* @param [in] pService - pointer to the service instance this characteristic belongs to. * @param [in] pService - pointer to the service instance this characteristic belongs to.
*/ */
NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties, NimBLEService* pService) NimBLECharacteristic::NimBLECharacteristic(const char* uuid, uint16_t properties,
: NimBLECharacteristic(NimBLEUUID(uuid), properties, pService) { uint16_t max_len, NimBLEService* pService)
: NimBLECharacteristic(NimBLEUUID(uuid), properties, max_len, pService) {
} }
/** /**
* @brief Construct a characteristic * @brief Construct a characteristic
* @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.
* @param [in] max_len - The maximum length in bytes that the characteristic value can hold. (Default: 512 bytes for esp32, 20 for all others).
* @param [in] pService - pointer to the service instance this characteristic belongs to. * @param [in] pService - pointer to the service instance this characteristic belongs to.
*/ */
NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties, NimBLEService* pService) { NimBLECharacteristic::NimBLECharacteristic(const NimBLEUUID &uuid, uint16_t properties,
uint16_t max_len, NimBLEService* pService)
: m_value(std::min(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH , (int)max_len), max_len) {
m_uuid = uuid; m_uuid = uuid;
m_handle = NULL_HANDLE; m_handle = NULL_HANDLE;
m_properties = properties; m_properties = properties;
m_pCallbacks = &defaultCallback; m_pCallbacks = &defaultCallback;
m_pService = pService; m_pService = pService;
m_value = "";
m_valMux = portMUX_INITIALIZER_UNLOCKED;
m_timestamp = 0;
m_removed = 0; m_removed = 0;
} // NimBLECharacteristic } // NimBLECharacteristic
@ -234,17 +234,14 @@ NimBLEUUID NimBLECharacteristic::getUUID() {
/** /**
* @brief Retrieve the current value of the characteristic. * @brief Retrieve the current value of the characteristic.
* @return A std::string containing the current characteristic value. * @return The NimBLEAttValue containing the current characteristic value.
*/ */
std::string NimBLECharacteristic::getValue(time_t *timestamp) { NimBLEAttValue NimBLECharacteristic::getValue(time_t *timestamp) {
portENTER_CRITICAL(&m_valMux);
std::string retVal = m_value;
if(timestamp != nullptr) { if(timestamp != nullptr) {
*timestamp = m_timestamp; m_value.getValue(timestamp);
} }
portEXIT_CRITICAL(&m_valMux);
return retVal; return m_value;
} // getValue } // getValue
@ -253,11 +250,7 @@ std::string NimBLECharacteristic::getValue(time_t *timestamp) {
* @return The length of the current characteristic data. * @return The length of the current characteristic data.
*/ */
size_t NimBLECharacteristic::getDataLength() { size_t NimBLECharacteristic::getDataLength() {
portENTER_CRITICAL(&m_valMux); return m_value.size();
size_t len = m_value.length();
portEXIT_CRITICAL(&m_valMux);
return len;
} }
@ -289,27 +282,27 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
pCharacteristic->m_pCallbacks->onRead(pCharacteristic, &desc); pCharacteristic->m_pCallbacks->onRead(pCharacteristic, &desc);
} }
portENTER_CRITICAL(&pCharacteristic->m_valMux); ble_npl_hw_enter_critical();
rc = os_mbuf_append(ctxt->om, (uint8_t*)pCharacteristic->m_value.data(), rc = os_mbuf_append(ctxt->om, pCharacteristic->m_value.data(), pCharacteristic->m_value.size());
pCharacteristic->m_value.length()); ble_npl_hw_exit_critical(0);
portEXIT_CRITICAL(&pCharacteristic->m_valMux);
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
} }
case BLE_GATT_ACCESS_OP_WRITE_CHR: { case BLE_GATT_ACCESS_OP_WRITE_CHR: {
if (ctxt->om->om_len > BLE_ATT_ATTR_MAX_LEN) { uint16_t att_max_len = pCharacteristic->m_value.max_size();
if (ctxt->om->om_len > att_max_len) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} }
uint8_t buf[BLE_ATT_ATTR_MAX_LEN]; uint8_t buf[att_max_len];
size_t len = ctxt->om->om_len; size_t len = ctxt->om->om_len;
memcpy(buf, ctxt->om->om_data,len); memcpy(buf, ctxt->om->om_data,len);
os_mbuf *next; os_mbuf *next;
next = SLIST_NEXT(ctxt->om, om_next); next = SLIST_NEXT(ctxt->om, om_next);
while(next != NULL){ while(next != NULL){
if((len + next->om_len) > BLE_ATT_ATTR_MAX_LEN) { if((len + next->om_len) > att_max_len) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} }
memcpy(&buf[len], next->om_data, next->om_len); memcpy(&buf[len], next->om_data, next->om_len);
@ -389,26 +382,60 @@ void NimBLECharacteristic::setSubscribe(struct ble_gap_event *event) {
/** /**
* @brief Send an indication.\n * @brief Send an indication.
* An indication is a transmission of up to the first 20 bytes of the characteristic value.\n
* An indication will block waiting for a positive confirmation from the client.
*/ */
void NimBLECharacteristic::indicate() { void NimBLECharacteristic::indicate() {
NIMBLE_LOGD(LOG_TAG, ">> indicate: length: %d", getDataLength());
notify(false); notify(false);
NIMBLE_LOGD(LOG_TAG, "<< indicate");
} // indicate } // indicate
/** /**
* @brief Send a notification.\n * @brief Send an indication.
* A notification is a transmission of up to the first 20 bytes of the characteristic value.\n * @param[in] value A pointer to the data to send.
* A notification will not block; it is a fire and forget. * @param[in] length The length of the data to send.
*/
void NimBLECharacteristic::indicate(const uint8_t* value, size_t length) {
notify(value, length, false);
} // indicate
/**
* @brief Send an indication.
* @param[in] value A std::vector<uint8_t> containing the value to send as the notification value.
*/
void NimBLECharacteristic::indicate(const std::vector<uint8_t>& value) {
notify(value.data(), value.size(), false);
} // indicate
/**
* @brief Send a notification or indication.
* @param[in] is_notification if true sends a notification, false sends an indication. * @param[in] is_notification if true sends a notification, false sends an indication.
*/ */
void NimBLECharacteristic::notify(bool is_notification) { void NimBLECharacteristic::notify(bool is_notification) {
NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", getDataLength()); notify(m_value.data(), m_value.length(), is_notification);
} // notify
/**
* @brief Send a notification or indication.
* @param[in] value A std::vector<uint8_t> containing the value to send as the notification value.
* @param[in] is_notification if true sends a notification, false sends an indication.
*/
void NimBLECharacteristic::notify(const std::vector<uint8_t>& value, bool is_notification) {
notify(value.data(), value.size(), is_notification);
} // notify
/**
* @brief Send a notification or indication.
* @param[in] value A pointer to the data to send.
* @param[in] length The length of the data to send.
* @param[in] is_notification if true sends a notification, false sends an indication.
*/
void NimBLECharacteristic::notify(const uint8_t* value, size_t length, bool is_notification) {
NIMBLE_LOGD(LOG_TAG, ">> notify: length: %d", length);
if(!(m_properties & NIMBLE_PROPERTY::NOTIFY) && if(!(m_properties & NIMBLE_PROPERTY::NOTIFY) &&
!(m_properties & NIMBLE_PROPERTY::INDICATE)) !(m_properties & NIMBLE_PROPERTY::INDICATE))
{ {
@ -424,15 +451,13 @@ void NimBLECharacteristic::notify(bool is_notification) {
m_pCallbacks->onNotify(this); m_pCallbacks->onNotify(this);
std::string value = getValue();
size_t length = value.length();
bool reqSec = (m_properties & BLE_GATT_CHR_F_READ_AUTHEN) || bool reqSec = (m_properties & BLE_GATT_CHR_F_READ_AUTHEN) ||
(m_properties & BLE_GATT_CHR_F_READ_AUTHOR) || (m_properties & BLE_GATT_CHR_F_READ_AUTHOR) ||
(m_properties & BLE_GATT_CHR_F_READ_ENC); (m_properties & BLE_GATT_CHR_F_READ_ENC);
int rc = 0; int rc = 0;
for (auto &it : m_subscribedVec) { for (auto &it : m_subscribedVec) {
uint16_t _mtu = getService()->getServer()->getPeerMTU(it.first); uint16_t _mtu = getService()->getServer()->getPeerMTU(it.first) - 3;
// check if connected and subscribed // check if connected and subscribed
if(_mtu == 0 || it.second == 0) { if(_mtu == 0 || it.second == 0) {
@ -448,8 +473,8 @@ void NimBLECharacteristic::notify(bool is_notification) {
} }
} }
if (length > _mtu - 3) { if (length > _mtu) {
NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu - 3); NIMBLE_LOGW(LOG_TAG, "- Truncating to %d bytes (maximum notify size)", _mtu);
} }
if(is_notification && (!(it.second & NIMBLE_SUB_NOTIFY))) { if(is_notification && (!(it.second & NIMBLE_SUB_NOTIFY))) {
@ -467,7 +492,7 @@ void NimBLECharacteristic::notify(bool is_notification) {
// don't create the m_buf until we are sure to send the data or else // don't create the m_buf until we are sure to send the data or else
// we could be allocating a buffer that doesn't get released. // we could be allocating a buffer that doesn't get released.
// We also must create it in each loop iteration because it is consumed with each host call. // We also must create it in each loop iteration because it is consumed with each host call.
os_mbuf *om = ble_hs_mbuf_from_flat((uint8_t*)value.data(), length); os_mbuf *om = ble_hs_mbuf_from_flat(value, length);
if(!is_notification && (m_properties & NIMBLE_PROPERTY::INDICATE)) { if(!is_notification && (m_properties & NIMBLE_PROPERTY::INDICATE)) {
if(!NimBLEDevice::getServer()->setIndicateWait(it.first)) { if(!NimBLEDevice::getServer()->setIndicateWait(it.first)) {
@ -511,40 +536,30 @@ NimBLECharacteristicCallbacks* NimBLECharacteristic::getCallbacks() {
/** /**
* @brief Set the value of the characteristic. * @brief Set the value of the characteristic from a data buffer .
* @param [in] data The data to set for the characteristic. * @param [in] data The data buffer to set for the characteristic.
* @param [in] length The length of the data in bytes. * @param [in] length The number of bytes in the data buffer.
*/ */
void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) { void NimBLECharacteristic::setValue(const uint8_t* data, size_t length) {
#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 4 #if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
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);
#endif #endif
if (length > BLE_ATT_ATTR_MAX_LEN) { m_value.setValue(data, length);
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, BLE_ATT_ATTR_MAX_LEN);
return;
}
time_t t = time(nullptr);
portENTER_CRITICAL(&m_valMux);
m_value = std::string((char*)data, length);
m_timestamp = t;
portEXIT_CRITICAL(&m_valMux);
NIMBLE_LOGD(LOG_TAG, "<< setValue"); NIMBLE_LOGD(LOG_TAG, "<< setValue");
} // setValue } // setValue
/** /**
* @brief Set the value of the characteristic from string data.\n * @brief Set the value of the characteristic from a `std::vector<uint8_t>`.\n
* We set the value of the characteristic from the bytes contained in the string. * @param [in] vec The std::vector<uint8_t> reference to set the characteristic value from.
* @param [in] value the std::string value of the characteristic.
*/ */
void NimBLECharacteristic::setValue(const std::string &value) { void NimBLECharacteristic::setValue(const std::vector<uint8_t>& vec) {
setValue((uint8_t*)(value.data()), value.length()); return setValue((uint8_t*)&vec[0], vec.size());
} // setValue }// setValue
/** /**
@ -641,6 +656,4 @@ void NimBLECharacteristicCallbacks::onSubscribe(NimBLECharacteristic* pCharacter
NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default"); NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onSubscribe: default");
} }
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */

View File

@ -13,13 +13,15 @@
#ifndef MAIN_NIMBLECHARACTERISTIC_H_ #ifndef MAIN_NIMBLECHARACTERISTIC_H_
#define MAIN_NIMBLECHARACTERISTIC_H_ #define MAIN_NIMBLECHARACTERISTIC_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_hs.h" #include "host/ble_hs.h"
#else
#include "nimble/nimble/host/include/host/ble_hs.h"
#endif
/**** FIX COMPILATION ****/ /**** FIX COMPILATION ****/
#undef min #undef min
#undef max #undef max
@ -42,6 +44,7 @@ typedef enum {
#include "NimBLEService.h" #include "NimBLEService.h"
#include "NimBLEDescriptor.h" #include "NimBLEDescriptor.h"
#include "NimBLEAttValue.h"
#include <string> #include <string>
#include <vector> #include <vector>
@ -63,11 +66,13 @@ public:
uint16_t properties = uint16_t properties =
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE, NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN,
NimBLEService* pService = nullptr); NimBLEService* pService = nullptr);
NimBLECharacteristic(const NimBLEUUID &uuid, NimBLECharacteristic(const NimBLEUUID &uuid,
uint16_t properties = uint16_t properties =
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE, NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN,
NimBLEService* pService = nullptr); NimBLEService* pService = nullptr);
~NimBLECharacteristic(); ~NimBLECharacteristic();
@ -75,64 +80,93 @@ public:
uint16_t getHandle(); uint16_t getHandle();
NimBLEUUID getUUID(); NimBLEUUID getUUID();
std::string toString(); std::string toString();
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
NimBLECharacteristicCallbacks*
getCallbacks();
void indicate(); void indicate();
void indicate(const uint8_t* value, size_t length);
void indicate(const std::vector<uint8_t>& value);
void notify(bool is_notification = true); void notify(bool is_notification = true);
void notify(const uint8_t* value, size_t length, bool is_notification = true);
void notify(const std::vector<uint8_t>& value, bool is_notification = true);
size_t getSubscribedCount(); size_t getSubscribedCount();
NimBLEDescriptor* createDescriptor(const char* uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = 100);
NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = 100);
void addDescriptor(NimBLEDescriptor *pDescriptor); void addDescriptor(NimBLEDescriptor *pDescriptor);
NimBLEDescriptor* getDescriptorByUUID(const char* uuid); NimBLEDescriptor* getDescriptorByUUID(const char* uuid);
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid); NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID &uuid);
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle); NimBLEDescriptor* getDescriptorByHandle(uint16_t handle);
void removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc = false); void removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc = false);
NimBLEService* getService();
std::string getValue(time_t *timestamp = nullptr); uint16_t getProperties();
NimBLEAttValue getValue(time_t *timestamp = nullptr);
size_t getDataLength(); size_t getDataLength();
/**
* @brief A template to convert the characteristic data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
* less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
std::string value = getValue();
if(!skipSizeCheck && value.size() < sizeof(T)) return T();
const char *pData = value.data();
return *((T *)pData);
}
void setValue(const uint8_t* data, size_t size); void setValue(const uint8_t* data, size_t size);
void setValue(const std::string &value); void setValue(const std::vector<uint8_t>& vec);
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
NimBLEDescriptor* createDescriptor(const char* uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);;
NimBLEDescriptor* createDescriptor(const NimBLEUUID &uuid,
uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
NimBLECharacteristicCallbacks* getCallbacks();
/*********************** Template Functions ************************/
/** /**
* @brief Convenience template to set the characteristic value to <type\>val. * @brief Template to set the characteristic value to <type\>val.
* @param [in] s The value to set. * @param [in] s The value to set.
*/ */
template<typename T> template<typename T>
void setValue(const T &s) { void setValue(const T &s) { m_value.setValue<T>(s); }
setValue((uint8_t*)&s, sizeof(T));
/**
* @brief Template to convert the characteristic data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp (Optional) A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck (Optional) If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
return m_value.getValue<T>(timestamp, skipSizeCheck);
} }
NimBLEService* getService(); /**
uint16_t getProperties(); * @brief Template to send a notification from a class type that has a c_str() and length() method.
* @tparam T The a reference to a class containing the data to send.
* @param[in] value The <type\>value to set.
* @param[in] is_notification if true sends a notification, false sends an indication.
* @details Only used if the <type\> has a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
void
#else
typename std::enable_if<Has_c_str_len<T>::value, void>::type
#endif
notify(const T& value, bool is_notification = true) {
notify((uint8_t*)value.c_str(), value.length(), is_notification);
}
/**
* @brief Template to send an indication from a class type that has a c_str() and length() method.
* @tparam T The a reference to a class containing the data to send.
* @param[in] value The <type\>value to set.
* @details Only used if the <type\> has a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
void
#else
typename std::enable_if<Has_c_str_len<T>::value, void>::type
#endif
indicate(const T& value) {
indicate((uint8_t*)value.c_str(), value.length());
}
private: private:
@ -149,10 +183,8 @@ private:
uint16_t m_properties; uint16_t m_properties;
NimBLECharacteristicCallbacks* m_pCallbacks; NimBLECharacteristicCallbacks* m_pCallbacks;
NimBLEService* m_pService; NimBLEService* m_pService;
std::string m_value; NimBLEAttValue m_value;
std::vector<NimBLEDescriptor*> m_dscVec; std::vector<NimBLEDescriptor*> m_dscVec;
portMUX_TYPE m_valMux;
time_t m_timestamp;
uint8_t m_removed; uint8_t m_removed;
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec; std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec;
@ -185,7 +217,7 @@ public:
ERROR_INDICATE_FAILURE ERROR_INDICATE_FAILURE
}Status; }Status;
virtual ~NimBLECharacteristicCallbacks(); virtual ~NimBLECharacteristicCallbacks();
virtual void onRead(NimBLECharacteristic* pCharacteristic); virtual void onRead(NimBLECharacteristic* pCharacteristic);
virtual void onRead(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc); virtual void onRead(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc);
virtual void onWrite(NimBLECharacteristic* pCharacteristic); virtual void onWrite(NimBLECharacteristic* pCharacteristic);
@ -195,6 +227,5 @@ public:
virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue); virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue);
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* CONFIG_BT_ENABLED */
#endif /*MAIN_NIMBLECHARACTERISTIC_H_*/ #endif /*MAIN_NIMBLECHARACTERISTIC_H_*/

View File

@ -11,11 +11,8 @@
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLEClient.h" #include "NimBLEClient.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
@ -23,9 +20,13 @@
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
#include <climits>
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "nimble/nimble_port.h" #include "nimble/nimble_port.h"
#else
#include "nimble/porting/nimble/include/nimble/nimble_port.h"
#endif
static const char* LOG_TAG = "NimBLEClient"; static const char* LOG_TAG = "NimBLEClient";
static NimBLEClientCallbacks defaultCallbacks; static NimBLEClientCallbacks defaultCallbacks;
@ -74,6 +75,7 @@ NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(pee
m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units
m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units
memset(&m_dcTimer, 0, sizeof(m_dcTimer));
ble_npl_callout_init(&m_dcTimer, nimble_port_get_dflt_eventq(), ble_npl_callout_init(&m_dcTimer, nimble_port_get_dflt_eventq(),
NimBLEClient::dcTimerCb, this); NimBLEClient::dcTimerCb, this);
} // NimBLEClient } // NimBLEClient
@ -453,6 +455,29 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
} // updateConnParams } // updateConnParams
/**
* @brief Request an update of the data packet length.
* * Can only be used after a connection has been established.
* @details Sends a data length update request to the server the client is connected to.
* The Data Length Extension (DLE) allows to increase the Data Channel Payload from 27 bytes to up to 251 bytes.
* The server needs to support the Bluetooth 4.2 specifications, to be capable of DLE.
* @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
*/
void NimBLEClient::setDataLen(uint16_t tx_octets) {
#if defined(CONFIG_NIMBLE_CPP_IDF) && defined(ESP_IDF_VERSION) && \
ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 && ESP_IDF_VERSION_PATCH >= 2
return;
#else
uint16_t tx_time = (tx_octets + 14) * 8;
int rc = ble_gap_set_data_len(m_conn_id, tx_octets, tx_time);
if(rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Set data length error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
}
#endif
} // setDataLen
/** /**
* @brief Get detailed information about the current peer connection. * @brief Get detailed information about the current peer connection.
*/ */
@ -586,7 +611,7 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
return m_servicesVector.back(); return m_servicesVector.back();
} }
// If the request was successful but 16/32 bit service not found // If the request was successful but 16/32 bit uuid not found
// try again with the 128 bit uuid. // try again with the 128 bit uuid.
if(uuid.bitSize() == BLE_UUID_TYPE_16 || if(uuid.bitSize() == BLE_UUID_TYPE_16 ||
uuid.bitSize() == BLE_UUID_TYPE_32) uuid.bitSize() == BLE_UUID_TYPE_32)
@ -594,6 +619,15 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
NimBLEUUID uuid128(uuid); NimBLEUUID uuid128(uuid);
uuid128.to128(); uuid128.to128();
return getService(uuid128); return getService(uuid128);
} else {
// If the request was successful but the 128 bit uuid not found
// try again with the 16 bit uuid.
NimBLEUUID uuid16(uuid);
uuid16.to16();
// if the uuid was 128 bit but not of the BLE base type this check will fail
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
return getService(uuid16);
}
} }
} }
@ -743,11 +777,11 @@ 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(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID) { NimBLEAttValue NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID) {
NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s", NIMBLE_LOGD(LOG_TAG, ">> getValue: serviceUUID: %s, characteristicUUID: %s",
serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
std::string ret = ""; NimBLEAttValue ret;
NimBLERemoteService* pService = getService(serviceUUID); NimBLERemoteService* pService = getService(serviceUUID);
if(pService != nullptr) { if(pService != nullptr) {
@ -771,7 +805,7 @@ std::string NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBLEUU
* @returns true if successful otherwise false * @returns true if successful otherwise false
*/ */
bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID, bool NimBLEClient::setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID,
const std::string &value, bool response) const NimBLEAttValue &value, bool response)
{ {
NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s", NIMBLE_LOGD(LOG_TAG, ">> setValue: serviceUUID: %s, characteristicUUID: %s",
serviceUUID.toString().c_str(), characteristicUUID.toString().c_str()); serviceUUID.toString().c_str(), characteristicUUID.toString().c_str());
@ -832,7 +866,7 @@ uint16_t NimBLEClient::getMTU() {
* @param [in] arg A pointer to the client instance that registered for this callback. * @param [in] arg A pointer to the client instance that registered for this callback.
*/ */
/*STATIC*/ /*STATIC*/
int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) { int NimBLEClient::handleGapEvent(struct ble_gap_event *event, void *arg) {
NimBLEClient* client = (NimBLEClient*)arg; NimBLEClient* client = (NimBLEClient*)arg;
int rc; int rc;
@ -950,19 +984,14 @@ uint16_t NimBLEClient::getMTU() {
NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s",
(*characteristic)->toString().c_str()); (*characteristic)->toString().c_str());
time_t t = time(nullptr); uint32_t data_len = OS_MBUF_PKTLEN(event->notify_rx.om);
portENTER_CRITICAL(&(*characteristic)->m_valMux); (*characteristic)->m_value.setValue(event->notify_rx.om->om_data, data_len);
(*characteristic)->m_value = std::string((char *)event->notify_rx.om->om_data,
event->notify_rx.om->om_len);
(*characteristic)->m_timestamp = t;
portEXIT_CRITICAL(&(*characteristic)->m_valMux);
if ((*characteristic)->m_notifyCallback != nullptr) { if ((*characteristic)->m_notifyCallback != nullptr) {
NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s",
(*characteristic)->toString().c_str()); (*characteristic)->toString().c_str());
(*characteristic)->m_notifyCallback(*characteristic, event->notify_rx.om->om_data, (*characteristic)->m_notifyCallback(*characteristic, event->notify_rx.om->om_data,
event->notify_rx.om->om_len, data_len, !event->notify_rx.indication);
!event->notify_rx.indication);
} }
break; break;
} }
@ -1060,7 +1089,7 @@ uint16_t NimBLEClient::getMTU() {
NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "ble_sm_inject_io result: %d", rc);
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp); NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp);
pkey.action = event->passkey.params.action; pkey.action = event->passkey.params.action;
// Compatibility only - Do not use, should be removed the in future // Compatibility only - Do not use, should be removed the in future
if(NimBLEDevice::m_securityCallbacks != nullptr) { if(NimBLEDevice::m_securityCallbacks != nullptr) {
@ -1205,5 +1234,4 @@ bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){
return true; return true;
} }
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // CONFIG_BT_ENABLED

View File

@ -14,16 +14,14 @@
#ifndef MAIN_NIMBLECLIENT_H_ #ifndef MAIN_NIMBLECLIENT_H_
#define MAIN_NIMBLECLIENT_H_ #define MAIN_NIMBLECLIENT_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLEAddress.h" #include "NimBLEAddress.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLEConnInfo.h" #include "NimBLEConnInfo.h"
#include "NimBLEAttValue.h"
#include "NimBLEAdvertisedDevice.h" #include "NimBLEAdvertisedDevice.h"
#include "NimBLERemoteService.h" #include "NimBLERemoteService.h"
@ -54,9 +52,9 @@ public:
NimBLERemoteService* getService(const NimBLEUUID &uuid); NimBLERemoteService* getService(const NimBLEUUID &uuid);
void deleteServices(); void deleteServices();
size_t deleteService(const NimBLEUUID &uuid); size_t deleteService(const NimBLEUUID &uuid);
std::string getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID); NimBLEAttValue getValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID);
bool setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID, bool setValue(const NimBLEUUID &serviceUUID, const NimBLEUUID &characteristicUUID,
const std::string &value, bool response = false); const NimBLEAttValue &value, bool response = false);
NimBLERemoteCharacteristic* getCharacteristic(const uint16_t handle); NimBLERemoteCharacteristic* getCharacteristic(const uint16_t handle);
bool isConnected(); bool isConnected();
void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks, void setClientCallbacks(NimBLEClientCallbacks *pClientCallbacks,
@ -71,6 +69,7 @@ public:
uint16_t scanInterval=16, uint16_t scanWindow=16); 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 setDataLen(uint16_t tx_octets);
void discoverAttributes(); void discoverAttributes();
NimBLEConnInfo getConnInfo(); NimBLEConnInfo getConnInfo();
int getLastError(); int getLastError();
@ -160,6 +159,5 @@ 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 && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // CONFIG_BT_ENABLED
#endif /* MAIN_NIMBLECLIENT_H_ */ #endif /* MAIN_NIMBLECLIENT_H_ */

View File

@ -11,11 +11,9 @@
* Created on: Jun 22, 2017 * Created on: Jun 22, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEService.h" #include "NimBLEService.h"
#include "NimBLEDescriptor.h" #include "NimBLEDescriptor.h"
@ -30,28 +28,32 @@ static NimBLEDescriptorCallbacks defaultCallbacks;
/** /**
* @brief NimBLEDescriptor constructor. * @brief Construct a descriptor
* @param [in] uuid - UUID (const char*) for the descriptor.
* @param [in] properties - Properties for the descriptor.
* @param [in] max_len - The maximum length in bytes that the descriptor value can hold. (Default: 512 bytes for esp32, 20 for all others).
* @param [in] pCharacteristic - pointer to the characteristic instance this descriptor belongs to.
*/ */
NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len, NimBLEDescriptor::NimBLEDescriptor(const char* uuid, uint16_t properties, uint16_t max_len,
NimBLECharacteristic* pCharacteristic) NimBLECharacteristic* pCharacteristic)
: NimBLEDescriptor(NimBLEUUID(uuid), max_len, properties, pCharacteristic) { : NimBLEDescriptor(NimBLEUUID(uuid), properties, max_len, pCharacteristic) {
} }
/** /**
* @brief NimBLEDescriptor constructor. * @brief Construct a descriptor
* @param [in] uuid - UUID (const char*) for the descriptor.
* @param [in] properties - Properties for the descriptor.
* @param [in] max_len - The maximum length in bytes that the descriptor value can hold. (Default: 512 bytes for esp32, 20 for all others).
* @param [in] pCharacteristic - pointer to the characteristic instance this descriptor belongs to.
*/ */
NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_t max_len, NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_t max_len,
NimBLECharacteristic* pCharacteristic) NimBLECharacteristic* pCharacteristic)
{ : m_value(std::min(CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH , (int)max_len), max_len) {
m_uuid = uuid; m_uuid = uuid;
m_value.attr_len = 0; // Initial length is 0.
m_value.attr_max_len = max_len; // Maximum length of the data.
m_handle = NULL_HANDLE; // Handle is initially unknown. m_handle = NULL_HANDLE; // Handle is initially unknown.
m_pCharacteristic = pCharacteristic; m_pCharacteristic = pCharacteristic;
m_pCallbacks = &defaultCallbacks; // No initial callback. m_pCallbacks = &defaultCallbacks; // No initial callback.
m_value.attr_value = (uint8_t*) calloc(max_len,1); // Allocate storage for the value.
m_valMux = portMUX_INITIALIZER_UNLOCKED;
m_properties = 0; m_properties = 0;
m_removed = 0; m_removed = 0;
@ -87,7 +89,6 @@ NimBLEDescriptor::NimBLEDescriptor(NimBLEUUID uuid, uint16_t properties, uint16_
* @brief NimBLEDescriptor destructor. * @brief NimBLEDescriptor destructor.
*/ */
NimBLEDescriptor::~NimBLEDescriptor() { NimBLEDescriptor::~NimBLEDescriptor() {
free(m_value.attr_value); // Release the storage we created in the constructor.
} // ~NimBLEDescriptor } // ~NimBLEDescriptor
/** /**
@ -104,7 +105,7 @@ uint16_t NimBLEDescriptor::getHandle() {
* @return The length (in bytes) of the value of this descriptor. * @return The length (in bytes) of the value of this descriptor.
*/ */
size_t NimBLEDescriptor::getLength() { size_t NimBLEDescriptor::getLength() {
return m_value.attr_len; return m_value.size();
} // getLength } // getLength
@ -118,10 +119,14 @@ NimBLEUUID NimBLEDescriptor::getUUID() {
/** /**
* @brief Get the value of this descriptor. * @brief Get the value of this descriptor.
* @return A pointer to the value of this descriptor. * @return The NimBLEAttValue of this descriptor.
*/ */
uint8_t* NimBLEDescriptor::getValue() { NimBLEAttValue NimBLEDescriptor::getValue(time_t *timestamp) {
return m_value.attr_value; if (timestamp != nullptr) {
m_value.getValue(timestamp);
}
return m_value;
} // getValue } // getValue
@ -130,7 +135,7 @@ uint8_t* NimBLEDescriptor::getValue() {
* @return A std::string instance containing a copy of the descriptor's value. * @return A std::string instance containing a copy of the descriptor's value.
*/ */
std::string NimBLEDescriptor::getStringValue() { std::string NimBLEDescriptor::getStringValue() {
return std::string((char *) m_value.attr_value, m_value.attr_len); return std::string(m_value);
} }
@ -145,6 +150,9 @@ NimBLECharacteristic* NimBLEDescriptor::getCharacteristic() {
int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle, int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg) { struct ble_gatt_access_ctxt *ctxt, void *arg) {
(void)conn_handle;
(void)attr_handle;
const ble_uuid_t *uuid; const ble_uuid_t *uuid;
int rc; int rc;
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg; NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
@ -161,24 +169,27 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
if(ctxt->om->om_pkthdr_len > 8) { if(ctxt->om->om_pkthdr_len > 8) {
pDescriptor->m_pCallbacks->onRead(pDescriptor); pDescriptor->m_pCallbacks->onRead(pDescriptor);
} }
portENTER_CRITICAL(&pDescriptor->m_valMux);
rc = os_mbuf_append(ctxt->om, pDescriptor->getValue(), pDescriptor->getLength()); ble_npl_hw_enter_critical();
portEXIT_CRITICAL(&pDescriptor->m_valMux); rc = os_mbuf_append(ctxt->om, pDescriptor->m_value.data(), pDescriptor->m_value.size());
ble_npl_hw_exit_critical(0);
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
} }
case BLE_GATT_ACCESS_OP_WRITE_DSC: { case BLE_GATT_ACCESS_OP_WRITE_DSC: {
if (ctxt->om->om_len > pDescriptor->m_value.attr_max_len) { uint16_t att_max_len = pDescriptor->m_value.max_size();
if (ctxt->om->om_len > att_max_len) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} }
uint8_t buf[pDescriptor->m_value.attr_max_len]; uint8_t buf[att_max_len];
size_t len = ctxt->om->om_len; size_t len = ctxt->om->om_len;
memcpy(buf, ctxt->om->om_data,len); memcpy(buf, ctxt->om->om_data,len);
os_mbuf *next; os_mbuf *next;
next = SLIST_NEXT(ctxt->om, om_next); next = SLIST_NEXT(ctxt->om, om_next);
while(next != NULL){ while(next != NULL){
if((len + next->om_len) > pDescriptor->m_value.attr_max_len) { if((len + next->om_len) > att_max_len) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} }
memcpy(&buf[len], next->om_data, next->om_len); memcpy(&buf[len], next->om_data, next->om_len);
@ -230,25 +241,19 @@ void NimBLEDescriptor::setHandle(uint16_t handle) {
* @param [in] length The length of the data in bytes. * @param [in] length The length of the data in bytes.
*/ */
void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) { void NimBLEDescriptor::setValue(const uint8_t* data, size_t length) {
if (length > m_value.attr_max_len) { m_value.setValue(data, length);
NIMBLE_LOGE(LOG_TAG, "Size %d too large, must be no bigger than %d", length, m_value.attr_max_len);
return;
}
portENTER_CRITICAL(&m_valMux);
m_value.attr_len = length;
memcpy(m_value.attr_value, data, length);
portEXIT_CRITICAL(&m_valMux);
} // setValue } // setValue
/** /**
* @brief Set the value of the descriptor. * @brief Set the value of the descriptor from a `std::vector<uint8_t>`.\n
* @param [in] value The value of the descriptor in string form. * @param [in] vec The std::vector<uint8_t> reference to set the descriptor value from.
*/ */
void NimBLEDescriptor::setValue(const std::string &value) { void NimBLEDescriptor::setValue(const std::vector<uint8_t>& vec) {
setValue((uint8_t*) value.data(), value.length()); return setValue((uint8_t*)&vec[0], vec.size());
} // setValue } // setValue
/** /**
* @brief Set the characteristic this descriptor belongs to. * @brief Set the characteristic this descriptor belongs to.
* @param [in] pChar A pointer to the characteristic this descriptior belongs to. * @param [in] pChar A pointer to the characteristic this descriptior belongs to.
@ -277,6 +282,7 @@ NimBLEDescriptorCallbacks::~NimBLEDescriptorCallbacks() {}
* @param [in] pDescriptor The descriptor that is the source of the event. * @param [in] pDescriptor The descriptor that is the source of the event.
*/ */
void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) { void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) {
(void)pDescriptor;
NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default"); NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default");
} // onRead } // onRead
@ -286,8 +292,8 @@ void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor) {
* @param [in] pDescriptor The descriptor that is the source of the event. * @param [in] pDescriptor The descriptor that is the source of the event.
*/ */
void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) { void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor) {
(void)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 && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* CONFIG_BT_ENABLED */

View File

@ -14,25 +14,16 @@
#ifndef MAIN_NIMBLEDESCRIPTOR_H_ #ifndef MAIN_NIMBLEDESCRIPTOR_H_
#define MAIN_NIMBLEDESCRIPTOR_H_ #define MAIN_NIMBLEDESCRIPTOR_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLECharacteristic.h" #include "NimBLECharacteristic.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
#include "NimBLEAttValue.h"
#include <string> #include <string>
typedef struct
{
uint16_t attr_max_len; /*!< attribute max value length */
uint16_t attr_len; /*!< attribute current value length */
uint8_t *attr_value; /*!< the pointer to attribute value */
} attr_value_t;
class NimBLEService; class NimBLEService;
class NimBLECharacteristic; class NimBLECharacteristic;
class NimBLEDescriptorCallbacks; class NimBLEDescriptorCallbacks;
@ -56,24 +47,36 @@ public:
uint16_t getHandle(); uint16_t getHandle();
NimBLEUUID getUUID(); NimBLEUUID getUUID();
std::string toString(); std::string toString();
void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks); void setCallbacks(NimBLEDescriptorCallbacks* pCallbacks);
NimBLECharacteristic* getCharacteristic();
size_t getLength(); size_t getLength();
uint8_t* getValue(); NimBLEAttValue getValue(time_t *timestamp = nullptr);
std::string getStringValue(); std::string getStringValue();
void setValue(const uint8_t* data, size_t size); void setValue(const uint8_t* data, size_t size);
void setValue(const std::string &value); void setValue(const std::vector<uint8_t>& vec);
NimBLECharacteristic* getCharacteristic();
/*********************** Template Functions ************************/
/** /**
* @brief Convenience template to set the descriptor value to <type\>val. * @brief Template to set the characteristic value to <type\>val.
* @param [in] s The value to set. * @param [in] s The value to set.
*/ */
template<typename T> template<typename T>
void setValue(const T &s) { void setValue(const T &s) { m_value.setValue<T>(s); }
setValue((uint8_t*)&s, sizeof(T));
/**
* @brief Template to convert the descriptor data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp (Optional) A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck (Optional) If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
return m_value.getValue<T>(timestamp, skipSizeCheck);
} }
private: private:
@ -91,8 +94,7 @@ private:
NimBLEDescriptorCallbacks* m_pCallbacks; NimBLEDescriptorCallbacks* m_pCallbacks;
NimBLECharacteristic* m_pCharacteristic; NimBLECharacteristic* m_pCharacteristic;
uint8_t m_properties; uint8_t m_properties;
attr_value_t m_value; NimBLEAttValue m_value;
portMUX_TYPE m_valMux;
uint8_t m_removed; uint8_t m_removed;
}; // NimBLEDescriptor }; // NimBLEDescriptor
@ -113,6 +115,5 @@ public:
#include "NimBLE2904.h" #include "NimBLE2904.h"
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_NIMBLEDESCRIPTOR_H_ */ #endif /* MAIN_NIMBLEDESCRIPTOR_H_ */

View File

@ -11,27 +11,45 @@
* Created on: Mar 16, 2017 * Created on: Mar 16, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "esp_err.h" #ifdef ESP_PLATFORM
#include "esp_bt.h" # include "esp_err.h"
#include "nvs_flash.h" # include "esp_bt.h"
#include "esp_nimble_hci.h" # include "nvs_flash.h"
#include "nimble/nimble_port.h" # if defined(CONFIG_NIMBLE_CPP_IDF)
#include "nimble/nimble_port_freertos.h" # include "esp_nimble_hci.h"
#include "host/ble_hs.h" # include "nimble/nimble_port.h"
#include "host/ble_hs_pvcy.h" # include "nimble/nimble_port_freertos.h"
#include "host/util/util.h" # include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h" # include "host/ble_hs_pvcy.h"
#include "services/gatt/ble_svc_gatt.h" # include "host/util/util.h"
# include "services/gap/ble_svc_gap.h"
# include "services/gatt/ble_svc_gatt.h"
# else
# include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h"
# endif
#else
# include "nimble/nimble/controller/include/controller/ble_phy.h"
#endif
#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS #ifndef CONFIG_NIMBLE_CPP_IDF
#include "esp32-hal-bt.h" # include "nimble/porting/nimble/include/nimble/nimble_port.h"
# include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h"
# include "nimble/nimble/host/include/host/ble_hs.h"
# include "nimble/nimble/host/include/host/ble_hs_pvcy.h"
# include "nimble/nimble/host/util/include/host/util/util.h"
# include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
# include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h"
#endif
#if defined(ESP_PLATFORM) && defined(CONFIG_ENABLE_ARDUINO_DEPENDS)
# include "esp32-hal-bt.h"
#endif #endif
#include "NimBLELog.h" #include "NimBLELog.h"
@ -63,9 +81,10 @@ std::list <NimBLEAddress> NimBLEDevice::m_ignoreList;
std::vector<NimBLEAddress> NimBLEDevice::m_whiteList; std::vector<NimBLEAddress> NimBLEDevice::m_whiteList;
NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr; NimBLESecurityCallbacks* NimBLEDevice::m_securityCallbacks = nullptr;
uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC; uint8_t NimBLEDevice::m_own_addr_type = BLE_OWN_ADDR_PUBLIC;
#ifdef ESP_PLATFORM
uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE; uint16_t NimBLEDevice::m_scanDuplicateSize = CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE;
uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DUPL_TYPE; uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DUPL_TYPE;
#endif
/** /**
* @brief Create a new instance of a server. * @brief Create a new instance of a server.
@ -130,7 +149,8 @@ void NimBLEDevice::stopAdvertising() {
* try and release/delete it. * try and release/delete it.
*/ */
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #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();
} }
@ -147,7 +167,8 @@ void NimBLEDevice::stopAdvertising() {
* @return A reference to the new client object. * @return A reference to the new client object.
*/ */
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
/* STATIC */ NimBLEClient* NimBLEDevice::createClient(NimBLEAddress peerAddress) { /* STATIC */
NimBLEClient* NimBLEDevice::createClient(NimBLEAddress peerAddress) {
if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) { if(m_cList.size() >= NIMBLE_MAX_CONNECTIONS) {
NIMBLE_LOGW(LOG_TAG,"Number of clients exceeds Max connections. Cur=%d Max=%d", NIMBLE_LOGW(LOG_TAG,"Number of clients exceeds Max connections. Cur=%d Max=%d",
m_cList.size(), NIMBLE_MAX_CONNECTIONS); m_cList.size(), NIMBLE_MAX_CONNECTIONS);
@ -165,7 +186,8 @@ void NimBLEDevice::stopAdvertising() {
* Checks if it is connected or trying to connect and disconnects/stops it first. * Checks if it is connected or trying to connect and disconnects/stops it first.
* @param [in] pClient A pointer to the client object. * @param [in] pClient A pointer to the client object.
*/ */
/* STATIC */ bool NimBLEDevice::deleteClient(NimBLEClient* pClient) { /* STATIC */
bool NimBLEDevice::deleteClient(NimBLEClient* pClient) {
if(pClient == nullptr) { if(pClient == nullptr) {
return false; return false;
} }
@ -209,7 +231,8 @@ void NimBLEDevice::stopAdvertising() {
* @brief Get the list of created client objects. * @brief Get the list of created client objects.
* @return A pointer to the list of clients. * @return A pointer to the list of clients.
*/ */
/* STATIC */std::list<NimBLEClient*>* NimBLEDevice::getClientList() { /* STATIC */
std::list<NimBLEClient*>* NimBLEDevice::getClientList() {
return &m_cList; return &m_cList;
} // getClientList } // getClientList
@ -218,7 +241,8 @@ void NimBLEDevice::stopAdvertising() {
* @brief Get the number of created client objects. * @brief Get the number of created client objects.
* @return Number of client objects created. * @return Number of client objects created.
*/ */
/* STATIC */size_t NimBLEDevice::getClientListSize() { /* STATIC */
size_t NimBLEDevice::getClientListSize() {
return m_cList.size(); return m_cList.size();
} // getClientList } // getClientList
@ -228,7 +252,8 @@ void NimBLEDevice::stopAdvertising() {
* @param [in] conn_id The client connection ID to search for. * @param [in] conn_id The client connection ID to search for.
* @return A pointer to the client object with the spcified connection ID. * @return A pointer to the client object with the spcified connection ID.
*/ */
/* STATIC */NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) { /* STATIC */
NimBLEClient* NimBLEDevice::getClientByID(uint16_t conn_id) {
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
if((*it)->getConnId() == conn_id) { if((*it)->getConnId() == conn_id) {
return (*it); return (*it);
@ -244,7 +269,8 @@ void NimBLEDevice::stopAdvertising() {
* @param [in] peer_addr The address of the peer to search for. * @param [in] peer_addr The address of the peer to search for.
* @return A pointer to the client object with the peer address. * @return A pointer to the client object with the peer address.
*/ */
/* STATIC */NimBLEClient* NimBLEDevice::getClientByPeerAddress(const 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);
@ -258,7 +284,8 @@ void NimBLEDevice::stopAdvertising() {
* @brief Finds the first disconnected client in the list. * @brief Finds the first disconnected client in the list.
* @return A pointer to the first client object that is not connected to a peer. * @return A pointer to the first client object that is not connected to a peer.
*/ */
/* STATIC */NimBLEClient* NimBLEDevice::getDisconnectedClient() { /* STATIC */
NimBLEClient* NimBLEDevice::getDisconnectedClient() {
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) { for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
if(!(*it)->isConnected()) { if(!(*it)->isConnected()) {
return (*it); return (*it);
@ -269,7 +296,7 @@ void NimBLEDevice::stopAdvertising() {
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif // #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#ifdef ESP_PLATFORM
/** /**
* @brief Set the transmission power. * @brief Set the transmission power.
* @param [in] powerLevel The power level to set, can be one of: * @param [in] powerLevel The power level to set, can be one of:
@ -295,12 +322,15 @@ void NimBLEDevice::stopAdvertising() {
* * ESP_BLE_PWR_TYPE_SCAN = 10, For scan * * ESP_BLE_PWR_TYPE_SCAN = 10, For scan
* * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value * * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value
*/ */
/* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) { /* STATIC */
void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) {
NIMBLE_LOGD(LOG_TAG, ">> setPower: %d (type: %d)", powerLevel, powerType); NIMBLE_LOGD(LOG_TAG, ">> setPower: %d (type: %d)", powerLevel, powerType);
esp_err_t errRc = esp_ble_tx_power_set(powerType, powerLevel); esp_err_t errRc = esp_ble_tx_power_set(powerType, powerLevel);
if (errRc != ESP_OK) { if (errRc != ESP_OK) {
NIMBLE_LOGE(LOG_TAG, "esp_ble_tx_power_set: rc=%d", errRc); NIMBLE_LOGE(LOG_TAG, "esp_ble_tx_power_set: rc=%d", errRc);
} }
NIMBLE_LOGD(LOG_TAG, "<< setPower"); NIMBLE_LOGD(LOG_TAG, "<< setPower");
} // setPower } // setPower
@ -322,9 +352,8 @@ void NimBLEDevice::stopAdvertising() {
* * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value * * ESP_BLE_PWR_TYPE_DEFAULT = 11, For default, if not set other, it will use default value
* @return the power level currently used by the type specified. * @return the power level currently used by the type specified.
*/ */
/* STATIC */
/* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) { int NimBLEDevice::getPower(esp_ble_power_type_t powerType) {
switch(esp_ble_tx_power_get(powerType)) { switch(esp_ble_tx_power_get(powerType)) {
case ESP_PWR_LVL_N12: case ESP_PWR_LVL_N12:
return -12; return -12;
@ -347,13 +376,25 @@ void NimBLEDevice::stopAdvertising() {
} }
} // getPower } // getPower
#else
void NimBLEDevice::setPower(int dbm) {
ble_phy_txpwr_set(dbm);
}
int NimBLEDevice::getPower() {
return ble_phy_txpwr_get();
}
#endif
/** /**
* @brief Get our device address. * @brief Get our device address.
* @return A NimBLEAddress object of our public address if we have one, * @return A NimBLEAddress object of our public address if we have one,
* if not then our current random address. * if not then our current random address.
*/ */
/* STATIC*/ NimBLEAddress NimBLEDevice::getAddress() { /* STATIC*/
NimBLEAddress NimBLEDevice::getAddress() {
ble_addr_t addr = {BLE_ADDR_PUBLIC, 0}; ble_addr_t addr = {BLE_ADDR_PUBLIC, 0};
if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) { if(BLE_HS_ENOADDR == ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL)) {
@ -370,7 +411,8 @@ void NimBLEDevice::stopAdvertising() {
* @brief Return a string representation of the address of this device. * @brief Return a string representation of the address of this device.
* @return A string representation of this device address. * @return A string representation of this device address.
*/ */
/* STATIC */ std::string NimBLEDevice::toString() { /* STATIC */
std::string NimBLEDevice::toString() {
return getAddress().toString(); return getAddress().toString();
} // toString } // toString
@ -380,7 +422,8 @@ void NimBLEDevice::stopAdvertising() {
* @param [in] mtu Value to set local mtu: * @param [in] mtu Value to set local mtu:
* * This should be larger than 23 and lower or equal to BLE_ATT_MTU_MAX = 527. * * This should be larger than 23 and lower or equal to BLE_ATT_MTU_MAX = 527.
*/ */
/* STATIC */int NimBLEDevice::setMTU(uint16_t mtu) { /* STATIC */
int NimBLEDevice::setMTU(uint16_t mtu) {
NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu); NIMBLE_LOGD(LOG_TAG, ">> setLocalMTU: %d", mtu);
int rc = ble_att_set_preferred_mtu(mtu); int rc = ble_att_set_preferred_mtu(mtu);
@ -398,11 +441,13 @@ void NimBLEDevice::stopAdvertising() {
* @brief Get local MTU value set. * @brief Get local MTU value set.
* @return The current preferred MTU setting. * @return The current preferred MTU setting.
*/ */
/* STATIC */uint16_t NimBLEDevice::getMTU() { /* STATIC */
uint16_t NimBLEDevice::getMTU() {
return ble_att_preferred_mtu(); return ble_att_preferred_mtu();
} }
#ifdef ESP_PLATFORM
/** /**
* @brief Set the duplicate filter cache size for filtering scanned devices. * @brief Set the duplicate filter cache size for filtering scanned devices.
* @param [in] cacheSize The number of advertisements filtered before the cache is reset.\n * @param [in] cacheSize The number of advertisements filtered before the cache is reset.\n
@ -448,6 +493,7 @@ void NimBLEDevice::setScanFilterMode(uint8_t mode) {
m_scanFilterMode = mode; m_scanFilterMode = mode;
} }
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL) || defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
/** /**
@ -470,7 +516,7 @@ int NimBLEDevice::getNumBonds() {
/** /**
* @brief Deletes all bonding information. * @brief Deletes all bonding information.
*/ */
/*STATIC*/ /*STATIC*/
void NimBLEDevice::deleteAllBonds() { void NimBLEDevice::deleteAllBonds() {
ble_store_clear(); ble_store_clear();
} }
@ -550,6 +596,7 @@ NimBLEAddress NimBLEDevice::getBondedAddress(int index) {
* @param [in] address The address to check for in the whitelist. * @param [in] address The address to check for in the whitelist.
* @returns true if the address is in the whitelist. * @returns true if the address is in the whitelist.
*/ */
/*STATIC*/
bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) { bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) {
for (auto &it : m_whiteList) { for (auto &it : m_whiteList) {
if (it == address) { if (it == address) {
@ -566,6 +613,7 @@ bool NimBLEDevice::onWhiteList(const NimBLEAddress & address) {
* @param [in] address The address to add to the whitelist. * @param [in] address The address to add to the whitelist.
* @returns true if successful. * @returns true if successful.
*/ */
/*STATIC*/
bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) { bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) {
if (NimBLEDevice::onWhiteList(address)) { if (NimBLEDevice::onWhiteList(address)) {
return true; return true;
@ -597,6 +645,7 @@ bool NimBLEDevice::whiteListAdd(const NimBLEAddress & address) {
* @param [in] address The address to remove from the whitelist. * @param [in] address The address to remove from the whitelist.
* @returns true if successful. * @returns true if successful.
*/ */
/*STATIC*/
bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) { bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) {
if (!NimBLEDevice::onWhiteList(address)) { if (!NimBLEDevice::onWhiteList(address)) {
return true; return true;
@ -636,6 +685,7 @@ bool NimBLEDevice::whiteListRemove(const NimBLEAddress & address) {
* @brief Gets the count of addresses in the whitelist. * @brief Gets the count of addresses in the whitelist.
* @returns The number of addresses in the whitelist. * @returns The number of addresses in the whitelist.
*/ */
/*STATIC*/
size_t NimBLEDevice::getWhiteListCount() { size_t NimBLEDevice::getWhiteListCount() {
return m_whiteList.size(); return m_whiteList.size();
} }
@ -646,6 +696,7 @@ size_t NimBLEDevice::getWhiteListCount() {
* @param [in] index The vector index to retrieve the address from. * @param [in] index The vector index to retrieve the address from.
* @returns the NimBLEAddress at the whitelist index or nullptr if not found. * @returns the NimBLEAddress at the whitelist index or nullptr if not found.
*/ */
/*STATIC*/
NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
if (index > m_whiteList.size()) { if (index > m_whiteList.size()) {
NIMBLE_LOGE(LOG_TAG, "Invalid index; %u", index); NIMBLE_LOGE(LOG_TAG, "Invalid index; %u", index);
@ -659,7 +710,8 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
* @brief Host reset, we pass the message so we don't make calls until resynced. * @brief Host reset, we pass the message so we don't make calls until resynced.
* @param [in] reason The reason code for the reset. * @param [in] reason The reason code for the reset.
*/ */
/* STATIC */ void NimBLEDevice::onReset(int reason) /* STATIC */
void NimBLEDevice::onReset(int reason)
{ {
if(!m_synced) { if(!m_synced) {
return; return;
@ -683,7 +735,8 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
/** /**
* @brief Host resynced with controller, all clear to make calls to the stack. * @brief Host resynced with controller, all clear to make calls to the stack.
*/ */
/* STATIC */ void NimBLEDevice::onSync(void) /* STATIC */
void NimBLEDevice::onSync(void)
{ {
NIMBLE_LOGI(LOG_TAG, "NimBle host synced."); NIMBLE_LOGI(LOG_TAG, "NimBle host synced.");
// This check is needed due to potentially being called multiple times in succession // This check is needed due to potentially being called multiple times in succession
@ -696,6 +749,14 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
int rc = ble_hs_util_ensure_addr(0); int rc = ble_hs_util_ensure_addr(0);
assert(rc == 0); assert(rc == 0);
#ifndef ESP_PLATFORM
rc = ble_hs_id_infer_auto(m_own_addr_type, &m_own_addr_type);
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "error determining address type; rc=%d", rc);
return;
}
#endif
// Yield for houskeeping before returning to operations. // Yield for houskeeping before returning to operations.
// Occasionally triggers exception without. // Occasionally triggers exception without.
taskYIELD(); taskYIELD();
@ -721,9 +782,11 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
/** /**
* @brief The main host task. * @brief The main host task.
*/ */
/* STATIC */ void NimBLEDevice::host_task(void *param) /* STATIC */
void NimBLEDevice::host_task(void *param)
{ {
NIMBLE_LOGI(LOG_TAG, "BLE Host Task Started"); NIMBLE_LOGI(LOG_TAG, "BLE Host Task Started");
/* This function will return only when nimble_port_stop() is executed */ /* This function will return only when nimble_port_stop() is executed */
nimble_port_run(); nimble_port_run();
@ -735,9 +798,11 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
* @brief Initialize the %BLE environment. * @brief Initialize the %BLE environment.
* @param [in] deviceName The device name of the device. * @param [in] deviceName The device name of the device.
*/ */
/* STATIC */ void NimBLEDevice::init(const std::string &deviceName) { /* STATIC */
void NimBLEDevice::init(const std::string &deviceName) {
if(!initialized){ if(!initialized){
int rc=0; int rc=0;
#ifdef ESP_PLATFORM
esp_err_t errRc = ESP_OK; esp_err_t errRc = ESP_OK;
#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS #ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
@ -757,7 +822,7 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
#ifdef CONFIG_IDF_TARGET_ESP32C3 #if defined (CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
bt_cfg.bluetooth_mode = ESP_BT_MODE_BLE; bt_cfg.bluetooth_mode = ESP_BT_MODE_BLE;
#else #else
bt_cfg.mode = ESP_BT_MODE_BLE; bt_cfg.mode = ESP_BT_MODE_BLE;
@ -769,6 +834,7 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE)); ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BLE));
ESP_ERROR_CHECK(esp_nimble_hci_init()); ESP_ERROR_CHECK(esp_nimble_hci_init());
#endif
nimble_port_init(); nimble_port_init();
// Setup callbacks for host events // Setup callbacks for host events
@ -793,9 +859,10 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
nimble_port_freertos_init(NimBLEDevice::host_task); nimble_port_freertos_init(NimBLEDevice::host_task);
} }
// Wait for host and controller to sync before returning and accepting new tasks // Wait for host and controller to sync before returning and accepting new tasks
while(!m_synced){ while(!m_synced){
vTaskDelay(1 / portTICK_PERIOD_MS); taskYIELD();
} }
initialized = true; // Set the initialization flag to ensure we are only initialized once. initialized = true; // Set the initialization flag to ensure we are only initialized once.
@ -807,16 +874,17 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
* @param [in] clearAll If true, deletes all server/advertising/scan/client objects after deinitializing. * @param [in] clearAll If true, deletes all server/advertising/scan/client objects after deinitializing.
* @note If clearAll is true when called, any references to the created objects become invalid. * @note If clearAll is true when called, any references to the created objects become invalid.
*/ */
/* STATIC */ void NimBLEDevice::deinit(bool clearAll) { /* STATIC */
void NimBLEDevice::deinit(bool clearAll) {
int ret = nimble_port_stop(); int ret = nimble_port_stop();
if (ret == 0) { if (ret == 0) {
nimble_port_deinit(); nimble_port_deinit();
#ifdef ESP_PLATFORM
ret = esp_nimble_hci_and_controller_deinit(); ret = esp_nimble_hci_and_controller_deinit();
if (ret != ESP_OK) { if (ret != ESP_OK) {
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);
} }
#endif
initialized = false; initialized = false;
m_synced = false; m_synced = false;
@ -863,6 +931,7 @@ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) {
* @brief Check if the initialization is complete. * @brief Check if the initialization is complete.
* @return true if initialized. * @return true if initialized.
*/ */
/*STATIC*/
bool NimBLEDevice::getInitialized() { bool NimBLEDevice::getInitialized() {
return initialized; return initialized;
} // getInitialized } // getInitialized
@ -874,7 +943,8 @@ bool NimBLEDevice::getInitialized() {
* @param mitm If true we are capable of man in the middle protection, false if not. * @param mitm If true we are capable of man in the middle protection, false if not.
* @param sc If true we will perform secure connection pairing, false we will use legacy pairing. * @param sc If true we will perform secure connection pairing, false we will use legacy pairing.
*/ */
/*STATIC*/ void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) { /*STATIC*/
void NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc) {
NIMBLE_LOGD(LOG_TAG, "Setting bonding: %d, mitm: %d, sc: %d",bonding,mitm,sc); NIMBLE_LOGD(LOG_TAG, "Setting bonding: %d, mitm: %d, sc: %d",bonding,mitm,sc);
ble_hs_cfg.sm_bonding = bonding; ble_hs_cfg.sm_bonding = bonding;
ble_hs_cfg.sm_mitm = mitm; ble_hs_cfg.sm_mitm = mitm;
@ -891,7 +961,8 @@ bool NimBLEDevice::getInitialized() {
* * 0x08 BLE_SM_PAIR_AUTHREQ_SC * * 0x08 BLE_SM_PAIR_AUTHREQ_SC
* * 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported. * * 0x10 BLE_SM_PAIR_AUTHREQ_KEYPRESS - not yet supported.
*/ */
/*STATIC*/void NimBLEDevice::setSecurityAuth(uint8_t auth_req) { /*STATIC*/
void NimBLEDevice::setSecurityAuth(uint8_t auth_req) {
NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0, NimBLEDevice::setSecurityAuth((auth_req & BLE_SM_PAIR_AUTHREQ_BOND)>0,
(auth_req & BLE_SM_PAIR_AUTHREQ_MITM)>0, (auth_req & BLE_SM_PAIR_AUTHREQ_MITM)>0,
(auth_req & BLE_SM_PAIR_AUTHREQ_SC)>0); (auth_req & BLE_SM_PAIR_AUTHREQ_SC)>0);
@ -907,7 +978,8 @@ bool NimBLEDevice::getInitialized() {
* * 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability * * 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability
* * 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability * * 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability
*/ */
/*STATIC*/ void NimBLEDevice::setSecurityIOCap(uint8_t iocap) { /*STATIC*/
void NimBLEDevice::setSecurityIOCap(uint8_t iocap) {
ble_hs_cfg.sm_io_cap = iocap; ble_hs_cfg.sm_io_cap = iocap;
} // setSecurityIOCap } // setSecurityIOCap
@ -921,7 +993,8 @@ bool NimBLEDevice::getInitialized() {
* * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN * * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
* * 0x08: BLE_SM_PAIR_KEY_DIST_LINK * * 0x08: BLE_SM_PAIR_KEY_DIST_LINK
*/ */
/*STATIC*/void NimBLEDevice::setSecurityInitKey(uint8_t init_key) { /*STATIC*/
void NimBLEDevice::setSecurityInitKey(uint8_t init_key) {
ble_hs_cfg.sm_our_key_dist = init_key; ble_hs_cfg.sm_our_key_dist = init_key;
} // setsSecurityInitKey } // setsSecurityInitKey
@ -935,7 +1008,8 @@ bool NimBLEDevice::getInitialized() {
* * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN * * 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
* * 0x08: BLE_SM_PAIR_KEY_DIST_LINK * * 0x08: BLE_SM_PAIR_KEY_DIST_LINK
*/ */
/*STATIC*/void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) { /*STATIC*/
void NimBLEDevice::setSecurityRespKey(uint8_t resp_key) {
ble_hs_cfg.sm_their_key_dist = resp_key; ble_hs_cfg.sm_their_key_dist = resp_key;
} // setsSecurityRespKey } // setsSecurityRespKey
@ -944,7 +1018,8 @@ bool NimBLEDevice::getInitialized() {
* @brief Set the passkey the server will ask for when pairing. * @brief Set the passkey the server will ask for when pairing.
* @param [in] pin The passkey to use. * @param [in] pin The passkey to use.
*/ */
/*STATIC*/void NimBLEDevice::setSecurityPasskey(uint32_t pin) { /*STATIC*/
void NimBLEDevice::setSecurityPasskey(uint32_t pin) {
m_passkey = pin; m_passkey = pin;
} // setSecurityPasskey } // setSecurityPasskey
@ -953,7 +1028,8 @@ bool NimBLEDevice::getInitialized() {
* @brief Get the current passkey used for pairing. * @brief Get the current passkey used for pairing.
* @return The current passkey. * @return The current passkey.
*/ */
/*STATIC*/uint32_t NimBLEDevice::getSecurityPasskey() { /*STATIC*/
uint32_t NimBLEDevice::getSecurityPasskey() {
return m_passkey; return m_passkey;
} // getSecurityPasskey } // getSecurityPasskey
@ -963,11 +1039,13 @@ bool NimBLEDevice::getInitialized() {
* @param [in] callbacks Pointer to NimBLESecurityCallbacks class * @param [in] callbacks Pointer to NimBLESecurityCallbacks class
* @deprecated For backward compatibility, New code should use client/server callback methods. * @deprecated For backward compatibility, New code should use client/server callback methods.
*/ */
/*STATIC*/
void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) { void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
NimBLEDevice::m_securityCallbacks = callbacks; NimBLEDevice::m_securityCallbacks = callbacks;
} // setSecurityCallbacks } // setSecurityCallbacks
#ifdef ESP_PLATFORM
/** /**
* @brief Set the own address type. * @brief Set the own address type.
* @param [in] own_addr_type Own Bluetooth Device address type.\n * @param [in] own_addr_type Own Bluetooth Device address type.\n
@ -978,6 +1056,7 @@ void NimBLEDevice::setSecurityCallbacks(NimBLESecurityCallbacks* callbacks) {
* * 0x03: BLE_OWN_ADDR_RPA_RANDOM_DEFAULT * * 0x03: BLE_OWN_ADDR_RPA_RANDOM_DEFAULT
* @param [in] useNRPA If true, and address type is random, uses a non-resolvable random address. * @param [in] useNRPA If true, and address type is random, uses a non-resolvable random address.
*/ */
/*STATIC*/
void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) { void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) {
m_own_addr_type = own_addr_type; m_own_addr_type = own_addr_type;
switch (own_addr_type) { switch (own_addr_type) {
@ -1001,18 +1080,15 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) {
break; break;
} }
} // setOwnAddrType } // setOwnAddrType
#endif
/** /**
* @brief Start the connection securing and authorization for this connection. * @brief Start the connection securing and authorization for this connection.
* @param conn_id The connection id of the peer device. * @param conn_id The connection id of the peer device.
* @returns NimBLE stack return code, 0 = success. * @returns NimBLE stack return code, 0 = success.
*/ */
/* STATIC */int NimBLEDevice::startSecurity(uint16_t conn_id) { /* STATIC */
/* if(m_securityCallbacks != nullptr) { int NimBLEDevice::startSecurity(uint16_t conn_id) {
m_securityCallbacks->onSecurityRequest();
}
*/
int rc = ble_gap_security_initiate(conn_id); int rc = ble_gap_security_initiate(conn_id);
if(rc != 0){ if(rc != 0){
NIMBLE_LOGE(LOG_TAG, "ble_gap_security_initiate: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "ble_gap_security_initiate: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
@ -1027,7 +1103,8 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) {
* @param [in] address The address to look for. * @param [in] address The address to look for.
* @return True if ignoring. * @return True if ignoring.
*/ */
/*STATIC*/ bool NimBLEDevice::isIgnored(const 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;
@ -1042,7 +1119,8 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) {
* @brief Add a device to the ignore list. * @brief Add a device to the ignore list.
* @param [in] address The address of the device we want to ignore. * @param [in] address The address of the device we want to ignore.
*/ */
/*STATIC*/ void NimBLEDevice::addIgnored(const NimBLEAddress &address) { /*STATIC*/
void NimBLEDevice::addIgnored(const NimBLEAddress &address) {
m_ignoreList.push_back(address); m_ignoreList.push_back(address);
} }
@ -1051,7 +1129,8 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) {
* @brief Remove a device from the ignore list. * @brief Remove a device from the ignore list.
* @param [in] address The address of the device we want to remove from the list. * @param [in] address The address of the device we want to remove from the list.
*/ */
/*STATIC*/void NimBLEDevice::removeIgnored(const 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);
@ -1065,6 +1144,7 @@ void NimBLEDevice::setOwnAddrType(uint8_t own_addr_type, bool useNRPA) {
* @brief Set a custom callback for gap events. * @brief Set a custom callback for gap events.
* @param [in] handler The function to call when gap events occur. * @param [in] handler The function to call when gap events occur.
*/ */
/*STATIC*/
void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) { void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) {
m_customGapHandler = handler; m_customGapHandler = handler;
int rc = ble_gap_event_listener_register(&m_listener, m_customGapHandler, NULL); int rc = ble_gap_event_listener_register(&m_listener, m_customGapHandler, NULL);
@ -1076,5 +1156,4 @@ void NimBLEDevice::setCustomGapHandler(gap_event_handler handler) {
} }
} // setCustomGapHandler } // setCustomGapHandler
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED

View File

@ -14,10 +14,9 @@
#ifndef MAIN_NIMBLEDEVICE_H_ #ifndef MAIN_NIMBLEDEVICE_H_
#define MAIN_NIMBLEDEVICE_H_ #define MAIN_NIMBLEDEVICE_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED)
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEScan.h" #include "NimBLEScan.h"
@ -39,7 +38,9 @@
#include "NimBLESecurity.h" #include "NimBLESecurity.h"
#include "NimBLEAddress.h" #include "NimBLEAddress.h"
#include "esp_bt.h" #ifdef ESP_PLATFORM
# include "esp_bt.h"
#endif
#include <map> #include <map>
#include <string> #include <string>
@ -110,8 +111,17 @@ public:
static NimBLEServer* getServer(); static NimBLEServer* getServer();
#endif #endif
#ifdef ESP_PLATFORM
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 setOwnAddrType(uint8_t own_addr_type, bool useNRPA=false);
static void setScanDuplicateCacheSize(uint16_t cacheSize);
static void setScanFilterMode(uint8_t type);
#else
static void setPower(int dbm);
static int getPower();
#endif
static void setCustomGapHandler(gap_event_handler handler); static void setCustomGapHandler(gap_event_handler handler);
static void setSecurityAuth(bool bonding, bool mitm, bool sc); static void setSecurityAuth(bool bonding, bool mitm, bool sc);
static void setSecurityAuth(uint8_t auth_req); static void setSecurityAuth(uint8_t auth_req);
@ -121,15 +131,12 @@ public:
static void setSecurityPasskey(uint32_t pin); static void setSecurityPasskey(uint32_t pin);
static uint32_t getSecurityPasskey(); static uint32_t getSecurityPasskey();
static void setSecurityCallbacks(NimBLESecurityCallbacks* pCallbacks); static void setSecurityCallbacks(NimBLESecurityCallbacks* pCallbacks);
static void setOwnAddrType(uint8_t own_addr_type, bool useNRPA=false);
static int startSecurity(uint16_t conn_id); static int startSecurity(uint16_t conn_id);
static int setMTU(uint16_t mtu); static int setMTU(uint16_t mtu);
static uint16_t getMTU(); static uint16_t getMTU();
static bool isIgnored(const NimBLEAddress &address); static bool isIgnored(const NimBLEAddress &address);
static void addIgnored(const NimBLEAddress &address); static void addIgnored(const NimBLEAddress &address);
static void removeIgnored(const NimBLEAddress &address); static void removeIgnored(const NimBLEAddress &address);
static void setScanDuplicateCacheSize(uint16_t cacheSize);
static void setScanFilterMode(uint8_t type);
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
static NimBLEAdvertising* getAdvertising(); static NimBLEAdvertising* getAdvertising();
@ -199,8 +206,10 @@ private:
static ble_gap_event_listener m_listener; static ble_gap_event_listener m_listener;
static gap_event_handler m_customGapHandler; static gap_event_handler m_customGapHandler;
static uint8_t m_own_addr_type; static uint8_t m_own_addr_type;
#ifdef ESP_PLATFORM
static uint16_t m_scanDuplicateSize; static uint16_t m_scanDuplicateSize;
static uint8_t m_scanFilterMode; static uint8_t m_scanFilterMode;
#endif
static std::vector<NimBLEAddress> m_whiteList; static std::vector<NimBLEAddress> m_whiteList;
}; };

View File

@ -11,12 +11,14 @@
* Created on: Mar 12, 2018 * Created on: Mar 12, 2018
* Author: pcbreflux * Author: pcbreflux
*/ */
#include "sdkconfig.h"
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "NimBLEEddystoneTLM.h" #include "NimBLEEddystoneTLM.h"
#include "NimBLELog.h" #include "NimBLELog.h"
#include <stdio.h>
#include <cstring> #include <cstring>
#define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8)) #define ENDIAN_CHANGE_U16(x) ((((x)&0xFF00)>>8) + (((x)&0xFF)<<8))
@ -124,30 +126,30 @@ std::string NimBLEEddystoneTLM::toString() {
out += " C\n"; out += " C\n";
out += "Adv. Count "; out += "Adv. Count ";
snprintf(val, sizeof(val), "%d", ENDIAN_CHANGE_U32(m_eddystoneData.advCount)); snprintf(val, sizeof(val), "%" PRIu32, ENDIAN_CHANGE_U32(m_eddystoneData.advCount));
out += val; out += val;
out += "\n"; out += "\n";
out += "Time in seconds "; out += "Time in seconds ";
snprintf(val, sizeof(val), "%d", rawsec/10); snprintf(val, sizeof(val), "%" PRIu32, rawsec/10);
out += val; out += val;
out += "\n"; out += "\n";
out += "Time "; out += "Time ";
snprintf(val, sizeof(val), "%04d", rawsec / 864000); snprintf(val, sizeof(val), "%04" PRIu32, rawsec / 864000);
out += val; out += val;
out += "."; out += ".";
snprintf(val, sizeof(val), "%02d", (rawsec / 36000) % 24); snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 36000) % 24);
out += val; out += val;
out += ":"; out += ":";
snprintf(val, sizeof(val), "%02d", (rawsec / 600) % 60); snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 600) % 60);
out += val; out += val;
out += ":"; out += ":";
snprintf(val, sizeof(val), "%02d", (rawsec / 10) % 60); snprintf(val, sizeof(val), "%02" PRIu32, (rawsec / 10) % 60);
out += val; out += val;
out += "\n"; out += "\n";

View File

@ -14,6 +14,7 @@
#ifndef _NimBLEEddystoneTLM_H_ #ifndef _NimBLEEddystoneTLM_H_
#define _NimBLEEddystoneTLM_H_ #define _NimBLEEddystoneTLM_H_
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
#include <string> #include <string>

View File

@ -11,7 +11,7 @@
* Created on: Mar 12, 2018 * Created on: Mar 12, 2018
* Author: pcbreflux * Author: pcbreflux
*/ */
#include "sdkconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "NimBLEEddystoneURL.h" #include "NimBLEEddystoneURL.h"

View File

@ -11,11 +11,9 @@
* Created on: Jan 03, 2018 * Created on: Jan 03, 2018
* Author: chegewara * Author: chegewara
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEHIDDevice.h" #include "NimBLEHIDDevice.h"
#include "NimBLE2904.h" #include "NimBLE2904.h"
@ -29,7 +27,7 @@ NimBLEHIDDevice::NimBLEHIDDevice(NimBLEServer* server) {
* Here we create mandatory services described in bluetooth specification * Here we create mandatory services described in bluetooth specification
*/ */
m_deviceInfoService = server->createService(NimBLEUUID((uint16_t) 0x180a)); m_deviceInfoService = server->createService(NimBLEUUID((uint16_t) 0x180a));
m_hidService = server->createService(NimBLEUUID((uint16_t) 0x1812), 40); m_hidService = server->createService(NimBLEUUID((uint16_t) 0x1812));
m_batteryService = server->createService(NimBLEUUID((uint16_t) 0x180f)); m_batteryService = server->createService(NimBLEUUID((uint16_t) 0x180f));
/* /*
@ -247,5 +245,4 @@ NimBLEService* NimBLEHIDDevice::batteryService() {
return m_batteryService; return m_batteryService;
} }
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // #if defined(CONFIG_BT_ENABLED)

View File

@ -15,11 +15,8 @@
#ifndef _BLEHIDDEVICE_H_ #ifndef _BLEHIDDEVICE_H_
#define _BLEHIDDEVICE_H_ #define _BLEHIDDEVICE_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
#include "NimBLECharacteristic.h" #include "NimBLECharacteristic.h"
#include "NimBLEService.h" #include "NimBLEService.h"
@ -84,6 +81,6 @@ private:
NimBLECharacteristic* m_protocolModeCharacteristic; //0x2a4e NimBLECharacteristic* m_protocolModeCharacteristic; //0x2a4e
NimBLECharacteristic* m_batteryLevelCharacteristic; //0x2a19 NimBLECharacteristic* m_batteryLevelCharacteristic; //0x2a19
}; };
#endif // CONFIG_BT_NIMBLE_ROLE_BROADCASTER
#endif // CONFIG_BT_ENABLED #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
#endif /* _BLEHIDDEVICE_H_ */ #endif /* _BLEHIDDEVICE_H_ */

View File

@ -12,59 +12,69 @@
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#ifdef ARDUINO_ARCH_ESP32 #if defined(CONFIG_NIMBLE_CPP_IDF) // using esp-idf
#include "syscfg/syscfg.h" # include "esp_log.h"
#include "modlog/modlog.h" # ifndef CONFIG_NIMBLE_CPP_LOG_LEVEL
# define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
# endif
// If Arduino is being used, strip out the colors and ignore log printing below ui setting. # define NIMBLE_CPP_LOG_PRINT(level, tag, format, ...) do { \
// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR if (CONFIG_NIMBLE_CPP_LOG_LEVEL >= level) \
// otherwise no messages will be printed above that level. ESP_LOG_LEVEL_LOCAL(level, tag, format, ##__VA_ARGS__); \
} while(0)
#ifndef CONFIG_NIMBLE_CPP_DEBUG_LEVEL # define NIMBLE_LOGD(tag, format, ...) \
#ifdef CORE_DEBUG_LEVEL NIMBLE_CPP_LOG_PRINT(ESP_LOG_DEBUG, tag, format, ##__VA_ARGS__)
#define CONFIG_NIMBLE_CPP_DEBUG_LEVEL CORE_DEBUG_LEVEL
#else
#define CONFIG_NIMBLE_CPP_DEBUG_LEVEL 0
#endif
#endif
#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 4 # define NIMBLE_LOGI(tag, format, ...) \
#define NIMBLE_LOGD( tag, format, ... ) MODLOG_DFLT(ERROR, "D %s: "#format"\n",tag,##__VA_ARGS__) NIMBLE_CPP_LOG_PRINT(ESP_LOG_INFO, tag, format, ##__VA_ARGS__)
#else
#define NIMBLE_LOGD( tag, format, ... ) (void)tag
#endif
#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 3 # define NIMBLE_LOGW(tag, format, ...) \
#define NIMBLE_LOGI( tag, format, ... ) MODLOG_DFLT(ERROR, "I %s: "#format"\n",tag,##__VA_ARGS__) NIMBLE_CPP_LOG_PRINT(ESP_LOG_WARN, tag, format, ##__VA_ARGS__)
#else
#define NIMBLE_LOGI( tag, format, ... ) (void)tag
#endif
#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 2 # define NIMBLE_LOGE(tag, format, ...) \
#define NIMBLE_LOGW( tag, format, ... ) MODLOG_DFLT(ERROR, "W %s: "#format"\n",tag,##__VA_ARGS__) NIMBLE_CPP_LOG_PRINT(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
#else
#define NIMBLE_LOGW( tag, format, ... ) (void)tag
#endif
#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 1 # define NIMBLE_LOGC(tag, format, ...) \
#define NIMBLE_LOGE( tag, format, ... ) MODLOG_DFLT(ERROR, "E %s: "#format"\n",tag,##__VA_ARGS__) NIMBLE_CPP_LOG_PRINT(ESP_LOG_ERROR, tag, format, ##__VA_ARGS__)
#else
#define NIMBLE_LOGE( tag, format, ... ) (void)tag
#endif
#define NIMBLE_LOGC( tag, format, ... ) MODLOG_DFLT(CRITICAL, "CRIT %s: "#format"\n",tag,##__VA_ARGS__) #else // using Arduino
# include "nimble/porting/nimble/include/syscfg/syscfg.h"
# include "nimble/console/console.h"
# ifndef CONFIG_NIMBLE_CPP_LOG_LEVEL
# if defined(ARDUINO_ARCH_ESP32) && defined(CORE_DEBUG_LEVEL)
# define CONFIG_NIMBLE_CPP_LOG_LEVEL CORE_DEBUG_LEVEL
# else
# define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
# endif
# endif
#else # if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
# define NIMBLE_LOGD( tag, format, ... ) console_printf("D %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_LOGD( tag, format, ... ) (void)tag
# endif
#include "esp_log.h" # if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 3
# define NIMBLE_LOGI( tag, format, ... ) console_printf("I %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_LOGI( tag, format, ... ) (void)tag
# endif
#define NIMBLE_LOGE(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__) # if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 2
#define NIMBLE_LOGW(tag, format, ...) ESP_LOGW(tag, format, ##__VA_ARGS__) # define NIMBLE_LOGW( tag, format, ... ) console_printf("W %s: " format "\n", tag, ##__VA_ARGS__)
#define NIMBLE_LOGI(tag, format, ...) ESP_LOGI(tag, format, ##__VA_ARGS__) # else
#define NIMBLE_LOGD(tag, format, ...) ESP_LOGD(tag, format, ##__VA_ARGS__) # define NIMBLE_LOGW( tag, format, ... ) (void)tag
#define NIMBLE_LOGC(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__) # endif
#endif /*ARDUINO_ARCH_ESP32*/ # if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 1
# define NIMBLE_LOGE( tag, format, ... ) console_printf("E %s: " format "\n", tag, ##__VA_ARGS__)
# define NIMBLE_LOGC( tag, format, ... ) console_printf("CRIT %s: " format "\n", tag, ##__VA_ARGS__)
# else
# define NIMBLE_LOGE( tag, format, ... ) (void)tag
# define NIMBLE_LOGC( tag, format, ... ) (void)tag
# endif
#endif /*CONFIG_BT_ENABLED*/ #endif /* CONFIG_NIMBLE_CPP_IDF */
#endif /*MAIN_NIMBLELOG_H_*/ #endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_NIMBLELOG_H_ */

View File

@ -12,16 +12,15 @@
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteCharacteristic.h" #include "NimBLERemoteCharacteristic.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
#include <climits>
static const char* LOG_TAG = "NimBLERemoteCharacteristic"; static const char* LOG_TAG = "NimBLERemoteCharacteristic";
/** /**
@ -59,8 +58,6 @@ 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_timestamp = 0;
m_valMux = portMUX_INITIALIZER_UNLOCKED;
NIMBLE_LOGD(LOG_TAG, "<< NimBLERemoteCharacteristic(): %s", m_uuid.toString().c_str()); NIMBLE_LOGD(LOG_TAG, "<< NimBLERemoteCharacteristic(): %s", m_uuid.toString().c_str());
} // NimBLERemoteCharacteristic } // NimBLERemoteCharacteristic
@ -319,7 +316,7 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
return m_descriptorVector.back(); return m_descriptorVector.back();
} }
// If the request was successful but 16/32 bit descriptor not found // If the request was successful but 16/32 bit uuid not found
// try again with the 128 bit uuid. // try again with the 128 bit uuid.
if(uuid.bitSize() == BLE_UUID_TYPE_16 || if(uuid.bitSize() == BLE_UUID_TYPE_16 ||
uuid.bitSize() == BLE_UUID_TYPE_32) uuid.bitSize() == BLE_UUID_TYPE_32)
@ -327,6 +324,15 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
NimBLEUUID uuid128(uuid); NimBLEUUID uuid128(uuid);
uuid128.to128(); uuid128.to128();
return getDescriptor(uuid128); return getDescriptor(uuid128);
} else {
// If the request was successful but the 128 bit uuid not found
// try again with the 16 bit uuid.
NimBLEUUID uuid16(uuid);
uuid16.to16();
// if the uuid was 128 bit but not of the BLE base type this check will fail
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
return getDescriptor(uuid16);
}
} }
} }
@ -416,15 +422,12 @@ NimBLEUUID NimBLERemoteCharacteristic::getUUID() {
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read. * @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @return The value of the remote characteristic. * @return The value of the remote characteristic.
*/ */
std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) { NimBLEAttValue NimBLERemoteCharacteristic::getValue(time_t *timestamp) {
portENTER_CRITICAL(&m_valMux);
std::string value = m_value;
if(timestamp != nullptr) { if(timestamp != nullptr) {
*timestamp = m_timestamp; *timestamp = m_value.getTimeStamp();
} }
portEXIT_CRITICAL(&m_valMux);
return value; return m_value;
} }
@ -472,12 +475,12 @@ float NimBLERemoteCharacteristic::readFloat() {
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read. * @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @return The value of the remote characteristic. * @return The value of the remote characteristic.
*/ */
std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) { NimBLEAttValue NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x", NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x",
getUUID().toString().c_str(), getHandle(), getHandle()); getUUID().toString().c_str(), getHandle(), getHandle());
NimBLEClient* pClient = getRemoteService()->getClient(); NimBLEClient* pClient = getRemoteService()->getClient();
std::string value; NimBLEAttValue value;
if (!pClient->isConnected()) { if (!pClient->isConnected()) {
NIMBLE_LOGE(LOG_TAG, "Disconnected"); NIMBLE_LOGE(LOG_TAG, "Disconnected");
@ -528,14 +531,11 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
} }
} while(rc != 0 && retryCount--); } while(rc != 0 && retryCount--);
time_t t = time(nullptr); value.setTimeStamp();
portENTER_CRITICAL(&m_valMux);
m_value = value; m_value = value;
m_timestamp = t;
if(timestamp != nullptr) { if(timestamp != nullptr) {
*timestamp = m_timestamp; *timestamp = value.getTimeStamp();
} }
portEXIT_CRITICAL(&m_valMux);
NIMBLE_LOGD(LOG_TAG, "<< readValue length: %d rc=%d", value.length(), rc); NIMBLE_LOGD(LOG_TAG, "<< readValue length: %d rc=%d", value.length(), rc);
return value; return value;
@ -560,17 +560,17 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
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);
std::string *strBuf = (std::string*)pTaskData->buf; NimBLEAttValue *valBuf = (NimBLEAttValue*)pTaskData->buf;
int rc = error->status; int rc = error->status;
if(rc == 0) { if(rc == 0) {
if(attr) { if(attr) {
uint32_t data_len = OS_MBUF_PKTLEN(attr->om); uint16_t data_len = OS_MBUF_PKTLEN(attr->om);
if(((*strBuf).length() + data_len) > BLE_ATT_ATTR_MAX_LEN) { if((valBuf->size() + data_len) > BLE_ATT_ATTR_MAX_LEN) {
rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} else { } else {
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", data_len); NIMBLE_LOGD(LOG_TAG, "Got %u bytes", data_len);
(*strBuf) += std::string((char*) attr->om->om_data, data_len); valBuf->append(attr->om->om_data, data_len);
return 0; return 0;
} }
} }
@ -721,22 +721,33 @@ std::string NimBLERemoteCharacteristic::toString() {
/** /**
* @brief Write the new value for the characteristic. * @brief Write a new value to the remote characteristic from a std::vector<uint8_t>.
* @param [in] newValue The new value to write. * @param [in] vec A std::vector<uint8_t> value to write to the remote characteristic.
* @param [in] response Do we expect a response? * @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 otherwise cannot perform write.
*/ */
bool NimBLERemoteCharacteristic::writeValue(const std::string &newValue, bool response) { bool NimBLERemoteCharacteristic::writeValue(const std::vector<uint8_t>& vec, bool response) {
return writeValue((uint8_t*)newValue.c_str(), newValue.length(), response); return writeValue((uint8_t*)&vec[0], vec.size(), response);
} // writeValue } // writeValue
/** /**
* @brief Write the new value for the characteristic from a data buffer. * @brief Write a new value to the remote characteristic from a const char*.
* @param [in] char_s A character string to write to the remote characteristic.
* @param [in] response Whether we require a response from the write.
* @return false if not connected or otherwise cannot perform write.
*/
bool NimBLERemoteCharacteristic::writeValue(const char* char_s, bool response) {
return writeValue((uint8_t*)char_s, strlen(char_s), response);
} // writeValue
/**
* @brief Write a new value to the remote characteristic from a data buffer.
* @param [in] data A pointer to a data buffer. * @param [in] data A pointer to a data buffer.
* @param [in] length The length of the data in the data buffer. * @param [in] length The length of the data in the data buffer.
* @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 otherwise cannot perform write.
*/ */
bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) { bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) {
@ -839,6 +850,4 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
return 0; return 0;
} }
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */

View File

@ -14,17 +14,16 @@
#ifndef COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ #ifndef COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_
#define COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ #define COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteService.h" #include "NimBLERemoteService.h"
#include "NimBLERemoteDescriptor.h" #include "NimBLERemoteDescriptor.h"
#include <vector> #include <vector>
#include <functional> #include <functional>
#include "NimBLELog.h"
class NimBLERemoteService; class NimBLERemoteService;
class NimBLERemoteDescriptor; class NimBLERemoteDescriptor;
@ -62,47 +61,15 @@ public:
uint16_t getHandle(); uint16_t getHandle();
uint16_t getDefHandle(); uint16_t getDefHandle();
NimBLEUUID getUUID(); NimBLEUUID getUUID();
std::string readValue(time_t *timestamp = nullptr); NimBLEAttValue readValue(time_t *timestamp = nullptr);
std::string toString();
/** NimBLERemoteService* getRemoteService();
* @brief A template to convert the remote characteristic data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
* less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>readValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T readValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
std::string value = readValue(timestamp);
if(!skipSizeCheck && value.size() < sizeof(T)) return T();
const char *pData = value.data();
return *((T *)pData);
}
uint8_t readUInt8() __attribute__ ((deprecated("Use template readValue<uint8_t>()"))); uint8_t readUInt8() __attribute__ ((deprecated("Use template readValue<uint8_t>()")));
uint16_t readUInt16() __attribute__ ((deprecated("Use template readValue<uint16_t>()"))); uint16_t readUInt16() __attribute__ ((deprecated("Use template readValue<uint16_t>()")));
uint32_t readUInt32() __attribute__ ((deprecated("Use template readValue<uint32_t>()"))); uint32_t readUInt32() __attribute__ ((deprecated("Use template readValue<uint32_t>()")));
float readFloat() __attribute__ ((deprecated("Use template readValue<float>()"))); float readFloat() __attribute__ ((deprecated("Use template readValue<float>()")));
std::string getValue(time_t *timestamp = nullptr); NimBLEAttValue getValue(time_t *timestamp = nullptr);
/**
* @brief A template to convert the remote characteristic data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
* less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
std::string value = getValue(timestamp);
if(!skipSizeCheck && value.size() < sizeof(T)) return T();
const char *pData = value.data();
return *((T *)pData);
}
bool subscribe(bool notifications = true, bool subscribe(bool notifications = true,
notify_callback notifyCallback = nullptr, notify_callback notifyCallback = nullptr,
@ -115,20 +82,74 @@ public:
bool writeValue(const uint8_t* data, bool writeValue(const uint8_t* data,
size_t length, size_t length,
bool response = false); bool response = false);
bool writeValue(const std::string &newValue, bool writeValue(const std::vector<uint8_t>& v, bool response = false);
bool response = false); bool writeValue(const char* s, bool response = false);
/*********************** Template Functions ************************/
/** /**
* @brief Convenience template to set the remote characteristic value to <type\>val. * @brief Template to set the remote characteristic value to <type\>val.
* @param [in] s The value to write. * @param [in] s The value to write.
* @param [in] response True == request write response. * @param [in] response True == request write response.
* @details Only used for non-arrays and types without a `c_str()` method.
*/ */
template<typename T> template<typename T>
bool writeValue(const T &s, bool response = false) { #ifdef _DOXYGEN_
bool
#else
typename std::enable_if<!std::is_array<T>::value && !Has_c_str_len<T>::value, bool>::type
#endif
writeValue(const T& s, bool response = false) {
return writeValue((uint8_t*)&s, sizeof(T), response); return writeValue((uint8_t*)&s, sizeof(T), response);
} }
std::string toString(); /**
NimBLERemoteService* getRemoteService(); * @brief Template to set the remote characteristic value to <type\>val.
* @param [in] s The value to write.
* @param [in] response True == request write response.
* @details Only used if the <type\> has a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
bool
#else
typename std::enable_if<Has_c_str_len<T>::value, bool>::type
#endif
writeValue(const T& s, bool response = false) {
return writeValue((uint8_t*)s.c_str(), s.length(), response);
}
/**
* @brief Template to convert the remote characteristic data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
* less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>getValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T getValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
if(!skipSizeCheck && m_value.size() < sizeof(T)) return T();
return *((T *)m_value.getValue(timestamp));
}
/**
* @brief Template to convert the remote characteristic data to <type\>.
* @tparam T The type to convert the data to.
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
* less than <tt>sizeof(<type\>)</tt>.
* @details <b>Use:</b> <tt>readValue<type>(&timestamp, skipSizeCheck);</tt>
*/
template<typename T>
T readValue(time_t *timestamp = nullptr, bool skipSizeCheck = false) {
NimBLEAttValue value = readValue();
if(!skipSizeCheck && value.size() < sizeof(T)) return T();
return *((T *)value.getValue(timestamp));
}
private: private:
@ -158,15 +179,12 @@ private:
uint16_t m_defHandle; uint16_t m_defHandle;
uint16_t m_endHandle; uint16_t m_endHandle;
NimBLERemoteService* m_pRemoteService; NimBLERemoteService* m_pRemoteService;
std::string m_value; NimBLEAttValue m_value;
notify_callback m_notifyCallback; notify_callback m_notifyCallback;
time_t m_timestamp;
portMUX_TYPE m_valMux;
// We maintain a vector of descriptors owned by this characteristic. // We maintain a vector of descriptors owned by this characteristic.
std::vector<NimBLERemoteDescriptor*> m_descriptorVector; std::vector<NimBLERemoteDescriptor*> m_descriptorVector;
}; // NimBLERemoteCharacteristic }; // NimBLERemoteCharacteristic
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */ #endif /* COMPONENTS_NIMBLEREMOTECHARACTERISTIC_H_ */

View File

@ -11,16 +11,16 @@
* Created on: Jul 8, 2017 * Created on: Jul 8, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteDescriptor.h" #include "NimBLERemoteDescriptor.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
#include <climits>
static const char* LOG_TAG = "NimBLERemoteDescriptor"; static const char* LOG_TAG = "NimBLERemoteDescriptor";
/** /**
@ -86,11 +86,7 @@ NimBLEUUID NimBLERemoteDescriptor::getUUID() {
* @deprecated Use readValue<uint8_t>(). * @deprecated Use readValue<uint8_t>().
*/ */
uint8_t NimBLERemoteDescriptor::readUInt8() { uint8_t NimBLERemoteDescriptor::readUInt8() {
std::string value = readValue(); return readValue<uint8_t>();
if (value.length() >= 1) {
return (uint8_t) value[0];
}
return 0;
} // readUInt8 } // readUInt8
@ -100,11 +96,7 @@ uint8_t NimBLERemoteDescriptor::readUInt8() {
* @deprecated Use readValue<uint16_t>(). * @deprecated Use readValue<uint16_t>().
*/ */
uint16_t NimBLERemoteDescriptor::readUInt16() { uint16_t NimBLERemoteDescriptor::readUInt16() {
std::string value = readValue(); return readValue<uint16_t>();
if (value.length() >= 2) {
return *(uint16_t*) value.data();
}
return 0;
} // readUInt16 } // readUInt16
@ -114,11 +106,7 @@ uint16_t NimBLERemoteDescriptor::readUInt16() {
* @deprecated Use readValue<uint32_t>(). * @deprecated Use readValue<uint32_t>().
*/ */
uint32_t NimBLERemoteDescriptor::readUInt32() { uint32_t NimBLERemoteDescriptor::readUInt32() {
std::string value = readValue(); return readValue<uint32_t>();
if (value.length() >= 4) {
return *(uint32_t*) value.data();
}
return 0;
} // readUInt32 } // readUInt32
@ -126,11 +114,11 @@ uint32_t NimBLERemoteDescriptor::readUInt32() {
* @brief Read the value of the remote descriptor. * @brief Read the value of the remote descriptor.
* @return The value of the remote descriptor. * @return The value of the remote descriptor.
*/ */
std::string NimBLERemoteDescriptor::readValue() { NimBLEAttValue 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(); NimBLEClient* pClient = getRemoteCharacteristic()->getRemoteService()->getClient();
std::string value; NimBLEAttValue value;
if (!pClient->isConnected()) { if (!pClient->isConnected()) {
NIMBLE_LOGE(LOG_TAG, "Disconnected"); NIMBLE_LOGE(LOG_TAG, "Disconnected");
@ -180,7 +168,7 @@ std::string NimBLERemoteDescriptor::readValue() {
} }
} while(rc != 0 && retryCount--); } while(rc != 0 && retryCount--);
NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %d rc=%d", value.length(), rc); NIMBLE_LOGD(LOG_TAG, "<< Descriptor readValue(): length: %u rc=%d", value.length(), rc);
return value; return value;
} // readValue } // readValue
@ -193,6 +181,7 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
const struct ble_gatt_error *error, const struct ble_gatt_error *error,
struct ble_gatt_attr *attr, void *arg) struct ble_gatt_attr *attr, void *arg)
{ {
(void)attr;
ble_task_data_t *pTaskData = (ble_task_data_t*)arg; ble_task_data_t *pTaskData = (ble_task_data_t*)arg;
NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)pTaskData->pATT; NimBLERemoteDescriptor* desc = (NimBLERemoteDescriptor*)pTaskData->pATT;
uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId(); uint16_t conn_id = desc->getRemoteCharacteristic()->getRemoteService()->getClient()->getConnId();
@ -203,17 +192,17 @@ int NimBLERemoteDescriptor::onReadCB(uint16_t conn_handle,
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);
std::string *strBuf = (std::string*)pTaskData->buf; NimBLEAttValue *valBuf = (NimBLEAttValue*)pTaskData->buf;
int rc = error->status; int rc = error->status;
if(rc == 0) { if(rc == 0) {
if(attr) { if(attr) {
uint32_t data_len = OS_MBUF_PKTLEN(attr->om); uint16_t data_len = OS_MBUF_PKTLEN(attr->om);
if(((*strBuf).length() + data_len) > BLE_ATT_ATTR_MAX_LEN) { if((valBuf->size() + data_len) > BLE_ATT_ATTR_MAX_LEN) {
rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} else { } else {
NIMBLE_LOGD(LOG_TAG, "Got %d bytes", data_len); NIMBLE_LOGD(LOG_TAG, "Got %u bytes", data_len);
(*strBuf) += std::string((char*) attr->om->om_data, data_len); valBuf->append(attr->om->om_data, data_len);
return 0; return 0;
} }
} }
@ -266,11 +255,33 @@ int NimBLERemoteDescriptor::onWriteCB(uint16_t conn_handle,
/** /**
* @brief Write data to the BLE Remote Descriptor. * @brief Write a new value to a remote descriptor from a std::vector<uint8_t>.
* @param [in] vec A std::vector<uint8_t> value to write to the remote descriptor.
* @param [in] response Whether we require a response from the write.
* @return false if not connected or otherwise cannot perform write.
*/
bool NimBLERemoteDescriptor::writeValue(const std::vector<uint8_t>& vec, bool response) {
return writeValue((uint8_t*)&vec[0], vec.size(), response);
} // writeValue
/**
* @brief Write a new value to the remote descriptor from a const char*.
* @param [in] char_s A character string to write to the remote descriptor.
* @param [in] response Whether we require a response from the write.
* @return false if not connected or otherwise cannot perform write.
*/
bool NimBLERemoteDescriptor::writeValue(const char* char_s, bool response) {
return writeValue((uint8_t*)char_s, strlen(char_s), response);
} // writeValue
/**
* @brief Write a new value to a remote descriptor.
* @param [in] data The data to send to the remote descriptor. * @param [in] data The data to send to the remote descriptor.
* @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 write response. * @param [in] response True if we expect a write response.
* @return True if successful * @return false if not connected or otherwise cannot perform write.
*/ */
bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) { bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool response) {
@ -351,15 +362,4 @@ bool NimBLERemoteDescriptor::writeValue(const uint8_t* data, size_t length, bool
} // writeValue } // writeValue
/** #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
* @brief Write data represented as a string to the BLE Remote Descriptor.
* @param [in] newValue The data to send to the remote descriptor.
* @param [in] response True if we expect a response.
* @return True if successful
*/
bool NimBLERemoteDescriptor::writeValue(const std::string &newValue, bool response) {
return writeValue((uint8_t*) newValue.data(), newValue.length(), response);
} // writeValue
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */

View File

@ -14,11 +14,9 @@
#ifndef COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ #ifndef COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_
#define COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ #define COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteCharacteristic.h" #include "NimBLERemoteCharacteristic.h"
@ -31,10 +29,53 @@ public:
uint16_t getHandle(); uint16_t getHandle();
NimBLERemoteCharacteristic* getRemoteCharacteristic(); NimBLERemoteCharacteristic* getRemoteCharacteristic();
NimBLEUUID getUUID(); NimBLEUUID getUUID();
std::string readValue(); NimBLEAttValue readValue();
uint8_t readUInt8() __attribute__ ((deprecated("Use template readValue<uint8_t>()")));
uint16_t readUInt16() __attribute__ ((deprecated("Use template readValue<uint16_t>()")));
uint32_t readUInt32() __attribute__ ((deprecated("Use template readValue<uint32_t>()")));
std::string toString(void);
bool writeValue(const uint8_t* data, size_t length, bool response = false);
bool writeValue(const std::vector<uint8_t>& v, bool response = false);
bool writeValue(const char* s, bool response = false);
/*********************** Template Functions ************************/
/** /**
* @brief A template to convert the remote descriptor data to <type\>. * @brief Template to set the remote descriptor value to <type\>val.
* @param [in] s The value to write.
* @param [in] response True == request write response.
* @details Only used for non-arrays and types without a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
bool
#else
typename std::enable_if<!std::is_array<T>::value && !Has_c_str_len<T>::value, bool>::type
#endif
writeValue(const T& s, bool response = false) {
return writeValue((uint8_t*)&s, sizeof(T), response);
}
/**
* @brief Template to set the remote descriptor value to <type\>val.
* @param [in] s The value to write.
* @param [in] response True == request write response.
* @details Only used if the <type\> has a `c_str()` method.
*/
template<typename T>
#ifdef _DOXYGEN_
bool
#else
typename std::enable_if<Has_c_str_len<T>::value, bool>::type
#endif
writeValue(const T& s, bool response = false) {
return writeValue((uint8_t*)s.c_str(), s.length(), response);
}
/**
* @brief Template to convert the remote descriptor data to <type\>.
* @tparam T The type to convert the data to. * @tparam T The type to convert the data to.
* @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>. * @param [in] skipSizeCheck If true it will skip checking if the data size is less than <tt>sizeof(<type\>)</tt>.
* @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is * @return The data converted to <type\> or NULL if skipSizeCheck is false and the data is
@ -42,28 +83,10 @@ public:
* @details <b>Use:</b> <tt>readValue<type>(skipSizeCheck);</tt> * @details <b>Use:</b> <tt>readValue<type>(skipSizeCheck);</tt>
*/ */
template<typename T> template<typename T>
T readValue(bool skipSizeCheck = false) { T readValue(bool skipSizeCheck = false) {
std::string value = readValue(); NimBLEAttValue value = readValue();
if(!skipSizeCheck && value.size() < sizeof(T)) return T(); if(!skipSizeCheck && value.size() < sizeof(T)) return T();
const char *pData = value.data(); return *((T *)value.data());
return *((T *)pData);
}
uint8_t readUInt8() __attribute__ ((deprecated("Use template readValue<uint8_t>()")));
uint16_t readUInt16() __attribute__ ((deprecated("Use template readValue<uint16_t>()")));
uint32_t readUInt32() __attribute__ ((deprecated("Use template readValue<uint32_t>()")));
std::string toString(void);
bool writeValue(const uint8_t* data, size_t length, bool response = false);
bool writeValue(const std::string &newValue, bool response = false);
/**
* @brief Convenience template to set the remote descriptor value to <type\>val.
* @param [in] s The value to write.
* @param [in] response True == request write response.
*/
template<typename T>
bool writeValue(const T &s, bool response = false) {
return writeValue((uint8_t*)&s, sizeof(T), response);
} }
private: private:
@ -81,6 +104,5 @@ private:
NimBLERemoteCharacteristic* m_pRemoteCharacteristic; NimBLERemoteCharacteristic* m_pRemoteCharacteristic;
}; };
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */ #endif /* COMPONENTS_NIMBLEREMOTEDESCRIPTOR_H_ */

View File

@ -11,17 +11,17 @@
* Created on: Jul 8, 2017 * Created on: Jul 8, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLERemoteService.h" #include "NimBLERemoteService.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
#include "NimBLELog.h" #include "NimBLELog.h"
#include <climits>
static const char* LOG_TAG = "NimBLERemoteService"; static const char* LOG_TAG = "NimBLERemoteService";
/** /**
@ -109,7 +109,7 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
return m_characteristicVector.back(); return m_characteristicVector.back();
} }
// If the request was successful but 16/32 bit characteristic not found // If the request was successful but 16/32 bit uuid not found
// try again with the 128 bit uuid. // try again with the 128 bit uuid.
if(uuid.bitSize() == BLE_UUID_TYPE_16 || if(uuid.bitSize() == BLE_UUID_TYPE_16 ||
uuid.bitSize() == BLE_UUID_TYPE_32) uuid.bitSize() == BLE_UUID_TYPE_32)
@ -117,6 +117,15 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
NimBLEUUID uuid128(uuid); NimBLEUUID uuid128(uuid);
uuid128.to128(); uuid128.to128();
return getCharacteristic(uuid128); return getCharacteristic(uuid128);
} else {
// If the request was successful but the 128 bit uuid not found
// try again with the 16 bit uuid.
NimBLEUUID uuid16(uuid);
uuid16.to16();
// if the uuid was 128 bit but not of the BLE base type this check will fail
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
return getCharacteristic(uuid16);
}
} }
} }
@ -391,6 +400,4 @@ std::string NimBLERemoteService::toString() {
return res; return res;
} // toString } // toString
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#endif /* CONFIG_BT_ENABLED */

View File

@ -14,11 +14,9 @@
#ifndef COMPONENTS_NIMBLEREMOTESERVICE_H_ #ifndef COMPONENTS_NIMBLEREMOTESERVICE_H_
#define COMPONENTS_NIMBLEREMOTESERVICE_H_ #define COMPONENTS_NIMBLEREMOTESERVICE_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
#include "NimBLEClient.h" #include "NimBLEClient.h"
#include "NimBLEUUID.h" #include "NimBLEUUID.h"
@ -83,6 +81,5 @@ private:
uint16_t m_endHandle; uint16_t m_endHandle;
}; // NimBLERemoteService }; // NimBLERemoteService
#endif // #if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */ #endif /* COMPONENTS_NIMBLEREMOTESERVICE_H_ */

View File

@ -11,17 +11,16 @@
* Created on: Jul 1, 2017 * Created on: Jul 1, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEScan.h" #include "NimBLEScan.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
#include "NimBLELog.h" #include "NimBLELog.h"
#include <string> #include <string>
#include <climits>
static const char* LOG_TAG = "NimBLEScan"; static const char* LOG_TAG = "NimBLEScan";
@ -284,7 +283,7 @@ bool NimBLEScan::isScanning() {
* @return True if scan started or false if there was an error. * @return True if scan started or false if there was an error.
*/ */
bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) { bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResults), bool is_continue) {
NIMBLE_LOGD(LOG_TAG, ">> start(duration=%d)", duration); NIMBLE_LOGD(LOG_TAG, ">> start: duration=%" PRIu32, duration);
// Save the callback to be invoked when the scan completes. // Save the callback to be invoked when the scan completes.
m_scanCompleteCB = scanCompleteCB; m_scanCompleteCB = scanCompleteCB;
@ -539,5 +538,4 @@ NimBLEAdvertisedDevice *NimBLEScanResults::getDevice(const NimBLEAddress &addres
return nullptr; return nullptr;
} }
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_OBSERVER */
#endif /* CONFIG_BT_ENABLED */

View File

@ -13,16 +13,18 @@
*/ */
#ifndef COMPONENTS_NIMBLE_SCAN_H_ #ifndef COMPONENTS_NIMBLE_SCAN_H_
#define COMPONENTS_NIMBLE_SCAN_H_ #define COMPONENTS_NIMBLE_SCAN_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER)
#include "NimBLEAdvertisedDevice.h" #include "NimBLEAdvertisedDevice.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_gap.h" #include "host/ble_gap.h"
#else
#include "nimble/nimble/host/include/host/ble_gap.h"
#endif
#include <vector> #include <vector>
@ -97,6 +99,5 @@ private:
uint8_t m_maxResults; uint8_t m_maxResults;
}; };
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) #endif /* CONFIG_BT_ENABLED CONFIG_BT_NIMBLE_ROLE_OBSERVER */
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_NIMBLE_SCAN_H_ */ #endif /* COMPONENTS_NIMBLE_SCAN_H_ */

View File

@ -12,7 +12,7 @@
* Author: chegewara * Author: chegewara
*/ */
#include "sdkconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "NimBLESecurity.h" #include "NimBLESecurity.h"

View File

@ -14,10 +14,16 @@
#ifndef COMPONENTS_NIMBLESECURITY_H_ #ifndef COMPONENTS_NIMBLESECURITY_H_
#define COMPONENTS_NIMBLESECURITY_H_ #define COMPONENTS_NIMBLESECURITY_H_
#include "sdkconfig.h"
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_gap.h" #include "host/ble_gap.h"
#else
#include "nimble/nimble/host/include/host/ble_gap.h"
#endif
/**** FIX COMPILATION ****/ /**** FIX COMPILATION ****/
#undef min #undef min
#undef max #undef max

View File

@ -12,19 +12,20 @@
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEServer.h" #include "NimBLEServer.h"
#include "NimBLEDevice.h" #include "NimBLEDevice.h"
#include "NimBLELog.h" #include "NimBLELog.h"
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "services/gap/ble_svc_gap.h" #include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h" #include "services/gatt/ble_svc_gatt.h"
#else
#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h"
#endif
static const char* LOG_TAG = "NimBLEServer"; static const char* LOG_TAG = "NimBLEServer";
static NimBLEServerCallbacks defaultCallbacks; static NimBLEServerCallbacks defaultCallbacks;
@ -74,23 +75,19 @@ NimBLEService* NimBLEServer::createService(const char* uuid) {
/** /**
* @brief Create a %BLE Service. * @brief Create a %BLE Service.
* @param [in] uuid The UUID of the new service. * @param [in] uuid The UUID of the new service.
* @param [in] numHandles The maximum number of handles associated with this service.
* @param [in] inst_id if we have 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(const NimBLEUUID &uuid, uint32_t numHandles, uint8_t inst_id) { NimBLEService* NimBLEServer::createService(const NimBLEUUID &uuid) {
NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str()); NIMBLE_LOGD(LOG_TAG, ">> createService - %s", uuid.toString().c_str());
// TODO: add functionality to use inst_id for multiple services with same uuid
(void)inst_id;
// Check that a service with the supplied UUID does not already exist. // Check that a service with the supplied UUID does not already exist.
if(getServiceByUUID(uuid) != nullptr) { if(getServiceByUUID(uuid) != nullptr) {
NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s", NIMBLE_LOGW(LOG_TAG, "Warning creating a duplicate service UUID: %s",
std::string(uuid).c_str()); std::string(uuid).c_str());
} }
NimBLEService* pService = new NimBLEService(uuid, numHandles, this); NimBLEService* pService = new NimBLEService(uuid);
m_svcVec.push_back(pService); // Save a reference to this service being on this server. m_svcVec.push_back(pService);
serviceChanged(); serviceChanged();
NIMBLE_LOGD(LOG_TAG, "<< createService"); NIMBLE_LOGD(LOG_TAG, "<< createService");
@ -181,7 +178,7 @@ void NimBLEServer::start() {
abort(); abort();
} }
#if CONFIG_NIMBLE_CPP_DEBUG_LEVEL >= 4 #if CONFIG_NIMBLE_CPP_LOG_LEVEL >= 4
ble_gatts_show_local(); ble_gatts_show_local();
#endif #endif
/*** Future use *** /*** Future use ***
@ -537,7 +534,7 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc); NIMBLE_LOGD(LOG_TAG, "BLE_SM_IOACT_DISP; ble_sm_inject_io result: %d", rc);
} else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) {
NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %d", event->passkey.params.numcmp); NIMBLE_LOGD(LOG_TAG, "Passkey on device's display: %" PRIu32, event->passkey.params.numcmp);
pkey.action = event->passkey.params.action; pkey.action = event->passkey.params.action;
// Compatibility only - Do not use, should be removed the in future // Compatibility only - Do not use, should be removed the in future
if(NimBLEDevice::m_securityCallbacks != nullptr) { if(NimBLEDevice::m_securityCallbacks != nullptr) {
@ -734,7 +731,7 @@ void NimBLEServer::startAdvertising() {
*/ */
void NimBLEServer::stopAdvertising() { void NimBLEServer::stopAdvertising() {
NimBLEDevice::stopAdvertising(); NimBLEDevice::stopAdvertising();
} // startAdvertising } // stopAdvertising
/** /**
@ -772,7 +769,31 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
if(rc != 0) { if(rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc)); NIMBLE_LOGE(LOG_TAG, "Update params error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
} }
}// updateConnParams } // updateConnParams
/**
* @brief Request an update of the data packet length.
* * Can only be used after a connection has been established.
* @details Sends a data length update request to the peer.
* The Data Length Extension (DLE) allows to increase the Data Channel Payload from 27 bytes to up to 251 bytes.
* The peer needs to support the Bluetooth 4.2 specifications, to be capable of DLE.
* @param [in] conn_handle The connection handle of the peer to send the request to.
* @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
*/
void NimBLEServer::setDataLen(uint16_t conn_handle, uint16_t tx_octets) {
#if defined(CONFIG_NIMBLE_CPP_IDF) && defined(ESP_IDF_VERSION) && \
ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 && ESP_IDF_VERSION_PATCH >= 2
return;
#else
uint16_t tx_time = (tx_octets + 14) * 8;
int rc = ble_gap_set_data_len(conn_handle, tx_octets, tx_time);
if(rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Set data length error: %d, %s", rc, NimBLEUtils::returnCodeToString(rc));
}
#endif
} // setDataLen
bool NimBLEServer::setIndicateWait(uint16_t conn_handle) { bool NimBLEServer::setIndicateWait(uint16_t conn_handle) {
@ -842,6 +863,4 @@ bool NimBLEServerCallbacks::onConfirmPIN(uint32_t pin){
return true; return true;
} }
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED

View File

@ -14,15 +14,15 @@
#ifndef MAIN_NIMBLESERVER_H_ #ifndef MAIN_NIMBLESERVER_H_
#define MAIN_NIMBLESERVER_H_ #define MAIN_NIMBLESERVER_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#define NIMBLE_ATT_REMOVE_HIDE 1 #define NIMBLE_ATT_REMOVE_HIDE 1
#define NIMBLE_ATT_REMOVE_DELETE 2 #define NIMBLE_ATT_REMOVE_DELETE 2
#define onMtuChanged onMTUChange
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLEAddress.h" #include "NimBLEAddress.h"
#include "NimBLEAdvertising.h" #include "NimBLEAdvertising.h"
@ -43,8 +43,7 @@ class NimBLEServer {
public: public:
size_t getConnectedCount(); size_t getConnectedCount();
NimBLEService* createService(const char* uuid); NimBLEService* createService(const char* uuid);
NimBLEService* createService(const NimBLEUUID &uuid, uint32_t numHandles=15, NimBLEService* createService(const NimBLEUUID &uuid);
uint8_t inst_id=0);
void removeService(NimBLEService* service, bool deleteSvc = false); void removeService(NimBLEService* service, bool deleteSvc = false);
void addService(NimBLEService* service); void addService(NimBLEService* service);
NimBLEAdvertising* getAdvertising(); NimBLEAdvertising* getAdvertising();
@ -61,6 +60,7 @@ public:
void updateConnParams(uint16_t conn_handle, void updateConnParams(uint16_t conn_handle,
uint16_t minInterval, uint16_t maxInterval, uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout); uint16_t latency, uint16_t timeout);
void setDataLen(uint16_t conn_handle, uint16_t tx_octets);
uint16_t getPeerMTU(uint16_t conn_id); uint16_t getPeerMTU(uint16_t conn_id);
std::vector<uint16_t> getPeerDevices(); std::vector<uint16_t> getPeerDevices();
NimBLEConnInfo getPeerInfo(size_t index); NimBLEConnInfo getPeerInfo(size_t index);
@ -168,7 +168,5 @@ public:
virtual bool onConfirmPIN(uint32_t pin); virtual bool onConfirmPIN(uint32_t pin);
}; // NimBLEServerCallbacks }; // NimBLEServerCallbacks
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif /* CONFIG_BT_ENABLED */
#endif /* MAIN_NIMBLESERVER_H_ */ #endif /* MAIN_NIMBLESERVER_H_ */

View File

@ -14,12 +14,10 @@
// A service is identified by a UUID. A service is also the container for one or more characteristics. // A service is identified by a UUID. A service is also the container for one or more characteristics.
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEDevice.h"
#include "NimBLEService.h" #include "NimBLEService.h"
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
@ -34,25 +32,19 @@ static const char* LOG_TAG = "NimBLEService"; // Tag for logging.
/** /**
* @brief Construct an instance of the NimBLEService * @brief Construct an instance of the NimBLEService
* @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] pServer A pointer to the server instance that this service belongs to.
*/ */
NimBLEService::NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer) NimBLEService::NimBLEService(const char* uuid)
: NimBLEService(NimBLEUUID(uuid), numHandles, pServer) { : NimBLEService(NimBLEUUID(uuid)) {
} }
/** /**
* @brief Construct an instance of the BLEService * @brief Construct an instance of the BLEService
* @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] pServer A pointer to the server instance that this service belongs to.
*/ */
NimBLEService::NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer) { NimBLEService::NimBLEService(const NimBLEUUID &uuid) {
m_uuid = uuid; m_uuid = uuid;
m_handle = NULL_HANDLE; m_handle = NULL_HANDLE;
m_pServer = pServer;
m_numHandles = numHandles;
m_pSvcDef = nullptr; m_pSvcDef = nullptr;
m_removed = 0; m_removed = 0;
@ -121,6 +113,12 @@ bool NimBLEService::start() {
// Rebuild the service definition if the server attributes have changed. // Rebuild the service definition if the server attributes have changed.
if(getServer()->m_svcChanged && m_pSvcDef != nullptr) { if(getServer()->m_svcChanged && m_pSvcDef != nullptr) {
if(m_pSvcDef[0].characteristics) {
if(m_pSvcDef[0].characteristics[0].descriptors) {
delete(m_pSvcDef[0].characteristics[0].descriptors);
}
delete(m_pSvcDef[0].characteristics);
}
delete(m_pSvcDef); delete(m_pSvcDef);
m_pSvcDef = nullptr; m_pSvcDef = nullptr;
} }
@ -258,10 +256,11 @@ uint16_t NimBLEService::getHandle() {
* @brief Create a new BLE Characteristic associated with this service. * @brief Create a new BLE Characteristic associated with this service.
* @param [in] uuid - The UUID of the characteristic. * @param [in] uuid - The UUID of the characteristic.
* @param [in] properties - The properties of the characteristic. * @param [in] properties - The properties of the characteristic.
* @param [in] max_len - The maximum length in bytes that the characteristic value can hold.
* @return The new BLE characteristic. * @return The new BLE characteristic.
*/ */
NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint32_t properties) { NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint32_t properties, uint16_t max_len) {
return createCharacteristic(NimBLEUUID(uuid), properties); return createCharacteristic(NimBLEUUID(uuid), properties, max_len);
} }
@ -269,10 +268,11 @@ NimBLECharacteristic* NimBLEService::createCharacteristic(const char* uuid, uint
* @brief Create a new BLE Characteristic associated with this service. * @brief Create a new BLE Characteristic associated with this service.
* @param [in] uuid - The UUID of the characteristic. * @param [in] uuid - The UUID of the characteristic.
* @param [in] properties - The properties of the characteristic. * @param [in] properties - The properties of the characteristic.
* @param [in] max_len - The maximum length in bytes that the characteristic value can hold.
* @return The new BLE characteristic. * @return The new BLE characteristic.
*/ */
NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties) { NimBLECharacteristic* NimBLEService::createCharacteristic(const NimBLEUUID &uuid, uint32_t properties, uint16_t max_len) {
NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, this); NimBLECharacteristic* pCharacteristic = new NimBLECharacteristic(uuid, properties, max_len, this);
if (getCharacteristic(uuid) != nullptr) { if (getCharacteristic(uuid) != nullptr) {
NIMBLE_LOGD(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s", NIMBLE_LOGD(LOG_TAG, "<< Adding a duplicate characteristic with UUID: %s",
@ -429,8 +429,7 @@ std::string NimBLEService::toString() {
* @return The BLEServer associated with this service. * @return The BLEServer associated with this service.
*/ */
NimBLEServer* NimBLEService::getServer() { NimBLEServer* NimBLEService::getServer() {
return m_pServer; return NimBLEDevice::getServer();
}// getServer }// getServer
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // CONFIG_BT_ENABLED

View File

@ -14,11 +14,9 @@
#ifndef MAIN_NIMBLESERVICE_H_ #ifndef MAIN_NIMBLESERVICE_H_
#define MAIN_NIMBLESERVICE_H_ #define MAIN_NIMBLESERVICE_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include "nimconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#include "NimBLEServer.h" #include "NimBLEServer.h"
#include "NimBLECharacteristic.h" #include "NimBLECharacteristic.h"
@ -36,8 +34,8 @@ class NimBLECharacteristic;
class NimBLEService { class NimBLEService {
public: public:
NimBLEService(const char* uuid, uint16_t numHandles, NimBLEServer* pServer); NimBLEService(const char* uuid);
NimBLEService(const NimBLEUUID &uuid, uint16_t numHandles, NimBLEServer* pServer); NimBLEService(const NimBLEUUID &uuid);
~NimBLEService(); ~NimBLEService();
NimBLEServer* getServer(); NimBLEServer* getServer();
@ -52,12 +50,14 @@ public:
NimBLECharacteristic* createCharacteristic(const char* uuid, NimBLECharacteristic* createCharacteristic(const char* uuid,
uint32_t properties = uint32_t properties =
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE); NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
NimBLECharacteristic* createCharacteristic(const NimBLEUUID &uuid, NimBLECharacteristic* createCharacteristic(const NimBLEUUID &uuid,
uint32_t properties = uint32_t properties =
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE); NIMBLE_PROPERTY::WRITE,
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
void addCharacteristic(NimBLECharacteristic* pCharacteristic); void addCharacteristic(NimBLECharacteristic* pCharacteristic);
void removeCharacteristic(NimBLECharacteristic* pCharacteristic, bool deleteChr = false); void removeCharacteristic(NimBLECharacteristic* pCharacteristic, bool deleteChr = false);
@ -76,16 +76,12 @@ private:
friend class NimBLEDevice; friend class NimBLEDevice;
uint16_t m_handle; uint16_t m_handle;
NimBLEServer* m_pServer;
NimBLEUUID m_uuid; NimBLEUUID m_uuid;
uint16_t m_numHandles;
ble_gatt_svc_def* m_pSvcDef; ble_gatt_svc_def* m_pSvcDef;
uint8_t m_removed; uint8_t m_removed;
std::vector<NimBLECharacteristic*> m_chrVec; std::vector<NimBLECharacteristic*> m_chrVec;
}; // NimBLEService }; // NimBLEService
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
#endif // CONFIG_BT_ENABLED
#endif /* MAIN_NIMBLESERVICE_H_ */ #endif /* MAIN_NIMBLESERVICE_H_ */

View File

@ -11,7 +11,8 @@
* Created on: Jun 21, 2017 * Created on: Jun 21, 2017
* Author: kolban * Author: kolban
*/ */
#include "sdkconfig.h"
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
@ -234,8 +235,8 @@ const ble_uuid_any_t* NimBLEUUID::getNative() const {
/** /**
* @brief Convert a UUID to its 128 bit representation. * @brief Convert a UUID to its 128 bit representation.
* @details A UUID can be internally represented as 16bit, 32bit or the full 128bit. This method * @details A UUID can be internally represented as 16bit, 32bit or the full 128bit.
* will convert 16 or 32 bit representations to the full 128bit. * This method will convert 16 or 32bit representations to the full 128bit.
* @return The NimBLEUUID converted to 128bit. * @return The NimBLEUUID converted to 128bit.
*/ */
const NimBLEUUID &NimBLEUUID::to128() { const NimBLEUUID &NimBLEUUID::to128() {
@ -256,6 +257,29 @@ const NimBLEUUID &NimBLEUUID::to128() {
} // to128 } // to128
/**
* @brief Convert 128 bit UUID to its 16 bit representation.
* @details A UUID can be internally represented as 16bit, 32bit or the full 128bit.
* This method will convert a 128bit uuid to 16bit if it contains the ble base uuid.
* @return The NimBLEUUID converted to 16bit if successful, otherwise the original uuid.
*/
const NimBLEUUID& NimBLEUUID::to16() {
if (!m_valueSet || m_uuid.u.type == BLE_UUID_TYPE_16) {
return *this;
}
if (m_uuid.u.type == BLE_UUID_TYPE_128) {
uint8_t base128[] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00,
0x00, 0x80, 0x00, 0x10, 0x00, 0x00};
if (memcmp(m_uuid.u128.value, base128, sizeof(base128)) == 0 ) {
*this = NimBLEUUID(*(uint16_t*)(m_uuid.u128.value + 12));
}
}
return *this;
}
/** /**
* @brief Get a string representation of the UUID. * @brief Get a string representation of the UUID.
* @details * @details

View File

@ -14,10 +14,16 @@
#ifndef COMPONENTS_NIMBLEUUID_H_ #ifndef COMPONENTS_NIMBLEUUID_H_
#define COMPONENTS_NIMBLEUUID_H_ #define COMPONENTS_NIMBLEUUID_H_
#include "sdkconfig.h"
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_uuid.h" #include "host/ble_uuid.h"
#else
#include "nimble/nimble/host/include/host/ble_uuid.h"
#endif
/**** FIX COMPILATION ****/ /**** FIX COMPILATION ****/
#undef min #undef min
#undef max #undef max
@ -42,6 +48,7 @@ public:
bool equals(const NimBLEUUID &uuid) const; bool equals(const NimBLEUUID &uuid) const;
const ble_uuid_any_t* getNative() const; const ble_uuid_any_t* getNative() const;
const NimBLEUUID & to128(); const NimBLEUUID & to128();
const NimBLEUUID& to16();
std::string toString() const; std::string toString() const;
static NimBLEUUID fromString(const std::string &uuid); static NimBLEUUID fromString(const std::string &uuid);

View File

@ -6,12 +6,13 @@
* *
*/ */
#include "sdkconfig.h" #include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#include "NimBLEUtils.h" #include "NimBLEUtils.h"
#include "NimBLELog.h" #include "NimBLELog.h"
#include "nimconfig.h"
#include <stdlib.h>
static const char* LOG_TAG = "NimBLEUtils"; static const char* LOG_TAG = "NimBLEUtils";
@ -342,6 +343,7 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
return "Unknown"; return "Unknown";
} }
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
(void)rc;
return ""; return "";
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT) #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT)
} }
@ -369,6 +371,7 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
return "Unknown flag"; return "Unknown flag";
} }
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
(void)advType;
return ""; return "";
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT) #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
} // adFlagsToString } // adFlagsToString
@ -416,8 +419,11 @@ char* NimBLEUtils::buildHexData(uint8_t* target, const uint8_t* source, uint8_t
* @param [in] arg Unused. * @param [in] arg Unused.
*/ */
void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){ void NimBLEUtils::dumpGapEvent(ble_gap_event *event, void *arg){
(void)arg;
#if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) #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));
#else
(void)event;
#endif #endif
} }
@ -504,6 +510,7 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) {
return "Unknown event type"; return "Unknown event type";
} }
#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) #else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
(void)eventType;
return ""; return "";
#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT) #endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT)
} // gapEventToString } // gapEventToString

View File

@ -8,10 +8,15 @@
#ifndef COMPONENTS_NIMBLEUTILS_H_ #ifndef COMPONENTS_NIMBLEUTILS_H_
#define COMPONENTS_NIMBLEUTILS_H_ #define COMPONENTS_NIMBLEUTILS_H_
#include "sdkconfig.h"
#include "nimconfig.h"
#if defined(CONFIG_BT_ENABLED) #if defined(CONFIG_BT_ENABLED)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_gap.h" #include "host/ble_gap.h"
#else
#include "nimble/nimble/host/include/host/ble_gap.h"
#endif
/**** FIX COMPILATION ****/ /**** FIX COMPILATION ****/
#undef min #undef min
@ -24,7 +29,7 @@ typedef struct {
void *pATT; void *pATT;
TaskHandle_t task; TaskHandle_t task;
int rc; int rc;
std::string *buf; void *buf;
} ble_task_data_t; } ble_task_data_t;

View File

@ -1,21 +0,0 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
//Licensed 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.
#ifndef _CONSOLE_H
#define _CONSOLE_H
#include <stdio.h>
#define console_printf printf
#endif

View File

@ -1,33 +0,0 @@
// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#ifndef __ESP_COMPILER_H
#define __ESP_COMPILER_H
/*
* The likely and unlikely macro pairs:
* These macros are useful to place when application
* knows the majority ocurrence of a decision paths,
* placing one of these macros can hint the compiler
* to reorder instructions producing more optimized
* code.
*/
#if (CONFIG_COMPILER_OPTIMIZATION_PERF)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif
#endif

View File

@ -0,0 +1,217 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed 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.
This product bundles queue.h 8.5, which is available under the "3-clause BSD"
license. For details, see porting/nimble/include/os/queue.h
This product partly derives from FreeBSD, which is available under the
"3-clause BSD" license. For details, see:
* porting/nimble/src/os_mbuf.c
This product bundles Gary S. Brown's CRC32 implementation, which is available
under the following license:
COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
code or tables extracted from it, as desired without restriction.
This product bundles tinycrypt, which is available under the "3-clause BSD"
license. For details, and bundled files see:
* ext/tinycrypt/LICENSE

View File

@ -1,5 +1,6 @@
Apache Mynewt NimBLE Apache Mynewt NimBLE
Copyright 2015-2018 The Apache Software Foundation Copyright 2015-2020 The Apache Software Foundation
Modifications Copyright 2017-2020 Espressif Systems (Shanghai) CO., LTD.
This product includes software developed at This product includes software developed at
The Apache Software Foundation (http://www.apache.org/). The Apache Software Foundation (http://www.apache.org/).

View File

@ -23,7 +23,7 @@
## Overview ## Overview
Apache NimBLE is an open-source Bluetooth 5.0 stack (both Host & Controller) Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller)
that completely replaces the proprietary SoftDevice on Nordic chipsets. It is that completely replaces the proprietary SoftDevice on Nordic chipsets. It is
part of [Apache Mynewt project](https://github.com/apache/mynewt-core). part of [Apache Mynewt project](https://github.com/apache/mynewt-core).
@ -33,7 +33,6 @@ Features highlight:
- Support for up to 32 simultaneous connections. - Support for up to 32 simultaneous connections.
- Legacy and SC (secure connections) SMP support (pairing and bonding). - Legacy and SC (secure connections) SMP support (pairing and bonding).
- Advertising Extensions. - Advertising Extensions.
- Periodic Advertising.
- Coded (aka Long Range) and 2M PHYs. - Coded (aka Long Range) and 2M PHYs.
- Bluetooth Mesh. - Bluetooth Mesh.
@ -84,27 +83,24 @@ There are also some sample applications that show how to Apache Mynewt NimBLE
stack. These sample applications are located in the `apps/` directory of stack. These sample applications are located in the `apps/` directory of
Apache Mynewt [repo](https://github.com/apache/mynewt-core). Some examples: Apache Mynewt [repo](https://github.com/apache/mynewt-core). Some examples:
* [blecent](https://github.com/apache/mynewt-core/tree/master/apps/blecent): * [blecent](https://github.com/apache/mynewt-nimble/tree/master/apps/blecent):
A basic central device with no user interface. This application scans for A basic central device with no user interface. This application scans for
a peripheral that supports the alert notification service (ANS). Upon a peripheral that supports the alert notification service (ANS). Upon
discovering such a peripheral, blecent connects and performs a characteristic discovering such a peripheral, blecent connects and performs a characteristic
read, characteristic write, and notification subscription. read, characteristic write, and notification subscription.
* [blehci](https://github.com/apache/mynewt-core/tree/master/apps/blehci): * [blehci](https://github.com/apache/mynewt-nimble/tree/master/apps/blehci):
Implements a BLE controller-only application. A separate host-only Implements a BLE controller-only application. A separate host-only
implementation, such as Linux's BlueZ, can interface with this application via implementation, such as Linux's BlueZ, can interface with this application via
HCI over UART. HCI over UART.
* [bleprph](https://github.com/apache/mynewt-core/tree/master/apps/bleprph): An * [bleprph](https://github.com/apache/mynewt-nimble/tree/master/apps/bleprph): An
implementation of a minimal BLE peripheral. implementation of a minimal BLE peripheral.
* [btshell](https://github.com/apache/mynewt-core/tree/master/apps/btshell): A * [btshell](https://github.com/apache/mynewt-nimble/tree/master/apps/btshell): A
shell-like application allowing to configure and use most of NimBLE shell-like application allowing to configure and use most of NimBLE
functionality from command line. functionality from command line.
* [bleuart](https://github.com/apache/mynewt-core/tree/master/apps/bleuart): * [bleuart](https://github.com/apache/mynewt-core/tree/master/apps/bleuart):
Implements a simple BLE peripheral that supports the Nordic Implements a simple BLE peripheral that supports the Nordic
UART / Serial Port Emulation service UART / Serial Port Emulation service
(https://developer.nordicsemi.com/nRF5_SDK/nRF51_SDK_v8.x.x/doc/8.0.0/s110/html/a00072.html). (https://developer.nordicsemi.com/nRF5_SDK/nRF51_SDK_v8.x.x/doc/8.0.0/s110/html/a00072.html).
* [test](https://github.com/apache/mynewt-core/tree/master/apps/test): Test
project which can be compiled either with the simulator, or on a per-architecture basis.
Test will run all the package's unit tests.
# Getting Help # Getting Help
@ -113,7 +109,7 @@ want to talk to a human about what you're working on, you can contact us via the
[developers mailing list](mailto:dev@mynewt.apache.org). [developers mailing list](mailto:dev@mynewt.apache.org).
Although not a formal channel, you can also find a number of core developers Although not a formal channel, you can also find a number of core developers
on the #mynewt channel on Freenode IRC or #general channel on [Mynewt Slack](https://join.slack.com/mynewt/shared_invite/MTkwMTg1ODM1NTg5LTE0OTYxNzQ4NzQtZTU1YmNhYjhkMg) on the #mynewt channel on Freenode IRC or #general channel on [Mynewt Slack](https://mynewt.slack.com/join/shared_invite/enQtNjA1MTg0NzgyNzg3LTcyMmZiOGQzOGMxM2U4ODFmMTIwNjNmYTE5Y2UwYjQwZWIxNTE0MTUzY2JmMTEzOWFjYWZkNGM0YmM4MzAxNWQ)
Also, be sure to checkout the [Frequently Asked Questions](https://mynewt.apache.org/faq/answers) Also, be sure to checkout the [Frequently Asked Questions](https://mynewt.apache.org/faq/answers)
for some help troubleshooting first. for some help troubleshooting first.

View File

@ -1,26 +1,32 @@
# RELEASE NOTES # RELEASE NOTES
16 July 2019 - Apache NimBLE v1.2.0 18 March 2020 - Apache NimBLE v1.3.0
For full release notes, please visit the For full release notes, please visit the
[Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes). [Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes).
Apache NimBLE is an open-source Bluetooth 5.0 stack (both Host & Controller) that completely Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller) that completely
replaces the proprietary SoftDevice on Nordic chipsets. replaces the proprietary SoftDevice on Nordic chipsets.
New features in this version of NimBLE include: New features in this version of NimBLE include:
* Perdiodic Advertising support with up to 1650 bytes of data (scanner and advertiser) * Support for Bluetooth Core Specification 5.1
* Support for scan request notification in GAP API * New blestress test application
* Updated host qualification ID * Dialog DA1469x CMAC driver
* Support for LE Secure Connections out-of-band (OOB) association model
* Support for automated generation of syscfg for ports
* Qualification related bugfixes * Qualification related bugfixes
* GAP API doxygen documentation update
* BLE Mesh improvements - fixes and resync with latest Zephyr code * BLE Mesh improvements - fixes and resync with latest Zephyr code
* RIOT OS port fixes and improvements * RIOT OS port fixes and improvements
* btshell sample application improvements * btshell sample application improvements
* improvements for bttester application * improvements for bttester application
* Controller duplicates filtering improvements * Controller duplicates filtering improvements
* Memory and CPU usage optimizations in controller * Multi PHY support improvements
* Memory and CPU usage optimizations
* Use of packed structs for HCI (code size reduction)
* Linux sample improvements
* PTS test instructions updates
* Clock managements improvements in controller
If working on next-generation RTOS and Bluetooth protocol stack If working on next-generation RTOS and Bluetooth protocol stack
sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt

View File

@ -0,0 +1,16 @@
#ifndef __CONSOLE_H__
#define __CONSOLE_H__
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#define console_printf printf
#ifdef __cplusplus
}
#endif
#endif /* __CONSOLE_H__ */

View File

@ -0,0 +1,51 @@
// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#ifndef __ESP_COMPILER_H
#define __ESP_COMPILER_H
/*
* The likely and unlikely macro pairs:
* These macros are useful to place when application
* knows the majority ocurrence of a decision paths,
* placing one of these macros can hint the compiler
* to reorder instructions producing more optimized
* code.
*/
#if (CONFIG_COMPILER_OPTIMIZATION_PERF)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif
/*
* Utility macros used for designated initializers, which work differently
* in C99 and C++ standards mainly for aggregate types.
* The member separator, comma, is already part of the macro, please omit the trailing comma.
* Usage example:
* struct config_t { char* pchr; char arr[SIZE]; } config = {
* ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(pchr)
* ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(arr, "Value")
* };
*/
#ifdef __cplusplus
#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) { .member = value },
#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) .member = { },
#else
#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) .member = value,
#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member)
#endif
#endif

View File

@ -19,10 +19,11 @@
* under the License. * under the License.
*/ */
#ifdef ESP_PLATFORM
#ifndef __ESP_NIMBLE_HCI_H__ #ifndef __ESP_NIMBLE_HCI_H__
#define __ESP_NIMBLE_HCI_H__ #define __ESP_NIMBLE_HCI_H__
#include "nimble/ble_hci_trans.h" #include "nimble/nimble/include/nimble/ble_hci_trans.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -136,3 +137,4 @@ esp_err_t esp_nimble_hci_and_controller_deinit(void);
#endif #endif
#endif /* __ESP_NIMBLE_HCI_H__ */ #endif /* __ESP_NIMBLE_HCI_H__ */
#endif

View File

@ -19,17 +19,19 @@
* under the License. * under the License.
*/ */
#ifdef ESP_PLATFORM
#include <assert.h> #include <assert.h>
#include "sysinit/sysinit.h" #include "nimble/porting/nimble/include/sysinit/sysinit.h"
#include "nimble/hci_common.h" #include "nimble/nimble/include/nimble/hci_common.h"
#include "host/ble_hs.h" #include "nimble/nimble/host/include/host/ble_hs.h"
#include "nimble/nimble_port.h" #include "nimble/porting/nimble/include/nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h" #include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h"
#include "esp_nimble_hci.h" #include "../include/esp_nimble_hci.h"
#include "esp_nimble_mem.h" #include "../../port/include/esp_nimble_mem.h"
#include "esp_bt.h" #include <esp_bt.h>
#include "freertos/semphr.h" #include <freertos/semphr.h>
#include "esp_compiler.h" #include "../include/esp_compiler.h"
/* IPC is used to improve performance when calls come from a processor not running the NimBLE stack */ /* IPC is used to improve performance when calls come from a processor not running the NimBLE stack */
/* but does not exist for solo */ /* but does not exist for solo */
#ifndef CONFIG_FREERTOS_UNICORE #ifndef CONFIG_FREERTOS_UNICORE
@ -110,7 +112,7 @@ int ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) { if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
/* esp_ipc_call_blocking does not exist for solo */ /* esp_ipc_call_blocking does not exist for solo */
#ifndef CONFIG_FREERTOS_UNICORE #ifndef CONFIG_FREERTOS_UNICORE
if (xPortGetCoreID() != CONFIG_BT_NIMBLE_PINNED_TO_CORE) { if (xPortGetCoreID() != CONFIG_BT_NIMBLE_PINNED_TO_CORE && !xPortInIsrContext()) {
esp_ipc_call_blocking(CONFIG_BT_NIMBLE_PINNED_TO_CORE, esp_ipc_call_blocking(CONFIG_BT_NIMBLE_PINNED_TO_CORE,
ble_hci_trans_hs_cmd_tx_on_core, cmd); ble_hci_trans_hs_cmd_tx_on_core, cmd);
} else { } else {
@ -166,7 +168,7 @@ int ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
/* Don't check core ID if unicore */ /* Don't check core ID if unicore */
#ifndef CONFIG_FREERTOS_UNICORE #ifndef CONFIG_FREERTOS_UNICORE
tx_using_nimble_core = xPortGetCoreID() != CONFIG_BT_NIMBLE_PINNED_TO_CORE; tx_using_nimble_core = xPortGetCoreID() != CONFIG_BT_NIMBLE_PINNED_TO_CORE;
if (tx_using_nimble_core) { if (tx_using_nimble_core && !xPortInIsrContext()) {
data[0] = len; data[0] = len;
data[1] = (len >> 8); data[1] = (len >> 8);
data[2] = BLE_HCI_UART_H4_ACL; data[2] = BLE_HCI_UART_H4_ACL;
@ -183,7 +185,7 @@ int ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) { if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
/* esp_ipc_call_blocking does not exist for solo */ /* esp_ipc_call_blocking does not exist for solo */
#ifndef CONFIG_FREERTOS_UNICORE #ifndef CONFIG_FREERTOS_UNICORE
if (tx_using_nimble_core) { if (tx_using_nimble_core && !xPortInIsrContext()) {
esp_ipc_call_blocking(CONFIG_BT_NIMBLE_PINNED_TO_CORE, esp_ipc_call_blocking(CONFIG_BT_NIMBLE_PINNED_TO_CORE,
ble_hci_trans_hs_acl_tx_on_core, data); ble_hci_trans_hs_acl_tx_on_core, data);
} else { } else {
@ -310,7 +312,6 @@ static struct os_mbuf *ble_hci_trans_acl_buf_alloc(void)
static void ble_hci_rx_acl(uint8_t *data, uint16_t len) static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
{ {
struct os_mbuf *m; struct os_mbuf *m;
int rc;
int sr; int sr;
if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) { if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) {
return; return;
@ -319,11 +320,9 @@ static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
m = ble_hci_trans_acl_buf_alloc(); m = ble_hci_trans_acl_buf_alloc();
if (!m) { if (!m) {
ESP_LOGE(TAG, "%s failed to allocate ACL buffers; increase ACL_BUF_COUNT", __func__);
return; return;
} }
if ((rc = os_mbuf_append(m, data, len)) != 0) { if (os_mbuf_append(m, data, len)) {
ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc);
os_mbuf_free_chain(m); os_mbuf_free_chain(m);
return; return;
} }
@ -531,7 +530,6 @@ esp_err_t esp_nimble_hci_and_controller_init(void)
if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) { if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) {
return ret; return ret;
} }
return esp_nimble_hci_init(); return esp_nimble_hci_init();
} }
@ -593,3 +591,5 @@ esp_err_t esp_nimble_hci_and_controller_deinit(void)
return ESP_OK; return ESP_OK;
} }
#endif

View File

@ -18,11 +18,12 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
#ifdef ESP_PLATFORM
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "nimconfig.h" #include "nimconfig.h"
#include "esp_nimble_mem.h" #include "../include/esp_nimble_mem.h"
IRAM_ATTR void *nimble_platform_mem_malloc(size_t size) IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
{ {
@ -54,3 +55,4 @@ IRAM_ATTR void nimble_platform_mem_free(void *ptr)
{ {
heap_caps_free(ptr); heap_caps_free(ptr);
} }
#endif

View File

@ -74,7 +74,7 @@
#ifndef __TC_CBC_MODE_H__ #ifndef __TC_CBC_MODE_H__
#define __TC_CBC_MODE_H__ #define __TC_CBC_MODE_H__
#include <tinycrypt/aes.h> #include "aes.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -74,7 +74,7 @@
#ifndef __TC_CCM_MODE_H__ #ifndef __TC_CCM_MODE_H__
#define __TC_CCM_MODE_H__ #define __TC_CCM_MODE_H__
#include <tinycrypt/aes.h> #include "aes.h"
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -97,7 +97,7 @@
#ifndef __TC_CMAC_MODE_H__ #ifndef __TC_CMAC_MODE_H__
#define __TC_CMAC_MODE_H__ #define __TC_CMAC_MODE_H__
#include <tinycrypt/aes.h> #include "aes.h"
#include <stddef.h> #include <stddef.h>

View File

@ -67,8 +67,8 @@
#ifndef __TC_CTR_MODE_H__ #ifndef __TC_CTR_MODE_H__
#define __TC_CTR_MODE_H__ #define __TC_CTR_MODE_H__
#include <tinycrypt/aes.h> #include "aes.h"
#include <tinycrypt/constants.h> #include "constants.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -59,7 +59,7 @@
#ifndef __TC_CTR_PRNG_H__ #ifndef __TC_CTR_PRNG_H__
#define __TC_CTR_PRNG_H__ #define __TC_CTR_PRNG_H__
#include <tinycrypt/aes.h> #include "aes.h"
#define TC_CTR_PRNG_RESEED_REQ -1 #define TC_CTR_PRNG_RESEED_REQ -1

View File

@ -69,7 +69,7 @@
#ifndef __TC_ECC_DH_H__ #ifndef __TC_ECC_DH_H__
#define __TC_ECC_DH_H__ #define __TC_ECC_DH_H__
#include <tinycrypt/ecc.h> #include "ecc.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -78,7 +78,7 @@
#ifndef __TC_ECC_DSA_H__ #ifndef __TC_ECC_DSA_H__
#define __TC_ECC_DSA_H__ #define __TC_ECC_DSA_H__
#include <tinycrypt/ecc.h> #include "ecc.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -63,7 +63,7 @@
#ifndef __TC_HMAC_H__ #ifndef __TC_HMAC_H__
#define __TC_HMAC_H__ #define __TC_HMAC_H__
#include <tinycrypt/sha256.h> #include "sha256.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -68,8 +68,8 @@
#ifndef __TC_HMAC_PRNG_H__ #ifndef __TC_HMAC_PRNG_H__
#define __TC_HMAC_PRNG_H__ #define __TC_HMAC_PRNG_H__
#include <tinycrypt/sha256.h> #include "sha256.h"
#include <tinycrypt/hmac.h> #include "hmac.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -30,9 +30,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/aes.h> #include "../include/tinycrypt/aes.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
static const uint8_t inv_sbox[256] = { static const uint8_t inv_sbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,

View File

@ -30,9 +30,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/aes.h> #include "../include/tinycrypt/aes.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
static const uint8_t sbox[256] = { static const uint8_t sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,

View File

@ -30,9 +30,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/cbc_mode.h> #include "../include/tinycrypt/cbc_mode.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, const uint8_t *iv, unsigned int inlen, const uint8_t *iv,

View File

@ -30,9 +30,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/ccm_mode.h> #include "../include/tinycrypt/ccm_mode.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
#include <stdio.h> #include <stdio.h>

View File

@ -30,10 +30,10 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/aes.h> #include "../include/tinycrypt/aes.h"
#include <tinycrypt/cmac_mode.h> #include "../include/tinycrypt/cmac_mode.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
/* max number of calls until change the key (2^48).*/ /* max number of calls until change the key (2^48).*/
const static uint64_t MAX_CALLS = ((uint64_t)1 << 48); const static uint64_t MAX_CALLS = ((uint64_t)1 << 48);

View File

@ -30,9 +30,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/ctr_mode.h> #include "../include/tinycrypt/ctr_mode.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)

View File

@ -27,9 +27,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/ctr_prng.h> #include "../include/tinycrypt/ctr_prng.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <string.h> #include <string.h>
/* /*

View File

@ -52,8 +52,8 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/ecc.h> #include "../include/tinycrypt/ecc.h"
#include <tinycrypt/ecc_platform_specific.h> #include "../include/tinycrypt/ecc_platform_specific.h"
#include <string.h> #include <string.h>
/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform

View File

@ -54,9 +54,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/ecc.h> #include "../include/tinycrypt/ecc.h"
#include <tinycrypt/ecc_dh.h> #include "../include/tinycrypt/ecc_dh.h"
#include <string.h> #include <string.h>
#if default_RNG_defined #if default_RNG_defined

View File

@ -53,9 +53,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/ecc.h> #include "../include/tinycrypt/ecc.h"
#include <tinycrypt/ecc_dsa.h> #include "../include/tinycrypt/ecc_dsa.h"
#if default_RNG_defined #if default_RNG_defined
static uECC_RNG_Function g_rng_function = &default_CSPRNG; static uECC_RNG_Function g_rng_function = &default_CSPRNG;

View File

@ -30,9 +30,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/hmac.h> #include "../include/tinycrypt/hmac.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size)
{ {

View File

@ -30,10 +30,10 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/hmac_prng.h> #include "../include/tinycrypt/hmac_prng.h"
#include <tinycrypt/hmac.h> #include "../include/tinycrypt/hmac.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
/* /*
* min bytes in the seed string. * min bytes in the seed string.

View File

@ -30,9 +30,9 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/sha256.h> #include "../include/tinycrypt/sha256.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
static void compress(unsigned int *iv, const uint8_t *data); static void compress(unsigned int *iv, const uint8_t *data);

View File

@ -30,8 +30,8 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <tinycrypt/utils.h> #include "../include/tinycrypt/utils.h"
#include <tinycrypt/constants.h> #include "../include/tinycrypt/constants.h"
#include <string.h> #include <string.h>

View File

@ -1,307 +0,0 @@
/*
* 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.
*/
#ifndef H_BLE_ATT_PRIV_
#define H_BLE_ATT_PRIV_
#include <inttypes.h>
#include "stats/stats.h"
#include "host/ble_att.h"
#include "host/ble_uuid.h"
#include "nimble/nimble_npl.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_mbuf;
struct ble_hs_conn;
struct ble_l2cap_chan;
struct ble_att_find_info_req;
struct ble_att_error_rsp;
struct ble_att_mtu_cmd;
struct ble_att_read_req;
struct ble_att_read_blob_req;
struct ble_att_read_type_req;
struct ble_att_read_group_type_req;
struct ble_att_read_group_type_rsp;
struct ble_att_find_type_value_req;
struct ble_att_write_req;
struct ble_att_prep_write_cmd;
struct ble_att_exec_write_req;
struct ble_att_notify_req;
struct ble_att_indicate_req;
STATS_SECT_START(ble_att_stats)
STATS_SECT_ENTRY(error_rsp_rx)
STATS_SECT_ENTRY(error_rsp_tx)
STATS_SECT_ENTRY(mtu_req_rx)
STATS_SECT_ENTRY(mtu_req_tx)
STATS_SECT_ENTRY(mtu_rsp_rx)
STATS_SECT_ENTRY(mtu_rsp_tx)
STATS_SECT_ENTRY(find_info_req_rx)
STATS_SECT_ENTRY(find_info_req_tx)
STATS_SECT_ENTRY(find_info_rsp_rx)
STATS_SECT_ENTRY(find_info_rsp_tx)
STATS_SECT_ENTRY(find_type_value_req_rx)
STATS_SECT_ENTRY(find_type_value_req_tx)
STATS_SECT_ENTRY(find_type_value_rsp_rx)
STATS_SECT_ENTRY(find_type_value_rsp_tx)
STATS_SECT_ENTRY(read_type_req_rx)
STATS_SECT_ENTRY(read_type_req_tx)
STATS_SECT_ENTRY(read_type_rsp_rx)
STATS_SECT_ENTRY(read_type_rsp_tx)
STATS_SECT_ENTRY(read_req_rx)
STATS_SECT_ENTRY(read_req_tx)
STATS_SECT_ENTRY(read_rsp_rx)
STATS_SECT_ENTRY(read_rsp_tx)
STATS_SECT_ENTRY(read_blob_req_rx)
STATS_SECT_ENTRY(read_blob_req_tx)
STATS_SECT_ENTRY(read_blob_rsp_rx)
STATS_SECT_ENTRY(read_blob_rsp_tx)
STATS_SECT_ENTRY(read_mult_req_rx)
STATS_SECT_ENTRY(read_mult_req_tx)
STATS_SECT_ENTRY(read_mult_rsp_rx)
STATS_SECT_ENTRY(read_mult_rsp_tx)
STATS_SECT_ENTRY(read_group_type_req_rx)
STATS_SECT_ENTRY(read_group_type_req_tx)
STATS_SECT_ENTRY(read_group_type_rsp_rx)
STATS_SECT_ENTRY(read_group_type_rsp_tx)
STATS_SECT_ENTRY(write_req_rx)
STATS_SECT_ENTRY(write_req_tx)
STATS_SECT_ENTRY(write_rsp_rx)
STATS_SECT_ENTRY(write_rsp_tx)
STATS_SECT_ENTRY(prep_write_req_rx)
STATS_SECT_ENTRY(prep_write_req_tx)
STATS_SECT_ENTRY(prep_write_rsp_rx)
STATS_SECT_ENTRY(prep_write_rsp_tx)
STATS_SECT_ENTRY(exec_write_req_rx)
STATS_SECT_ENTRY(exec_write_req_tx)
STATS_SECT_ENTRY(exec_write_rsp_rx)
STATS_SECT_ENTRY(exec_write_rsp_tx)
STATS_SECT_ENTRY(notify_req_rx)
STATS_SECT_ENTRY(notify_req_tx)
STATS_SECT_ENTRY(indicate_req_rx)
STATS_SECT_ENTRY(indicate_req_tx)
STATS_SECT_ENTRY(indicate_rsp_rx)
STATS_SECT_ENTRY(indicate_rsp_tx)
STATS_SECT_ENTRY(write_cmd_rx)
STATS_SECT_ENTRY(write_cmd_tx)
STATS_SECT_END
extern STATS_SECT_DECL(ble_att_stats) ble_att_stats;
struct ble_att_prep_entry {
SLIST_ENTRY(ble_att_prep_entry) bape_next;
uint16_t bape_handle;
uint16_t bape_offset;
/* XXX: This is wasteful; we should use one mbuf chain for the entire
* prepared write, and compress the data into as few mbufs as possible.
*/
struct os_mbuf *bape_value;
};
SLIST_HEAD(ble_att_prep_entry_list, ble_att_prep_entry);
struct ble_att_svr_conn {
/** This list is sorted by attribute handle ID. */
struct ble_att_prep_entry_list basc_prep_list;
ble_npl_time_t basc_prep_timeout_at;
};
/**
* Handles a host attribute request.
*
* @param entry The host attribute being requested.
* @param op The operation being performed on the attribute.
* @param arg The request data associated with that host
* attribute.
*
* @return 0 on success;
* One of the BLE_ATT_ERR_[...] codes on
* failure.
*/
typedef int ble_att_svr_access_fn(uint16_t conn_handle, uint16_t attr_handle,
uint8_t op, uint16_t offset,
struct os_mbuf **om, void *arg);
int ble_att_svr_register(const ble_uuid_t *uuid, uint8_t flags,
uint8_t min_key_size, uint16_t *handle_id,
ble_att_svr_access_fn *cb, void *cb_arg);
struct ble_att_svr_entry {
STAILQ_ENTRY(ble_att_svr_entry) ha_next;
const ble_uuid_t *ha_uuid;
uint8_t ha_flags;
uint8_t ha_min_key_size;
uint16_t ha_handle_id;
ble_att_svr_access_fn *ha_cb;
void *ha_cb_arg;
};
SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry);
/*** @gen */
struct ble_l2cap_chan *ble_att_create_chan(uint16_t conn_handle);
int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn,
struct ble_l2cap_chan **out_chan);
void ble_att_inc_tx_stat(uint8_t att_op);
void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan,
struct os_mbuf *txom);
void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu);
uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan);
int ble_att_init(void);
#define BLE_ATT_LOG_CMD(is_tx, cmd_name, conn_handle, log_cb, cmd) \
BLE_HS_LOG_CMD((is_tx), "att", (cmd_name), (conn_handle), (log_cb), (cmd))
#define BLE_ATT_LOG_EMPTY_CMD(is_tx, cmd_name, conn_handle) \
BLE_HS_LOG_EMPTY_CMD((is_tx), "att", (cmd_name), (conn_handle))
/*** @svr */
int ble_att_svr_start(void);
void ble_att_svr_stop(void);
struct ble_att_svr_entry *
ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at,
const ble_uuid_t *uuid,
uint16_t end_handle);
uint16_t ble_att_svr_prev_handle(void);
int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom);
struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id);
int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr,
ble_npl_time_t now);
int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_svr_rx_find_type_value(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_read_type(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_read_group_type(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_read(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_read_blob(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_read_mult(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_write(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_svr_rx_prep_write(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_exec_write(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_notify(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_svr_rx_indicate(uint16_t conn_handle,
struct os_mbuf **rxom);
void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list);
int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle,
uint16_t offset, struct os_mbuf *om,
uint8_t *out_att_err);
void ble_att_svr_reset(void);
int ble_att_svr_init(void);
void ble_att_svr_hide_range(uint16_t start_handle, uint16_t end_handle);
void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle);
int ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom,
uint8_t req_op, uint16_t handle,
uint8_t error_code);
/*** $clt */
/** An information-data entry in a find information response. */
struct ble_att_find_info_idata {
uint16_t attr_handle;
ble_uuid_any_t uuid;
};
/** A handles-information entry in a find by type value response. */
struct ble_att_find_type_value_hinfo {
uint16_t attr_handle;
uint16_t group_end_handle;
};
/** An attribute-data entry in a read by type response. */
struct ble_att_read_type_adata {
uint16_t att_handle;
int value_len;
uint8_t *value;
};
/** An attribute-data entry in a read by group type response. */
struct ble_att_read_group_type_adata {
uint16_t att_handle;
uint16_t end_group_handle;
int value_len;
uint8_t *value;
};
int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu);
int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle);
int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle,
uint16_t offset);
int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_mult(uint16_t conn_handle,
const uint16_t *handles, int num_handles);
int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, const ble_uuid_t *uuid);
int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_read_group_type(uint16_t conn_handle,
uint16_t start_handle, uint16_t end_handle,
const ble_uuid_t *uuid128);
int ble_att_clt_rx_read_group_type(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle);
int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle,
uint16_t end_handle, uint16_t attribute_type,
const void *attribute_value, int value_len);
int ble_att_clt_rx_find_type_value(uint16_t conn_handle,
struct os_mbuf **rxom);
int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle,
struct os_mbuf *txom);
int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle,
struct os_mbuf *txom);
int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle,
uint16_t offset, struct os_mbuf *txom);
int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags);
int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom);
int ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle,
struct os_mbuf *txom);
int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle,
struct os_mbuf *txom);
int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,128 +0,0 @@
/*
* 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.
*/
#ifndef H_BLE_HS_CONN_
#define H_BLE_HS_CONN_
#include <inttypes.h>
#include "ble_l2cap_priv.h"
#include "ble_gatt_priv.h"
#include "ble_att_priv.h"
#ifdef __cplusplus
extern "C" {
#endif
struct hci_le_conn_complete;
struct hci_create_conn;
struct ble_l2cap_chan;
typedef uint8_t ble_hs_conn_flags_t;
#define BLE_HS_CONN_F_MASTER 0x01
#define BLE_HS_CONN_F_TERMINATING 0x02
#define BLE_HS_CONN_F_TX_FRAG 0x04 /* Cur ACL packet partially txed. */
struct ble_hs_conn {
SLIST_ENTRY(ble_hs_conn) bhc_next;
uint16_t bhc_handle;
uint8_t bhc_our_addr_type;
#if MYNEWT_VAL(BLE_EXT_ADV)
uint8_t bhc_our_rnd_addr[6];
#endif
ble_addr_t bhc_peer_addr;
ble_addr_t bhc_our_rpa_addr;
ble_addr_t bhc_peer_rpa_addr;
uint16_t bhc_itvl;
uint16_t bhc_latency;
uint16_t bhc_supervision_timeout;
uint8_t bhc_master_clock_accuracy;
uint32_t supported_feat;
ble_hs_conn_flags_t bhc_flags;
struct ble_l2cap_chan_list bhc_channels;
struct ble_l2cap_chan *bhc_rx_chan; /* Channel rxing current packet. */
ble_npl_time_t bhc_rx_timeout;
/**
* Count of packets sent over this connection that the controller has not
* transmitted or flushed yet.
*/
uint16_t bhc_outstanding_pkts;
#if MYNEWT_VAL(BLE_HS_FLOW_CTRL)
/**
* Count of packets received over this connection that have been processed
* and freed.
*/
uint16_t bhc_completed_pkts;
#endif
/** Queue of outgoing packets that could not be sent. */
STAILQ_HEAD(, os_mbuf_pkthdr) bhc_tx_q;
struct ble_att_svr_conn bhc_att_svr;
struct ble_gatts_conn bhc_gatt_svr;
struct ble_gap_sec_state bhc_sec_state;
ble_gap_event_fn *bhc_cb;
void *bhc_cb_arg;
};
struct ble_hs_conn_addrs {
ble_addr_t our_id_addr;
ble_addr_t peer_id_addr;
ble_addr_t our_ota_addr;
ble_addr_t peer_ota_addr;
};
int ble_hs_conn_can_alloc(void);
struct ble_hs_conn *ble_hs_conn_alloc(uint16_t conn_handle);
void ble_hs_conn_free(struct ble_hs_conn *conn);
void ble_hs_conn_insert(struct ble_hs_conn *conn);
void ble_hs_conn_remove(struct ble_hs_conn *conn);
struct ble_hs_conn *ble_hs_conn_find(uint16_t conn_handle);
struct ble_hs_conn *ble_hs_conn_find_assert(uint16_t conn_handle);
struct ble_hs_conn *ble_hs_conn_find_by_addr(const ble_addr_t *addr);
struct ble_hs_conn *ble_hs_conn_find_by_idx(int idx);
int ble_hs_conn_exists(uint16_t conn_handle);
struct ble_hs_conn *ble_hs_conn_first(void);
struct ble_l2cap_chan *ble_hs_conn_chan_find_by_scid(struct ble_hs_conn *conn,
uint16_t cid);
struct ble_l2cap_chan *ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn,
uint16_t cid);
int ble_hs_conn_chan_insert(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan);
void
ble_hs_conn_delete_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan);
void ble_hs_conn_addrs(const struct ble_hs_conn *conn,
struct ble_hs_conn_addrs *addrs);
int32_t ble_hs_conn_timer(void);
int ble_hs_conn_init(void);
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More