update nimble lib
This commit is contained in:
29
lib/NimBLE-Arduino/docs/Bluetooth 5 features.md
Normal file
29
lib/NimBLE-Arduino/docs/Bluetooth 5 features.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Bluetooth 5.x features
|
||||||
|
|
||||||
|
## About extended advertising
|
||||||
|
Extended advertising allows for much more capability and flexibility.
|
||||||
|
|
||||||
|
* Allows for 251 bytes of advertisement data and up to 1650 bytes when chained (configuration dependant) vs 31.
|
||||||
|
|
||||||
|
* New PHY's (physical layers) that allow for faster data rate (2M PHY) or long range/slower data rates (CODED PHY) as well as the original 1M PHY.
|
||||||
|
|
||||||
|
* New periodic advertising, allowing the scanning device to sync with the advertisements of a beacon. This allows for the scanning device to sleep or perform other tasks before the next expected advertisement is sent, preserving cpu cycles and power (To be implemented).
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Enabling extended advertising
|
||||||
|
Extended advertising is supported when enabled with the config option `CONFIG_BT_NIMBLE_EXT_ADV` set to a value of 1. This is done in menuconfig under `Component config > Bluetooth > NimBLE options >
|
||||||
|
Enable extended advertising`.
|
||||||
|
|
||||||
|
When enabled the following will occur:
|
||||||
|
* `NimBLEScan::start` method will scan on both the 1M PHY and the coded PHY standards automatically.
|
||||||
|
|
||||||
|
* `NimBLEClient::connect` will use the primary PHY the device is listening on, unless specified (see below).
|
||||||
|
|
||||||
|
* `NimBLEClient::setConnectPhy` becomes available to specify the PHY's to connect with (default is all).
|
||||||
|
|
||||||
|
* `NimBLEAdvertising` is no longer available for use and is replaced by `NimBLEExtAdvertising`. `NimBLEDevice::getAdvertising` will now return an instance of `NimBLEExtAdvertising`.
|
||||||
|
|
||||||
|
* `NimBLEAdvertisementData` is no longer available for use and is replaced by `NimBLEExtAdvertisement`. This new class is where everything about the advertisement is configured, including the advertisement intervals and advertisement ended callback.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ characteristic or descriptor is constructed before a value is read/notifed.
|
|||||||
Increasing this will reduce reallocations but increase memory footprint.
|
Increasing this will reduce reallocations but increase memory footprint.
|
||||||
Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
|
Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
|
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
|
||||||
|
|
||||||
Sets the default MTU size.
|
Sets the default MTU size.
|
||||||
@@ -140,3 +140,34 @@ Set the task stack size for the NimBLE core.
|
|||||||
- Default is 4096
|
- Default is 4096
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
## Extended advertising settings, For use with ESP32C3, ESP32S3, ESP32H2 ONLY!
|
||||||
|
|
||||||
|
`CONFIG_BT_NIMBLE_EXT_ADV`
|
||||||
|
|
||||||
|
Set to 1 to enable extended advertising features.
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
`CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES`
|
||||||
|
|
||||||
|
Sets the max number of extended advertising instances
|
||||||
|
- Range: 0 - 4
|
||||||
|
- Default is 1
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
`CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN`
|
||||||
|
|
||||||
|
Set the max extended advertising data size,
|
||||||
|
- Range: 31 - 1650
|
||||||
|
- Default is 255
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
`CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV`
|
||||||
|
|
||||||
|
Set to 1 to enable periodic advertising.
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
`CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS`
|
||||||
|
|
||||||
|
Set the maximum number of periodically synced devices.
|
||||||
|
- Range: 1 - 8
|
||||||
|
- Default is 1
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ At the top of your application file add `#include NimBLEDevice.h`, this is the o
|
|||||||
## Using the Library
|
## Using the Library
|
||||||
In order to perform any BLE tasks you must first initialize the library, this prepares the NimBLE stack to be ready for commands.
|
In order to perform any BLE tasks you must first initialize the library, this prepares the NimBLE stack to be ready for commands.
|
||||||
|
|
||||||
To do this you must call `NimBLEDevice::initialize("your device name here")`, the parameter passed is a character string containing the name you want to advertise.
|
To do this you must call `NimBLEDevice::init("your device name here")`, the parameter passed is a character string containing the name you want to advertise.
|
||||||
If you're not creating a server or do not want to advertise a name, simply pass an empty string for the parameter.
|
If you're not creating a server or do not want to advertise a name, simply pass an empty string for the parameter.
|
||||||
|
|
||||||
This can be called any time you wish to use BLE functions and does not need to be called from app_main(IDF) or setup(Arduino) but usually is.
|
This can be called any time you wish to use BLE functions and does not need to be called from app_main(IDF) or setup(Arduino) but usually is.
|
||||||
@@ -41,7 +41,7 @@ For this example we will keep it simple and use a 16 bit value: ABCD.
|
|||||||
// void setup() in Arduino
|
// void setup() in Arduino
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
NimBLEDevice::initialize("NimBLE");
|
NimBLEDevice::init("NimBLE");
|
||||||
|
|
||||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||||
NimBLEService *pService = pServer->createService("ABCD");
|
NimBLEService *pService = pServer->createService("ABCD");
|
||||||
@@ -83,7 +83,7 @@ The function call will simply be `pService->createCharacteristic("1234");`
|
|||||||
// void setup() in Arduino
|
// void setup() in Arduino
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
NimBLEDevice::initialize("NimBLE");
|
NimBLEDevice::init("NimBLE");
|
||||||
|
|
||||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||||
NimBLEService *pService = pServer->createService("ABCD");
|
NimBLEService *pService = pServer->createService("ABCD");
|
||||||
@@ -117,7 +117,7 @@ That's it, this will be enough to create a BLE server with a service and a chara
|
|||||||
// void setup() in Arduino
|
// void setup() in Arduino
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
NimBLEDevice::initialize("NimBLE");
|
NimBLEDevice::init("NimBLE");
|
||||||
|
|
||||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||||
NimBLEService *pService = pServer->createService("ABCD");
|
NimBLEService *pService = pServer->createService("ABCD");
|
||||||
@@ -159,7 +159,7 @@ This call returns an instance of `NimBLEScanResults` when the scan completes whi
|
|||||||
// void setup() in Arduino
|
// void setup() in Arduino
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
NimBLEDevice::initialize("");
|
NimBLEDevice::init("");
|
||||||
|
|
||||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||||
NimBLEScanResults results = pScan->start(10);
|
NimBLEScanResults results = pScan->start(10);
|
||||||
@@ -299,7 +299,7 @@ Note that there is no need to disconnect as that will be done when deleting the
|
|||||||
// void setup() in Arduino
|
// void setup() in Arduino
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
NimBLEDevice::initialize("");
|
NimBLEDevice::init("");
|
||||||
|
|
||||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||||
NimBLEScanResults results = pScan->start(10);
|
NimBLEScanResults results = pScan->start(10);
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
|
||||||
|
/** NimBLE Extended Client Demo:
|
||||||
|
*
|
||||||
|
* Demonstrates the Bluetooth 5.x client capabilities.
|
||||||
|
*
|
||||||
|
* Created: on April 2 2022
|
||||||
|
* Author: H2zero
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/****************************************************
|
||||||
|
* For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
|
||||||
|
/**************************************************/
|
||||||
|
|
||||||
|
#include <NimBLEDevice.h>
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
# error Must enable extended advertising, see nimconfig.h file.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void scanEndedCB(NimBLEScanResults results);
|
||||||
|
|
||||||
|
#define SERVICE_UUID "ABCD"
|
||||||
|
#define CHARACTERISTIC_UUID "1234"
|
||||||
|
|
||||||
|
static NimBLEAdvertisedDevice* advDevice;
|
||||||
|
static bool doConnect = false;
|
||||||
|
static uint32_t scanTime = 10; /* 0 = scan forever */
|
||||||
|
|
||||||
|
/* Define the PHY's to use when connecting to peer devices, can be 1, 2, or all 3 (default).*/
|
||||||
|
static uint8_t connectPhys = BLE_GAP_LE_PHY_CODED_MASK | BLE_GAP_LE_PHY_1M_MASK /*| BLE_GAP_LE_PHY_2M_MASK */ ;
|
||||||
|
|
||||||
|
/* Define a class to handle the callbacks for client connection events */
|
||||||
|
class ClientCallbacks : public NimBLEClientCallbacks {
|
||||||
|
void onConnect(NimBLEClient* pClient) {
|
||||||
|
Serial.printf("Connected\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
void onDisconnect(NimBLEClient* pClient) {
|
||||||
|
Serial.printf("%s Disconnected - Starting scan\n", pClient->getPeerAddress().toString().c_str());
|
||||||
|
NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Define a class to handle the callbacks when advertisements are received */
|
||||||
|
class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {
|
||||||
|
|
||||||
|
void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
|
||||||
|
Serial.printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
|
||||||
|
if(advertisedDevice->isAdvertisingService(NimBLEUUID("ABCD")))
|
||||||
|
{
|
||||||
|
Serial.printf("Found Our Service\n");
|
||||||
|
/* Ready to connect now */
|
||||||
|
doConnect = true;
|
||||||
|
/* Save the device reference in a global for the client to use*/
|
||||||
|
advDevice = advertisedDevice;
|
||||||
|
/* stop scan before connecting */
|
||||||
|
NimBLEDevice::getScan()->stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Callback to process the results of the last scan or restart it */
|
||||||
|
void scanEndedCB(NimBLEScanResults results){
|
||||||
|
Serial.printf("Scan Ended\n");
|
||||||
|
if (!doConnect) { /* Don't start the scan while connecting */
|
||||||
|
NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Handles the provisioning of clients and connects / interfaces with the server */
|
||||||
|
bool connectToServer() {
|
||||||
|
NimBLEClient* pClient = nullptr;
|
||||||
|
|
||||||
|
pClient = NimBLEDevice::createClient();
|
||||||
|
pClient->setClientCallbacks(new ClientCallbacks, false);
|
||||||
|
|
||||||
|
/* Set the PHY's to use for this connection. This is a bitmask that represents the PHY's:
|
||||||
|
* * 0x01 BLE_GAP_LE_PHY_1M_MASK
|
||||||
|
* * 0x02 BLE_GAP_LE_PHY_2M_MASK
|
||||||
|
* * 0x04 BLE_GAP_LE_PHY_CODED_MASK
|
||||||
|
* Combine these with OR ("|"), eg BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK;
|
||||||
|
*/
|
||||||
|
pClient->setConnectPhy(connectPhys);
|
||||||
|
|
||||||
|
/** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
|
||||||
|
pClient->setConnectTimeout(10);
|
||||||
|
|
||||||
|
if (!pClient->connect(advDevice)) {
|
||||||
|
/* Created a client but failed to connect, don't need to keep it as it has no data */
|
||||||
|
NimBLEDevice::deleteClient(pClient);
|
||||||
|
Serial.printf("Failed to connect, deleted client\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("Connected to: %s RSSI: %d\n",
|
||||||
|
pClient->getPeerAddress().toString().c_str(),
|
||||||
|
pClient->getRssi());
|
||||||
|
|
||||||
|
/* Now we can read/write/subscribe the charateristics of the services we are interested in */
|
||||||
|
NimBLERemoteService* pSvc = nullptr;
|
||||||
|
NimBLERemoteCharacteristic* pChr = nullptr;
|
||||||
|
|
||||||
|
pSvc = pClient->getService(SERVICE_UUID);
|
||||||
|
|
||||||
|
if (pSvc) {
|
||||||
|
pChr = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
|
||||||
|
|
||||||
|
if (pChr) {
|
||||||
|
// Read the value of the characteristic.
|
||||||
|
if (pChr->canRead()) {
|
||||||
|
std::string value = pChr->readValue();
|
||||||
|
Serial.printf("Characteristic value: %s\n", value.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Serial.printf("ABCD service not found.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
NimBLEDevice::deleteClient(pClient);
|
||||||
|
Serial.printf("Done with this device!\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup () {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.printf("Starting NimBLE Client\n");
|
||||||
|
|
||||||
|
/* Initialize NimBLE, no device name specified as we are not advertising */
|
||||||
|
NimBLEDevice::init("");
|
||||||
|
NimBLEScan* pScan = NimBLEDevice::getScan();
|
||||||
|
|
||||||
|
/* create a callback that gets called when advertisers are found */
|
||||||
|
pScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
|
||||||
|
|
||||||
|
/* Set scan interval (how often) and window (how long) in milliseconds */
|
||||||
|
pScan->setInterval(97);
|
||||||
|
pScan->setWindow(67);
|
||||||
|
|
||||||
|
/* Active scan will gather scan response data from advertisers
|
||||||
|
* but will use more energy from both devices
|
||||||
|
*/
|
||||||
|
pScan->setActiveScan(true);
|
||||||
|
|
||||||
|
/* Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
|
||||||
|
* Optional callback for when scanning stops.
|
||||||
|
*/
|
||||||
|
pScan->start(scanTime, scanEndedCB);
|
||||||
|
|
||||||
|
Serial.printf("Scanning for peripherals\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop () {
|
||||||
|
/* Loop here until we find a device we want to connect to */
|
||||||
|
if (doConnect) {
|
||||||
|
/* Found a device we want to connect to, do it now */
|
||||||
|
if (connectToServer()) {
|
||||||
|
Serial.printf("Success!, scanning for more!\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("Failed to connect, starting scan\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
doConnect = false;
|
||||||
|
NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
/** NimBLE Extended Advertiser Demo:
|
||||||
|
*
|
||||||
|
* Demonstrates the Bluetooth 5.x extended advertising capabilities.
|
||||||
|
*
|
||||||
|
* This demo will advertise a long data string on the CODED and 1M Phy's and
|
||||||
|
* starts a server allowing connection over either PHY's. It will advertise for
|
||||||
|
* 5 seconds then sleep for 20 seconds, if a client connects it will sleep once
|
||||||
|
* it has disconnected then repeats.
|
||||||
|
*
|
||||||
|
* Created: on April 2 2022
|
||||||
|
* Author: H2zero
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/****************************************************
|
||||||
|
* For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
|
||||||
|
/**************************************************/
|
||||||
|
|
||||||
|
#include "NimBLEDevice.h"
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
# error Must enable extended advertising, see nimconfig.h file.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
|
||||||
|
#define SERVICE_UUID "ABCD"
|
||||||
|
#define CHARACTERISTIC_UUID "1234"
|
||||||
|
|
||||||
|
/* Time in milliseconds to advertise */
|
||||||
|
static uint32_t advTime = 5000;
|
||||||
|
|
||||||
|
/* Time to sleep between advertisements */
|
||||||
|
static uint32_t sleepSeconds = 20;
|
||||||
|
|
||||||
|
/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
|
||||||
|
static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
|
||||||
|
|
||||||
|
/* Secondary PHY used for advertising and connecting,
|
||||||
|
* can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
|
||||||
|
*/
|
||||||
|
static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
|
||||||
|
|
||||||
|
|
||||||
|
/* Handler class for server events */
|
||||||
|
class ServerCallbacks: public NimBLEServerCallbacks {
|
||||||
|
void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
|
||||||
|
Serial.printf("Client connected:: %s\n", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
|
||||||
|
};
|
||||||
|
|
||||||
|
void onDisconnect(NimBLEServer* pServer) {
|
||||||
|
Serial.printf("Client disconnected - sleeping for %u seconds\n", sleepSeconds);
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Callback class to handle advertising events */
|
||||||
|
class advertisingCallbacks: public NimBLEExtAdvertisingCallbacks {
|
||||||
|
void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t inst_id) {
|
||||||
|
/* Check the reason advertising stopped, don't sleep if client is connecting */
|
||||||
|
printf("Advertising instance %u stopped\n", inst_id);
|
||||||
|
switch (reason) {
|
||||||
|
case 0:
|
||||||
|
printf("Client connecting\n");
|
||||||
|
return;
|
||||||
|
case BLE_HS_ETIMEOUT:
|
||||||
|
printf("Time expired - sleeping for %u seconds\n", sleepSeconds);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup () {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
NimBLEDevice::init("Extended advertiser");
|
||||||
|
|
||||||
|
/* Create the server and add the services/characteristics/descriptors */
|
||||||
|
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||||
|
pServer->setCallbacks(new ServerCallbacks);
|
||||||
|
|
||||||
|
NimBLEService *pService = pServer->createService(SERVICE_UUID);
|
||||||
|
NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,
|
||||||
|
NIMBLE_PROPERTY::READ |
|
||||||
|
NIMBLE_PROPERTY::WRITE |
|
||||||
|
NIMBLE_PROPERTY::NOTIFY);
|
||||||
|
|
||||||
|
pCharacteristic->setValue("Hello World");
|
||||||
|
|
||||||
|
/* Start the services */
|
||||||
|
pService->start();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create an extended advertisement with the instance ID 0 and set the PHY's.
|
||||||
|
* Multiple instances can be added as long as the instance ID is incremented.
|
||||||
|
*/
|
||||||
|
NimBLEExtAdvertisement extAdv(primaryPhy, secondaryPhy);
|
||||||
|
|
||||||
|
/* Set the advertisement as connectable */
|
||||||
|
extAdv.setConnectable(true);
|
||||||
|
|
||||||
|
/* As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
|
||||||
|
extAdv.setScannable(false); // The default is false, set here for demonstration.
|
||||||
|
|
||||||
|
/* Extended advertising allows for 251 bytes (minus header bytes ~20) in a single advertisement or up to 1650 if chained */
|
||||||
|
extAdv.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Extended Advertising Demo.\r\n"
|
||||||
|
"Extended advertising allows for "
|
||||||
|
"251 bytes of data in a single advertisement,\r\n"
|
||||||
|
"or up to 1650 bytes with chaining.\r\n"
|
||||||
|
"This example message is 226 bytes long "
|
||||||
|
"and is using CODED_PHY for long range."));
|
||||||
|
|
||||||
|
extAdv.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
|
||||||
|
|
||||||
|
/* When extended advertising is enabled `NimBLEDevice::getAdvertising` returns a pointer to `NimBLEExtAdvertising */
|
||||||
|
NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
|
|
||||||
|
/* Set the callbacks for advertising events */
|
||||||
|
pAdvertising->setCallbacks(new advertisingCallbacks);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NimBLEExtAdvertising::setInstanceData takes the instance ID and
|
||||||
|
* a reference to a `NimBLEExtAdvertisement` object. This sets the data
|
||||||
|
* that will be advertised for this instance ID, returns true if successful.
|
||||||
|
*
|
||||||
|
* Note: It is safe to create the advertisement as a local variable if setInstanceData
|
||||||
|
* is called before exiting the code block as the data will be copied.
|
||||||
|
*/
|
||||||
|
if (pAdvertising->setInstanceData(0, extAdv)) {
|
||||||
|
/*
|
||||||
|
* `NimBLEExtAdvertising::start` takes the advertisement instance ID to start
|
||||||
|
* and a duration in milliseconds or a max number of advertisements to send (or both).
|
||||||
|
*/
|
||||||
|
if (pAdvertising->start(0, advTime)) {
|
||||||
|
Serial.printf("Started advertising\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("Failed to start advertising\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Serial.printf("Failed to register advertisment data\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_sleep_enable_timer_wakeup(sleepSeconds * 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop () {
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
/** NimBLE Multi Advertiser Demo:
|
||||||
|
*
|
||||||
|
* Demonstrates the Bluetooth 5.x extended advertising capabilities.
|
||||||
|
*
|
||||||
|
* This demo will advertise 2 advertisements, and extended scannable instance
|
||||||
|
* and a connectable legacy instance. They will advertise for 5 seconds then
|
||||||
|
* sleep for 20 seconds. The extended scannable instance will use the scan
|
||||||
|
* request callback to update it's data when a scan response is requested.
|
||||||
|
*
|
||||||
|
* Created: on April 9 2022
|
||||||
|
* Author: H2zero
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/****************************************************
|
||||||
|
* For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
|
||||||
|
/**************************************************/
|
||||||
|
|
||||||
|
#include <NimBLEDevice.h>
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
# error Must enable extended advertising, see nimconfig.h file.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
|
||||||
|
#define SERVICE_UUID "ABCD"
|
||||||
|
#define CHARACTERISTIC_UUID "1234"
|
||||||
|
|
||||||
|
/* Time in milliseconds to advertise */
|
||||||
|
static uint32_t advTime = 5000;
|
||||||
|
|
||||||
|
/* Time to sleep between advertisements */
|
||||||
|
static uint32_t sleepTime = 20;
|
||||||
|
|
||||||
|
/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
|
||||||
|
static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
|
||||||
|
|
||||||
|
/* Secondary PHY used for advertising and connecting,
|
||||||
|
* can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
|
||||||
|
*/
|
||||||
|
static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
|
||||||
|
|
||||||
|
|
||||||
|
/* Handler class for server events */
|
||||||
|
class ServerCallbacks: public NimBLEServerCallbacks {
|
||||||
|
void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
|
||||||
|
Serial.printf("Client connected: %s\n", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
|
||||||
|
};
|
||||||
|
|
||||||
|
void onDisconnect(NimBLEServer* pServer) {
|
||||||
|
Serial.printf("Client disconnected\n");
|
||||||
|
// if still advertising we won't sleep yet.
|
||||||
|
if (!pServer->getAdvertising()->isAdvertising()) {
|
||||||
|
Serial.printf("Sleeping for %u seconds\n", sleepTime);
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Callback class to handle advertising events */
|
||||||
|
class advCallbacks: public NimBLEExtAdvertisingCallbacks {
|
||||||
|
void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t inst_id) {
|
||||||
|
/* Check the reason advertising stopped, don't sleep if client is connecting */
|
||||||
|
Serial.printf("Advertising instance %u stopped\n", inst_id);
|
||||||
|
switch (reason) {
|
||||||
|
case 0:
|
||||||
|
Serial.printf(" client connecting\n");
|
||||||
|
return;
|
||||||
|
case BLE_HS_ETIMEOUT:
|
||||||
|
Serial.printf("Time expired - sleeping for %u seconds\n", sleepTime);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_updatedSR = false;
|
||||||
|
|
||||||
|
void onScanRequest(NimBLEExtAdvertising* pAdv, uint8_t inst_id, NimBLEAddress addr) {
|
||||||
|
Serial.printf("Scan request for instance %u\n", inst_id);
|
||||||
|
// if the data has already been updated we don't need to change it again.
|
||||||
|
if (!m_updatedSR) {
|
||||||
|
Serial.printf("Updating scan data\n");
|
||||||
|
NimBLEExtAdvertisement sr;
|
||||||
|
sr.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Hello from scan response!"));
|
||||||
|
pAdv->setScanResponseData(inst_id, sr);
|
||||||
|
m_updatedSR = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup () {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
NimBLEDevice::init("Multi advertiser");
|
||||||
|
|
||||||
|
/* Create a server for our legacy advertiser */
|
||||||
|
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||||
|
pServer->setCallbacks(new ServerCallbacks);
|
||||||
|
|
||||||
|
NimBLEService *pService = pServer->createService(SERVICE_UUID);
|
||||||
|
NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,
|
||||||
|
NIMBLE_PROPERTY::READ |
|
||||||
|
NIMBLE_PROPERTY::WRITE |
|
||||||
|
NIMBLE_PROPERTY::NOTIFY);
|
||||||
|
|
||||||
|
pCharacteristic->setValue("Hello World");
|
||||||
|
|
||||||
|
/* Start the service */
|
||||||
|
pService->start();
|
||||||
|
|
||||||
|
/* Create our multi advertising instances */
|
||||||
|
|
||||||
|
// extended scannable instance advertising on coded and 1m PHY's.
|
||||||
|
NimBLEExtAdvertisement extScannable(primaryPhy, secondaryPhy);
|
||||||
|
|
||||||
|
// Legacy advertising as a connectable device.
|
||||||
|
NimBLEExtAdvertisement legacyConnectable;
|
||||||
|
|
||||||
|
// Optional scan response data.
|
||||||
|
NimBLEExtAdvertisement legacyScanResponse;
|
||||||
|
|
||||||
|
/* As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
|
||||||
|
extScannable.setScannable(true);
|
||||||
|
extScannable.setConnectable(false);
|
||||||
|
|
||||||
|
/* Set the initial data */
|
||||||
|
extScannable.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Scan me!"));
|
||||||
|
|
||||||
|
/* enable the scan response callback, we will use this to update the data. */
|
||||||
|
extScannable.enableScanRequestCallback(true);
|
||||||
|
|
||||||
|
/* Optional custom address for this advertisment. */
|
||||||
|
legacyConnectable.setAddress(NimBLEAddress("DE:AD:BE:EF:BA:AD"));
|
||||||
|
|
||||||
|
/* Set the advertising data. */
|
||||||
|
legacyConnectable.setName("Legacy");
|
||||||
|
legacyConnectable.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
|
||||||
|
|
||||||
|
/* Set the legacy and connectable flags. */
|
||||||
|
legacyConnectable.setLegacyAdvertising(true);
|
||||||
|
legacyConnectable.setConnectable(true);
|
||||||
|
|
||||||
|
/* Put some data in the scan response if desired. */
|
||||||
|
legacyScanResponse.setServiceData(NimBLEUUID(SERVICE_UUID), "Legacy SR");
|
||||||
|
|
||||||
|
/* Get the advertising ready */
|
||||||
|
NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
|
||||||
|
|
||||||
|
/* Set the callbacks to handle advertising events */
|
||||||
|
pAdvertising->setCallbacks(new advCallbacks);
|
||||||
|
|
||||||
|
/* Set instance data.
|
||||||
|
* Up to 5 instances can be used if configured in menuconfig, instance 0 is always available.
|
||||||
|
*
|
||||||
|
* We will set the extended scannable data on instance 0 and the legacy data on instance 1.
|
||||||
|
* Note that the legacy scan response data needs to be set to the same instance (1).
|
||||||
|
*/
|
||||||
|
if (pAdvertising->setInstanceData( 0, extScannable ) &&
|
||||||
|
pAdvertising->setInstanceData( 1, legacyConnectable ) &&
|
||||||
|
pAdvertising->setScanResponseData( 1, legacyScanResponse )) {
|
||||||
|
/*
|
||||||
|
* `NimBLEExtAdvertising::start` takes the advertisement instance ID to start
|
||||||
|
* and a duration in milliseconds or a max number of advertisements to send (or both).
|
||||||
|
*/
|
||||||
|
if (pAdvertising->start(0, advTime) && pAdvertising->start(1, advTime)) {
|
||||||
|
Serial.printf("Started advertising\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("Failed to start advertising\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Serial.printf("Failed to register advertisment data\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_sleep_enable_timer_wakeup(sleepTime * 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
}
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLELog.h"
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
||||||
|
|
||||||
|
|
||||||
@@ -69,7 +71,7 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
|
|||||||
* @return The appearance of the advertised device.
|
* @return The appearance of the advertised device.
|
||||||
*/
|
*/
|
||||||
uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
|
|
||||||
if(findAdvField(BLE_HS_ADV_TYPE_APPEARANCE, 0, &data_loc) > 0) {
|
if(findAdvField(BLE_HS_ADV_TYPE_APPEARANCE, 0, &data_loc) > 0) {
|
||||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
@@ -87,7 +89,7 @@ uint16_t NimBLEAdvertisedDevice::getAppearance() {
|
|||||||
* @return The advertisement interval in 0.625ms units.
|
* @return The advertisement interval in 0.625ms units.
|
||||||
*/
|
*/
|
||||||
uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
|
uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
|
|
||||||
if(findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL, 0, &data_loc) > 0) {
|
if(findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL, 0, &data_loc) > 0) {
|
||||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
@@ -105,7 +107,7 @@ uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
|
|||||||
* @return The preferred min connection interval in 1.25ms units.
|
* @return The preferred min connection interval in 1.25ms units.
|
||||||
*/
|
*/
|
||||||
uint16_t NimBLEAdvertisedDevice::getMinInterval() {
|
uint16_t NimBLEAdvertisedDevice::getMinInterval() {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
|
|
||||||
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
@@ -123,7 +125,7 @@ uint16_t NimBLEAdvertisedDevice::getMinInterval() {
|
|||||||
* @return The preferred max connection interval in 1.25ms units.
|
* @return The preferred max connection interval in 1.25ms units.
|
||||||
*/
|
*/
|
||||||
uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
|
uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
|
|
||||||
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
|
||||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
@@ -141,7 +143,7 @@ uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
|
|||||||
* @return The manufacturer data of the advertised device.
|
* @return The manufacturer data of the advertised device.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
|
|
||||||
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, 0, &data_loc) > 0) {
|
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, 0, &data_loc) > 0) {
|
||||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
@@ -159,7 +161,7 @@ std::string NimBLEAdvertisedDevice::getManufacturerData() {
|
|||||||
* @return The URI data.
|
* @return The URI data.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getURI() {
|
std::string NimBLEAdvertisedDevice::getURI() {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
|
|
||||||
if(findAdvField(BLE_HS_ADV_TYPE_URI, 0, &data_loc) > 0) {
|
if(findAdvField(BLE_HS_ADV_TYPE_URI, 0, &data_loc) > 0) {
|
||||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
@@ -177,7 +179,7 @@ std::string NimBLEAdvertisedDevice::getURI() {
|
|||||||
* @return The name of the advertised device.
|
* @return The name of the advertised device.
|
||||||
*/
|
*/
|
||||||
std::string NimBLEAdvertisedDevice::getName() {
|
std::string NimBLEAdvertisedDevice::getName() {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
|
|
||||||
if(findAdvField(BLE_HS_ADV_TYPE_COMP_NAME, 0, &data_loc) > 0 ||
|
if(findAdvField(BLE_HS_ADV_TYPE_COMP_NAME, 0, &data_loc) > 0 ||
|
||||||
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME, 0, &data_loc) > 0)
|
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME, 0, &data_loc) > 0)
|
||||||
@@ -214,7 +216,7 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() {
|
|||||||
* @brief Get the number of target addresses.
|
* @brief Get the number of target addresses.
|
||||||
* @return The number of addresses.
|
* @return The number of addresses.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
uint8_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
|
|
||||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
|
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
|
||||||
@@ -232,7 +234,7 @@ size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
|||||||
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
||||||
ble_hs_adv_field *field = nullptr;
|
ble_hs_adv_field *field = nullptr;
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
uint8_t data_loc = 0xFF;
|
size_t data_loc = ULONG_MAX;
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
|
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
|
||||||
@@ -242,7 +244,7 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
|||||||
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
|
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(count > 0 && data_loc != 0xFF) {
|
if(count > 0 && data_loc != ULONG_MAX) {
|
||||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
if(field->length < index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
if(field->length < index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
|
||||||
index -= count - field->length / BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
index -= count - field->length / BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
|
||||||
@@ -264,9 +266,9 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
|||||||
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
|
||||||
ble_hs_adv_field *field = nullptr;
|
ble_hs_adv_field *field = nullptr;
|
||||||
uint8_t bytes;
|
uint8_t bytes;
|
||||||
uint8_t data_loc = findServiceData(index, &bytes);
|
size_t data_loc = findServiceData(index, &bytes);
|
||||||
|
|
||||||
if(data_loc != 0xFF) {
|
if(data_loc != ULONG_MAX) {
|
||||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
if(field->length > bytes) {
|
if(field->length > bytes) {
|
||||||
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
|
||||||
@@ -286,9 +288,9 @@ std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
|
|||||||
ble_hs_adv_field *field = nullptr;
|
ble_hs_adv_field *field = nullptr;
|
||||||
uint8_t bytes;
|
uint8_t bytes;
|
||||||
uint8_t index = 0;
|
uint8_t index = 0;
|
||||||
uint8_t data_loc = findServiceData(index, &bytes);
|
size_t data_loc = findServiceData(index, &bytes);
|
||||||
|
size_t plSize = m_payload.size() - 2;
|
||||||
uint8_t uuidBytes = uuid.bitSize() / 8;
|
uint8_t uuidBytes = uuid.bitSize() / 8;
|
||||||
uint8_t plSize = m_payload.size() - 2;
|
|
||||||
|
|
||||||
while(data_loc < plSize) {
|
while(data_loc < plSize) {
|
||||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
@@ -313,9 +315,9 @@ std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
|
|||||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||||
ble_hs_adv_field *field = nullptr;
|
ble_hs_adv_field *field = nullptr;
|
||||||
uint8_t bytes;
|
uint8_t bytes;
|
||||||
uint8_t data_loc = findServiceData(index, &bytes);
|
size_t data_loc = findServiceData(index, &bytes);
|
||||||
|
|
||||||
if(data_loc != 0xFF) {
|
if(data_loc != ULONG_MAX) {
|
||||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
if(field->length >= bytes) {
|
if(field->length >= bytes) {
|
||||||
return NimBLEUUID(field->value, bytes, false);
|
return NimBLEUUID(field->value, bytes, false);
|
||||||
@@ -330,10 +332,10 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
|||||||
* @brief Find the service data at the index.
|
* @brief Find the service data at the index.
|
||||||
* @param [in] index The index of the service data to find.
|
* @param [in] index The index of the service data to find.
|
||||||
* @param [in] bytes A pointer to storage for the number of the bytes in the UUID.
|
* @param [in] bytes A pointer to storage for the number of the bytes in the UUID.
|
||||||
* @return The index in the vector where the data is located, 0xFF if not found.
|
* @return The index in the vector where the data is located, ULONG_MAX if not found.
|
||||||
*/
|
*/
|
||||||
uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
uint8_t found = 0;
|
uint8_t found = 0;
|
||||||
|
|
||||||
*bytes = 0;
|
*bytes = 0;
|
||||||
@@ -358,7 +360,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
|||||||
return data_loc;
|
return data_loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0xFF;
|
return ULONG_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -366,7 +368,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
|||||||
* @brief Get the count of advertised service data UUIDS
|
* @brief Get the count of advertised service data UUIDS
|
||||||
* @return The number of service data UUIDS in the vector.
|
* @return The number of service data UUIDS in the vector.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
uint8_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
|
|
||||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
|
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
|
||||||
@@ -384,7 +386,7 @@ size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
|||||||
*/
|
*/
|
||||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
uint8_t uuidBytes = 0;
|
uint8_t uuidBytes = 0;
|
||||||
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||||
ble_hs_adv_field *field = nullptr;
|
ble_hs_adv_field *field = nullptr;
|
||||||
@@ -431,7 +433,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
|||||||
* @brief Get the number of services advertised
|
* @brief Get the number of services advertised
|
||||||
* @return The count of services in the advertising packet.
|
* @return The count of services in the advertising packet.
|
||||||
*/
|
*/
|
||||||
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
uint8_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
|
|
||||||
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
|
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
|
||||||
@@ -467,7 +469,7 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) {
|
|||||||
* @return The TX Power of the advertised device.
|
* @return The TX Power of the advertised device.
|
||||||
*/
|
*/
|
||||||
int8_t NimBLEAdvertisedDevice::getTXPower() {
|
int8_t NimBLEAdvertisedDevice::getTXPower() {
|
||||||
uint8_t data_loc = 0;
|
size_t data_loc = 0;
|
||||||
|
|
||||||
if(findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL, 0, &data_loc) > 0) {
|
if(findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL, 0, &data_loc) > 0) {
|
||||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||||
@@ -581,17 +583,60 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
|
|||||||
} // haveTXPower
|
} // haveTXPower
|
||||||
|
|
||||||
|
|
||||||
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_t *data_loc) {
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
ble_hs_adv_field *field = nullptr;
|
/**
|
||||||
uint8_t data = 0;
|
* @brief Get the set ID of the extended advertisement.
|
||||||
uint8_t length = m_payload.size();
|
* @return The set ID.
|
||||||
uint8_t count = 0;
|
*/
|
||||||
|
uint8_t NimBLEAdvertisedDevice::getSetId() {
|
||||||
|
return m_sid;
|
||||||
|
} // getSetId
|
||||||
|
|
||||||
if(length < 2) {
|
|
||||||
|
/**
|
||||||
|
* @brief Get the primary PHY used by this advertisement.
|
||||||
|
* @return The PHY type, one of:
|
||||||
|
* * BLE_HCI_LE_PHY_1M
|
||||||
|
* * BLE_HCI_LE_PHY_CODED
|
||||||
|
*/
|
||||||
|
uint8_t NimBLEAdvertisedDevice::getPrimaryPhy() {
|
||||||
|
return m_primPhy;
|
||||||
|
} // getPrimaryPhy
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the primary PHY used by this advertisement.
|
||||||
|
* @return The PHY type, one of:
|
||||||
|
* * BLE_HCI_LE_PHY_1M
|
||||||
|
* * BLE_HCI_LE_PHY_2M
|
||||||
|
* * BLE_HCI_LE_PHY_CODED
|
||||||
|
*/
|
||||||
|
uint8_t NimBLEAdvertisedDevice::getSecondaryPhy() {
|
||||||
|
return m_secPhy;
|
||||||
|
} // getSecondaryPhy
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the periodic interval of the advertisement.
|
||||||
|
* @return The periodic advertising interval, 0 if not periodic advertising.
|
||||||
|
*/
|
||||||
|
uint16_t NimBLEAdvertisedDevice::getPeriodicInterval() {
|
||||||
|
return m_periodicItvl;
|
||||||
|
} // getPeriodicInterval
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, size_t * data_loc) {
|
||||||
|
ble_hs_adv_field *field = nullptr;
|
||||||
|
size_t length = m_payload.size();
|
||||||
|
size_t data = 0;
|
||||||
|
uint8_t count = 0;
|
||||||
|
|
||||||
|
if (length < 3) {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (length > 1) {
|
while (length > 2) {
|
||||||
field = (ble_hs_adv_field*)&m_payload[data];
|
field = (ble_hs_adv_field*)&m_payload[data];
|
||||||
|
|
||||||
if (field->length >= length) {
|
if (field->length >= length) {
|
||||||
@@ -599,7 +644,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (field->type == type) {
|
if (field->type == type) {
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
||||||
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
||||||
count += field->length / 2;
|
count += field->length / 2;
|
||||||
@@ -625,8 +670,8 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data_loc != nullptr) {
|
if (data_loc != nullptr) {
|
||||||
if(index == 0 || count >= index) {
|
if (index == 0 || count >= index) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -636,7 +681,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
|||||||
data += 1 + field->length;
|
data += 1 + field->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data_loc != nullptr && field != nullptr) {
|
if (data_loc != nullptr && field != nullptr) {
|
||||||
*data_loc = data;
|
*data_loc = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,8 +702,13 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
|
|||||||
* @brief Set the adFlag for this device.
|
* @brief Set the adFlag for this device.
|
||||||
* @param [in] advType The advertisement flag data from the advertisement.
|
* @param [in] advType The advertisement flag data from the advertisement.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
|
void NimBLEAdvertisedDevice::setAdvType(uint8_t advType, bool isLegacyAdv) {
|
||||||
m_advType = advType;
|
m_advType = advType;
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
m_isLegacyAdv = isLegacyAdv;
|
||||||
|
#else
|
||||||
|
(void)isLegacyAdv;
|
||||||
|
#endif
|
||||||
} // setAdvType
|
} // setAdvType
|
||||||
|
|
||||||
|
|
||||||
@@ -703,10 +753,10 @@ std::string NimBLEAdvertisedDevice::toString() {
|
|||||||
res += val;
|
res += val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(haveServiceData()) {
|
if (haveServiceData()) {
|
||||||
size_t count = getServiceDataCount();
|
uint8_t count = getServiceDataCount();
|
||||||
res += "\nService Data:";
|
res += "\nService Data:";
|
||||||
for(size_t i = 0; i < count; i++) {
|
for(uint8_t i = 0; i < count; i++) {
|
||||||
res += "\nUUID: " + std::string(getServiceDataUUID(i));
|
res += "\nUUID: " + std::string(getServiceDataUUID(i));
|
||||||
res += ", Data: " + getServiceData(i);
|
res += ", Data: " + getServiceData(i);
|
||||||
}
|
}
|
||||||
@@ -781,5 +831,34 @@ size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
|||||||
return m_payload.size();
|
return m_payload.size();
|
||||||
} // getPayloadLength
|
} // getPayloadLength
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if this device is advertising as connectable.
|
||||||
|
* @return True if the device is connectable.
|
||||||
|
*/
|
||||||
|
bool NimBLEAdvertisedDevice::isConnectable() {
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
if (m_isLegacyAdv) {
|
||||||
|
return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND ||
|
||||||
|
m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return (m_advType & BLE_HCI_ADV_CONN_MASK) ||
|
||||||
|
(m_advType & BLE_HCI_ADV_DIRECT_MASK);
|
||||||
|
} // isConnectable
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if this advertisement is a legacy or extended type
|
||||||
|
* @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
|
||||||
|
*/
|
||||||
|
bool NimBLEAdvertisedDevice::isLegacyAdvertisement() {
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
return m_isLegacyAdv;
|
||||||
|
# else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
} // isLegacyAdvertisement
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
std::string getName();
|
std::string getName();
|
||||||
int getRSSI();
|
int getRSSI();
|
||||||
NimBLEScan* getScan();
|
NimBLEScan* getScan();
|
||||||
size_t getServiceDataCount();
|
uint8_t getServiceDataCount();
|
||||||
std::string getServiceData(uint8_t index = 0);
|
std::string getServiceData(uint8_t index = 0);
|
||||||
std::string getServiceData(const NimBLEUUID &uuid);
|
std::string getServiceData(const NimBLEUUID &uuid);
|
||||||
|
|
||||||
@@ -111,9 +111,9 @@ public:
|
|||||||
|
|
||||||
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
||||||
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
||||||
size_t getServiceUUIDCount();
|
uint8_t getServiceUUIDCount();
|
||||||
NimBLEAddress getTargetAddress(uint8_t index = 0);
|
NimBLEAddress getTargetAddress(uint8_t index = 0);
|
||||||
size_t getTargetAddressCount();
|
uint8_t getTargetAddressCount();
|
||||||
int8_t getTXPower();
|
int8_t getTXPower();
|
||||||
uint8_t* getPayload();
|
uint8_t* getPayload();
|
||||||
uint8_t getAdvLength();
|
uint8_t getAdvLength();
|
||||||
@@ -133,16 +133,30 @@ public:
|
|||||||
bool haveTargetAddress();
|
bool haveTargetAddress();
|
||||||
bool haveURI();
|
bool haveURI();
|
||||||
std::string toString();
|
std::string toString();
|
||||||
|
bool isConnectable();
|
||||||
|
bool isLegacyAdvertisement();
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
uint8_t getSetId();
|
||||||
|
uint8_t getPrimaryPhy();
|
||||||
|
uint8_t getSecondaryPhy();
|
||||||
|
uint16_t getPeriodicInterval();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEScan;
|
friend class NimBLEScan;
|
||||||
|
|
||||||
void setAddress(NimBLEAddress address);
|
void setAddress(NimBLEAddress address);
|
||||||
void setAdvType(uint8_t advType);
|
void setAdvType(uint8_t advType, bool isLegacyAdv);
|
||||||
void setPayload(const uint8_t *payload, uint8_t length, bool append);
|
void setPayload(const uint8_t *payload, uint8_t length, bool append);
|
||||||
void setRSSI(int rssi);
|
void setRSSI(int rssi);
|
||||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
void setSetId(uint8_t sid) { m_sid = sid; }
|
||||||
|
void setPrimaryPhy(uint8_t phy) { m_primPhy = phy; }
|
||||||
|
void setSecondaryPhy(uint8_t phy) { m_secPhy = phy; }
|
||||||
|
void setPeriodicInterval(uint16_t itvl) { m_periodicItvl = itvl; }
|
||||||
|
#endif
|
||||||
|
uint8_t findAdvField(uint8_t type, uint8_t index = 0, size_t * data_loc = nullptr);
|
||||||
|
size_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||||
|
|
||||||
NimBLEAddress m_address = NimBLEAddress("");
|
NimBLEAddress m_address = NimBLEAddress("");
|
||||||
uint8_t m_advType;
|
uint8_t m_advType;
|
||||||
@@ -150,6 +164,13 @@ private:
|
|||||||
time_t m_timestamp;
|
time_t m_timestamp;
|
||||||
bool m_callbackSent;
|
bool m_callbackSent;
|
||||||
uint8_t m_advLength;
|
uint8_t m_advLength;
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
bool m_isLegacyAdv;
|
||||||
|
uint8_t m_sid;
|
||||||
|
uint8_t m_primPhy;
|
||||||
|
uint8_t m_secPhy;
|
||||||
|
uint16_t m_periodicItvl;
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<uint8_t> m_payload;
|
std::vector<uint8_t> m_payload;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#if (defined(CONFIG_BT_ENABLED) && \
|
||||||
|
defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
|
||||||
|
!CONFIG_BT_NIMBLE_EXT_ADV) || defined(_DOXYGEN_)
|
||||||
|
|
||||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
#include "services/gap/ble_svc_gap.h"
|
#include "services/gap/ble_svc_gap.h"
|
||||||
@@ -412,7 +414,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||||||
// If already advertising just return
|
// If already advertising just return
|
||||||
if(ble_gap_adv_active()) {
|
if(ble_gap_adv_active()) {
|
||||||
NIMBLE_LOGW(LOG_TAG, "Advertising already active");
|
NIMBLE_LOGW(LOG_TAG, "Advertising already active");
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the duration incase of host reset so we can restart with the same params
|
// Save the duration incase of host reset so we can restart with the same params
|
||||||
@@ -625,7 +627,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||||||
&m_advParams,
|
&m_advParams,
|
||||||
(pServer != nullptr) ? NimBLEServer::handleGapEvent :
|
(pServer != nullptr) ? NimBLEServer::handleGapEvent :
|
||||||
NimBLEAdvertising::handleGapEvent,
|
NimBLEAdvertising::handleGapEvent,
|
||||||
(pServer != nullptr) ? (void*)pServer : (void*)this);
|
(void*)this);
|
||||||
#else
|
#else
|
||||||
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type, NULL, duration,
|
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type, NULL, duration,
|
||||||
&m_advParams, NimBLEAdvertising::handleGapEvent, this);
|
&m_advParams, NimBLEAdvertising::handleGapEvent, this);
|
||||||
@@ -634,6 +636,10 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BLE_HS_EALREADY:
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Advertisement Already active");
|
||||||
|
break;
|
||||||
|
|
||||||
case BLE_HS_EINVAL:
|
case BLE_HS_EINVAL:
|
||||||
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Duration too long");
|
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Duration too long");
|
||||||
break;
|
break;
|
||||||
@@ -656,24 +662,26 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
|||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
|
NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
|
||||||
return (rc == 0);
|
return (rc == 0 || rc == BLE_HS_EALREADY);
|
||||||
} // start
|
} // start
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop advertising.
|
* @brief Stop advertising.
|
||||||
|
* @return True if advertising stopped successfully.
|
||||||
*/
|
*/
|
||||||
void NimBLEAdvertising::stop() {
|
bool NimBLEAdvertising::stop() {
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> stop");
|
NIMBLE_LOGD(LOG_TAG, ">> stop");
|
||||||
|
|
||||||
int rc = ble_gap_adv_stop();
|
int rc = ble_gap_adv_stop();
|
||||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s",
|
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s",
|
||||||
rc, NimBLEUtils::returnCodeToString(rc));
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< stop");
|
NIMBLE_LOGD(LOG_TAG, "<< stop");
|
||||||
|
return true;
|
||||||
} // stop
|
} // stop
|
||||||
|
|
||||||
|
|
||||||
@@ -1026,4 +1034,4 @@ std::string NimBLEAdvertisementData::getPayload() {
|
|||||||
return m_payload;
|
return m_payload;
|
||||||
} // getPayload
|
} // getPayload
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
#ifndef MAIN_BLEADVERTISING_H_
|
#ifndef MAIN_BLEADVERTISING_H_
|
||||||
#define MAIN_BLEADVERTISING_H_
|
#define MAIN_BLEADVERTISING_H_
|
||||||
#include "nimconfig.h"
|
#include "nimconfig.h"
|
||||||
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#if (defined(CONFIG_BT_ENABLED) && \
|
||||||
|
defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
|
||||||
|
!CONFIG_BT_NIMBLE_EXT_ADV) || defined(_DOXYGEN_)
|
||||||
|
|
||||||
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
#include "host/ble_gap.h"
|
#include "host/ble_gap.h"
|
||||||
@@ -89,7 +91,7 @@ public:
|
|||||||
void addServiceUUID(const char* serviceUUID);
|
void addServiceUUID(const char* serviceUUID);
|
||||||
void removeServiceUUID(const NimBLEUUID &serviceUUID);
|
void removeServiceUUID(const NimBLEUUID &serviceUUID);
|
||||||
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
||||||
void stop();
|
bool stop();
|
||||||
void setAppearance(uint16_t appearance);
|
void setAppearance(uint16_t appearance);
|
||||||
void setName(const std::string &name);
|
void setName(const std::string &name);
|
||||||
void setManufacturerData(const std::string &data);
|
void setManufacturerData(const std::string &data);
|
||||||
@@ -111,6 +113,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class NimBLEDevice;
|
friend class NimBLEDevice;
|
||||||
|
friend class NimBLEServer;
|
||||||
|
|
||||||
void onHostSync();
|
void onHostSync();
|
||||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||||
@@ -134,5 +137,5 @@ private:
|
|||||||
std::vector<uint8_t> m_uri;
|
std::vector<uint8_t> m_uri;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
|
||||||
#endif /* MAIN_BLEADVERTISING_H_ */
|
#endif /* MAIN_BLEADVERTISING_H_ */
|
||||||
|
|||||||
@@ -65,6 +65,11 @@ NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(pee
|
|||||||
m_pTaskData = nullptr;
|
m_pTaskData = nullptr;
|
||||||
m_connEstablished = false;
|
m_connEstablished = false;
|
||||||
m_lastErr = 0;
|
m_lastErr = 0;
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
m_phyMask = BLE_GAP_LE_PHY_1M_MASK |
|
||||||
|
BLE_GAP_LE_PHY_2M_MASK |
|
||||||
|
BLE_GAP_LE_PHY_CODED_MASK;
|
||||||
|
#endif
|
||||||
|
|
||||||
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
|
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
|
||||||
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
|
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
|
||||||
@@ -220,9 +225,22 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
|
|||||||
* Loop on BLE_HS_EBUSY if the scan hasn't stopped yet.
|
* Loop on BLE_HS_EBUSY if the scan hasn't stopped yet.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
rc = ble_gap_ext_connect(NimBLEDevice::m_own_addr_type,
|
||||||
|
&peerAddr_t,
|
||||||
|
m_connectTimeout,
|
||||||
|
m_phyMask,
|
||||||
|
&m_pConnParams,
|
||||||
|
&m_pConnParams,
|
||||||
|
&m_pConnParams,
|
||||||
|
NimBLEClient::handleGapEvent,
|
||||||
|
this);
|
||||||
|
|
||||||
|
#else
|
||||||
rc = ble_gap_connect(NimBLEDevice::m_own_addr_type, &peerAddr_t,
|
rc = ble_gap_connect(NimBLEDevice::m_own_addr_type, &peerAddr_t,
|
||||||
m_connectTimeout, &m_pConnParams,
|
m_connectTimeout, &m_pConnParams,
|
||||||
NimBLEClient::handleGapEvent, this);
|
NimBLEClient::handleGapEvent, this);
|
||||||
|
#endif
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
@@ -397,6 +415,21 @@ int NimBLEClient::disconnect(uint8_t reason) {
|
|||||||
} // disconnect
|
} // disconnect
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
/**
|
||||||
|
* @brief Set the PHY types to use when connecting to a server.
|
||||||
|
* @param [in] mask A bitmask indicating what PHYS to connect with.\n
|
||||||
|
* The available bits are:
|
||||||
|
* * 0x01 BLE_GAP_LE_PHY_1M_MASK
|
||||||
|
* * 0x02 BLE_GAP_LE_PHY_2M_MASK
|
||||||
|
* * 0x04 BLE_GAP_LE_PHY_CODED_MASK
|
||||||
|
*/
|
||||||
|
void NimBLEClient::setConnectPhy(uint8_t mask) {
|
||||||
|
m_phyMask = mask;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the connection paramaters to use when connecting to a server.
|
* @brief Set the connection paramaters to use when connecting to a server.
|
||||||
* @param [in] minInterval The minimum connection interval in 1.25ms units.
|
* @param [in] minInterval The minimum connection interval in 1.25ms units.
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ public:
|
|||||||
void discoverAttributes();
|
void discoverAttributes();
|
||||||
NimBLEConnInfo getConnInfo();
|
NimBLEConnInfo getConnInfo();
|
||||||
int getLastError();
|
int getLastError();
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
void setConnectPhy(uint8_t mask);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NimBLEClient(const NimBLEAddress &peerAddress);
|
NimBLEClient(const NimBLEAddress &peerAddress);
|
||||||
@@ -98,6 +101,9 @@ private:
|
|||||||
NimBLEClientCallbacks* m_pClientCallbacks;
|
NimBLEClientCallbacks* m_pClientCallbacks;
|
||||||
ble_task_data_t* m_pTaskData;
|
ble_task_data_t* m_pTaskData;
|
||||||
ble_npl_callout m_dcTimer;
|
ble_npl_callout m_dcTimer;
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
uint8_t m_phyMask;
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<NimBLERemoteService*> m_servicesVector;
|
std::vector<NimBLERemoteService*> m_servicesVector;
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,11 @@ NimBLEServer* NimBLEDevice::m_pServer = nullptr;
|
|||||||
uint32_t NimBLEDevice::m_passkey = 123456;
|
uint32_t NimBLEDevice::m_passkey = 123456;
|
||||||
bool NimBLEDevice::m_synced = false;
|
bool NimBLEDevice::m_synced = false;
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
NimBLEExtAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
||||||
|
# else
|
||||||
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gap_event_handler NimBLEDevice::m_customGapHandler = nullptr;
|
gap_event_handler NimBLEDevice::m_customGapHandler = nullptr;
|
||||||
@@ -114,6 +118,45 @@ uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DU
|
|||||||
|
|
||||||
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
/**
|
||||||
|
* @brief Get the instance of the advertising object.
|
||||||
|
* @return A pointer to the advertising object.
|
||||||
|
*/
|
||||||
|
NimBLEExtAdvertising* NimBLEDevice::getAdvertising() {
|
||||||
|
if(m_bleAdvertising == nullptr) {
|
||||||
|
m_bleAdvertising = new NimBLEExtAdvertising();
|
||||||
|
}
|
||||||
|
return m_bleAdvertising;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convenience function to begin advertising.
|
||||||
|
* @param [in] inst_id The extended advertisement instance ID to start.
|
||||||
|
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
|
||||||
|
* @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
|
||||||
|
* @return True if advertising started successfully.
|
||||||
|
*/
|
||||||
|
bool NimBLEDevice::startAdvertising(uint8_t inst_id,
|
||||||
|
int duration,
|
||||||
|
int max_events) {
|
||||||
|
return getAdvertising()->start(inst_id, duration, max_events);
|
||||||
|
} // startAdvertising
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convenience function to stop advertising a data set.
|
||||||
|
* @param [in] inst_id The extended advertisement instance ID to stop advertising.
|
||||||
|
* @return True if advertising stopped successfully.
|
||||||
|
*/
|
||||||
|
bool NimBLEDevice::stopAdvertising(uint8_t inst_id) {
|
||||||
|
return getAdvertising()->stop(inst_id);
|
||||||
|
} // stopAdvertising
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||||
/**
|
/**
|
||||||
* @brief Get the instance of the advertising object.
|
* @brief Get the instance of the advertising object.
|
||||||
* @return A pointer to the advertising object.
|
* @return A pointer to the advertising object.
|
||||||
@@ -128,17 +171,19 @@ NimBLEAdvertising* NimBLEDevice::getAdvertising() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convenience function to begin advertising.
|
* @brief Convenience function to begin advertising.
|
||||||
|
* @return True if advertising started successfully.
|
||||||
*/
|
*/
|
||||||
void NimBLEDevice::startAdvertising() {
|
bool NimBLEDevice::startAdvertising() {
|
||||||
getAdvertising()->start();
|
return getAdvertising()->start();
|
||||||
} // startAdvertising
|
} // startAdvertising
|
||||||
|
# endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convenience function to stop advertising.
|
* @brief Convenience function to stop all advertising.
|
||||||
|
* @return True if advertising stopped successfully.
|
||||||
*/
|
*/
|
||||||
void NimBLEDevice::stopAdvertising() {
|
bool NimBLEDevice::stopAdvertising() {
|
||||||
getAdvertising()->stop();
|
return getAdvertising()->stop();
|
||||||
} // stopAdvertising
|
} // stopAdvertising
|
||||||
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
|
||||||
@@ -479,7 +524,7 @@ void NimBLEDevice::setScanDuplicateCacheSize(uint16_t cacheSize) {
|
|||||||
* * CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE (2)\n
|
* * CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE (2)\n
|
||||||
Filter by address and data, advertisements from the same address will be reported only once,\n
|
Filter by address and data, advertisements from the same address will be reported only once,\n
|
||||||
except if the data in the advertisement has changed, then it will be reported again.
|
except if the data in the advertisement has changed, then it will be reported again.
|
||||||
* @details Must only be called before calling NimBLEDevice::initialize.
|
* @details Must only be called before calling NimBLEDevice::init.
|
||||||
*/
|
*/
|
||||||
/*STATIC*/
|
/*STATIC*/
|
||||||
void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
||||||
@@ -806,7 +851,7 @@ void NimBLEDevice::init(const std::string &deviceName) {
|
|||||||
esp_err_t errRc = ESP_OK;
|
esp_err_t errRc = ESP_OK;
|
||||||
|
|
||||||
#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
|
#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
|
||||||
// make sure the linker includes esp32-hal-bt.c so ardruino initialize doesn't release BLE memory.
|
// make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory.
|
||||||
btStarted();
|
btStarted();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -866,7 +911,7 @@ void NimBLEDevice::init(const std::string &deviceName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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.
|
||||||
} // initialize
|
} // init
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,7 +23,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
#include "NimBLEAdvertising.h"
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
# include "NimBLEExtAdvertising.h"
|
||||||
|
# else
|
||||||
|
# include "NimBLEAdvertising.h"
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
@@ -139,9 +143,18 @@ public:
|
|||||||
static void removeIgnored(const NimBLEAddress &address);
|
static void removeIgnored(const NimBLEAddress &address);
|
||||||
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
static NimBLEAdvertising* getAdvertising();
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
static void startAdvertising();
|
static NimBLEExtAdvertising* getAdvertising();
|
||||||
static void stopAdvertising();
|
static bool startAdvertising(uint8_t inst_id,
|
||||||
|
int duration = 0,
|
||||||
|
int max_events = 0);
|
||||||
|
static bool stopAdvertising(uint8_t inst_id);
|
||||||
|
static bool stopAdvertising();
|
||||||
|
# else
|
||||||
|
static NimBLEAdvertising* getAdvertising();
|
||||||
|
static bool startAdvertising();
|
||||||
|
static bool stopAdvertising();
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
@@ -178,6 +191,10 @@ private:
|
|||||||
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
friend class NimBLEAdvertising;
|
friend class NimBLEAdvertising;
|
||||||
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
friend class NimBLEExtAdvertising;
|
||||||
|
friend class NimBLEExtAdvertisement;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void onReset(int reason);
|
static void onReset(int reason);
|
||||||
@@ -194,7 +211,11 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||||
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
static NimBLEExtAdvertising* m_bleAdvertising;
|
||||||
|
# else
|
||||||
static NimBLEAdvertising* m_bleAdvertising;
|
static NimBLEAdvertising* m_bleAdvertising;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||||
|
|||||||
870
lib/NimBLE-Arduino/src/NimBLEExtAdvertising.cpp
Normal file
870
lib/NimBLE-Arduino/src/NimBLEExtAdvertising.cpp
Normal file
@@ -0,0 +1,870 @@
|
|||||||
|
/*
|
||||||
|
* NimBLEExtAdvertising.cpp
|
||||||
|
*
|
||||||
|
* Created: on February 6, 2022
|
||||||
|
* Author H2zero
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_ENABLED) && \
|
||||||
|
defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
|
||||||
|
CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
|
||||||
|
#if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
|
#include "services/gap/ble_svc_gap.h"
|
||||||
|
#else
|
||||||
|
#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
|
||||||
|
#endif
|
||||||
|
#include "NimBLEExtAdvertising.h"
|
||||||
|
#include "NimBLEDevice.h"
|
||||||
|
#include "NimBLEServer.h"
|
||||||
|
#include "NimBLEUtils.h"
|
||||||
|
#include "NimBLELog.h"
|
||||||
|
|
||||||
|
static NimBLEExtAdvertisingCallbacks defaultCallbacks;
|
||||||
|
static const char* LOG_TAG = "NimBLEExtAdvertising";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor: deletes callback instances if requested.
|
||||||
|
*/
|
||||||
|
NimBLEExtAdvertising::~NimBLEExtAdvertising() {
|
||||||
|
if(m_deleteCallbacks && m_pCallbacks != &defaultCallbacks) {
|
||||||
|
delete m_pCallbacks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register the extended advertisement data.
|
||||||
|
* @param [in] inst_id The extended advertisement instance ID to assign to this data.
|
||||||
|
* @param [in] adv The extended advertisement instance with the data to set.
|
||||||
|
* @return True if advertising started successfully.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::setInstanceData(uint8_t inst_id, NimBLEExtAdvertisement& adv) {
|
||||||
|
adv.m_params.sid = inst_id;
|
||||||
|
|
||||||
|
// Legacy advertising as connectable requires the scannable flag also.
|
||||||
|
if (adv.m_params.legacy_pdu && adv.m_params.connectable) {
|
||||||
|
adv.m_params.scannable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If connectable or not scannable disable the callback for scan response requests
|
||||||
|
if (adv.m_params.connectable || !adv.m_params.scannable) {
|
||||||
|
adv.m_params.scan_req_notif = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
NimBLEServer* pServer = NimBLEDevice::getServer();
|
||||||
|
if (pServer != nullptr) {
|
||||||
|
if (!pServer->m_gattsStarted) {
|
||||||
|
pServer->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = ble_gap_ext_adv_configure(inst_id,
|
||||||
|
&adv.m_params,
|
||||||
|
NULL,
|
||||||
|
(pServer != nullptr) ? NimBLEServer::handleGapEvent :
|
||||||
|
NimBLEExtAdvertising::handleGapEvent,
|
||||||
|
NULL);
|
||||||
|
#else
|
||||||
|
int rc = ble_gap_ext_adv_configure(inst_id,
|
||||||
|
&data.m_params,
|
||||||
|
NULL,
|
||||||
|
NimBLEExtAdvertising::handleGapEvent,
|
||||||
|
NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Advertising config error: rc = %d", rc);
|
||||||
|
} else {
|
||||||
|
os_mbuf *buf;
|
||||||
|
buf = os_msys_get_pkthdr(adv.m_payload.size(), 0);
|
||||||
|
if (!buf) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Data buffer allocation failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = os_mbuf_append(buf, &adv.m_payload[0], adv.m_payload.size());
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Unable to copy data: rc = %d", rc);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (adv.m_params.scannable && !adv.m_params.legacy_pdu) {
|
||||||
|
rc = ble_gap_ext_adv_rsp_set_data(inst_id, buf);
|
||||||
|
} else {
|
||||||
|
rc = ble_gap_ext_adv_set_data(inst_id, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Invalid advertisement data: rc = %d", rc);
|
||||||
|
} else {
|
||||||
|
if (adv.m_advAddress != NimBLEAddress("")) {
|
||||||
|
ble_addr_t addr;
|
||||||
|
memcpy(&addr.val, adv.m_advAddress.getNative(), 6);
|
||||||
|
// Custom advertising address must be random.
|
||||||
|
addr.type = BLE_OWN_ADDR_RANDOM;
|
||||||
|
rc = ble_gap_ext_adv_set_addr(inst_id, &addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Error setting advertisement address: rc = %d", rc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the scan response data for a legacy advertisement.
|
||||||
|
* @param [in] inst_id The extended advertisement instance ID to assign to this data.
|
||||||
|
* @param [in] lsr A reference to a NimBLEExtAdvertisement that contains the data.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::setScanResponseData(uint8_t inst_id, NimBLEExtAdvertisement & lsr) {
|
||||||
|
os_mbuf *buf = os_msys_get_pkthdr(lsr.m_payload.size(), 0);
|
||||||
|
if (!buf) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Data buffer allocation failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = os_mbuf_append(buf, &lsr.m_payload[0], lsr.m_payload.size());
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Unable to copy scan data: rc = %d", rc);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
rc = ble_gap_ext_adv_rsp_set_data(inst_id, buf);
|
||||||
|
}
|
||||||
|
return (rc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start extended advertising.
|
||||||
|
* @param [in] inst_id The extended advertisement instance ID to start.
|
||||||
|
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
|
||||||
|
* @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
|
||||||
|
* @return True if advertising started successfully.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::start(uint8_t inst_id, int duration, int max_events) {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, ">> Extended Advertising start");
|
||||||
|
|
||||||
|
// If Host is not synced we cannot start advertising.
|
||||||
|
if(!NimBLEDevice::m_synced) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Host reset, wait for sync.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = ble_gap_ext_adv_start(inst_id, duration / 10, max_events);
|
||||||
|
|
||||||
|
switch (rc) {
|
||||||
|
case 0:
|
||||||
|
m_advStatus[inst_id] = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLE_HS_EINVAL:
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Value Error");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLE_HS_EALREADY:
|
||||||
|
NIMBLE_LOGI(LOG_TAG, "Advertisement Already active");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLE_HS_ETIMEOUT_HCI:
|
||||||
|
case BLE_HS_EOS:
|
||||||
|
case BLE_HS_ECONTROLLER:
|
||||||
|
case BLE_HS_ENOTSYNCED:
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Host Reset");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Error enabling advertising; rc=%d, %s",
|
||||||
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "<< Extended Advertising start");
|
||||||
|
return (rc == 0 || rc == BLE_HS_EALREADY);
|
||||||
|
} // start
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop and remove this instance data from the advertisement set.
|
||||||
|
* @param [in] inst_id The extended advertisement instance to stop advertising.
|
||||||
|
* @return True if successful.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::removeInstance(uint8_t inst_id) {
|
||||||
|
if (stop(inst_id)) {
|
||||||
|
int rc = ble_gap_ext_adv_remove(inst_id);
|
||||||
|
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_remove rc = %d %s",
|
||||||
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // removeInstance
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop and remove all advertising instance data.
|
||||||
|
* @return True if successful.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::removeAll() {
|
||||||
|
if (stop()) {
|
||||||
|
int rc = ble_gap_ext_adv_clear();
|
||||||
|
if (rc == 0 || rc == BLE_HS_EALREADY) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_clear rc = %d %s",
|
||||||
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // removeAll
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop advertising this instance data.
|
||||||
|
* @param [in] inst_id The extended advertisement instance to stop advertising.
|
||||||
|
* @return True if successful.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::stop(uint8_t inst_id) {
|
||||||
|
int rc = ble_gap_ext_adv_stop(inst_id);
|
||||||
|
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_stop rc = %d %s",
|
||||||
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_advStatus[inst_id] = false;
|
||||||
|
return true;
|
||||||
|
} // stop
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop all advertisements.
|
||||||
|
* @return True if successful.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::stop() {
|
||||||
|
int rc = ble_gap_ext_adv_clear();
|
||||||
|
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_stop rc = %d %s",
|
||||||
|
rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto it : m_advStatus) {
|
||||||
|
it = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} // stop
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set a callback to call when the advertisement stops.
|
||||||
|
* @param [in] pCallbacks A pointer to a callback to be invoked when an advertisment stops.
|
||||||
|
* @param [in] deleteCallbacks if true callback class will be deleted when advertising is destructed.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertising::setCallbacks(NimBLEExtAdvertisingCallbacks* pCallbacks,
|
||||||
|
bool deleteCallbacks) {
|
||||||
|
if (pCallbacks != nullptr){
|
||||||
|
m_pCallbacks = pCallbacks;
|
||||||
|
m_deleteCallbacks = deleteCallbacks;
|
||||||
|
} else {
|
||||||
|
m_pCallbacks = &defaultCallbacks;
|
||||||
|
}
|
||||||
|
} // setCallbacks
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if currently advertising.
|
||||||
|
* @param [in] inst_id The instance ID of the advertised data to get the status of.
|
||||||
|
* @return True if advertising is active.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::isActive(uint8_t inst_id) {
|
||||||
|
return m_advStatus[inst_id];
|
||||||
|
} // isAdvertising
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if any instances are currently advertising.
|
||||||
|
* @return True if any instance is active.
|
||||||
|
*/
|
||||||
|
bool NimBLEExtAdvertising::isAdvertising() {
|
||||||
|
for (auto it : m_advStatus) {
|
||||||
|
if (it) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} // isAdvertising
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Host reset seems to clear advertising data,
|
||||||
|
* we need clear the flag so it reloads it.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertising::onHostSync() {
|
||||||
|
NIMBLE_LOGD(LOG_TAG, "Host re-synced");
|
||||||
|
for(auto it : m_advStatus) {
|
||||||
|
it = false;
|
||||||
|
}
|
||||||
|
} // onHostSync
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handler for gap events when not using peripheral role.
|
||||||
|
* @param [in] event the event data.
|
||||||
|
* @param [in] arg pointer to the advertising instance.
|
||||||
|
*/
|
||||||
|
/*STATIC*/
|
||||||
|
int NimBLEExtAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||||
|
(void)arg;
|
||||||
|
NimBLEExtAdvertising* pAdv = NimBLEDevice::getAdvertising();
|
||||||
|
|
||||||
|
switch (event->type) {
|
||||||
|
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
||||||
|
switch (event->adv_complete.reason) {
|
||||||
|
// Don't call the callback if host reset, we want to
|
||||||
|
// preserve the active flag until re-sync to restart advertising.
|
||||||
|
case BLE_HS_ETIMEOUT_HCI:
|
||||||
|
case BLE_HS_EOS:
|
||||||
|
case BLE_HS_ECONTROLLER:
|
||||||
|
case BLE_HS_ENOTSYNCED:
|
||||||
|
NIMBLE_LOGC(LOG_TAG, "host reset, rc = %d", event->adv_complete.reason);
|
||||||
|
NimBLEDevice::onReset(event->adv_complete.reason);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pAdv->m_advStatus[event->adv_complete.instance] = false;
|
||||||
|
pAdv->m_pCallbacks->onStopped(pAdv, event->adv_complete.reason,
|
||||||
|
event->adv_complete.instance);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_SCAN_REQ_RCVD: {
|
||||||
|
pAdv->m_pCallbacks->onScanRequest(pAdv, event->scan_req_rcvd.instance,
|
||||||
|
NimBLEAddress(event->scan_req_rcvd.scan_addr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} // handleGapEvent
|
||||||
|
|
||||||
|
|
||||||
|
/** Default callback handlers */
|
||||||
|
void NimBLEExtAdvertisingCallbacks::onStopped(NimBLEExtAdvertising *pAdv,
|
||||||
|
int reason, uint8_t inst_id) {
|
||||||
|
NIMBLE_LOGD("NimBLEExtAdvertisingCallbacks", "onStopped: Default");
|
||||||
|
} // onStopped
|
||||||
|
|
||||||
|
|
||||||
|
void NimBLEExtAdvertisingCallbacks::onScanRequest(NimBLEExtAdvertising *pAdv,
|
||||||
|
uint8_t inst_id, NimBLEAddress addr) {
|
||||||
|
NIMBLE_LOGD("NimBLEExtAdvertisingCallbacks", "onScanRequest: Default");
|
||||||
|
} // onScanRequest
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a BLE extended advertisement.
|
||||||
|
* @param [in] priPhy The primary Phy to advertise on, can be one of:
|
||||||
|
* * BLE_HCI_LE_PHY_1M
|
||||||
|
* * BLE_HCI_LE_PHY_CODED
|
||||||
|
* @param [in] secPhy The secondary Phy to advertise on, can be one of:
|
||||||
|
* * BLE_HCI_LE_PHY_1M
|
||||||
|
* * BLE_HCI_LE_PHY_2M
|
||||||
|
* * BLE_HCI_LE_PHY_CODED
|
||||||
|
*/
|
||||||
|
NimBLEExtAdvertisement::NimBLEExtAdvertisement(uint8_t priPhy, uint8_t secPhy)
|
||||||
|
: m_advAddress("")
|
||||||
|
{
|
||||||
|
memset (&m_params, 0, sizeof(m_params));
|
||||||
|
m_params.own_addr_type = NimBLEDevice::m_own_addr_type;
|
||||||
|
m_params.primary_phy = priPhy;
|
||||||
|
m_params.secondary_phy = secPhy;
|
||||||
|
m_params.tx_power = 127;
|
||||||
|
} // NimBLEExtAdvertisement
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets wether the advertisement should use legacy (BLE 4.0, 31 bytes max) advertising.
|
||||||
|
* @param [in] val true = using legacy advertising.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setLegacyAdvertising(bool val) {
|
||||||
|
m_params.legacy_pdu = val;
|
||||||
|
} // setLegacyAdvertising
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets wether the advertisement has scan response data available.
|
||||||
|
* @param [in] val true = scan response is available.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setScannable(bool val) {
|
||||||
|
m_params.scannable = val;
|
||||||
|
} // setScannable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the transmission power level for this advertisement.
|
||||||
|
* @param [in] dbm the transmission power to use in dbm.
|
||||||
|
* @details The allowable value range depends on device hardware. \n
|
||||||
|
* The ESP32C3 and ESP32S3 have a range of -27 to +18.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setTxPower(int8_t dbm) {
|
||||||
|
m_params.tx_power = dbm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets wether this advertisement should advertise as a connectable device.
|
||||||
|
* @param [in] val True = connectable.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setConnectable(bool val) {
|
||||||
|
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
||||||
|
m_params.connectable = val;
|
||||||
|
#endif
|
||||||
|
} // setConnectable
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the address to use for this advertisement.
|
||||||
|
* @param [in] addr The address to use.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setAddress(const NimBLEAddress & addr) {
|
||||||
|
m_advAddress = addr;
|
||||||
|
// Must use random address type.
|
||||||
|
m_params.own_addr_type = BLE_OWN_ADDR_RANDOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets The primary channels to advertise on.
|
||||||
|
* @param [in] ch37 Advertise on channel 37.
|
||||||
|
* @param [in] ch38 Advertise on channel 38.
|
||||||
|
* @param [in] ch39 Advertise on channel 39.
|
||||||
|
* @details This will set a bitmask using the input parameters to allow different \n
|
||||||
|
* combinations. If all inputs are false then all 3 channels will be used.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setPrimaryChannels(bool ch37, bool ch38, bool ch39) {
|
||||||
|
m_params.channel_map = (ch37 | (ch38 << 1) | (ch39 << 2));
|
||||||
|
} // setPrimaryChannels
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the filtering for the scan filter.
|
||||||
|
* @param [in] scanRequestWhitelistOnly If true, only allow scan requests from those on the white list.
|
||||||
|
* @param [in] connectWhitelistOnly If true, only allow connections from those on the white list.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly) {
|
||||||
|
if (!scanRequestWhitelistOnly && !connectWhitelistOnly) {
|
||||||
|
m_params.filter_policy = BLE_HCI_ADV_FILT_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (scanRequestWhitelistOnly && !connectWhitelistOnly) {
|
||||||
|
m_params.filter_policy = BLE_HCI_ADV_FILT_SCAN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!scanRequestWhitelistOnly && connectWhitelistOnly) {
|
||||||
|
m_params.filter_policy = BLE_HCI_ADV_FILT_CONN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (scanRequestWhitelistOnly && connectWhitelistOnly) {
|
||||||
|
m_params.filter_policy = BLE_HCI_ADV_FILT_BOTH;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} // setScanFilter
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the peer to directly advertise to.
|
||||||
|
* @param [in] addr The address of the peer to direct the advertisements.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setDirectedPeer(const NimBLEAddress & addr) {
|
||||||
|
ble_addr_t peerAddr;
|
||||||
|
memcpy(&peerAddr.val, addr.getNative(), 6);
|
||||||
|
peerAddr.type = addr.getType();
|
||||||
|
m_params.peer = peerAddr;
|
||||||
|
} // setDirectedPeer
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable or disable direct advertisements to the peer set with `NimBLEExtAdvertisement::setDirectedPeer`
|
||||||
|
* @param [in] val true = send directed advertisements to peer.
|
||||||
|
* @param [in] high_duty true = use fast advertising rate, default - true.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setDirected(bool val, bool high_duty) {
|
||||||
|
m_params.directed = val;
|
||||||
|
m_params.high_duty_directed = high_duty;
|
||||||
|
} // setDirected
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the minimum advertising interval.
|
||||||
|
* @param [in] mininterval Minimum value for advertising interval in 0.625ms units, 0 = use default.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setMinInterval(uint32_t mininterval) {
|
||||||
|
m_params.itvl_min = mininterval;
|
||||||
|
} // setMinInterval
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the maximum advertising interval.
|
||||||
|
* @param [in] maxinterval Maximum value for advertising interval in 0.625ms units, 0 = use default.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setMaxInterval(uint32_t maxinterval) {
|
||||||
|
m_params.itvl_max = maxinterval;
|
||||||
|
} // setMaxInterval
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the primary advertising PHY to use
|
||||||
|
* @param [in] phy Can be one of following constants:
|
||||||
|
* * BLE_HCI_LE_PHY_1M
|
||||||
|
* * BLE_HCI_LE_PHY_CODED
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setPrimaryPhy(uint8_t phy) {
|
||||||
|
m_params.primary_phy = phy;
|
||||||
|
} // setPrimaryPhy
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the secondary advertising PHY to use
|
||||||
|
* @param [in] phy Can be one of following constants:
|
||||||
|
* * BLE_HCI_LE_PHY_1M
|
||||||
|
* * BLE_HCI_LE_PHY_2M
|
||||||
|
* * BLE_HCI_LE_PHY_CODED
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setSecondaryPhy(uint8_t phy) {
|
||||||
|
m_params.secondary_phy = phy;
|
||||||
|
} // setSecondaryPhy
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets whether the advertisement should be anonymous.
|
||||||
|
* @param [in] val Set to true to enable anonymous advertising.
|
||||||
|
*
|
||||||
|
* @details Anonymous advertising omits the device's address from the advertisement.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setAnonymous(bool val) {
|
||||||
|
m_params.anonymous = val;
|
||||||
|
} // setAnonymous
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets whether the scan response request callback should be called.
|
||||||
|
* @param [in] enable If true the scan response request callback will be called for this advertisement.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::enableScanRequestCallback(bool enable) {
|
||||||
|
m_params.scan_req_notif = enable;
|
||||||
|
} // enableScanRequestCallback
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the data stored in this instance, does not change settings.
|
||||||
|
* @details This will clear all data but preserves advertising parameter settings.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::clearData() {
|
||||||
|
std::vector<uint8_t> swap;
|
||||||
|
std::swap(m_payload, swap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the size of the current data.
|
||||||
|
*/
|
||||||
|
size_t NimBLEExtAdvertisement::getDataSize() {
|
||||||
|
return m_payload.size();
|
||||||
|
} // getDataSize
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the advertisement data.
|
||||||
|
* @param [in] data The data to be set as the payload.
|
||||||
|
* @param [in] length The size of data.
|
||||||
|
* @details This will completely replace any data that was previously set.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setData(const uint8_t * data, size_t length) {
|
||||||
|
m_payload.assign(data, data + length);
|
||||||
|
} // setData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add data to the payload to be advertised.
|
||||||
|
* @param [in] data The data to be added to the payload.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::addData(const std::string &data) {
|
||||||
|
addData((uint8_t*)data.data(), data.length());
|
||||||
|
} // addData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add data to the payload to be advertised.
|
||||||
|
* @param [in] data The data to be added to the payload.
|
||||||
|
* @param [in] length The size of data to be added to the payload.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::addData(const uint8_t * data, size_t length) {
|
||||||
|
m_payload.insert(m_payload.end(), data, data + length);
|
||||||
|
} // addData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the appearance.
|
||||||
|
* @param [in] appearance The appearance code value.
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setAppearance(uint16_t appearance) {
|
||||||
|
char cdata[2];
|
||||||
|
cdata[0] = 3;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19
|
||||||
|
addData(std::string(cdata, 2) + std::string((char*) &appearance, 2));
|
||||||
|
} // setAppearance
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the advertisement flags.
|
||||||
|
* @param [in] flag The flags to be set in the advertisement.
|
||||||
|
* * BLE_HS_ADV_F_DISC_LTD
|
||||||
|
* * BLE_HS_ADV_F_DISC_GEN
|
||||||
|
* * BLE_HS_ADV_F_BREDR_UNSUP - must always use with NimBLE
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setFlags(uint8_t flag) {
|
||||||
|
char cdata[3];
|
||||||
|
cdata[0] = 2;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01
|
||||||
|
cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP;
|
||||||
|
addData(std::string(cdata, 3));
|
||||||
|
} // setFlags
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set manufacturer specific data.
|
||||||
|
* @param [in] data The manufacturer data to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setManufacturerData(const std::string &data) {
|
||||||
|
char cdata[2];
|
||||||
|
cdata[0] = data.length() + 1;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
|
||||||
|
addData(std::string(cdata, 2) + data);
|
||||||
|
} // setManufacturerData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the URI to advertise.
|
||||||
|
* @param [in] uri The uri to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setURI(const std::string &uri) {
|
||||||
|
char cdata[2];
|
||||||
|
cdata[0] = uri.length() + 1;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_URI;
|
||||||
|
addData(std::string(cdata, 2) + uri);
|
||||||
|
} // setURI
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the complete name of this device.
|
||||||
|
* @param [in] name The name to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setName(const std::string &name) {
|
||||||
|
char cdata[2];
|
||||||
|
cdata[0] = name.length() + 1;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
|
||||||
|
addData(std::string(cdata, 2) + name);
|
||||||
|
} // setName
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set a single service to advertise as a complete list of services.
|
||||||
|
* @param [in] uuid The service to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setCompleteServices(const NimBLEUUID &uuid) {
|
||||||
|
setServices(true, uuid.bitSize(), {uuid});
|
||||||
|
} // setCompleteServices
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the complete list of 16 bit services to advertise.
|
||||||
|
* @param [in] v_uuid A vector of 16 bit UUID's to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setCompleteServices16(const std::vector<NimBLEUUID>& v_uuid) {
|
||||||
|
setServices(true, 16, v_uuid);
|
||||||
|
} // setCompleteServices16
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the complete list of 32 bit services to advertise.
|
||||||
|
* @param [in] v_uuid A vector of 32 bit UUID's to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setCompleteServices32(const std::vector<NimBLEUUID>& v_uuid) {
|
||||||
|
setServices(true, 32, v_uuid);
|
||||||
|
} // setCompleteServices32
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set a single service to advertise as a partial list of services.
|
||||||
|
* @param [in] uuid The service to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setPartialServices(const NimBLEUUID &uuid) {
|
||||||
|
setServices(false, uuid.bitSize(), {uuid});
|
||||||
|
} // setPartialServices
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the partial list of services to advertise.
|
||||||
|
* @param [in] v_uuid A vector of 16 bit UUID's to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setPartialServices16(const std::vector<NimBLEUUID>& v_uuid) {
|
||||||
|
setServices(false, 16, v_uuid);
|
||||||
|
} // setPartialServices16
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the partial list of services to advertise.
|
||||||
|
* @param [in] v_uuid A vector of 32 bit UUID's to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setPartialServices32(const std::vector<NimBLEUUID>& v_uuid) {
|
||||||
|
setServices(false, 32, v_uuid);
|
||||||
|
} // setPartialServices32
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Utility function to create the list of service UUID's from a vector.
|
||||||
|
* @param [in] complete If true the vector is the complete set of services.
|
||||||
|
* @param [in] size The bit size of the UUID's in the vector. (16, 32, or 128).
|
||||||
|
* @param [in] v_uuid The vector of service UUID's to advertise.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setServices(const bool complete, const uint8_t size,
|
||||||
|
const std::vector<NimBLEUUID> &v_uuid)
|
||||||
|
{
|
||||||
|
char cdata[2];
|
||||||
|
cdata[0] = (size / 8) * v_uuid.size() + 1;
|
||||||
|
switch(size) {
|
||||||
|
case 16:
|
||||||
|
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32;
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string uuids;
|
||||||
|
|
||||||
|
for(auto &it : v_uuid){
|
||||||
|
if(it.bitSize() != size) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
switch(size) {
|
||||||
|
case 16:
|
||||||
|
uuids += std::string((char*)&it.getNative()->u16.value, 2);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
uuids += std::string((char*)&it.getNative()->u32.value, 4);
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
uuids += std::string((char*)&it.getNative()->u128.value, 16);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addData(std::string(cdata, 2) + uuids);
|
||||||
|
} // setServices
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the service data (UUID + data)
|
||||||
|
* @param [in] uuid The UUID to set with the service data.
|
||||||
|
* @param [in] data The data to be associated with the service data advertised.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
|
||||||
|
char cdata[2];
|
||||||
|
switch (uuid.bitSize()) {
|
||||||
|
case 16: {
|
||||||
|
// [Len] [0x16] [UUID16] data
|
||||||
|
cdata[0] = data.length() + 3;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16
|
||||||
|
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 32: {
|
||||||
|
// [Len] [0x20] [UUID32] data
|
||||||
|
cdata[0] = data.length() + 5;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20
|
||||||
|
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 128: {
|
||||||
|
// [Len] [0x21] [UUID128] data
|
||||||
|
cdata[0] = data.length() + 17;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21
|
||||||
|
addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} // setServiceData
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the short name.
|
||||||
|
* @param [in] name The short name of the device.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setShortName(const std::string &name) {
|
||||||
|
char cdata[2];
|
||||||
|
cdata[0] = name.length() + 1;
|
||||||
|
cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
|
||||||
|
addData(std::string(cdata, 2) + name);
|
||||||
|
} // setShortName
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds Tx power level to the advertisement data.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::addTxPower() {
|
||||||
|
m_params.include_tx_power = 1;
|
||||||
|
} // addTxPower
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the preferred connection interval parameters.
|
||||||
|
* @param [in] min The minimum interval desired.
|
||||||
|
* @param [in] max The maximum interval desired.
|
||||||
|
*/
|
||||||
|
void NimBLEExtAdvertisement::setPreferredParams(uint16_t min, uint16_t max) {
|
||||||
|
uint8_t data[6];
|
||||||
|
data[0] = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1;
|
||||||
|
data[1] = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE;
|
||||||
|
data[2] = min;
|
||||||
|
data[3] = min >> 8;
|
||||||
|
data[4] = max;
|
||||||
|
data[5] = max >> 8;
|
||||||
|
addData(data, 6);
|
||||||
|
} // setPreferredParams
|
||||||
|
|
||||||
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV */
|
||||||
152
lib/NimBLE-Arduino/src/NimBLEExtAdvertising.h
Normal file
152
lib/NimBLE-Arduino/src/NimBLEExtAdvertising.h
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* NimBLEExtAdvertising.h
|
||||||
|
*
|
||||||
|
* Created: on February 6, 2022
|
||||||
|
* Author H2zero
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAIN_BLEEXTADVERTISING_H_
|
||||||
|
#define MAIN_BLEEXTADVERTISING_H_
|
||||||
|
#include "nimconfig.h"
|
||||||
|
#if defined(CONFIG_BT_ENABLED) && \
|
||||||
|
defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
|
||||||
|
CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
|
||||||
|
# if defined(CONFIG_NIMBLE_CPP_IDF)
|
||||||
|
# include "host/ble_gap.h"
|
||||||
|
# else
|
||||||
|
# include "nimble/nimble/host/include/host/ble_gap.h"
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/**** FIX COMPILATION ****/
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
/**************************/
|
||||||
|
|
||||||
|
#include "NimBLEAddress.h"
|
||||||
|
#include "NimBLEUUID.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class NimBLEExtAdvertisingCallbacks;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extended advertisement data
|
||||||
|
*/
|
||||||
|
class NimBLEExtAdvertisement {
|
||||||
|
public:
|
||||||
|
NimBLEExtAdvertisement(uint8_t priPhy = BLE_HCI_LE_PHY_1M,
|
||||||
|
uint8_t secPhy = BLE_HCI_LE_PHY_1M);
|
||||||
|
void setAppearance(uint16_t appearance);
|
||||||
|
void setCompleteServices(const NimBLEUUID &uuid);
|
||||||
|
void setCompleteServices16(const std::vector<NimBLEUUID> &v_uuid);
|
||||||
|
void setCompleteServices32(const std::vector<NimBLEUUID> &v_uuid);
|
||||||
|
void setFlags(uint8_t flag);
|
||||||
|
void setManufacturerData(const std::string &data);
|
||||||
|
void setURI(const std::string &uri);
|
||||||
|
void setName(const std::string &name);
|
||||||
|
void setPartialServices(const NimBLEUUID &uuid);
|
||||||
|
void setPartialServices16(const std::vector<NimBLEUUID> &v_uuid);
|
||||||
|
void setPartialServices32(const std::vector<NimBLEUUID> &v_uuid);
|
||||||
|
void setServiceData(const NimBLEUUID &uuid, const std::string &data);
|
||||||
|
void setShortName(const std::string &name);
|
||||||
|
void setData(const uint8_t * data, size_t length);
|
||||||
|
void addData(const std::string &data);
|
||||||
|
void addData(const uint8_t * data, size_t length);
|
||||||
|
void addTxPower();
|
||||||
|
void setPreferredParams(uint16_t min, uint16_t max);
|
||||||
|
void setLegacyAdvertising(bool val);
|
||||||
|
void setConnectable(bool val);
|
||||||
|
void setScannable(bool val);
|
||||||
|
void setMinInterval(uint32_t mininterval);
|
||||||
|
void setMaxInterval(uint32_t maxinterval);
|
||||||
|
void setPrimaryPhy(uint8_t phy);
|
||||||
|
void setSecondaryPhy(uint8_t phy);
|
||||||
|
void setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly);
|
||||||
|
void setDirectedPeer(const NimBLEAddress & addr);
|
||||||
|
void setDirected(bool val, bool high_duty = true);
|
||||||
|
void setAnonymous(bool val);
|
||||||
|
void setPrimaryChannels(bool ch37, bool ch38, bool ch39);
|
||||||
|
void setTxPower(int8_t dbm);
|
||||||
|
void setAddress(const NimBLEAddress & addr);
|
||||||
|
void enableScanRequestCallback(bool enable);
|
||||||
|
void clearData();
|
||||||
|
size_t getDataSize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class NimBLEExtAdvertising;
|
||||||
|
|
||||||
|
void setServices(const bool complete, const uint8_t size,
|
||||||
|
const std::vector<NimBLEUUID> &v_uuid);
|
||||||
|
|
||||||
|
std::vector<uint8_t> m_payload;
|
||||||
|
ble_gap_ext_adv_params m_params;
|
||||||
|
NimBLEAddress m_advAddress;
|
||||||
|
}; // NimBLEExtAdvertisement
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extended advertising class.
|
||||||
|
*/
|
||||||
|
class NimBLEExtAdvertising {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Construct an extended advertising object.
|
||||||
|
*/
|
||||||
|
NimBLEExtAdvertising() :m_advStatus(CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES + 1, false) {}
|
||||||
|
~NimBLEExtAdvertising();
|
||||||
|
bool start(uint8_t inst_id, int duration = 0, int max_events = 0);
|
||||||
|
bool setInstanceData(uint8_t inst_id, NimBLEExtAdvertisement& adv);
|
||||||
|
bool setScanResponseData(uint8_t inst_id, NimBLEExtAdvertisement & data);
|
||||||
|
bool removeInstance(uint8_t inst_id);
|
||||||
|
bool removeAll();
|
||||||
|
bool stop(uint8_t inst_id);
|
||||||
|
bool stop();
|
||||||
|
bool isActive(uint8_t inst_id);
|
||||||
|
bool isAdvertising();
|
||||||
|
void setCallbacks(NimBLEExtAdvertisingCallbacks* callbacks,
|
||||||
|
bool deleteCallbacks = true);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class NimBLEDevice;
|
||||||
|
friend class NimBLEServer;
|
||||||
|
|
||||||
|
void onHostSync();
|
||||||
|
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||||
|
|
||||||
|
bool m_scanResp;
|
||||||
|
bool m_deleteCallbacks;
|
||||||
|
NimBLEExtAdvertisingCallbacks* m_pCallbacks;
|
||||||
|
ble_gap_ext_adv_params m_advParams;
|
||||||
|
std::vector<bool> m_advStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callbacks associated with NimBLEExtAdvertising class.
|
||||||
|
*/
|
||||||
|
class NimBLEExtAdvertisingCallbacks {
|
||||||
|
public:
|
||||||
|
virtual ~NimBLEExtAdvertisingCallbacks() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle an advertising stop event.
|
||||||
|
* @param [in] pAdv A convenience pointer to the extended advertising interface.
|
||||||
|
* @param [in] reason The reason code for stopping the advertising.
|
||||||
|
* @param [in] inst_id The instance ID of the advertisement that was stopped.
|
||||||
|
*/
|
||||||
|
virtual void onStopped(NimBLEExtAdvertising *pAdv, int reason, uint8_t inst_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle a scan response request.
|
||||||
|
* This is called when a scanning device requests a scan response.
|
||||||
|
* @param [in] pAdv A convenience pointer to the extended advertising interface.
|
||||||
|
* @param [in] inst_id The instance ID of the advertisement that the scan response request was made.
|
||||||
|
* @param [in] addr The address of the device making the request.
|
||||||
|
*/
|
||||||
|
virtual void onScanRequest(NimBLEExtAdvertising *pAdv, uint8_t inst_id, NimBLEAddress addr);
|
||||||
|
}; // NimBLEExtAdvertisingCallbacks
|
||||||
|
|
||||||
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV */
|
||||||
|
#endif /* MAIN_BLEADVERTISING_H_ */
|
||||||
@@ -256,7 +256,9 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_characteristicVector.back()->m_endHandle = getEndHandle();
|
if (m_characteristicVector.size() > 0) {
|
||||||
|
m_characteristicVector.back()->m_endHandle = getEndHandle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
|
||||||
|
|||||||
@@ -56,18 +56,27 @@ NimBLEScan::~NimBLEScan() {
|
|||||||
* @param [in] param Parameter data for this event.
|
* @param [in] param Parameter data for this event.
|
||||||
*/
|
*/
|
||||||
/*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
/*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||||
|
(void)arg;
|
||||||
NimBLEScan* pScan = (NimBLEScan*)arg;
|
NimBLEScan* pScan = NimBLEDevice::getScan();
|
||||||
|
|
||||||
switch(event->type) {
|
switch(event->type) {
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_EXT_DISC:
|
||||||
case BLE_GAP_EVENT_DISC: {
|
case BLE_GAP_EVENT_DISC: {
|
||||||
if(pScan->m_ignoreResults) {
|
if(pScan->m_ignoreResults) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
|
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
NimBLEAddress advertisedAddress(event->disc.addr);
|
const auto& disc = event->ext_disc;
|
||||||
|
const bool isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
|
||||||
|
const auto event_type = isLegacyAdv ? disc.legacy_event_type : disc.props;
|
||||||
|
#else
|
||||||
|
const auto& disc = event->disc;
|
||||||
|
const bool isLegacyAdv = true;
|
||||||
|
const auto event_type = disc.event_type;
|
||||||
|
#endif
|
||||||
|
NimBLEAddress advertisedAddress(disc.addr);
|
||||||
|
|
||||||
// Examine our list of ignored addresses and stop processing if we don't want to see it or are already connected
|
// Examine our list of ignored addresses and stop processing if we don't want to see it or are already connected
|
||||||
if(NimBLEDevice::isIgnored(advertisedAddress)) {
|
if(NimBLEDevice::isIgnored(advertisedAddress)) {
|
||||||
@@ -79,7 +88,12 @@ NimBLEScan::~NimBLEScan() {
|
|||||||
|
|
||||||
// If we've seen this device before get a pointer to it from the vector
|
// If we've seen this device before get a pointer to it from the vector
|
||||||
for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) {
|
for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) {
|
||||||
if(it->getAddress() == advertisedAddress) {
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
// Same address but different set ID should create a new advertised device.
|
||||||
|
if (it->getAddress() == advertisedAddress && it->getSetId() == disc.sid) {
|
||||||
|
#else
|
||||||
|
if (it->getAddress() == advertisedAddress) {
|
||||||
|
#endif
|
||||||
advertisedDevice = it;
|
advertisedDevice = it;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -87,20 +101,27 @@ NimBLEScan::~NimBLEScan() {
|
|||||||
|
|
||||||
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
// If we haven't seen this device before; create a new instance and insert it in the vector.
|
||||||
// Otherwise just update the relevant parameters of the already known device.
|
// Otherwise just update the relevant parameters of the already known device.
|
||||||
if(advertisedDevice == nullptr && event->disc.event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP){
|
if (advertisedDevice == nullptr &&
|
||||||
|
(!isLegacyAdv || event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP)) {
|
||||||
// Check if we have reach the scan results limit, ignore this one if so.
|
// Check if we have reach the scan results limit, ignore this one if so.
|
||||||
// We still need to store each device when maxResults is 0 to be able to append the scan results
|
// We still need to store each device when maxResults is 0 to be able to append the scan results
|
||||||
if(pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
if (pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
||||||
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults))
|
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults)) {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||||
advertisedDevice->setAddress(advertisedAddress);
|
advertisedDevice->setAddress(advertisedAddress);
|
||||||
advertisedDevice->setAdvType(event->disc.event_type);
|
advertisedDevice->setAdvType(event_type, isLegacyAdv);
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
advertisedDevice->setSetId(disc.sid);
|
||||||
|
advertisedDevice->setPrimaryPhy(disc.prim_phy);
|
||||||
|
advertisedDevice->setSecondaryPhy(disc.sec_phy);
|
||||||
|
advertisedDevice->setPeriodicInterval(disc.periodic_adv_itvl);
|
||||||
|
#endif
|
||||||
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
|
||||||
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
|
||||||
} else if(advertisedDevice != nullptr) {
|
} else if (advertisedDevice != nullptr) {
|
||||||
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
|
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
|
||||||
} else {
|
} else {
|
||||||
// Scan response from unknown device
|
// Scan response from unknown device
|
||||||
@@ -108,14 +129,14 @@ NimBLEScan::~NimBLEScan() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
advertisedDevice->m_timestamp = time(nullptr);
|
advertisedDevice->m_timestamp = time(nullptr);
|
||||||
advertisedDevice->setRSSI(event->disc.rssi);
|
advertisedDevice->setRSSI(disc.rssi);
|
||||||
advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
|
advertisedDevice->setPayload(disc.data, disc.length_data, (isLegacyAdv &&
|
||||||
event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP);
|
event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP));
|
||||||
|
|
||||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||||
// If not active scanning or scan response is not available
|
// If not active scanning or scan response is not available
|
||||||
// report the result to the callback now.
|
// or extended advertisement scanning, report the result to the callback now.
|
||||||
if(pScan->m_scan_params.passive ||
|
if(pScan->m_scan_params.passive || !isLegacyAdv ||
|
||||||
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
|
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
|
||||||
advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
|
advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
|
||||||
{
|
{
|
||||||
@@ -123,7 +144,7 @@ NimBLEScan::~NimBLEScan() {
|
|||||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||||
|
|
||||||
// Otherwise, wait for the scan response so we can report the complete data.
|
// Otherwise, wait for the scan response so we can report the complete data.
|
||||||
} else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
} else if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
|
||||||
advertisedDevice->m_callbackSent = true;
|
advertisedDevice->m_callbackSent = true;
|
||||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||||
}
|
}
|
||||||
@@ -304,9 +325,28 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
|||||||
m_ignoreResults = true;
|
m_ignoreResults = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = ble_gap_disc(NimBLEDevice::m_own_addr_type, duration, &m_scan_params,
|
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
NimBLEScan::handleGapEvent, this);
|
ble_gap_ext_disc_params scan_params;
|
||||||
|
scan_params.passive = m_scan_params.passive;
|
||||||
|
scan_params.itvl = m_scan_params.itvl;
|
||||||
|
scan_params.window = m_scan_params.window;
|
||||||
|
int rc = ble_gap_ext_disc(NimBLEDevice::m_own_addr_type,
|
||||||
|
duration/10,
|
||||||
|
0,
|
||||||
|
m_scan_params.filter_duplicates,
|
||||||
|
m_scan_params.filter_policy,
|
||||||
|
m_scan_params.limited,
|
||||||
|
&scan_params,
|
||||||
|
&scan_params,
|
||||||
|
NimBLEScan::handleGapEvent,
|
||||||
|
NULL);
|
||||||
|
#else
|
||||||
|
int rc = ble_gap_disc(NimBLEDevice::m_own_addr_type,
|
||||||
|
duration,
|
||||||
|
&m_scan_params,
|
||||||
|
NimBLEScan::handleGapEvent,
|
||||||
|
NULL);
|
||||||
|
#endif
|
||||||
switch(rc) {
|
switch(rc) {
|
||||||
case 0:
|
case 0:
|
||||||
if(!is_continue) {
|
if(!is_continue) {
|
||||||
|
|||||||
@@ -46,13 +46,13 @@
|
|||||||
#define ESP_IO_CAP_NONE 3 /*!< NoInputNoOutput */ /* relate to BTM_IO_CAP_NONE in stack/btm_api.h */
|
#define ESP_IO_CAP_NONE 3 /*!< NoInputNoOutput */ /* relate to BTM_IO_CAP_NONE in stack/btm_api.h */
|
||||||
#define ESP_IO_CAP_KBDISP 4 /*!< Keyboard display */ /* relate to BTM_IO_CAP_KBDISP in stack/btm_api.h */
|
#define ESP_IO_CAP_KBDISP 4 /*!< Keyboard display */ /* relate to BTM_IO_CAP_KBDISP in stack/btm_api.h */
|
||||||
|
|
||||||
/// Used to exchange the encryption key in the initialize key & response key
|
/// Used to exchange the encryption key in the init key & response key
|
||||||
#define ESP_BLE_ENC_KEY_MASK (1 << 0) /* relate to BTM_BLE_ENC_KEY_MASK in stack/btm_api.h */
|
#define ESP_BLE_ENC_KEY_MASK (1 << 0) /* relate to BTM_BLE_ENC_KEY_MASK in stack/btm_api.h */
|
||||||
/// Used to exchange the IRK key in the initialize key & response key
|
/// Used to exchange the IRK key in the init key & response key
|
||||||
#define ESP_BLE_ID_KEY_MASK (1 << 1) /* relate to BTM_BLE_ID_KEY_MASK in stack/btm_api.h */
|
#define ESP_BLE_ID_KEY_MASK (1 << 1) /* relate to BTM_BLE_ID_KEY_MASK in stack/btm_api.h */
|
||||||
/// Used to exchange the CSRK key in the initialize key & response key
|
/// Used to exchange the CSRK key in the init key & response key
|
||||||
#define ESP_BLE_CSR_KEY_MASK (1 << 2) /* relate to BTM_BLE_CSR_KEY_MASK in stack/btm_api.h */
|
#define ESP_BLE_CSR_KEY_MASK (1 << 2) /* relate to BTM_BLE_CSR_KEY_MASK in stack/btm_api.h */
|
||||||
/// Used to exchange the link key(this key just used in the BLE & BR/EDR coexist mode) in the initialize key & response key
|
/// Used to exchange the link key(this key just used in the BLE & BR/EDR coexist mode) in the init key & response key
|
||||||
#define ESP_BLE_LINK_KEY_MASK (1 << 3) /* relate to BTM_BLE_LINK_KEY_MASK in stack/btm_api.h */
|
#define ESP_BLE_LINK_KEY_MASK (1 << 3) /* relate to BTM_BLE_LINK_KEY_MASK in stack/btm_api.h */
|
||||||
|
|
||||||
typedef uint8_t esp_ble_auth_req_t; /*!< combination of the above bit pattern */
|
typedef uint8_t esp_ble_auth_req_t; /*!< combination of the above bit pattern */
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ NimBLEServer::NimBLEServer() {
|
|||||||
// m_svcChgChrHdl = 0xffff; // Future Use
|
// m_svcChgChrHdl = 0xffff; // Future Use
|
||||||
m_pServerCallbacks = &defaultCallbacks;
|
m_pServerCallbacks = &defaultCallbacks;
|
||||||
m_gattsStarted = false;
|
m_gattsStarted = false;
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
m_advertiseOnDisconnect = true;
|
m_advertiseOnDisconnect = true;
|
||||||
|
#endif
|
||||||
m_svcChanged = false;
|
m_svcChanged = false;
|
||||||
m_deleteCallbacks = true;
|
m_deleteCallbacks = true;
|
||||||
} // NimBLEServer
|
} // NimBLEServer
|
||||||
@@ -139,15 +141,26 @@ NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
/**
|
||||||
|
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||||
|
* @return An advertising object.
|
||||||
|
*/
|
||||||
|
NimBLEExtAdvertising* NimBLEServer::getAdvertising() {
|
||||||
|
return NimBLEDevice::getAdvertising();
|
||||||
|
} // getAdvertising
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
|
||||||
*
|
|
||||||
* @return An advertising object.
|
* @return An advertising object.
|
||||||
*/
|
*/
|
||||||
NimBLEAdvertising* NimBLEServer::getAdvertising() {
|
NimBLEAdvertising* NimBLEServer::getAdvertising() {
|
||||||
return NimBLEDevice::getAdvertising();
|
return NimBLEDevice::getAdvertising();
|
||||||
} // getAdvertising
|
} // getAdvertising
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sends a service changed notification and resets the GATT server.
|
* @brief Sends a service changed notification and resets the GATT server.
|
||||||
@@ -240,6 +253,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
|||||||
} // disconnect
|
} // disconnect
|
||||||
|
|
||||||
|
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||||
/**
|
/**
|
||||||
* @brief Set the server to automatically start advertising when a client disconnects.
|
* @brief Set the server to automatically start advertising when a client disconnects.
|
||||||
* @param [in] aod true == advertise, false == don't advertise.
|
* @param [in] aod true == advertise, false == don't advertise.
|
||||||
@@ -247,7 +261,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
|
|||||||
void NimBLEServer::advertiseOnDisconnect(bool aod) {
|
void NimBLEServer::advertiseOnDisconnect(bool aod) {
|
||||||
m_advertiseOnDisconnect = aod;
|
m_advertiseOnDisconnect = aod;
|
||||||
} // advertiseOnDisconnect
|
} // advertiseOnDisconnect
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the number of connected clients.
|
* @brief Return the number of connected clients.
|
||||||
@@ -325,7 +339,7 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
|||||||
*/
|
*/
|
||||||
/*STATIC*/
|
/*STATIC*/
|
||||||
int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||||
NimBLEServer* server = (NimBLEServer*)arg;
|
NimBLEServer* server = NimBLEDevice::getServer();
|
||||||
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s",
|
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s",
|
||||||
NimBLEUtils::gapEventToString(event->type));
|
NimBLEUtils::gapEventToString(event->type));
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -337,7 +351,9 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
if (event->connect.status != 0) {
|
if (event->connect.status != 0) {
|
||||||
/* Connection failed; resume advertising */
|
/* Connection failed; resume advertising */
|
||||||
NIMBLE_LOGE(LOG_TAG, "Connection failed");
|
NIMBLE_LOGE(LOG_TAG, "Connection failed");
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
NimBLEDevice::startAdvertising();
|
NimBLEDevice::startAdvertising();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
server->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
server->m_connectedPeersVec.push_back(event->connect.conn_handle);
|
||||||
@@ -382,9 +398,11 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
server->m_pServerCallbacks->onDisconnect(server);
|
server->m_pServerCallbacks->onDisconnect(server);
|
||||||
server->m_pServerCallbacks->onDisconnect(server, &event->disconnect.conn);
|
server->m_pServerCallbacks->onDisconnect(server, &event->disconnect.conn);
|
||||||
|
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
if(server->m_advertiseOnDisconnect) {
|
if(server->m_advertiseOnDisconnect) {
|
||||||
server->startAdvertising();
|
server->startAdvertising();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
} // BLE_GAP_EVENT_DISCONNECT
|
} // BLE_GAP_EVENT_DISCONNECT
|
||||||
|
|
||||||
@@ -472,11 +490,15 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
|||||||
return 0;
|
return 0;
|
||||||
} // BLE_GAP_EVENT_NOTIFY_TX
|
} // BLE_GAP_EVENT_NOTIFY_TX
|
||||||
|
|
||||||
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
|
||||||
NIMBLE_LOGD(LOG_TAG, "Advertising Complete");
|
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||||
NimBLEDevice::getAdvertising()->advCompleteCB();
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
return 0;
|
case BLE_GAP_EVENT_SCAN_REQ_RCVD:
|
||||||
}
|
return NimBLEExtAdvertising::handleGapEvent(event, arg);
|
||||||
|
#else
|
||||||
|
return NimBLEAdvertising::handleGapEvent(event, arg);
|
||||||
|
#endif
|
||||||
|
// BLE_GAP_EVENT_ADV_COMPLETE | BLE_GAP_EVENT_SCAN_REQ_RCVD
|
||||||
|
|
||||||
case BLE_GAP_EVENT_CONN_UPDATE: {
|
case BLE_GAP_EVENT_CONN_UPDATE: {
|
||||||
NIMBLE_LOGD(LOG_TAG, "Connection parameters updated.");
|
NIMBLE_LOGD(LOG_TAG, "Connection parameters updated.");
|
||||||
@@ -653,7 +675,9 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
|
|||||||
|
|
||||||
service->m_removed = deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
|
service->m_removed = deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
|
||||||
serviceChanged();
|
serviceChanged();
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
|
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -716,22 +740,52 @@ void NimBLEServer::resetGATT() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
/**
|
/**
|
||||||
* @brief Start advertising.
|
* @brief Start advertising.
|
||||||
*
|
* @param [in] inst_id The extended advertisement instance ID to start.
|
||||||
* Start the server advertising its existence. This is a convenience function and is equivalent to
|
* @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
|
||||||
|
* @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
|
||||||
|
* @return True if advertising started successfully.
|
||||||
|
* @details Start the server advertising its existence. This is a convenience function and is equivalent to
|
||||||
* retrieving the advertising object and invoking start upon it.
|
* retrieving the advertising object and invoking start upon it.
|
||||||
*/
|
*/
|
||||||
void NimBLEServer::startAdvertising() {
|
bool NimBLEServer::startAdvertising(uint8_t inst_id,
|
||||||
NimBLEDevice::startAdvertising();
|
int duration,
|
||||||
|
int max_events) {
|
||||||
|
return getAdvertising()->start(inst_id, duration, max_events);
|
||||||
} // startAdvertising
|
} // startAdvertising
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop advertising.
|
* @brief Convenience function to stop advertising a data set.
|
||||||
|
* @param [in] inst_id The extended advertisement instance ID to stop advertising.
|
||||||
|
* @return True if advertising stopped successfully.
|
||||||
*/
|
*/
|
||||||
void NimBLEServer::stopAdvertising() {
|
bool NimBLEServer::stopAdvertising(uint8_t inst_id) {
|
||||||
NimBLEDevice::stopAdvertising();
|
return getAdvertising()->stop(inst_id);
|
||||||
|
} // stopAdvertising
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV|| defined(_DOXYGEN_)
|
||||||
|
/**
|
||||||
|
* @brief Start advertising.
|
||||||
|
* @return True if advertising started successfully.
|
||||||
|
* @details Start the server advertising its existence. This is a convenience function and is equivalent to
|
||||||
|
* retrieving the advertising object and invoking start upon it.
|
||||||
|
*/
|
||||||
|
bool NimBLEServer::startAdvertising() {
|
||||||
|
return getAdvertising()->start();
|
||||||
|
} // startAdvertising
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop advertising.
|
||||||
|
* @return True if advertising stopped successfully.
|
||||||
|
*/
|
||||||
|
bool NimBLEServer::stopAdvertising() {
|
||||||
|
return getAdvertising()->stop();
|
||||||
} // stopAdvertising
|
} // stopAdvertising
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,11 @@
|
|||||||
|
|
||||||
#include "NimBLEUtils.h"
|
#include "NimBLEUtils.h"
|
||||||
#include "NimBLEAddress.h"
|
#include "NimBLEAddress.h"
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
#include "NimBLEExtAdvertising.h"
|
||||||
|
#else
|
||||||
#include "NimBLEAdvertising.h"
|
#include "NimBLEAdvertising.h"
|
||||||
|
#endif
|
||||||
#include "NimBLEService.h"
|
#include "NimBLEService.h"
|
||||||
#include "NimBLESecurity.h"
|
#include "NimBLESecurity.h"
|
||||||
#include "NimBLEConnInfo.h"
|
#include "NimBLEConnInfo.h"
|
||||||
@@ -46,11 +50,19 @@ public:
|
|||||||
NimBLEService* createService(const NimBLEUUID &uuid);
|
NimBLEService* createService(const NimBLEUUID &uuid);
|
||||||
void removeService(NimBLEService* service, bool deleteSvc = false);
|
void removeService(NimBLEService* service, bool deleteSvc = false);
|
||||||
void addService(NimBLEService* service);
|
void addService(NimBLEService* service);
|
||||||
NimBLEAdvertising* getAdvertising();
|
|
||||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks,
|
void setCallbacks(NimBLEServerCallbacks* pCallbacks,
|
||||||
bool deleteCallbacks = true);
|
bool deleteCallbacks = true);
|
||||||
void startAdvertising();
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
void stopAdvertising();
|
NimBLEExtAdvertising* getAdvertising();
|
||||||
|
bool startAdvertising(uint8_t inst_id,
|
||||||
|
int duration = 0,
|
||||||
|
int max_events = 0);
|
||||||
|
bool stopAdvertising(uint8_t inst_id);
|
||||||
|
#else
|
||||||
|
NimBLEAdvertising* getAdvertising();
|
||||||
|
bool startAdvertising();
|
||||||
|
#endif
|
||||||
|
bool stopAdvertising();
|
||||||
void start();
|
void start();
|
||||||
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
|
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
|
||||||
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
|
||||||
@@ -66,7 +78,9 @@ public:
|
|||||||
NimBLEConnInfo getPeerInfo(size_t index);
|
NimBLEConnInfo getPeerInfo(size_t index);
|
||||||
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
|
||||||
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||||
void advertiseOnDisconnect(bool);
|
void advertiseOnDisconnect(bool);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NimBLEServer();
|
NimBLEServer();
|
||||||
@@ -75,9 +89,15 @@ private:
|
|||||||
friend class NimBLEService;
|
friend class NimBLEService;
|
||||||
friend class NimBLEDevice;
|
friend class NimBLEDevice;
|
||||||
friend class NimBLEAdvertising;
|
friend class NimBLEAdvertising;
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
friend class NimBLEExtAdvertising;
|
||||||
|
friend class NimBLEExtAdvertisementData;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool m_gattsStarted;
|
bool m_gattsStarted;
|
||||||
|
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
bool m_advertiseOnDisconnect;
|
bool m_advertiseOnDisconnect;
|
||||||
|
#endif
|
||||||
bool m_svcChanged;
|
bool m_svcChanged;
|
||||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||||
bool m_deleteCallbacks;
|
bool m_deleteCallbacks;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ esp_err_t esp_nimble_hci_init(void);
|
|||||||
* transport buffers to be exchanged between NimBLE host and ESP controller.
|
* transport buffers to be exchanged between NimBLE host and ESP controller.
|
||||||
* It also registers required host callbacks with the controller.
|
* It also registers required host callbacks with the controller.
|
||||||
*
|
*
|
||||||
* Below is the sequence of APIs to be called to initialize/enable NimBLE host and ESP controller:
|
* Below is the sequence of APIs to be called to init/enable NimBLE host and ESP controller:
|
||||||
*
|
*
|
||||||
* @code{c}
|
* @code{c}
|
||||||
* void ble_host_task(void *param)
|
* void ble_host_task(void *param)
|
||||||
|
|||||||
@@ -93,11 +93,11 @@ int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
|
|||||||
unsigned int key_size);
|
unsigned int key_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief HMAC initialize procedure
|
* @brief HMAC init procedure
|
||||||
* Initializes ctx to begin the next HMAC operation
|
* Initializes ctx to begin the next HMAC operation
|
||||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||||
* returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
|
* returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
|
||||||
* @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to initialize
|
* @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init
|
||||||
*/
|
*/
|
||||||
int tc_hmac_init(TCHmacState_t ctx);
|
int tc_hmac_init(TCHmacState_t ctx);
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
|
|||||||
* nonce. TinyCrypts requires instead a non-null personalization
|
* nonce. TinyCrypts requires instead a non-null personalization
|
||||||
* (which is easily computed) and indirectly requires an entropy
|
* (which is easily computed) and indirectly requires an entropy
|
||||||
* seed (since the reseed function is mandatorily called after
|
* seed (since the reseed function is mandatorily called after
|
||||||
* initialize)
|
* init)
|
||||||
* @param prng IN/OUT -- the PRNG state to initialize
|
* @param prng IN/OUT -- the PRNG state to initialize
|
||||||
* @param personalization IN -- personalization string
|
* @param personalization IN -- personalization string
|
||||||
* @param plen IN -- personalization length in bytes
|
* @param plen IN -- personalization length in bytes
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ struct ble_dev_addr
|
|||||||
* -> AdvA (6 bytes)
|
* -> AdvA (6 bytes)
|
||||||
* -> LLData (22 bytes)
|
* -> LLData (22 bytes)
|
||||||
* -> Access address (4 bytes)
|
* -> Access address (4 bytes)
|
||||||
* -> CRC initialize (3 bytes)
|
* -> CRC init (3 bytes)
|
||||||
* -> WinSize (1 byte)
|
* -> WinSize (1 byte)
|
||||||
* -> WinOffset (2 bytes)
|
* -> WinOffset (2 bytes)
|
||||||
* -> Interval (2 bytes)
|
* -> Interval (2 bytes)
|
||||||
|
|||||||
@@ -1425,7 +1425,7 @@ ble_ll_reset(void)
|
|||||||
/* Reset connection module */
|
/* Reset connection module */
|
||||||
ble_ll_conn_module_reset();
|
ble_ll_conn_module_reset();
|
||||||
|
|
||||||
/* All this does is re-initialize the event masks so call the hci initialize */
|
/* All this does is re-initialize the event masks so call the hci init */
|
||||||
ble_ll_hci_init();
|
ble_ll_hci_init();
|
||||||
|
|
||||||
/* Reset scheduler */
|
/* Reset scheduler */
|
||||||
|
|||||||
@@ -3037,7 +3037,7 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
|
|||||||
|
|
||||||
/* Get connection state machine to use if connection to be established */
|
/* Get connection state machine to use if connection to be established */
|
||||||
connsm = g_ble_ll_conn_create_sm;
|
connsm = g_ble_ll_conn_create_sm;
|
||||||
/* This could happen if connection initialize was cancelled while isr end was
|
/* This could happen if connection init was cancelled while isr end was
|
||||||
* already pending
|
* already pending
|
||||||
*/
|
*/
|
||||||
if (!connsm) {
|
if (!connsm) {
|
||||||
|
|||||||
@@ -3942,12 +3942,12 @@ ble_ll_scan_reset(void)
|
|||||||
os_mempool_clear(&ext_scan_aux_pool);
|
os_mempool_clear(&ext_scan_aux_pool);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Call the common initialize function again */
|
/* Call the common init function again */
|
||||||
ble_ll_scan_common_init();
|
ble_ll_scan_common_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ble ll scan initialize
|
* ble ll scan init
|
||||||
*
|
*
|
||||||
* Initialize a scanner. Must be called before scanning can be started.
|
* Initialize a scanner. Must be called before scanning can be started.
|
||||||
* Expected to be called with a un-initialized scanning state machine.
|
* Expected to be called with a un-initialized scanning state machine.
|
||||||
|
|||||||
@@ -835,7 +835,7 @@ ble_phy_isr(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ble phy initialize
|
* ble phy init
|
||||||
*
|
*
|
||||||
* Initialize the PHY.
|
* Initialize the PHY.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1381,7 +1381,7 @@ ble_phy_dbg_time_setup(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ble phy initialize
|
* ble phy init
|
||||||
*
|
*
|
||||||
* Initialize the PHY.
|
* Initialize the PHY.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -451,7 +451,7 @@ struct bt_mesh_model_cb {
|
|||||||
*/
|
*/
|
||||||
int (*const settings_commit)(struct bt_mesh_model *model);
|
int (*const settings_commit)(struct bt_mesh_model *model);
|
||||||
|
|
||||||
/** @brief Model initialize callback.
|
/** @brief Model init callback.
|
||||||
*
|
*
|
||||||
* Called on every model instance during mesh initialization.
|
* Called on every model instance during mesh initialization.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ static inline struct os_mbuf * NET_BUF_SIMPLE(uint16_t size)
|
|||||||
static inline void net_buf_simple_init(struct os_mbuf *buf,
|
static inline void net_buf_simple_init(struct os_mbuf *buf,
|
||||||
size_t reserve_head)
|
size_t reserve_head)
|
||||||
{
|
{
|
||||||
/* This is called in Zephyr after initialize.
|
/* This is called in Zephyr after init.
|
||||||
* Note in Mynewt case we don't care abour reserved head*/
|
* Note in Mynewt case we don't care abour reserved head*/
|
||||||
buf->om_data = &buf->om_databuf[buf->om_pkthdr_len] + reserve_head;
|
buf->om_data = &buf->om_databuf[buf->om_pkthdr_len] + reserve_head;
|
||||||
buf->om_len = 0;
|
buf->om_len = 0;
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ void bt_mesh_adv_init(void)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Advertising should only be initialized once. Calling
|
/* Advertising should only be initialized once. Calling
|
||||||
* os_task initialize the second time will result in an assert. */
|
* os_task init the second time will result in an assert. */
|
||||||
if (adv_initialized) {
|
if (adv_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ static inline int bt_mesh_beacon_key(const u8_t net_key[16],
|
|||||||
}
|
}
|
||||||
|
|
||||||
int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
|
int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
|
||||||
const u8_t net_id[16], u32_t iv_index,
|
const u8_t net_id[8], u32_t iv_index,
|
||||||
u8_t auth[8]);
|
u8_t auth[8]);
|
||||||
|
|
||||||
static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1])
|
static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1])
|
||||||
|
|||||||
@@ -1422,7 +1422,7 @@ dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle,
|
|||||||
/*
|
/*
|
||||||
* We should never never enter this callback - it's attached to notify-only
|
* We should never never enter this callback - it's attached to notify-only
|
||||||
* characteristic which are notified directly from mbuf. And we can't pass
|
* characteristic which are notified directly from mbuf. And we can't pass
|
||||||
* NULL as access_cb because gatts will assert on initialize...
|
* NULL as access_cb because gatts will assert on init...
|
||||||
*/
|
*/
|
||||||
BLE_HS_DBG_ASSERT(0);
|
BLE_HS_DBG_ASSERT(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -482,10 +482,6 @@ ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc)
|
|||||||
{
|
{
|
||||||
struct ble_hs_conn *conn;
|
struct ble_hs_conn *conn;
|
||||||
|
|
||||||
if (!ble_hs_is_enabled()) {
|
|
||||||
return BLE_HS_EDISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
|
|
||||||
conn = ble_hs_conn_find(handle);
|
conn = ble_hs_conn_find(handle);
|
||||||
@@ -2147,10 +2143,6 @@ ble_gap_set_event_cb(uint16_t conn_handle, ble_gap_event_fn *cb, void *cb_arg)
|
|||||||
{
|
{
|
||||||
struct ble_hs_conn *conn;
|
struct ble_hs_conn *conn;
|
||||||
|
|
||||||
if (!ble_hs_is_enabled()) {
|
|
||||||
return BLE_HS_EDISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
|
|
||||||
conn = ble_hs_conn_find(conn_handle);
|
conn = ble_hs_conn_find(conn_handle);
|
||||||
@@ -2754,10 +2746,6 @@ ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields)
|
|||||||
uint8_t buf_sz;
|
uint8_t buf_sz;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!ble_hs_is_enabled()) {
|
|
||||||
return BLE_HS_EDISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ble_hs_adv_set_fields(rsp_fields, buf, &buf_sz, sizeof buf);
|
rc = ble_hs_adv_set_fields(rsp_fields, buf, &buf_sz, sizeof buf);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -552,20 +552,21 @@ ble_hs_hci_evt_le_rd_rem_used_feat_complete(uint8_t subevent, const void *data,
|
|||||||
static int
|
static int
|
||||||
ble_hs_hci_decode_legacy_type(uint16_t evt_type)
|
ble_hs_hci_decode_legacy_type(uint16_t evt_type)
|
||||||
{
|
{
|
||||||
switch (evt_type) {
|
switch (evt_type) {
|
||||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND:
|
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND:
|
||||||
return BLE_HCI_ADV_RPT_EVTYPE_ADV_IND;
|
return BLE_HCI_ADV_RPT_EVTYPE_ADV_IND;
|
||||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND:
|
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND:
|
||||||
return BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
|
return BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
|
||||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND:
|
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND:
|
||||||
return BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND;
|
return BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND;
|
||||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND:
|
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND:
|
||||||
return BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND;
|
return BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND;
|
||||||
case BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND:
|
case BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND:
|
||||||
return BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP;
|
case BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_SCAN_IND:
|
||||||
default:
|
return BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP;
|
||||||
return -1;
|
default:
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ ble_hs_startup_read_sup_f_tx(void)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for now we don't use it outside of initialize sequence so check this here
|
/* for now we don't use it outside of init sequence so check this here
|
||||||
* LE Supported (Controller) byte 4, bit 6
|
* LE Supported (Controller) byte 4, bit 6
|
||||||
*/
|
*/
|
||||||
if (!(rsp.features & 0x0000006000000000)) {
|
if (!(rsp.features & 0x0000006000000000)) {
|
||||||
|
|||||||
@@ -65,6 +65,20 @@ static struct trng_dev *g_trng;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep forward-compatibility with Mbed TLS 3.x.
|
||||||
|
*
|
||||||
|
* Direct access to fields of structures declared in public headers is no longer
|
||||||
|
* supported. In Mbed TLS 3, the layout of structures is not considered part of
|
||||||
|
* the stable API, and minor versions (3.1, 3.2, etc.) may add, remove, rename,
|
||||||
|
* reorder or change the type of structure fields.
|
||||||
|
*/
|
||||||
|
#if (MBEDTLS_VERSION_NUMBER < 0x03000000)
|
||||||
|
#ifndef MBEDTLS_PRIVATE
|
||||||
|
#define MBEDTLS_PRIVATE(member) member
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ble_sm_alg_xor_128(const uint8_t *p, const uint8_t *q, uint8_t *r)
|
ble_sm_alg_xor_128(const uint8_t *p, const uint8_t *q, uint8_t *r)
|
||||||
{
|
{
|
||||||
@@ -533,15 +547,15 @@ ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_
|
|||||||
mbedtls_mpi_init(&z);
|
mbedtls_mpi_init(&z);
|
||||||
|
|
||||||
/* Below 3 steps are to validate public key on curve secp256r1 */
|
/* Below 3 steps are to validate public key on curve secp256r1 */
|
||||||
if (mbedtls_ecp_group_load(&keypair.grp, MBEDTLS_ECP_DP_SECP256R1) != 0) {
|
if (mbedtls_ecp_group_load(&keypair.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1) != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mbedtls_ecp_point_read_binary(&keypair.grp, &pt, pub, 65) != 0) {
|
if (mbedtls_ecp_point_read_binary(&keypair.MBEDTLS_PRIVATE(grp), &pt, pub, 65) != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mbedtls_ecp_check_pubkey(&keypair.grp, &pt) != 0) {
|
if (mbedtls_ecp_check_pubkey(&keypair.MBEDTLS_PRIVATE(grp), &pt) != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +566,7 @@ ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare point Q from pub key */
|
/* Prepare point Q from pub key */
|
||||||
if (mbedtls_ecp_point_read_binary(&keypair.grp, &Q, pub, 65) != 0) {
|
if (mbedtls_ecp_point_read_binary(&keypair.MBEDTLS_PRIVATE(grp), &Q, pub, 65) != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,7 +574,7 @@ ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = mbedtls_ecdh_compute_shared(&keypair.grp, &z, &Q, &d,
|
rc = mbedtls_ecdh_compute_shared(&keypair.MBEDTLS_PRIVATE(grp), &z, &Q, &d,
|
||||||
mbedtls_ctr_drbg_random, &ctr_drbg);
|
mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -640,14 +654,14 @@ mbedtls_gen_keypair(uint8_t *public_key, uint8_t *private_key)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (( rc = mbedtls_mpi_write_binary(&keypair.d, private_key, 32)) != 0) {
|
if (( rc = mbedtls_mpi_write_binary(&keypair.MBEDTLS_PRIVATE(d), private_key, 32)) != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t olen = 0;
|
size_t olen = 0;
|
||||||
uint8_t pub[65] = {0};
|
uint8_t pub[65] = {0};
|
||||||
|
|
||||||
if ((rc = mbedtls_ecp_point_write_binary(&keypair.grp, &keypair.Q, MBEDTLS_ECP_PF_UNCOMPRESSED,
|
if ((rc = mbedtls_ecp_point_write_binary(&keypair.MBEDTLS_PRIVATE(grp), &keypair.MBEDTLS_PRIVATE(Q), MBEDTLS_ECP_PF_UNCOMPRESSED,
|
||||||
&olen, pub, 65)) != 0) {
|
&olen, pub, 65)) != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ static const uint8_t ble_sm_lgcy_init_ioa[5 /*resp*/ ][5 /*init*/ ] =
|
|||||||
/* This is the responder passkey action action depending on the io
|
/* This is the responder passkey action action depending on the io
|
||||||
* capabilities of both parties
|
* capabilities of both parties
|
||||||
*/
|
*/
|
||||||
static const uint8_t ble_sm_lgcy_resp_ioa[5 /*resp*/ ][5 /*initialize*/ ] =
|
static const uint8_t ble_sm_lgcy_resp_ioa[5 /*resp*/ ][5 /*init*/ ] =
|
||||||
{
|
{
|
||||||
{IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
|
{IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
|
||||||
{IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
|
{IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ static const uint8_t ble_sm_sc_init_ioa[5 /*resp*/ ][5 /*init*/ ] =
|
|||||||
*/
|
*/
|
||||||
static const uint8_t ble_sm_sc_resp_ioa[5 /*resp*/ ][5 /*init*/ ] =
|
static const uint8_t ble_sm_sc_resp_ioa[5 /*resp*/ ][5 /*init*/ ] =
|
||||||
{
|
{
|
||||||
/* initialize */
|
/* init */
|
||||||
/*r*/ {IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
|
/*r*/ {IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
|
||||||
/*e*/ {IOACT_NONE, IOACT_NUMCMP, IOACT_DISP, IOACT_NONE, IOACT_NUMCMP},
|
/*e*/ {IOACT_NONE, IOACT_NUMCMP, IOACT_DISP, IOACT_NONE, IOACT_NUMCMP},
|
||||||
/*s*/ {IOACT_INPUT, IOACT_INPUT, IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
|
/*s*/ {IOACT_INPUT, IOACT_INPUT, IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ nrf52_timer5_irq_handler(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hal timer initialize
|
* hal timer init
|
||||||
*
|
*
|
||||||
* Initialize platform specific timer items
|
* Initialize platform specific timer items
|
||||||
*
|
*
|
||||||
@@ -457,7 +457,7 @@ hal_timer_init(int timer_num, void *cfg)
|
|||||||
|
|
||||||
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
|
NRF52_HAL_TIMER_RESOLVE(timer_num, bsptimer);
|
||||||
|
|
||||||
/* If timer is enabled do not allow initialize */
|
/* If timer is enabled do not allow init */
|
||||||
if (bsptimer->tmr_enabled) {
|
if (bsptimer->tmr_enabled) {
|
||||||
rc = EINVAL;
|
rc = EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
|
|||||||
@@ -31,6 +31,32 @@
|
|||||||
*/
|
*/
|
||||||
// #define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
|
// #define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************
|
||||||
|
* Extended advertising settings *
|
||||||
|
* For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
|
||||||
|
***************************************************/
|
||||||
|
|
||||||
|
/** @brief Un-comment to enable extended advertising */
|
||||||
|
// #define CONFIG_BT_NIMBLE_EXT_ADV 1
|
||||||
|
|
||||||
|
/** @brief Un-comment to set the max number of extended advertising instances (Range: 0 - 4) */
|
||||||
|
// #define CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES 1
|
||||||
|
|
||||||
|
/** @brief Un-comment to set the max extended advertising data size (Range: 31 - 1650) */
|
||||||
|
// #define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN 251
|
||||||
|
|
||||||
|
/** @brief Un-comment to enable periodic advertising */
|
||||||
|
// #define CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV 1
|
||||||
|
|
||||||
|
/** @brief Un-comment to change the maximum number of periodically synced devices */
|
||||||
|
// #define CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS 1
|
||||||
|
|
||||||
|
/****************************************************
|
||||||
|
* END For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
|
||||||
|
***************************************************/
|
||||||
|
|
||||||
|
|
||||||
/** @brief Un-comment to change the default MTU size */
|
/** @brief Un-comment to change the default MTU size */
|
||||||
// #define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
|
// #define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
|
||||||
|
|
||||||
@@ -207,7 +233,11 @@
|
|||||||
#define CONFIG_BT_NIMBLE_ACL_BUF_SIZE 255
|
#define CONFIG_BT_NIMBLE_ACL_BUF_SIZE 255
|
||||||
|
|
||||||
/** @brief HCI Event Buffer size */
|
/** @brief HCI Event Buffer size */
|
||||||
#define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 70
|
#if CONFIG_BT_NIMBLE_EXT_ADV || CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV
|
||||||
|
# define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 257
|
||||||
|
#else
|
||||||
|
# define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 70
|
||||||
|
#endif
|
||||||
|
|
||||||
/** @brief Number of high priority HCI event buffers */
|
/** @brief Number of high priority HCI event buffers */
|
||||||
#define CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT 30
|
#define CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT 30
|
||||||
@@ -249,6 +279,31 @@
|
|||||||
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
#define CONFIG_IDF_TARGET_ESP32 1
|
#define CONFIG_IDF_TARGET_ESP32 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV || CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV
|
||||||
|
# if defined(CONFIG_IDF_TARGET_ESP32)
|
||||||
|
# error Extended advertising is not supported on ESP32.
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV && !CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
# error Extended advertising must be enabled to use periodic advertising.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Must have max instances and data length set if extended advertising is enabled */
|
||||||
|
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||||
|
# if !defined(CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES)
|
||||||
|
# define CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES 1
|
||||||
|
# endif
|
||||||
|
# if !defined(CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN)
|
||||||
|
# define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN 251
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Must set max number of syncs if periodic advertising is enabled */
|
||||||
|
#if CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV && !defined(CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS)
|
||||||
|
# define CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Cannot use client without scan */
|
/* Cannot use client without scan */
|
||||||
|
|||||||
Reference in New Issue
Block a user