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.
|
||||
Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
|
||||
<br/>
|
||||
|
||||
|
||||
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
|
||||
|
||||
Sets the default MTU size.
|
||||
@@ -140,3 +140,34 @@ Set the task stack size for the NimBLE core.
|
||||
- Default is 4096
|
||||
<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
|
||||
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.
|
||||
|
||||
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 app_main(void)
|
||||
{
|
||||
NimBLEDevice::initialize("NimBLE");
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
NimBLEService *pService = pServer->createService("ABCD");
|
||||
@@ -83,7 +83,7 @@ The function call will simply be `pService->createCharacteristic("1234");`
|
||||
// void setup() in Arduino
|
||||
void app_main(void)
|
||||
{
|
||||
NimBLEDevice::initialize("NimBLE");
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
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 app_main(void)
|
||||
{
|
||||
NimBLEDevice::initialize("NimBLE");
|
||||
NimBLEDevice::init("NimBLE");
|
||||
|
||||
NimBLEServer *pServer = NimBLEDevice::createServer();
|
||||
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 app_main(void)
|
||||
{
|
||||
NimBLEDevice::initialize("");
|
||||
NimBLEDevice::init("");
|
||||
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
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 app_main(void)
|
||||
{
|
||||
NimBLEDevice::initialize("");
|
||||
NimBLEDevice::init("");
|
||||
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
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 "NimBLELog.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
static const char* LOG_TAG = "NimBLEAdvertisedDevice";
|
||||
|
||||
|
||||
@@ -69,7 +71,7 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
|
||||
* @return The appearance of the advertised device.
|
||||
*/
|
||||
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) {
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
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.
|
||||
*/
|
||||
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 ||
|
||||
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.
|
||||
* @return The number of addresses.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||
uint8_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||
uint8_t count = 0;
|
||||
|
||||
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
|
||||
@@ -232,7 +234,7 @@ size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
|
||||
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t count = 0;
|
||||
uint8_t data_loc = 0xFF;
|
||||
size_t data_loc = ULONG_MAX;
|
||||
|
||||
index++;
|
||||
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);
|
||||
}
|
||||
|
||||
if(count > 0 && data_loc != 0xFF) {
|
||||
if(count > 0 && data_loc != ULONG_MAX) {
|
||||
field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
if(field->length < index * 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) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
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];
|
||||
if(field->length > bytes) {
|
||||
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;
|
||||
uint8_t bytes;
|
||||
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 plSize = m_payload.size() - 2;
|
||||
|
||||
while(data_loc < plSize) {
|
||||
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) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
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];
|
||||
if(field->length >= bytes) {
|
||||
return NimBLEUUID(field->value, bytes, false);
|
||||
@@ -330,10 +332,10 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
|
||||
* @brief Find the service data at the index.
|
||||
* @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.
|
||||
* @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) {
|
||||
uint8_t data_loc = 0;
|
||||
size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||
size_t data_loc = 0;
|
||||
uint8_t found = 0;
|
||||
|
||||
*bytes = 0;
|
||||
@@ -358,7 +360,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
|
||||
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
|
||||
* @return The number of service data UUIDS in the vector.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
uint8_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
uint8_t count = 0;
|
||||
|
||||
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
|
||||
@@ -384,7 +386,7 @@ size_t NimBLEAdvertisedDevice::getServiceDataCount() {
|
||||
*/
|
||||
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||
uint8_t count = 0;
|
||||
uint8_t data_loc = 0;
|
||||
size_t data_loc = 0;
|
||||
uint8_t uuidBytes = 0;
|
||||
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
@@ -431,7 +433,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
|
||||
* @brief Get the number of services advertised
|
||||
* @return The count of services in the advertising packet.
|
||||
*/
|
||||
size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||
uint8_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
|
||||
uint8_t count = 0;
|
||||
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
|
||||
@@ -581,17 +583,60 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
|
||||
} // haveTXPower
|
||||
|
||||
|
||||
uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_t *data_loc) {
|
||||
ble_hs_adv_field *field = nullptr;
|
||||
uint8_t data = 0;
|
||||
uint8_t length = m_payload.size();
|
||||
uint8_t count = 0;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Get the set ID of the extended advertisement.
|
||||
* @return The set ID.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
while (length > 1) {
|
||||
while (length > 2) {
|
||||
field = (ble_hs_adv_field*)&m_payload[data];
|
||||
|
||||
if (field->length >= length) {
|
||||
@@ -599,7 +644,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
||||
}
|
||||
|
||||
if (field->type == type) {
|
||||
switch(type) {
|
||||
switch (type) {
|
||||
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
|
||||
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
|
||||
count += field->length / 2;
|
||||
@@ -625,8 +670,8 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
||||
break;
|
||||
}
|
||||
|
||||
if(data_loc != nullptr) {
|
||||
if(index == 0 || count >= index) {
|
||||
if (data_loc != nullptr) {
|
||||
if (index == 0 || count >= index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -636,7 +681,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
|
||||
data += 1 + field->length;
|
||||
}
|
||||
|
||||
if(data_loc != nullptr && field != nullptr) {
|
||||
if (data_loc != nullptr && field != nullptr) {
|
||||
*data_loc = data;
|
||||
}
|
||||
|
||||
@@ -657,8 +702,13 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
|
||||
* @brief Set the adFlag for this device.
|
||||
* @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;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
m_isLegacyAdv = isLegacyAdv;
|
||||
#else
|
||||
(void)isLegacyAdv;
|
||||
#endif
|
||||
} // setAdvType
|
||||
|
||||
|
||||
@@ -703,10 +753,10 @@ std::string NimBLEAdvertisedDevice::toString() {
|
||||
res += val;
|
||||
}
|
||||
|
||||
if(haveServiceData()) {
|
||||
size_t count = getServiceDataCount();
|
||||
if (haveServiceData()) {
|
||||
uint8_t count = getServiceDataCount();
|
||||
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 += ", Data: " + getServiceData(i);
|
||||
}
|
||||
@@ -781,5 +831,34 @@ size_t NimBLEAdvertisedDevice::getPayloadLength() {
|
||||
return m_payload.size();
|
||||
} // 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 */
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
std::string getName();
|
||||
int getRSSI();
|
||||
NimBLEScan* getScan();
|
||||
size_t getServiceDataCount();
|
||||
uint8_t getServiceDataCount();
|
||||
std::string getServiceData(uint8_t index = 0);
|
||||
std::string getServiceData(const NimBLEUUID &uuid);
|
||||
|
||||
@@ -111,9 +111,9 @@ public:
|
||||
|
||||
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
|
||||
NimBLEUUID getServiceUUID(uint8_t index = 0);
|
||||
size_t getServiceUUIDCount();
|
||||
uint8_t getServiceUUIDCount();
|
||||
NimBLEAddress getTargetAddress(uint8_t index = 0);
|
||||
size_t getTargetAddressCount();
|
||||
uint8_t getTargetAddressCount();
|
||||
int8_t getTXPower();
|
||||
uint8_t* getPayload();
|
||||
uint8_t getAdvLength();
|
||||
@@ -133,16 +133,30 @@ public:
|
||||
bool haveTargetAddress();
|
||||
bool haveURI();
|
||||
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:
|
||||
friend class NimBLEScan;
|
||||
|
||||
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 setRSSI(int rssi);
|
||||
uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
|
||||
uint8_t findServiceData(uint8_t index, uint8_t* bytes);
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
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("");
|
||||
uint8_t m_advType;
|
||||
@@ -150,6 +164,13 @@ private:
|
||||
time_t m_timestamp;
|
||||
bool m_callbackSent;
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
*
|
||||
*/
|
||||
#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)
|
||||
#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(ble_gap_adv_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
|
||||
@@ -625,7 +627,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
&m_advParams,
|
||||
(pServer != nullptr) ? NimBLEServer::handleGapEvent :
|
||||
NimBLEAdvertising::handleGapEvent,
|
||||
(pServer != nullptr) ? (void*)pServer : (void*)this);
|
||||
(void*)this);
|
||||
#else
|
||||
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type, NULL, duration,
|
||||
&m_advParams, NimBLEAdvertising::handleGapEvent, this);
|
||||
@@ -634,6 +636,10 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case BLE_HS_EALREADY:
|
||||
NIMBLE_LOGI(LOG_TAG, "Advertisement Already active");
|
||||
break;
|
||||
|
||||
case BLE_HS_EINVAL:
|
||||
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Duration too long");
|
||||
break;
|
||||
@@ -656,24 +662,26 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
|
||||
return (rc == 0);
|
||||
return (rc == 0 || rc == BLE_HS_EALREADY);
|
||||
} // start
|
||||
|
||||
|
||||
/**
|
||||
* @brief Stop advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
void NimBLEAdvertising::stop() {
|
||||
bool NimBLEAdvertising::stop() {
|
||||
NIMBLE_LOGD(LOG_TAG, ">> stop");
|
||||
|
||||
int rc = ble_gap_adv_stop();
|
||||
if (rc != 0 && rc != BLE_HS_EALREADY) {
|
||||
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s",
|
||||
rc, NimBLEUtils::returnCodeToString(rc));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
NIMBLE_LOGD(LOG_TAG, "<< stop");
|
||||
return true;
|
||||
} // stop
|
||||
|
||||
|
||||
@@ -1026,4 +1034,4 @@ std::string NimBLEAdvertisementData::getPayload() {
|
||||
return m_payload;
|
||||
} // 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_
|
||||
#define MAIN_BLEADVERTISING_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)
|
||||
#include "host/ble_gap.h"
|
||||
@@ -89,7 +91,7 @@ public:
|
||||
void addServiceUUID(const char* serviceUUID);
|
||||
void removeServiceUUID(const NimBLEUUID &serviceUUID);
|
||||
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
|
||||
void stop();
|
||||
bool stop();
|
||||
void setAppearance(uint16_t appearance);
|
||||
void setName(const std::string &name);
|
||||
void setManufacturerData(const std::string &data);
|
||||
@@ -111,6 +113,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLEServer;
|
||||
|
||||
void onHostSync();
|
||||
static int handleGapEvent(struct ble_gap_event *event, void *arg);
|
||||
@@ -134,5 +137,5 @@ private:
|
||||
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_ */
|
||||
|
||||
@@ -65,6 +65,11 @@ NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(pee
|
||||
m_pTaskData = nullptr;
|
||||
m_connEstablished = false;
|
||||
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_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.
|
||||
*/
|
||||
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,
|
||||
m_connectTimeout, &m_pConnParams,
|
||||
NimBLEClient::handleGapEvent, this);
|
||||
#endif
|
||||
switch (rc) {
|
||||
case 0:
|
||||
break;
|
||||
@@ -397,6 +415,21 @@ int NimBLEClient::disconnect(uint8_t reason) {
|
||||
} // 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.
|
||||
* @param [in] minInterval The minimum connection interval in 1.25ms units.
|
||||
|
||||
@@ -73,6 +73,9 @@ public:
|
||||
void discoverAttributes();
|
||||
NimBLEConnInfo getConnInfo();
|
||||
int getLastError();
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
void setConnectPhy(uint8_t mask);
|
||||
#endif
|
||||
|
||||
private:
|
||||
NimBLEClient(const NimBLEAddress &peerAddress);
|
||||
@@ -98,6 +101,9 @@ private:
|
||||
NimBLEClientCallbacks* m_pClientCallbacks;
|
||||
ble_task_data_t* m_pTaskData;
|
||||
ble_npl_callout m_dcTimer;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
uint8_t m_phyMask;
|
||||
#endif
|
||||
|
||||
std::vector<NimBLERemoteService*> m_servicesVector;
|
||||
|
||||
|
||||
@@ -69,7 +69,11 @@ NimBLEServer* NimBLEDevice::m_pServer = nullptr;
|
||||
uint32_t NimBLEDevice::m_passkey = 123456;
|
||||
bool NimBLEDevice::m_synced = false;
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEExtAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
||||
# else
|
||||
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
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 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.
|
||||
* @return A pointer to the advertising object.
|
||||
@@ -128,17 +171,19 @@ NimBLEAdvertising* NimBLEDevice::getAdvertising() {
|
||||
|
||||
/**
|
||||
* @brief Convenience function to begin advertising.
|
||||
* @return True if advertising started successfully.
|
||||
*/
|
||||
void NimBLEDevice::startAdvertising() {
|
||||
getAdvertising()->start();
|
||||
bool NimBLEDevice::startAdvertising() {
|
||||
return getAdvertising()->start();
|
||||
} // startAdvertising
|
||||
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Convenience function to stop advertising.
|
||||
* @brief Convenience function to stop all advertising.
|
||||
* @return True if advertising stopped successfully.
|
||||
*/
|
||||
void NimBLEDevice::stopAdvertising() {
|
||||
getAdvertising()->stop();
|
||||
bool NimBLEDevice::stopAdvertising() {
|
||||
return getAdvertising()->stop();
|
||||
} // stopAdvertising
|
||||
#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
|
||||
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.
|
||||
* @details Must only be called before calling NimBLEDevice::initialize.
|
||||
* @details Must only be called before calling NimBLEDevice::init.
|
||||
*/
|
||||
/*STATIC*/
|
||||
void NimBLEDevice::setScanFilterMode(uint8_t mode) {
|
||||
@@ -806,7 +851,7 @@ void NimBLEDevice::init(const std::string &deviceName) {
|
||||
esp_err_t errRc = ESP_OK;
|
||||
|
||||
#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();
|
||||
#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.
|
||||
} // initialize
|
||||
} // init
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,11 @@
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
@@ -139,9 +143,18 @@ public:
|
||||
static void removeIgnored(const NimBLEAddress &address);
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
static NimBLEAdvertising* getAdvertising();
|
||||
static void startAdvertising();
|
||||
static void stopAdvertising();
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
static NimBLEExtAdvertising* getAdvertising();
|
||||
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
|
||||
|
||||
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
|
||||
@@ -178,6 +191,10 @@ private:
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
friend class NimBLEAdvertising;
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
friend class NimBLEExtAdvertising;
|
||||
friend class NimBLEExtAdvertisement;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static void onReset(int reason);
|
||||
@@ -194,7 +211,11 @@ private:
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
static NimBLEExtAdvertising* m_bleAdvertising;
|
||||
# else
|
||||
static NimBLEAdvertising* m_bleAdvertising;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#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()");
|
||||
|
||||
@@ -56,18 +56,27 @@ NimBLEScan::~NimBLEScan() {
|
||||
* @param [in] param Parameter data for this event.
|
||||
*/
|
||||
/*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
|
||||
|
||||
NimBLEScan* pScan = (NimBLEScan*)arg;
|
||||
(void)arg;
|
||||
NimBLEScan* pScan = NimBLEDevice::getScan();
|
||||
|
||||
switch(event->type) {
|
||||
|
||||
case BLE_GAP_EVENT_EXT_DISC:
|
||||
case BLE_GAP_EVENT_DISC: {
|
||||
if(pScan->m_ignoreResults) {
|
||||
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NimBLEAddress advertisedAddress(event->disc.addr);
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
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
|
||||
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
|
||||
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;
|
||||
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.
|
||||
// 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.
|
||||
// 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 &&
|
||||
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults))
|
||||
{
|
||||
if (pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
|
||||
(pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
advertisedDevice = new NimBLEAdvertisedDevice();
|
||||
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);
|
||||
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());
|
||||
} else {
|
||||
// Scan response from unknown device
|
||||
@@ -108,14 +129,14 @@ NimBLEScan::~NimBLEScan() {
|
||||
}
|
||||
|
||||
advertisedDevice->m_timestamp = time(nullptr);
|
||||
advertisedDevice->setRSSI(event->disc.rssi);
|
||||
advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
|
||||
event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP);
|
||||
advertisedDevice->setRSSI(disc.rssi);
|
||||
advertisedDevice->setPayload(disc.data, disc.length_data, (isLegacyAdv &&
|
||||
event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP));
|
||||
|
||||
if (pScan->m_pAdvertisedDeviceCallbacks) {
|
||||
// If not active scanning or scan response is not available
|
||||
// report the result to the callback now.
|
||||
if(pScan->m_scan_params.passive ||
|
||||
// or extended advertisement scanning, report the result to the callback now.
|
||||
if(pScan->m_scan_params.passive || !isLegacyAdv ||
|
||||
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
|
||||
advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
|
||||
{
|
||||
@@ -123,7 +144,7 @@ NimBLEScan::~NimBLEScan() {
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
|
||||
// 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;
|
||||
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
|
||||
}
|
||||
@@ -304,9 +325,28 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
|
||||
m_ignoreResults = true;
|
||||
}
|
||||
|
||||
int rc = ble_gap_disc(NimBLEDevice::m_own_addr_type, duration, &m_scan_params,
|
||||
NimBLEScan::handleGapEvent, this);
|
||||
|
||||
# if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
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) {
|
||||
case 0:
|
||||
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_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 */
|
||||
/// 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 */
|
||||
/// 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 */
|
||||
/// 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 */
|
||||
|
||||
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_pServerCallbacks = &defaultCallbacks;
|
||||
m_gattsStarted = false;
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
m_advertiseOnDisconnect = true;
|
||||
#endif
|
||||
m_svcChanged = false;
|
||||
m_deleteCallbacks = true;
|
||||
} // NimBLEServer
|
||||
@@ -139,15 +141,26 @@ NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
|
||||
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.
|
||||
*
|
||||
* @return An advertising object.
|
||||
*/
|
||||
NimBLEAdvertising* NimBLEServer::getAdvertising() {
|
||||
return NimBLEDevice::getAdvertising();
|
||||
} // getAdvertising
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
||||
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
/**
|
||||
* @brief Set the server to automatically start advertising when a client disconnects.
|
||||
* @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) {
|
||||
m_advertiseOnDisconnect = aod;
|
||||
} // advertiseOnDisconnect
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Return the number of connected clients.
|
||||
@@ -325,7 +339,7 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
|
||||
*/
|
||||
/*STATIC*/
|
||||
int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
NimBLEServer* server = (NimBLEServer*)arg;
|
||||
NimBLEServer* server = NimBLEDevice::getServer();
|
||||
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s",
|
||||
NimBLEUtils::gapEventToString(event->type));
|
||||
int rc = 0;
|
||||
@@ -337,7 +351,9 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
if (event->connect.status != 0) {
|
||||
/* Connection failed; resume advertising */
|
||||
NIMBLE_LOGE(LOG_TAG, "Connection failed");
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEDevice::startAdvertising();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
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, &event->disconnect.conn);
|
||||
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
if(server->m_advertiseOnDisconnect) {
|
||||
server->startAdvertising();
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_DISCONNECT
|
||||
|
||||
@@ -472,11 +490,15 @@ int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
|
||||
return 0;
|
||||
} // BLE_GAP_EVENT_NOTIFY_TX
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE: {
|
||||
NIMBLE_LOGD(LOG_TAG, "Advertising Complete");
|
||||
NimBLEDevice::getAdvertising()->advCompleteCB();
|
||||
return 0;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
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: {
|
||||
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;
|
||||
serviceChanged();
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -716,22 +740,52 @@ void NimBLEServer::resetGATT() {
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
/**
|
||||
* @brief Start advertising.
|
||||
*
|
||||
* Start the server advertising its existence. This is a convenience function and is equivalent to
|
||||
* @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.
|
||||
* @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.
|
||||
*/
|
||||
void NimBLEServer::startAdvertising() {
|
||||
NimBLEDevice::startAdvertising();
|
||||
bool NimBLEServer::startAdvertising(uint8_t inst_id,
|
||||
int duration,
|
||||
int max_events) {
|
||||
return getAdvertising()->start(inst_id, duration, max_events);
|
||||
} // 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() {
|
||||
NimBLEDevice::stopAdvertising();
|
||||
bool NimBLEServer::stopAdvertising(uint8_t inst_id) {
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,11 @@
|
||||
|
||||
#include "NimBLEUtils.h"
|
||||
#include "NimBLEAddress.h"
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
#include "NimBLEExtAdvertising.h"
|
||||
#else
|
||||
#include "NimBLEAdvertising.h"
|
||||
#endif
|
||||
#include "NimBLEService.h"
|
||||
#include "NimBLESecurity.h"
|
||||
#include "NimBLEConnInfo.h"
|
||||
@@ -46,11 +50,19 @@ public:
|
||||
NimBLEService* createService(const NimBLEUUID &uuid);
|
||||
void removeService(NimBLEService* service, bool deleteSvc = false);
|
||||
void addService(NimBLEService* service);
|
||||
NimBLEAdvertising* getAdvertising();
|
||||
void setCallbacks(NimBLEServerCallbacks* pCallbacks,
|
||||
bool deleteCallbacks = true);
|
||||
void startAdvertising();
|
||||
void stopAdvertising();
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
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();
|
||||
NimBLEService* getServiceByUUID(const char* 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(const NimBLEAddress& address);
|
||||
NimBLEConnInfo getPeerIDInfo(uint16_t id);
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
|
||||
void advertiseOnDisconnect(bool);
|
||||
#endif
|
||||
|
||||
private:
|
||||
NimBLEServer();
|
||||
@@ -75,9 +89,15 @@ private:
|
||||
friend class NimBLEService;
|
||||
friend class NimBLEDevice;
|
||||
friend class NimBLEAdvertising;
|
||||
#if CONFIG_BT_NIMBLE_EXT_ADV
|
||||
friend class NimBLEExtAdvertising;
|
||||
friend class NimBLEExtAdvertisementData;
|
||||
#endif
|
||||
|
||||
bool m_gattsStarted;
|
||||
#if !CONFIG_BT_NIMBLE_EXT_ADV
|
||||
bool m_advertiseOnDisconnect;
|
||||
#endif
|
||||
bool m_svcChanged;
|
||||
NimBLEServerCallbacks* m_pServerCallbacks;
|
||||
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.
|
||||
* 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}
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* @brief HMAC initialize procedure
|
||||
* @brief HMAC init procedure
|
||||
* Initializes ctx to begin the next HMAC operation
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* 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);
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
|
||||
* nonce. TinyCrypts requires instead a non-null personalization
|
||||
* (which is easily computed) and indirectly requires an entropy
|
||||
* seed (since the reseed function is mandatorily called after
|
||||
* initialize)
|
||||
* init)
|
||||
* @param prng IN/OUT -- the PRNG state to initialize
|
||||
* @param personalization IN -- personalization string
|
||||
* @param plen IN -- personalization length in bytes
|
||||
|
||||
@@ -379,7 +379,7 @@ struct ble_dev_addr
|
||||
* -> AdvA (6 bytes)
|
||||
* -> LLData (22 bytes)
|
||||
* -> Access address (4 bytes)
|
||||
* -> CRC initialize (3 bytes)
|
||||
* -> CRC init (3 bytes)
|
||||
* -> WinSize (1 byte)
|
||||
* -> WinOffset (2 bytes)
|
||||
* -> Interval (2 bytes)
|
||||
|
||||
@@ -1425,7 +1425,7 @@ ble_ll_reset(void)
|
||||
/* Reset connection module */
|
||||
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();
|
||||
|
||||
/* 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 */
|
||||
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
|
||||
*/
|
||||
if (!connsm) {
|
||||
|
||||
@@ -3942,12 +3942,12 @@ ble_ll_scan_reset(void)
|
||||
os_mempool_clear(&ext_scan_aux_pool);
|
||||
#endif
|
||||
|
||||
/* Call the common initialize function again */
|
||||
/* Call the common init function again */
|
||||
ble_ll_scan_common_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* ble ll scan initialize
|
||||
* ble ll scan init
|
||||
*
|
||||
* Initialize a scanner. Must be called before scanning can be started.
|
||||
* 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.
|
||||
*
|
||||
|
||||
@@ -1381,7 +1381,7 @@ ble_phy_dbg_time_setup(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy initialize
|
||||
* ble phy init
|
||||
*
|
||||
* Initialize the PHY.
|
||||
*
|
||||
|
||||
@@ -451,7 +451,7 @@ struct bt_mesh_model_cb {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
||||
@@ -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,
|
||||
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*/
|
||||
buf->om_data = &buf->om_databuf[buf->om_pkthdr_len] + reserve_head;
|
||||
buf->om_len = 0;
|
||||
|
||||
@@ -317,7 +317,7 @@ void bt_mesh_adv_init(void)
|
||||
int rc;
|
||||
|
||||
/* 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) {
|
||||
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,
|
||||
const u8_t net_id[16], u32_t iv_index,
|
||||
const u8_t net_id[8], u32_t iv_index,
|
||||
u8_t auth[8]);
|
||||
|
||||
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
|
||||
* 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);
|
||||
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;
|
||||
|
||||
if (!ble_hs_is_enabled()) {
|
||||
return BLE_HS_EDISABLED;
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
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;
|
||||
|
||||
if (!ble_hs_is_enabled()) {
|
||||
return BLE_HS_EDISABLED;
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
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;
|
||||
int rc;
|
||||
|
||||
if (!ble_hs_is_enabled()) {
|
||||
return BLE_HS_EDISABLED;
|
||||
}
|
||||
|
||||
rc = ble_hs_adv_set_fields(rsp_fields, buf, &buf_sz, sizeof buf);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
|
||||
@@ -552,20 +552,21 @@ ble_hs_hci_evt_le_rd_rem_used_feat_complete(uint8_t subevent, const void *data,
|
||||
static int
|
||||
ble_hs_hci_decode_legacy_type(uint16_t evt_type)
|
||||
{
|
||||
switch (evt_type) {
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_ADV_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
switch (evt_type) {
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_ADV_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND;
|
||||
case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_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_SCAN_IND:
|
||||
return BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ ble_hs_startup_read_sup_f_tx(void)
|
||||
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
|
||||
*/
|
||||
if (!(rsp.features & 0x0000006000000000)) {
|
||||
|
||||
@@ -65,6 +65,20 @@ static struct trng_dev *g_trng;
|
||||
#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
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (mbedtls_ecp_check_pubkey(&keypair.grp, &pt) != 0) {
|
||||
if (mbedtls_ecp_check_pubkey(&keypair.MBEDTLS_PRIVATE(grp), &pt) != 0) {
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -560,7 +574,7 @@ ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_
|
||||
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);
|
||||
if (rc != 0) {
|
||||
goto exit;
|
||||
@@ -640,14 +654,14 @@ mbedtls_gen_keypair(uint8_t *public_key, uint8_t *private_key)
|
||||
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;
|
||||
}
|
||||
|
||||
size_t olen = 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) {
|
||||
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
|
||||
* 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},
|
||||
|
||||
@@ -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*/ ] =
|
||||
{
|
||||
/* initialize */
|
||||
/* init */
|
||||
/*r*/ {IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
|
||||
/*e*/ {IOACT_NONE, IOACT_NUMCMP, IOACT_DISP, IOACT_NONE, IOACT_NUMCMP},
|
||||
/*s*/ {IOACT_INPUT, IOACT_INPUT, IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
|
||||
|
||||
@@ -437,7 +437,7 @@ nrf52_timer5_irq_handler(void)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hal timer initialize
|
||||
* hal timer init
|
||||
*
|
||||
* Initialize platform specific timer items
|
||||
*
|
||||
@@ -457,7 +457,7 @@ hal_timer_init(int timer_num, void *cfg)
|
||||
|
||||
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) {
|
||||
rc = EINVAL;
|
||||
goto err;
|
||||
|
||||
@@ -31,6 +31,32 @@
|
||||
*/
|
||||
// #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 */
|
||||
// #define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
|
||||
|
||||
@@ -207,7 +233,11 @@
|
||||
#define CONFIG_BT_NIMBLE_ACL_BUF_SIZE 255
|
||||
|
||||
/** @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 */
|
||||
#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)
|
||||
#define CONFIG_IDF_TARGET_ESP32 1
|
||||
#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
|
||||
|
||||
/* Cannot use client without scan */
|
||||
|
||||
Reference in New Issue
Block a user