diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/README.md b/examples/bluetooth/nimble/throughput_app/blecent_throughput/README.md index e963e8fdd6..51cd8f3733 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/README.md +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/README.md @@ -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 diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/Kconfig.projbuild b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/Kconfig.projbuild index f82a600bcf..6cca927de7 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/Kconfig.projbuild @@ -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 diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/main.c b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/main.c index 709d36db52..c365a1a783 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/main.c @@ -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)) { diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/scli.c b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/scli.c index 3e03db1f7b..9b9455a9ec 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/scli.c +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/main/scli.c @@ -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; diff --git a/examples/bluetooth/nimble/throughput_app/blecent_throughput/sdkconfig.defaults b/examples/bluetooth/nimble/throughput_app/blecent_throughput/sdkconfig.defaults index 4a39777ef6..a8b0c5145c 100644 --- a/examples/bluetooth/nimble/throughput_app/blecent_throughput/sdkconfig.defaults +++ b/examples/bluetooth/nimble/throughput_app/blecent_throughput/sdkconfig.defaults @@ -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 diff --git a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/Kconfig.projbuild b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/Kconfig.projbuild new file mode 100644 index 0000000000..8e5ab9f250 --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/Kconfig.projbuild @@ -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 diff --git a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c index a21e9756f8..5ccfd62914 100644 --- a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/main/main.c @@ -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 (¶ms, 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, ¶ms, 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); diff --git a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/sdkconfig.defaults b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/sdkconfig.defaults index cbacfa4662..d6e31cf3ad 100644 --- a/examples/bluetooth/nimble/throughput_app/bleprph_throughput/sdkconfig.defaults +++ b/examples/bluetooth/nimble/throughput_app/bleprph_throughput/sdkconfig.defaults @@ -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