From f98706cbc5e9dd962961e3173af72e22806a539c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Mon, 19 Mar 2018 14:16:39 +0100 Subject: [PATCH 1/2] nimble/mesh: Add possibility to use extended advertising With this patch Mesh can make use of multi instances which came with advertising extension. It creates one advertising instance for PB-ADV and one for PB-GATT and PROXY. That said, it is possible to create additional instances which are used for non mesh purpose. Note that this brings limitation on Mesh Friendship due to timings. To make use of it application needs to set BLE_EXT_ADV and BLE_MULTI_ADV_INSTANCES at least to 1. Mesh will use last available advertising instance for PB-ADV and second to last for PB-GATT and PROXY --- nimble/host/mesh/include/mesh/glue.h | 2 +- nimble/host/mesh/src/glue.c | 188 ++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 5 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index bcea0a7ca..7e6b40f67 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -238,7 +238,6 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve); #define net_buf_add_be32(a, b) net_buf_simple_add_be32(a, b) #define net_buf_add_be16(a, b) net_buf_simple_add_be16(a, b) -#define bt_le_adv_stop() ble_gap_adv_stop() #define BT_GATT_CCC_NOTIFY BLE_GATT_CHR_PROP_NOTIFY #define bt_gatt_attr ble_gatt_attr @@ -277,6 +276,7 @@ void bt_mesh_register_gatt(void); int bt_le_adv_start(const struct ble_gap_adv_params *param, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len); +int bt_le_adv_stop(void); struct k_delayed_work { struct os_callout work; diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index 9b0f0fc93..0f0bf1edf 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -19,10 +19,31 @@ #include "mesh/glue.h" #include "adv.h" + #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG)) +#if MYNEWT_VAL(BLE_EXT_ADV) +#define BT_MESH_ADV_INST (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)) + +#if MYNEWT_VAL(BLE_MESH_PROXY) +/* Note that BLE_MULTI_ADV_INSTANCES contains number of additional instances. + * Instance 0 is always there + */ +#if MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) < 1 +#error "Mesh needs at least BLE_MULTI_ADV_INSTANCES set to 1" +#endif +#define BT_MESH_ADV_PROXY_INST (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) - 1) +#endif /* BLE_MESH_PROXY */ +#endif /* BLE_EXT_ADV */ + extern u8_t g_mesh_addr_type; +#if MYNEWT_VAL(BLE_EXT_ADV) +#define BLE_ADV_PB_ADV_IDX (0) +#define BLE_ADV_PB_GATT_IDX (1) +static struct ble_gap_adv_params ble_adv_cur_conf[2]; +#endif + const char * bt_hex(const void *buf, size_t len) { @@ -471,16 +492,168 @@ set_ad(const struct bt_data *ad, size_t ad_len, u8_t *buf, u8_t *buf_len) return 0; } +#if MYNEWT_VAL(BLE_EXT_ADV) +static void +ble_adv_copy_to_ext_param(struct ble_gap_ext_adv_params *ext_param, + const struct ble_gap_adv_params *param) +{ + memset(ext_param, 0, sizeof(*ext_param)); + + ext_param->legacy_pdu = 1; + ext_param->scannable = 1; + + if (param->conn_mode != BLE_GAP_CONN_MODE_NON) { + ext_param->connectable = 1; + } + + ext_param->itvl_max = param->itvl_max; + ext_param->itvl_min = param->itvl_min; + ext_param->channel_map = param->channel_map; + ext_param->high_duty_directed = param->high_duty_cycle; +} + +static int +ble_adv_conf_adv_instance(const struct ble_gap_adv_params *param, int *instance) +{ + struct ble_gap_ext_adv_params ext_params; + struct ble_gap_adv_params *cur_conf; + int err = 0; + + if (param->conn_mode == BLE_GAP_CONN_MODE_NON) { + *instance = BT_MESH_ADV_INST; + cur_conf = &ble_adv_cur_conf[BLE_ADV_PB_ADV_IDX]; + } else { +#if MYNEWT_VAL(BLE_MESH_PROXY) + *instance = BT_MESH_ADV_PROXY_INST; + cur_conf = &ble_adv_cur_conf[BLE_ADV_PB_GATT_IDX]; +#else + assert(0); +#endif + } + + /* Checking interval max as it has to be in place if instance was configured + * before. + */ + if (cur_conf->itvl_max == 0) { + goto configure; + } + + if (memcmp(param, cur_conf, sizeof(*cur_conf)) == 0) { + /* Same parameters - skip reconfiguring */ + goto done; + } + + ble_gap_ext_adv_stop(*instance); + err = ble_gap_ext_adv_remove(*instance); + if (err) { + assert(0); + goto done; + } + +configure: + ble_adv_copy_to_ext_param(&ext_params, param); + + err = ble_gap_ext_adv_configure(*instance, &ext_params, 0, + ble_adv_gap_mesh_cb, NULL); + if (!err) { + memcpy(cur_conf, param, sizeof(*cur_conf)); + } + +done: + return err; +} + +int +bt_le_adv_start(const struct ble_gap_adv_params *param, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len) +{ + struct os_mbuf *data; + int instance; + int err; + uint8_t buf[BLE_HS_ADV_MAX_SZ]; + uint8_t buf_len = 0; + + err = ble_adv_conf_adv_instance(param, &instance); + if (err) { + return err; + } + + if (ad_len > 0) { + err = set_ad(ad, ad_len, buf, &buf_len); + if (err) { + return err; + } + + /* For now let's use msys pool. We are not putting more then legacy */ + data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0); + if (!data) { + return OS_ENOMEM; + } + + err = os_mbuf_append(data, buf, buf_len); + if (err) { + goto error; + } + + err = ble_gap_ext_adv_set_data(instance, data); + if (err) { + return err; + } + + data = NULL; + } + + if (sd_len > 0) { + buf_len = 0; + + err = set_ad(sd, sd_len, buf, &buf_len); + if (err) { + return err; + } + + /* For now let's use msys pool. We are not putting more then legace*/ + data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0); + if (!data) { + return OS_ENOMEM; + } + + err = os_mbuf_append(data, buf, buf_len); + if (err) { + goto error; + } + + err = ble_gap_ext_adv_rsp_set_data(instance, data); + if (err) { + goto error; + } + } + + /*TODO: We could use duration and max events in the future */ + err = ble_gap_ext_adv_start(instance, 0, 0); + return err; + +error: + if (data) { + os_mbuf_free_chain(data); + } + + return err; +} + +int bt_le_adv_stop(void) +{ + return ble_gap_ext_adv_stop(BT_MESH_ADV_INST); +} + +#else + int bt_le_adv_start(const struct ble_gap_adv_params *param, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) { -#if MYNEWT_VAL(BLE_EXT_ADV) - uint8_t buf[MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)]; -#else uint8_t buf[BLE_HS_ADV_MAX_SZ]; -#endif uint8_t buf_len = 0; int err; @@ -520,6 +693,13 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, return 0; } +int bt_le_adv_stop(void) +{ + return ble_gap_adv_stop(); +} + +#endif + #if MYNEWT_VAL(BLE_MESH_PROXY) int bt_mesh_proxy_svcs_register(void); #endif From bd8f451583a8d9b22d53c1c77887667847380d15 Mon Sep 17 00:00:00 2001 From: Grzegorz Kolodziejczyk Date: Wed, 9 May 2018 16:48:41 +0200 Subject: [PATCH 2/2] nimble/host: Start extended scan if possible While enabling scan for mesh, appropriate scan type should be use. --- nimble/host/mesh/src/adv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/nimble/host/mesh/src/adv.c b/nimble/host/mesh/src/adv.c index 0b84bae1b..84c267b49 100644 --- a/nimble/host/mesh/src/adv.c +++ b/nimble/host/mesh/src/adv.c @@ -369,6 +369,16 @@ done: int bt_mesh_scan_enable(void) { +#if MYNEWT_VAL(BLE_EXT_ADV) + struct ble_gap_ext_disc_params uncoded_params = + { .itvl = MESH_SCAN_INTERVAL, .window = MESH_SCAN_WINDOW, + .passive = 1 }; + + BT_DBG(""); + + return ble_gap_ext_disc(g_mesh_addr_type, 0, 0, 0, 0, 0, + &uncoded_params, NULL, NULL, NULL); +#else struct ble_gap_disc_params scan_param = { .passive = 1, .filter_duplicates = 0, .itvl = MESH_SCAN_INTERVAL, .window = MESH_SCAN_WINDOW }; @@ -376,6 +386,7 @@ int bt_mesh_scan_enable(void) BT_DBG(""); return ble_gap_disc(g_mesh_addr_type, BLE_HS_FOREVER, &scan_param, NULL, NULL); +#endif } int bt_mesh_scan_disable(void)