fix(nimble): Added support for 1m, 2m, coded phy channels and optimized throughput

This commit is contained in:
Shreeyash
2025-03-17 11:34:37 +05:30
parent 4066380f48
commit d236459656
8 changed files with 422 additions and 68 deletions

View File

@ -14,29 +14,34 @@ It performs read operation on peripheral's `THRPT_LONG_CHR_READ_WRITE` character
### Procedure to use this demo example
* `idf.py menuconfig` and configure the parameters as needed (connection related parameters in example parameters).
* To test throughput on 1M PHY, make sure to disable the Example Configuration -> Enable Extended Adv flag in menuconfig on both sides.
* To test on 2M PHY or Coded PHY (S2/S8), you must enable the Example Configuration -> Enable Extended Adv flag on both sides.
* `bleprph_throughput` example needs to be run along with this client side example.
* After connection link is established between these two devices, user is given a window of `YES_NO_PARAM` (5 seconds) to customize connection parameters. If user has configured parameters from menuconfig, this step can be skipped by either waiting it out or entering `Insert no`.
* User needs to enter `Insert yes` to customize connection parameters. Enter `MTU` and other connection parameters as directed on console instructions e.g. `MTU 512` for MTU and `conn 6 120 0 500 0 0` for connection parameters in sequence of `min conn_itvl`, `max conn_itvl`, `latency`, `supervision timeout`, `min conn_evt_len` and `max_conn_evt_len`.
* User will be now presented with throughput test related console prints, this suggests application is now ready to be run throughput test for user defined time. The prints may appear like below
```
==================================================================
| Steps to test nimble throughput |
| |
| 1. Enter throughput [--Type] [--Test time] |
| Type: read/write/notify. |
| Test time: Enter value in seconds. |
| |
| e.g. throughput read 600 |
| |
| ** Enter 'throughput read 60' for reading char for 60 seconds |
| OR 'throughput write 60' for writing to char for 60 seconds |
| OR 'throughput notify 60' for notifications (for 60 seconds)**|
| |
=================================================================
====================================================================================
| Steps to test nimble throughput |
| |
| 1. Enter throughput [--Type] [--Test time] [--Phy] |
| Type: read/write/notify. |
| Test time: Enter value in seconds. |
| Phy mode: Enter value in 0 for 1M, 1 for 2M ,2 for Coded S2, |
| 3 for Coded S8. |
| |
| e.g. throughput read 600 3 |
| |
| ** Enter 'throughput read 60 0' for reading char for 60 seconds on 1M phy |
| OR 'throughput write 60 1' for writing to char for 60 seconds on 2M phy |
| OR 'throughput notify 60 2' for notifications (for 60 seconds on s=2 coded phy)**|
| |
=====================================================================================
```
* If user fail to enter any values for next 30 seconds, the app falls to default behavior of READ for 60 seconds mode.
* If user fail to enter any values for next 30 seconds, the app falls to default behavior of READ for 60 seconds mode and 1M phy channel.
* Read and write throughput numbers will be presented in `blecent_throughput` console output. For notification `bleprph_throughput` console shall be referred, as the peripheral is the one who is sending notifications. Below is the sample output of the app:
```
@ -82,20 +87,23 @@ GATT procedure initiated: discover all descriptors; chr_val_handle=17 end_handle
I (36933) blecent_throughput: Service discovery complete; status=0 conn_handle=0
I (36933) blecent_throughput: Format for throughput demo:: throughput read 100
==================================================================
| Steps to test nimble throughput |
| |
| 1. Enter throughput [--Type] [--Test time] |
| Type: read/write/notify. |
| Test time: Enter value in seconds. |
| |
| e.g. throughput read 600 |
| |
| ** Enter 'throughput read 60' for reading char for 60 seconds |
| OR 'throughput write 60' for writing to char for 60 seconds |
| OR 'throughput notify 60' for notifications (for 60 seconds)**|
| |
=================================================================
====================================================================================
| Steps to test nimble throughput |
| |
| 1. Enter throughput [--Type] [--Test time] [--Phy] |
| Type: read/write/notify. |
| Test time: Enter value in seconds. |
| Phy mode: Enter value in 0 for 1M, 1 for 2M ,2 for Coded S2, |
| 3 for Coded S8. |
| |
| e.g. throughput read 600 3 |
| |
| ** Enter 'throughput read 60 0' for reading char for 60 seconds on 1M phy |
| OR 'throughput write 60 1' for writing to char for 60 seconds on 2M phy |
| OR 'throughput notify 60 2' for notifications (for 60 seconds on s=2 coded phy)**|
| |
=====================================================================================
Throughput demo >> throughput read 10
I (55333) Throughput demo handler: throughput read 10

View File

@ -8,13 +8,13 @@ menu "Example Configuration"
config EXAMPLE_CONN_ITVL_MIN
int "Minimum connection itvl"
default 6
default 104
help
Set the minimum connection interval in 1.25msec units.
config EXAMPLE_CONN_ITVL_MAX
int "Maximum connection itvl"
default 6
default 104
help
Set the maximum connection interval in 1.25msec units.
@ -26,7 +26,7 @@ menu "Example Configuration"
config EXAMPLE_CONN_TIMEOUT
int "Supervision timeout"
default 500
default 600
help
Set the supervision timeout in 10msec units.
@ -41,4 +41,16 @@ menu "Example Configuration"
default 12
help
Set the maximum connection event length in 0.625msec units.
config EXAMPLE_EXTENDED_ADV
bool
depends on SOC_BLE_50_SUPPORTED && BT_NIMBLE_50_FEATURE_SUPPORT
default y if SOC_ESP_NIMBLE_CONTROLLER
select BT_NIMBLE_EXT_ADV
prompt "Enable Extended Adv"
help
Use this option to enable extended advertising in the example.
If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is
also disabled from Nimble stack menuconfig
endmenu

View File

@ -50,7 +50,7 @@
#define NOTIFY_THROUGHPUT 3
#define READ_THROUGHPUT_PAYLOAD 500
#define WRITE_THROUGHPUT_PAYLOAD 500
#define WRITE_THROUGHPUT_PAYLOAD 495
#define LL_PACKET_TIME 2120
#define LL_PACKET_LENGTH 251
static const char *tag = "blecent_throughput";
@ -59,6 +59,19 @@ static SemaphoreHandle_t xSemaphore;
static int mbuf_len_total;
static int failure_count;
static int conn_params_def[] = {40, 40, 0, 500, 80, 80};
/* test_data accepts test_name and test_time from CLI */
static int test_data[] = {1, 600, 0};
static int mtu_def = 512;
static ble_addr_t conn_addr;
static uint16_t handle;
#define PHY_1M 0
#if CONFIG_EXAMPLE_EXTENDED_ADV
static int current_phy_updated;
#define PHY_2M 1
#define PHY_CODED_S2 2
#define PHY_CODED_S8 3
#endif
static struct ble_gap_upd_params conn_params = {
/** Minimum value for connection interval in 1.25ms units */
.itvl_min = CONFIG_EXAMPLE_CONN_ITVL_MIN,
@ -74,11 +87,21 @@ static struct ble_gap_upd_params conn_params = {
.max_ce_len = CONFIG_EXAMPLE_CONN_CE_LEN_MAX,
};
static int mtu_def = 512;
/* test_data accepts test_name and test_time from CLI */
static int test_data[] = {1, 600};
void ble_store_config_init(void);
#if CONFIG_EXAMPLE_EXTENDED_ADV
void set_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask)
{
int rc = ble_gap_set_prefered_default_le_phy(tx_phys_mask, rx_phys_mask);
if (rc == 0) {
ESP_LOGI(tag, "Default LE PHY set successfully; tx_phy = %d, rx_phy = %d",
tx_phys_mask, rx_phys_mask);
} else {
ESP_LOGE(tag, "Failed to set default LE PHY");
}
}
#endif
static int
blecent_notify(uint16_t conn_handle, uint16_t val_handle,
ble_gatt_attr_fn *cb, struct peer *peer, int test_time)
@ -207,6 +230,65 @@ err:
return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
#if CONFIG_EXAMPLE_EXTENDED_ADV
// Function to update PHY dynamically
int update_phy(uint16_t conn_handle, uint8_t phy_mode)
{
int rc;
switch (phy_mode) {
case PHY_1M:
current_phy_updated = 0;
rc = ble_gap_set_prefered_le_phy(conn_handle, BLE_HCI_LE_PHY_1M_PREF_MASK, BLE_HCI_LE_PHY_1M_PREF_MASK, 0);
if(rc != 0) {
ESP_LOGI(tag, "Requested PHY: 1M failed.");
}
else {
ESP_LOGI(tag, "Requested PHY: 1M");
}
return rc;
case PHY_2M:
current_phy_updated = 0;
rc = ble_gap_set_prefered_le_phy(conn_handle, BLE_HCI_LE_PHY_2M_PREF_MASK, BLE_HCI_LE_PHY_2M_PREF_MASK, 0);
if(rc != 0) {
ESP_LOGI(tag, "Requested PHY: 2M failed.");
}
else {
ESP_LOGI(tag, "Requested PHY: 2M");
}
return rc;
case PHY_CODED_S2:
current_phy_updated = 0;
rc = ble_gap_set_prefered_le_phy(conn_handle, BLE_HCI_LE_PHY_CODED_PREF_MASK, BLE_HCI_LE_PHY_CODED_PREF_MASK, 0x01);
if(rc != 0) {
ESP_LOGI(tag, "Requested PHY: Coded S2 failed.");
}
else {
ESP_LOGI(tag, "Requested PHY: Coded S2");
}
return rc;
case PHY_CODED_S8:
current_phy_updated = 0;
rc = ble_gap_set_prefered_le_phy(conn_handle, BLE_HCI_LE_PHY_CODED_PREF_MASK, BLE_HCI_LE_PHY_CODED_PREF_MASK, 0x02);
if(rc != 0) {
ESP_LOGI(tag, "Requested PHY: Coded S8 failed.");
}
else {
ESP_LOGI(tag, "Requested PHY: Coded S8");
}
return rc;
default:
ESP_LOGE(tag, "Invalid PHY mode selected.");
return BLE_HS_EINVAL;
}
return rc;
}
#endif
static void throughput_task(void *arg)
{
struct peer *peer = (struct peer *)arg;
@ -217,20 +299,22 @@ static void throughput_task(void *arg)
while (1) {
vTaskDelay(4000 / portTICK_PERIOD_MS);
ESP_LOGI(tag, "Format for throughput demo:: throughput read 100");
printf(" ==================================================================\n");
printf(" | Steps to test nimble throughput |\n");
printf(" | |\n");
printf(" | 1. Enter throughput [--Type] [--Test time] |\n");
printf(" | Type: read/write/notify. |\n");
printf(" | Test time: Enter value in seconds. |\n");
printf(" | |\n");
printf(" | e.g. throughput read 600 |\n");
printf(" | |\n");
printf(" | ** Enter 'throughput read 60' for reading char for 60 seconds |\n");
printf(" | OR 'throughput write 60' for writing to char for 60 seconds |\n");
printf(" | OR 'throughput notify 60' for notifications (for 60 seconds)**|\n");
printf(" | |\n");
printf(" =================================================================\n\n");
printf(" ====================================================================================\n");
printf(" | Steps to test nimble throughput |\n");
printf(" | |\n");
printf(" | 1. Enter throughput [--Type] [--Test time] [--Phy] |\n");
printf(" | Type: read/write/notify. |\n");
printf(" | Test time: Enter value in seconds. |\n");
printf(" | Phy mode: Enter value in 0 for 1M, 1 for 2M ,2 for Coded S2, |\n");
printf(" | 3 for Coded S8. |\n");
printf(" | |\n");
printf(" | e.g. throughput read 600 3 |\n");
printf(" | |\n");
printf(" | ** Enter 'throughput read 60 0' for reading char for 60 seconds on 1M Phy |\n");
printf(" | OR 'throughput write 60 1' for writing to char for 60 seconds on 2M Phy |\n");
printf(" | OR 'throughput notify 60 2' for notifications (for 60 seconds) on s=2 coded phy**|\n");
printf(" | |\n");
printf(" =====================================================================================\n\n");
/* XXX Delay ? */
vTaskDelay(1000 / portTICK_PERIOD_MS);
@ -238,10 +322,22 @@ static void throughput_task(void *arg)
/* No command supplied, start with reading */
test_data[0] = READ_THROUGHPUT;
test_data[1] = 60;
test_data[2] = 0;
ESP_LOGI(tag, "No command received from user, start with READ op"
" with 60 seconds test time");
}
scli_reset_queue();
#if CONFIG_EXAMPLE_EXTENDED_ADV
if(test_data[2] >= 0) {
rc = update_phy(handle, test_data[2]);
if(rc != 0) {
ESP_LOGI(tag, "Failed to update phy.\n");
}
while (!current_phy_updated) {
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
#endif
switch (test_data[0]) {
@ -405,6 +501,62 @@ blecent_scan(void)
}
}
#if CONFIG_EXAMPLE_EXTENDED_ADV
/**
* Indicates whether we should try to connect to the sender of the specified
* advertisement. The function returns a positive result if the device
* advertises connectability and support for the LE PHY service.
*/
static int
ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc)
{
int offset = 0;
int ad_struct_len = 0;
uint8_t test_addr[6];
uint32_t peer_addr[6];
if (disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND &&
disc->legacy_event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) {
return 0;
}
if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) {
// ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR);
/* Convert string to address */
sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%lx:%lx:%lx:%lx:%lx:%lx",
&peer_addr[5], &peer_addr[4], &peer_addr[3],
&peer_addr[2], &peer_addr[1], &peer_addr[0]);
/* Conversion */
for (int i=0; i<6; i++) {
test_addr[i] = (uint8_t )peer_addr[i];
}
if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) {
return 0;
}
}
/* The device has to advertise support LE PHY UUID (0xABF2).
*/
do {
ad_struct_len = disc->data[offset];
if (!ad_struct_len) {
break;
}
/* Search if LE PHY UUID is advertised */
if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) {
if ( disc->data[offset + 2] == 0xAB && disc->data[offset + 3] == 0xF2 ) {
return 1;
}
}
offset += ad_struct_len + 1;
} while ( offset < disc->length_data );
return 0;
}
#else
/**
* Indicates whether we should try to connect to the sender of the specified
* advertisement. The function returns a positive result if the device
@ -463,6 +615,7 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
}
return 0;
}
#endif
/**
* Connects to the sender of the specified advertisement of it looks
@ -470,15 +623,27 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc)
* support for the Alert Notification service.
*/
static void
blecent_connect_if_interesting(const struct ble_gap_disc_desc *disc)
blecent_connect_if_interesting(void *disc)
{
uint8_t own_addr_type;
int rc;
/* Don't do anything if we don't care about this advertiser. */
if (!blecent_should_connect(disc)) {
#if CONFIG_EXAMPLE_EXTENDED_ADV
const struct ble_gap_ext_disc_desc *disc_ext = (const struct ble_gap_ext_disc_desc *)disc;
if (!ext_blecent_should_connect(disc_ext)) {
return;
}
/* Copy addr information for next connection */
memcpy(&conn_addr, &disc_ext->addr, sizeof(conn_addr));
#else
const struct ble_gap_disc_desc *disc_desc = (const struct ble_gap_disc_desc *)disc;
if (!blecent_should_connect(disc_desc)) {
return;
}
/* Copy addr information for next connection */
memcpy(&conn_addr, &disc_desc->addr, sizeof(conn_addr));
#endif
#if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN))
/* Scanning must be stopped before a connection can be initiated. */
@ -499,12 +664,12 @@ blecent_connect_if_interesting(const struct ble_gap_disc_desc *disc)
/* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
* timeout.
*/
rc = ble_gap_connect(own_addr_type, &disc->addr, 30000, NULL,
rc = ble_gap_connect(own_addr_type, &conn_addr, 30000, NULL,
blecent_gap_event, NULL);
if (rc != 0) {
ESP_LOGE(tag, "Error: Failed to connect to device; addr_type=%d "
"addr=%s; rc=%d\n",
disc->addr.type, addr_str(disc->addr.val), rc);
conn_addr.type, addr_str(conn_addr.val), rc);
return;
}
}
@ -599,6 +764,7 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
blecent_scan();
}
handle = event->connect.conn_handle;
return 0;
case BLE_GAP_EVENT_DISCONNECT:
@ -609,6 +775,8 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
/* Forget about peer. */
peer_delete(event->disconnect.conn.conn_handle);
vTaskDelay(200);
/* Resume scanning. */
blecent_scan();
return 0;
@ -630,7 +798,7 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_NOTIFY_RX:
/* Peer sent us a notification or indication. */
mbuf_len_total = mbuf_len_total + OS_MBUF_PKTLEN(event->notify_rx.om);
ESP_LOGI(tag, "received %s; conn_handle = %d attr_handle = %d "
ESP_LOGD(tag, "received %s; conn_handle = %d attr_handle = %d "
"attr_len = %d ; Total length = %d",
event->notify_rx.indication ?
"indication" :
@ -649,6 +817,21 @@ blecent_gap_event(struct ble_gap_event *event, void *arg)
event->mtu.value);
return 0;
#if CONFIG_EXAMPLE_EXTENDED_ADV
case BLE_GAP_EVENT_EXT_DISC:
/* An advertisement report was received during GAP discovery. */
blecent_connect_if_interesting(&event->ext_disc);
return 0;
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE:
current_phy_updated = 1;
ESP_LOGI(tag, "PHY Update Event: Status=%d, Conn_Handle=0x%04X, TX_PHY=%d, RX_PHY=%d",
event->phy_updated.status, event->phy_updated.conn_handle,
event->phy_updated.tx_phy, event->phy_updated.rx_phy);
return 0;
#endif
default:
return 0;
}
@ -665,11 +848,20 @@ blecent_on_sync(void)
{
int rc;
bool yes = false;
#if CONFIG_EXAMPLE_EXTENDED_ADV
uint8_t all_phy;
#endif
/* Make sure we have proper identity address set (public preferred) */
rc = ble_hs_util_ensure_addr(0);
assert(rc == 0);
#if CONFIG_EXAMPLE_EXTENDED_ADV
all_phy = BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK;
set_default_le_phy(all_phy, all_phy);
#endif
ESP_LOGI(tag, "Do you want to configure connection params ? ");
ESP_LOGI(tag, "If yes then enter in this format: `Insert Yes` ");
if (scli_receive_yesno(&yes)) {

View File

@ -22,7 +22,7 @@
#define YES_NO_PARAM (5000 / portTICK_PERIOD_MS)
static QueueHandle_t cli_handle;
static int key[2];
static int key[3];
static int conn_param[10];
static int mtu;
@ -71,7 +71,7 @@ static int throughput_demo_handler(int argc, char *argv[])
{
char pkey[8];
if (argc != 3) {
if (argc != 4) {
return -1;
}
@ -88,8 +88,8 @@ static int throughput_demo_handler(int argc, char *argv[])
}
sscanf(argv[2], "%d", &key[1]);
ESP_LOGI("Throughput demo handler", "%s %s %d", argv[0], argv[1], key[1]);
sscanf(argv[3], "%d", &key[2]);
ESP_LOGI("Throughput demo handler", "%s %s %d %d", argv[0], argv[1], key[1], key[2]);
xQueueSend(cli_handle, &key[0], 500 / portTICK_PERIOD_MS);
return 0;

View File

@ -11,5 +11,7 @@ CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=512
CONFIG_BT_NIMBLE_ACL_BUF_COUNT=20
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=255
CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=20
CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=255
CONFIG_BT_NIMBLE_LOG_LEVEL=4
CONFIG_BT_NIMBLE_LOG_LEVEL_NONE=y

View File

@ -0,0 +1,14 @@
menu "Example Configuration"
config EXAMPLE_EXTENDED_ADV
bool
depends on SOC_BLE_50_SUPPORTED && BT_NIMBLE_50_FEATURE_SUPPORT
default y if SOC_ESP_NIMBLE_CONTROLLER
select BT_NIMBLE_EXT_ADV
prompt "Enable Extended Adv"
help
Use this option to enable extended advertising in the example.
If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is
also disabled from Nimble stack menuconfig
endmenu

View File

@ -17,7 +17,20 @@
#include "gatts_sens.h"
#include "../src/ble_hs_hci_priv.h"
#define NOTIFY_THROUGHPUT_PAYLOAD 500
#if CONFIG_EXAMPLE_EXTENDED_ADV
static uint8_t ext_adv_pattern[] = {
0x02, 0x01, 0x06,
0x03, 0x03, 0xab, 0xcd,
0x03, 0x03, 0xAB, 0xF2,
0x0e, 0X09, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'b', 'l', 'e', 'p', 'r', 'p', 'h'
};
static uint8_t s_current_phy;
#else
static const char *device_name = "nimble_prph";
#endif
#define NOTIFY_THROUGHPUT_PAYLOAD 495
#define MIN_REQUIRED_MBUF 2 /* Assuming payload of 500Bytes and each mbuf can take 292Bytes. */
#define PREFERRED_MTU_VALUE 512
#define LL_PACKET_TIME 2120
@ -25,7 +38,6 @@
#define MTU_DEF 512
static const char *tag = "bleprph_throughput";
static const char *device_name = "nimble_prph";
static SemaphoreHandle_t notify_sem;
static bool notify_state;
static int notify_test_time = 60;
@ -36,6 +48,33 @@ static uint8_t gatts_addr_type;
static int gatts_gap_event(struct ble_gap_event *event, void *arg);
#if CONFIG_EXAMPLE_EXTENDED_ADV
void set_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask)
{
int rc = ble_gap_set_prefered_default_le_phy(tx_phys_mask, rx_phys_mask);
if (rc == 0) {
ESP_LOGI(tag, "Default LE PHY set successfully");
} else {
ESP_LOGE(tag, "Failed to set default LE PHY");
}
}
static struct os_mbuf *
ext_get_data(uint8_t ext_adv_pattern[], int size)
{
struct os_mbuf *data;
int rc;
data = os_msys_get_pkthdr(size, 0);
assert(data);
rc = os_mbuf_append(data, ext_adv_pattern, size);
assert(rc == 0);
return data;
}
#endif
/**
* Utility function to log an array of bytes.
*/
@ -83,6 +122,54 @@ bleprph_print_conn_desc(struct ble_gap_conn_desc *desc)
desc->sec_state.bonded);
}
#if CONFIG_EXAMPLE_EXTENDED_ADV
/**
* Enables advertising with the following parameters:
* o General discoverable mode.
* o Undirected connectable mode.
*/
static void
ext_bleprph_advertise(void)
{
struct ble_gap_ext_adv_params params;
struct os_mbuf *data = NULL;
uint8_t instance = 0;
int rc;
/* use defaults for non-set params */
memset (&params, 0, sizeof(params));
params.scannable = 1;
params.legacy_pdu = 1;
/*enable connectable advertising for all Phy*/
params.connectable = 1;
/* advertise using random addr */
params.own_addr_type = BLE_OWN_ADDR_PUBLIC;
/* Set current phy; get mbuf for scan rsp data; fill mbuf with scan rsp data */
params.primary_phy = BLE_HCI_LE_PHY_1M_PREF_MASK ;
params.secondary_phy = BLE_HCI_LE_PHY_2M_PREF_MASK ;
data = ext_get_data(ext_adv_pattern, sizeof(ext_adv_pattern));
params.sid = 0;
params.itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
params.itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
/* configure instance 0 */
rc = ble_gap_ext_adv_configure(instance, &params, NULL,
gatts_gap_event, NULL);
assert (rc == 0);
rc = ble_gap_ext_adv_set_data(instance, data);
assert (rc == 0);
/* start advertising */
rc = ble_gap_ext_adv_start(instance, 0, 0);
assert (rc == 0);
}
#else
/*
* Enables advertising with parameters:
* o General discoverable mode
@ -139,6 +226,7 @@ gatts_advertise(void)
return;
}
}
#endif
/* This function sends notifications to the client */
static void
@ -189,7 +277,6 @@ notify_task(void *arg)
om = ble_hs_mbuf_from_flat(payload, sizeof(payload));
if (om == NULL) {
/* Memory not available for mbuf */
ESP_LOGE(tag, "No MBUFs available from pool, retry..");
vTaskDelay(100 / portTICK_PERIOD_MS);
}
} while (om == NULL);
@ -251,7 +338,11 @@ gatts_gap_event(struct ble_gap_event *event, void *arg)
if (event->connect.status != 0) {
/* Connection failed; resume advertising */
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_bleprph_advertise();
#else
gatts_advertise();
#endif
}
rc = ble_hs_hci_util_set_data_len(event->connect.conn_handle,
@ -268,7 +359,12 @@ gatts_gap_event(struct ble_gap_event *event, void *arg)
ESP_LOGI(tag, "disconnect; reason = %d", event->disconnect.reason);
/* Connection terminated; resume advertising */
#if CONFIG_EXAMPLE_EXTENDED_ADV
ble_gap_ext_adv_stop(0);
ext_bleprph_advertise();
#else
gatts_advertise();
#endif
break;
case BLE_GAP_EVENT_CONN_UPDATE:
@ -282,7 +378,11 @@ gatts_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_ADV_COMPLETE:
ESP_LOGI(tag, "adv complete ");
#if CONFIG_EXAMPLE_EXTENDED_ADV
ext_bleprph_advertise();
#else
gatts_advertise();
#endif
break;
case BLE_GAP_EVENT_SUBSCRIBE:
@ -321,7 +421,15 @@ gatts_gap_event(struct ble_gap_event *event, void *arg)
event->mtu.conn_handle,
event->mtu.value);
break;
}
#if CONFIG_EXAMPLE_EXTENDED_ADV
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE:
ESP_LOGI(tag, "PHY Update Event: Status=%d, Conn_Handle=0x%04X, TX_PHY=%d, RX_PHY=%d",
event->phy_updated.status, event->phy_updated.conn_handle,
event->phy_updated.tx_phy, event->phy_updated.rx_phy);
#endif
}
return 0;
}
@ -329,6 +437,9 @@ static void
gatts_on_sync(void)
{
int rc;
#if CONFIG_EXAMPLE_EXTENDED_ADV
uint8_t all_phy;
#endif
uint8_t addr_val[6] = {0};
rc = ble_hs_id_infer_auto(0, &gatts_addr_type);
@ -338,7 +449,18 @@ gatts_on_sync(void)
ESP_LOGI(tag, "Device Address: ");
print_addr(addr_val);
/* Begin advertising */
#if CONFIG_EXAMPLE_EXTENDED_ADV
s_current_phy = BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK;;
all_phy = BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_2M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK;
set_default_le_phy(all_phy, all_phy);
ext_bleprph_advertise();
#else
gatts_advertise();
#endif
}
static void
@ -390,9 +512,11 @@ void app_main(void)
rc = gatt_svr_init();
assert(rc == 0);
#if !(CONFIG_EXAMPLE_EXTENDED_ADV)
/* Set the default device name */
rc = ble_svc_gap_device_name_set(device_name);
assert(rc == 0);
#endif
/* Start the task */
nimble_port_freertos_init(gatts_host_task);

View File

@ -11,6 +11,8 @@ CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=512
CONFIG_BT_NIMBLE_ACL_BUF_COUNT=20
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=255
CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT=50
CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=20
CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=255
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=50
CONFIG_BT_NIMBLE_LOG_LEVEL=4
CONFIG_BT_NIMBLE_LOG_LEVEL_NONE=y