Open buganini opened 3 months ago
HI,must use nimble-mesh,This comes from the accompanying code for nimble,But the examples provided in the idf seem to have bugs,first running ,I found that it wouldn't broadcast, and there was a stack error after I corrected the sample code as explained in the comments
I am using this patch to have my NimBLE GATT Services + ESP-BLE-MESH working together
diff --git a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
index 1cb239a3ca..2a0b1a8077 100644
--- a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
+++ b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
@@ -20,6 +20,8 @@
extern "C" {
#endif
+#define BLE_MESH_EXT_ADV_IDX 0
+
/* BLE Mesh Max Connection Count */
#ifdef CONFIG_BT_BLUEDROID_ENABLED
#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS
@@ -513,7 +515,7 @@ struct bt_mesh_conn_cb {
* @param conn New connection object.
* @param err HCI error. Zero for success, non-zero otherwise.
*/
- void (*connected)(struct bt_mesh_conn *conn, uint8_t err);
+ void (*connected)(struct bt_mesh_conn *conn, uint8_t status);
/** @brief A connection has been disconnected.
*
@@ -718,6 +720,8 @@ int bt_le_update_white_list(struct bt_mesh_white_list *wl);
void bt_mesh_gatts_conn_cb_register(struct bt_mesh_conn_cb *cb);
void bt_mesh_gatts_conn_cb_deregister(void);
+struct bt_mesh_conn_cb * bt_mesh_gatts_conn_cb_current();
+int (*bt_mesh_gap_event_cb(void))(struct ble_gap_event *event, void *arg);
int bt_mesh_gatts_disconnect(struct bt_mesh_conn *conn, uint8_t reason);
@@ -799,6 +803,8 @@ int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
+void esp_ble_mesh_init_gatts(void);
+
enum {
BLE_MESH_EXCEP_LIST_SUB_CODE_ADD = 0,
BLE_MESH_EXCEP_LIST_SUB_CODE_REMOVE,
diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
index 0418b76c54..9d0e9e40cb 100644
--- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
+++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
@@ -17,6 +17,7 @@
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "host/ble_att.h"
+#include "host/ble_gap.h"
#include "host/ble_gatt.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
@@ -652,7 +653,7 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle);
if (index < BLE_MESH_MAX_CONN) {
bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle);
- (bt_mesh_gatts_conn_cb->connected)(&bt_mesh_gatts_conn[index], 0);
+ (bt_mesh_gatts_conn_cb->connected)(&bt_mesh_gatts_conn[index], event->connect.status);
}
memcpy(bt_mesh_gatts_addr, desc.peer_id_addr.val, BLE_MESH_ADDR_LEN);
/* This is for EspBleMesh Android app. When it tries to connect with the
@@ -777,6 +778,21 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
}
#endif /* CONFIG_BLE_MESH_NODE */
+#if MYNEWT_VAL(BLE_EXT_ADV)
+struct ble_gap_ext_adv_params params = {
+ .connectable = 1,
+ .scannable = 1,
+ .directed = 0,
+ .own_addr_type = BLE_OWN_ADDR_PUBLIC,
+ .primary_phy = BLE_HCI_LE_PHY_1M,
+ .secondary_phy = BLE_HCI_LE_PHY_2M,
+ .sid = BLE_MESH_EXT_ADV_IDX,
+ .itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN,
+ .itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MIN,
+ .legacy_pdu = 1,
+};
+#endif
+
/* APIs functions */
int bt_le_adv_start(const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *ad, size_t ad_len,
@@ -800,6 +816,71 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
return err;
}
+#if MYNEWT_VAL(BLE_EXT_ADV)
+ if (ble_gap_ext_adv_active(BLE_MESH_EXT_ADV_IDX))
+ {
+ ble_gap_ext_adv_stop(BLE_MESH_EXT_ADV_IDX);
+ }
+
+ err = ble_gap_ext_adv_configure(BLE_MESH_EXT_ADV_IDX, ¶ms, NULL,
+ gap_event_cb, NULL);
+ if (err != 0) {
+ BT_ERR("Extended Advertising configure failed: err %d", err);
+ return err;
+ }
+
+ struct os_mbuf *data = os_msys_get_pkthdr(buf_len, 0);
+ if (data == NULL) {
+ BT_ERR("Extended Advertising configure failed: os_msys_get_pkthdr");
+ return -1;
+ }
+
+ err = os_mbuf_append(data, buf, buf_len);
+ if (err != 0) {
+ BT_ERR("Extended Advertising os_mbuf_append failed: err %d", err);
+ return err;
+ }
+
+ err = ble_gap_ext_adv_set_data(BLE_MESH_EXT_ADV_IDX, data);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_set_data failed: err %d", err);
+ return err;
+ }
+
+ if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) {
+ buf_len = 0;
+
+ err = set_ad(sd, sd_len, buf, &buf_len);
+ if (err) {
+ BT_ERR("set_ad failed: err %d", err);
+ return err;
+ }
+
+ struct os_mbuf *rsp_data = os_msys_get_pkthdr(buf_len, 0);
+ if (rsp_data == NULL) {
+ BT_ERR("Extended Advertising configure rsp failed: os_msys_get_pkthdr");
+ return -1;
+ }
+
+ err = os_mbuf_append(rsp_data, buf, buf_len);
+ if (err != 0) {
+ BT_ERR("Extended Advertising rsp os_mbuf_append failed: err %d", err);
+ return err;
+ }
+
+ err = ble_gap_ext_adv_rsp_set_data(BLE_MESH_EXT_ADV_IDX, rsp_data);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_rsp_set_data failed: err %d", err);
+ return err;
+ }
+ }
+
+ err = ble_gap_ext_adv_start(BLE_MESH_EXT_ADV_IDX, 0, 0);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_start failed: err %d", err);
+ return err;
+ }
+#else
err = ble_gap_adv_set_data(buf, buf_len);
if (err != 0) {
BT_ERR("Advertising set failed: err %d", err);
@@ -866,6 +947,7 @@ again:
BT_ERR("Advertising start failed: err %d", err);
return err;
}
+#endif
#if BLE_MESH_DEV
bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING);
@@ -959,7 +1041,12 @@ int bt_le_adv_stop(void)
return 0;
}
#endif
+
+#if MYNEWT_VAL(BLE_EXT_ADV)
+ ble_gap_ext_adv_stop(BLE_MESH_EXT_ADV_IDX);
+#else
ble_gap_adv_stop();
+#endif
#if BLE_MESH_DEV
bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING);
@@ -1039,6 +1126,15 @@ void bt_mesh_gatts_conn_cb_deregister(void)
bt_mesh_gatts_conn_cb = NULL;
}
+struct bt_mesh_conn_cb * bt_mesh_gatts_conn_cb_current()
+{
+ return bt_mesh_gatts_conn_cb;
+}
+
+int (*bt_mesh_gap_event_cb(void))(struct ble_gap_event *event, void *arg) {
+ return gap_event_cb;
+}
+
static struct bt_mesh_gatt_attr *bt_mesh_gatts_find_attr_by_handle(uint16_t handle)
{
struct bt_mesh_gatt_service *svc = NULL;
@@ -1717,6 +1813,10 @@ void gatt_register_cb(struct ble_gatt_register_ctxt *ctxt,
}
}
+__attribute__((weak)) void esp_ble_mesh_init_gatts(void) {
+ // register your services here
+}
+
void bt_mesh_gatt_init(void)
{
ble_att_set_preferred_mtu(BLE_ATT_MTU_DFLT);
@@ -1737,6 +1837,8 @@ void bt_mesh_gatt_init(void)
rc = ble_gatts_add_svcs(svc_defs);
assert(rc == 0);
+ esp_ble_mesh_init_gatts();
+
ble_gatts_start();
ble_gatts_svc_set_visibility(prov_svc_start_handle, 1);
#include "esp_ble_mesh_ble_api.h"
#include "mesh/adapter.h" // bt_mesh_gap_event_cb
#if MYNEWT_VAL(BLE_EXT_ADV)
static int
bleprph_gap_event(struct ble_gap_event *event, void *arg)
{
bt_mesh_gap_event_cb()(event, arg);
// your gap event handler here
return 0;
}
#else
static struct bt_mesh_conn_cb * proxy_conn_cb;
static void gap_connected(struct bt_mesh_conn *conn, uint8_t status) {
// feedback to ESP-BLE-MESH
proxy_conn_cb->connected(conn, status);
uint16_t conn_handle = conn->handle;
printf("gap_connected: conn_handle=%d, status=%d\n", (int)conn_handle, (int)status);
}
static void gap_disconnected(struct bt_mesh_conn *conn, uint8_t reason) {
// feedback to ESP-BLE-MESH
proxy_conn_cb->disconnected(conn, reason);
uint16_t conn_handle = conn->handle;
printf("gap_disconnected: conn_handle=%d, reason=%d\n", (int)conn_handle, (int)reason);
}
struct bt_mesh_conn_cb conn_cb = {
.connected = gap_connected,
.disconnected = gap_disconnected,
};
#endif
// called in esp_ble_mesh_init()
void esp_ble_mesh_init_gatts(void) {
int rc = ble_gatts_count_cfg(gatt_svr_svcs);
if (rc != 0) {
return;
}
rc = ble_gatts_add_svcs(gatt_svr_svcs);
if (rc != 0) {
return;
}
}
void ble_on_sync_proc() {
rc = esp_ble_mesh_init(&provision, &composition);
if (rc != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize mesh stack (err %d)", rc);
return;
}
#if MYNEWT_VAL(BLE_EXT_ADV)
int err = ble_gap_ext_adv_configure(YOUR_ADV_IDX, ¶ms, NULL,
bleprph_gap_event, NULL);
// ble_gap_ext_adv_set_data
// ble_gap_ext_adv_start
#else
// obtain the current gatt proxy callback for event feedback
proxy_conn_cb = bt_mesh_gatts_conn_cb_current();
// overwrite gap events callback
bt_mesh_gatts_conn_cb_register(&conn_cb);
#endif
esp_ble_mesh_node_prov_enable((esp_ble_mesh_prov_bearer_t)(ESP_BLE_MESH_PROV_ADV|ESP_BLE_MESH_PROV_GATT));
}
Here is a new patch to allow GATT Proxy + ESP-BLE-MESH working together, with less intrusive to the original code, but more flexible.
weak_esp_ble_mesh_gap_event_cb
for esp_ble_mesh_gap_event_cb
(original disc_cb
) to allow injection of gap event handlingdiff --git a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
index 1cb239a3ca..3f038ece24 100644
--- a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
+++ b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
@@ -20,6 +20,8 @@
extern "C" {
#endif
+#define BLE_MESH_EXT_ADV_IDX 0
+
/* BLE Mesh Max Connection Count */
#ifdef CONFIG_BT_BLUEDROID_ENABLED
#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS
@@ -799,6 +801,10 @@ int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
+int weak_esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg);
+int esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg);
+void esp_ble_mesh_init_gatts(void);
+
enum {
BLE_MESH_EXCEP_LIST_SUB_CODE_ADD = 0,
BLE_MESH_EXCEP_LIST_SUB_CODE_REMOVE,
diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
index 0418b76c54..2e4f49c64e 100644
--- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
+++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
@@ -17,6 +17,7 @@
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "host/ble_att.h"
+#include "host/ble_gap.h"
#include "host/ble_gatt.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
@@ -628,7 +629,11 @@ static int set_ad(const struct bt_mesh_adv_data *ad, size_t ad_len, uint8_t *buf
#if CONFIG_BLE_MESH_NODE
static struct bt_mesh_gatt_attr *bt_mesh_gatts_find_attr_by_handle(uint16_t handle);
-static int gap_event_cb(struct ble_gap_event *event, void *arg)
+__attribute__((weak)) int weak_esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg) {
+ return esp_ble_mesh_gap_event_cb(event, arg);
+}
+
+int esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg)
{
struct ble_gap_conn_desc desc;
int rc;
@@ -771,12 +776,27 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
return 0;
}
#else
-static int gap_event_cb(struct ble_gap_event *event, void *arg)
+static int weak_esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg)
{
return 0;
}
#endif /* CONFIG_BLE_MESH_NODE */
+#if MYNEWT_VAL(BLE_EXT_ADV)
+struct ble_gap_ext_adv_params params = {
+ .connectable = 1,
+ .scannable = 1,
+ .directed = 0,
+ .own_addr_type = BLE_OWN_ADDR_PUBLIC,
+ .primary_phy = BLE_HCI_LE_PHY_1M,
+ .secondary_phy = BLE_HCI_LE_PHY_2M,
+ .sid = BLE_MESH_EXT_ADV_IDX,
+ .itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN,
+ .itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MIN,
+ .legacy_pdu = 1,
+};
+#endif
+
/* APIs functions */
int bt_le_adv_start(const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *ad, size_t ad_len,
@@ -800,6 +820,71 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
return err;
}
+#if MYNEWT_VAL(BLE_EXT_ADV)
+ if (ble_gap_ext_adv_active(BLE_MESH_EXT_ADV_IDX))
+ {
+ ble_gap_ext_adv_stop(BLE_MESH_EXT_ADV_IDX);
+ }
+
+ err = ble_gap_ext_adv_configure(BLE_MESH_EXT_ADV_IDX, ¶ms, NULL,
+ weak_esp_ble_mesh_gap_event_cb, NULL);
+ if (err != 0) {
+ BT_ERR("Extended Advertising configure failed: err %d", err);
+ return err;
+ }
+
+ struct os_mbuf *data = os_msys_get_pkthdr(buf_len, 0);
+ if (data == NULL) {
+ BT_ERR("Extended Advertising configure failed: os_msys_get_pkthdr");
+ return -1;
+ }
+
+ err = os_mbuf_append(data, buf, buf_len);
+ if (err != 0) {
+ BT_ERR("Extended Advertising os_mbuf_append failed: err %d", err);
+ return err;
+ }
+
+ err = ble_gap_ext_adv_set_data(BLE_MESH_EXT_ADV_IDX, data);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_set_data failed: err %d", err);
+ return err;
+ }
+
+ if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) {
+ buf_len = 0;
+
+ err = set_ad(sd, sd_len, buf, &buf_len);
+ if (err) {
+ BT_ERR("set_ad failed: err %d", err);
+ return err;
+ }
+
+ struct os_mbuf *rsp_data = os_msys_get_pkthdr(buf_len, 0);
+ if (rsp_data == NULL) {
+ BT_ERR("Extended Advertising configure rsp failed: os_msys_get_pkthdr");
+ return -1;
+ }
+
+ err = os_mbuf_append(rsp_data, buf, buf_len);
+ if (err != 0) {
+ BT_ERR("Extended Advertising rsp os_mbuf_append failed: err %d", err);
+ return err;
+ }
+
+ err = ble_gap_ext_adv_rsp_set_data(BLE_MESH_EXT_ADV_IDX, rsp_data);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_rsp_set_data failed: err %d", err);
+ return err;
+ }
+ }
+
+ err = ble_gap_ext_adv_start(BLE_MESH_EXT_ADV_IDX, 0, 0);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_start failed: err %d", err);
+ return err;
+ }
+#else
err = ble_gap_adv_set_data(buf, buf_len);
if (err != 0) {
BT_ERR("Advertising set failed: err %d", err);
@@ -856,7 +941,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
again:
err = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params,
- gap_event_cb, NULL);
+ weak_esp_ble_mesh_gap_event_cb, NULL);
if (err) {
if (err == BLE_HS_EALREADY) {
ble_gap_adv_stop();
@@ -866,6 +951,7 @@ again:
BT_ERR("Advertising start failed: err %d", err);
return err;
}
+#endif
#if BLE_MESH_DEV
bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING);
@@ -941,7 +1027,7 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param,
}
err = ble_gap_adv_start(param->own_addr_type, &p_dir_bda, BLE_HS_FOREVER, &adv_params,
- gap_event_cb, NULL);
+ weak_esp_ble_mesh_gap_event_cb, NULL);
if (err) {
BT_ERR("Failed to start advertising, err %d", err);
return err;
@@ -959,7 +1045,12 @@ int bt_le_adv_stop(void)
return 0;
}
#endif
+
+#if MYNEWT_VAL(BLE_EXT_ADV)
+ ble_gap_ext_adv_stop(BLE_MESH_EXT_ADV_IDX);
+#else
ble_gap_adv_stop();
+#endif
#if BLE_MESH_DEV
bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING);
@@ -1717,6 +1808,10 @@ void gatt_register_cb(struct ble_gatt_register_ctxt *ctxt,
}
}
+__attribute__((weak)) void esp_ble_mesh_init_gatts(void) {
+ // register your services here
+}
+
void bt_mesh_gatt_init(void)
{
ble_att_set_preferred_mtu(BLE_ATT_MTU_DFLT);
@@ -1737,6 +1832,8 @@ void bt_mesh_gatt_init(void)
rc = ble_gatts_add_svcs(svc_defs);
assert(rc == 0);
+ esp_ble_mesh_init_gatts();
+
ble_gatts_start();
ble_gatts_svc_set_visibility(prov_svc_start_handle, 1);
#include "esp_ble_mesh_ble_api.h"
#include "mesh/adapter.h" // bt_mesh_gap_event_cb
int weak_esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg)
{
esp_ble_mesh_gap_event_cb(event, arg);
// your gap event handler here
return 0;
}
// called in esp_ble_mesh_init()
void esp_ble_mesh_init_gatts(void) {
int rc = ble_gatts_count_cfg(gatt_svr_svcs);
if (rc != 0) {
return;
}
rc = ble_gatts_add_svcs(gatt_svr_svcs);
if (rc != 0) {
return;
}
}
void ble_on_sync_proc() {
rc = esp_ble_mesh_init(&provision, &composition);
if (rc != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize mesh stack (err %d)", rc);
return;
}
#if MYNEWT_VAL(BLE_EXT_ADV)
int err = ble_gap_ext_adv_configure(YOUR_ADV_IDX, ¶ms, NULL,
weak_esp_ble_mesh_gap_event_cb, NULL);
// ble_gap_ext_adv_set_data
// ble_gap_ext_adv_start
#else
esp_ble_mesh_start_ble_advertising(&adv_param, &adv_data);
#endif
esp_ble_mesh_node_prov_enable((esp_ble_mesh_prov_bearer_t)(ESP_BLE_MESH_PROV_ADV|ESP_BLE_MESH_PROV_GATT));
}
The new patch allows NimBLE GATT Peripheral + ESP-BLE-MESH to work together, with a less intrusive approach to the original code, but providing more flexibility.
weak_esp_ble_mesh_gap_event_cb
for esp_ble_mesh_gap_event_cb
(original disc_cb
) to allow injection of gap event handling
BLE_GAP_EVENT_EXT_DISC
in disc_cb
for receiving mesh packetsdiff --git a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
index 1cb239a3ca..3f038ece24 100644
--- a/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
+++ b/components/bt/esp_ble_mesh/core/include/mesh/adapter.h
@@ -20,6 +20,8 @@
extern "C" {
#endif
+#define BLE_MESH_EXT_ADV_IDX 0
+
/* BLE Mesh Max Connection Count */
#ifdef CONFIG_BT_BLUEDROID_ENABLED
#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS
@@ -799,6 +801,10 @@ int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16]);
+int weak_esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg);
+int esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg);
+void esp_ble_mesh_init_gatts(void);
+
enum {
BLE_MESH_EXCEP_LIST_SUB_CODE_ADD = 0,
BLE_MESH_EXCEP_LIST_SUB_CODE_REMOVE,
diff --git a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
index 0418b76c54..a08838f923 100644
--- a/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
+++ b/components/bt/esp_ble_mesh/core/nimble_host/adapter.c
@@ -17,6 +17,7 @@
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "host/ble_att.h"
+#include "host/ble_gap.h"
#include "host/ble_gatt.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
@@ -424,6 +425,20 @@ static int disc_cb(struct ble_gap_event *event, void *arg)
}
break;
}
+#if MYNEWT_VAL(BLE_EXT_ADV)
+ case BLE_GAP_EVENT_EXT_DISC: {
+ struct net_buf_simple buf = {0};
+
+ struct ble_gap_ext_disc_desc * desc = &event->ext_disc;
+ net_buf_simple_init_with_data(&buf, (void *)desc->data, desc->length_data);
+
+ if (bt_mesh_scan_dev_found_cb) {
+ /* TODO: Support Scan Response data length for NimBLE host */
+ bt_mesh_scan_dev_found_cb((bt_mesh_addr_t *)&desc->addr, desc->rssi, desc->legacy_event_type, &buf, 0);
+ }
+ break;
+ }
+#endif
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT
case BLE_GAP_EVENT_CONNECT:
@@ -628,7 +643,11 @@ static int set_ad(const struct bt_mesh_adv_data *ad, size_t ad_len, uint8_t *buf
#if CONFIG_BLE_MESH_NODE
static struct bt_mesh_gatt_attr *bt_mesh_gatts_find_attr_by_handle(uint16_t handle);
-static int gap_event_cb(struct ble_gap_event *event, void *arg)
+__attribute__((weak)) int weak_esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg) {
+ return esp_ble_mesh_gap_event_cb(event, arg);
+}
+
+int esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg)
{
struct ble_gap_conn_desc desc;
int rc;
@@ -771,12 +790,27 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
return 0;
}
#else
-static int gap_event_cb(struct ble_gap_event *event, void *arg)
+static int weak_esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg)
{
return 0;
}
#endif /* CONFIG_BLE_MESH_NODE */
+#if MYNEWT_VAL(BLE_EXT_ADV)
+struct ble_gap_ext_adv_params params = {
+ .connectable = 0,
+ .scannable = 0,
+ .directed = 0,
+ .own_addr_type = BLE_OWN_ADDR_PUBLIC,
+ .primary_phy = BLE_HCI_LE_PHY_1M,
+ .secondary_phy = BLE_HCI_LE_PHY_2M,
+ .sid = BLE_MESH_EXT_ADV_IDX,
+ .itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN,
+ .itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MIN,
+ .legacy_pdu = 1,
+};
+#endif
+
/* APIs functions */
int bt_le_adv_start(const struct bt_mesh_adv_param *param,
const struct bt_mesh_adv_data *ad, size_t ad_len,
@@ -800,6 +834,74 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
return err;
}
+#if MYNEWT_VAL(BLE_EXT_ADV)
+ if (ble_gap_ext_adv_active(BLE_MESH_EXT_ADV_IDX))
+ {
+ ble_gap_ext_adv_stop(BLE_MESH_EXT_ADV_IDX);
+ }
+
+ params.connectable = (param->options & BLE_MESH_ADV_OPT_CONNECTABLE) ? 1 : 0;
+ params.scannable = sd_len > 0 ? 1 : 0;
+
+ err = ble_gap_ext_adv_configure(BLE_MESH_EXT_ADV_IDX, ¶ms, NULL,
+ weak_esp_ble_mesh_gap_event_cb, NULL);
+ if (err != 0) {
+ BT_ERR("Extended Advertising configure failed: err %d", err);
+ return err;
+ }
+
+ struct os_mbuf *data = os_msys_get_pkthdr(buf_len, 0);
+ if (data == NULL) {
+ BT_ERR("Extended Advertising configure failed: os_msys_get_pkthdr");
+ return -1;
+ }
+
+ err = os_mbuf_append(data, buf, buf_len);
+ if (err != 0) {
+ BT_ERR("Extended Advertising os_mbuf_append failed: err %d", err);
+ return err;
+ }
+
+ err = ble_gap_ext_adv_set_data(BLE_MESH_EXT_ADV_IDX, data);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_set_data failed: err %d", err);
+ return err;
+ }
+
+ if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) {
+ buf_len = 0;
+
+ err = set_ad(sd, sd_len, buf, &buf_len);
+ if (err) {
+ BT_ERR("set_ad failed: err %d", err);
+ return err;
+ }
+
+ struct os_mbuf *rsp_data = os_msys_get_pkthdr(buf_len, 0);
+ if (rsp_data == NULL) {
+ BT_ERR("Extended Advertising configure rsp failed: os_msys_get_pkthdr");
+ return -1;
+ }
+
+ err = os_mbuf_append(rsp_data, buf, buf_len);
+ if (err != 0) {
+ BT_ERR("Extended Advertising rsp os_mbuf_append failed: err %d", err);
+ return err;
+ }
+
+ err = ble_gap_ext_adv_rsp_set_data(BLE_MESH_EXT_ADV_IDX, rsp_data);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_rsp_set_data failed: err %d", err);
+ return err;
+ }
+ }
+
+ err = ble_gap_ext_adv_start(BLE_MESH_EXT_ADV_IDX, 0, 0);
+ if (err != 0) {
+ BT_ERR("Extended Advertising ble_gap_ext_adv_start failed: err %d", err);
+ return err;
+ }
+#else
err = ble_gap_adv_set_data(buf, buf_len);
if (err != 0) {
BT_ERR("Advertising set failed: err %d", err);
@@ -856,7 +958,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param,
again:
err = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params,
- gap_event_cb, NULL);
+ weak_esp_ble_mesh_gap_event_cb, NULL);
if (err) {
if (err == BLE_HS_EALREADY) {
ble_gap_adv_stop();
@@ -866,6 +968,7 @@ again:
BT_ERR("Advertising start failed: err %d", err);
return err;
}
+#endif
#if BLE_MESH_DEV
bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING);
@@ -941,7 +1044,7 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param,
}
err = ble_gap_adv_start(param->own_addr_type, &p_dir_bda, BLE_HS_FOREVER, &adv_params,
- gap_event_cb, NULL);
+ weak_esp_ble_mesh_gap_event_cb, NULL);
if (err) {
BT_ERR("Failed to start advertising, err %d", err);
return err;
@@ -959,7 +1062,12 @@ int bt_le_adv_stop(void)
return 0;
}
#endif
+
+#if MYNEWT_VAL(BLE_EXT_ADV)
+ ble_gap_ext_adv_stop(BLE_MESH_EXT_ADV_IDX);
+#else
ble_gap_adv_stop();
+#endif
#if BLE_MESH_DEV
bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING);
@@ -1717,6 +1825,10 @@ void gatt_register_cb(struct ble_gatt_register_ctxt *ctxt,
}
}
+__attribute__((weak)) void esp_ble_mesh_init_gatts(void) {
+ // register your services here
+}
+
void bt_mesh_gatt_init(void)
{
ble_att_set_preferred_mtu(BLE_ATT_MTU_DFLT);
@@ -1737,6 +1849,8 @@ void bt_mesh_gatt_init(void)
rc = ble_gatts_add_svcs(svc_defs);
assert(rc == 0);
+ esp_ble_mesh_init_gatts();
+
ble_gatts_start();
ble_gatts_svc_set_visibility(prov_svc_start_handle, 1);
#include "esp_ble_mesh_ble_api.h"
#include "mesh/adapter.h" // bt_mesh_gap_event_cb
int weak_esp_ble_mesh_gap_event_cb(struct ble_gap_event *event, void *arg)
{
esp_ble_mesh_gap_event_cb(event, arg);
// your gap event handler here
return 0;
}
// called in esp_ble_mesh_init()
void esp_ble_mesh_init_gatts(void) {
int rc = ble_gatts_count_cfg(gatt_svr_svcs);
if (rc != 0) {
return;
}
rc = ble_gatts_add_svcs(gatt_svr_svcs);
if (rc != 0) {
return;
}
}
void ble_on_sync_proc() {
rc = esp_ble_mesh_init(&provision, &composition);
if (rc != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize mesh stack (err %d)", rc);
return;
}
#if MYNEWT_VAL(BLE_EXT_ADV)
int err = ble_gap_ext_adv_configure(YOUR_ADV_IDX, ¶ms, NULL,
weak_esp_ble_mesh_gap_event_cb, NULL);
// ble_gap_ext_adv_set_data
// ble_gap_ext_adv_start
#else
esp_ble_mesh_start_ble_advertising(&adv_param, &adv_data);
#endif
esp_ble_mesh_node_prov_enable((esp_ble_mesh_prov_bearer_t)(ESP_BLE_MESH_PROV_ADV|ESP_BLE_MESH_PROV_GATT));
}
Answers checklist.
General issue report
ESP-IDF: v5.3
sdkconfig includes:
I used to have
Bluedroid
Gatt Server +ESP-BLE-MESH
coexistence by usingesp_ble_mesh_start_ble_advertising
, it will send both advertisements and both gatts_profile_event_handler/esp_ble_mesh_prov_callback are invoked to handle BLE pairing/bonding and BLE-MESH provisioning.But due to the following issue I have to move to NimBLE https://github.com/meshtastic/firmware/issues/266
NimBLE GATT Server works and ESP-IDF-MESH works, but when both are enabled, only one of them functions correctly.
With NimBLE I have to call
ble_gap_adv_start
to register GAP event handler for pairing/bonding, I have tried different combinations and orders ofesp_ble_mesh_start_ble_advertising
,ble_gap_adv_start
,esp_ble_mesh_init/esp_ble_mesh_provisioner_prov_enable
, but I just cannot get both handlers to work simultaneously. It seems that ESP-BLE-MESH is not integrated with NimBLE. Can someone confirm this?