diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index 44d7fec6b..4309cdb3e 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -590,8 +590,7 @@ if BLE_MESH endif # BLE_MESH_LOW_POWER config BLE_MESH_FRIEND - bool "Support for acting as a Friend Node" - depends on BLE_MESH_NODE + bool "Support for Friend feature" help Enable this option to be able to act as a Friend Node. diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index 415a543a0..7bd500ae2 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -783,7 +783,6 @@ static void btc_ble_mesh_heartbeat_msg_recv_cb(u8_t hops, u16_t feature) return; } -#if CONFIG_BLE_MESH_NODE #if CONFIG_BLE_MESH_LOW_POWER static void btc_ble_mesh_lpn_cb(u16_t friend_addr, bool established) { @@ -831,7 +830,6 @@ void btc_ble_mesh_friend_cb(bool establish, u16_t lpn_addr, u8_t reason) return; } #endif /* CONFIG_BLE_MESH_FRIEND */ -#endif /* CONFIG_BLE_MESH_NODE */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT static void btc_ble_mesh_proxy_client_adv_recv_cb(const bt_mesh_addr_t *addr, @@ -1507,12 +1505,6 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) arg->mesh_init.prov->link_close_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_link_close_cb; arg->mesh_init.prov->complete_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_complete_cb; arg->mesh_init.prov->reset_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_reset_cb; -#if CONFIG_BLE_MESH_LOW_POWER - bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb); -#endif /* CONFIG_BLE_MESH_LOW_POWER */ -#if CONFIG_BLE_MESH_FRIEND - bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb); -#endif /* CONFIG_BLE_MESH_FRIEND */ #endif /* CONFIG_BLE_MESH_NODE */ #if CONFIG_BLE_MESH_PROVISIONER arg->mesh_init.prov->provisioner_prov_read_oob_pub_key = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_read_oob_pub_key_cb; @@ -1523,6 +1515,12 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) arg->mesh_init.prov->provisioner_prov_comp = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_complete_cb; bt_mesh_prov_adv_pkt_cb_register(btc_ble_mesh_provisioner_recv_unprov_adv_pkt_cb); #endif /* CONFIG_BLE_MESH_PROVISIONER */ +#if CONFIG_BLE_MESH_LOW_POWER + bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb); +#endif /* CONFIG_BLE_MESH_LOW_POWER */ +#if CONFIG_BLE_MESH_FRIEND + bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb); +#endif /* CONFIG_BLE_MESH_FRIEND */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT bt_mesh_proxy_client_set_adv_recv_cb(btc_ble_mesh_proxy_client_adv_recv_cb); bt_mesh_proxy_client_set_conn_cb(btc_ble_mesh_proxy_client_connect_cb); diff --git a/components/bt/esp_ble_mesh/mesh_core/friend.c b/components/bt/esp_ble_mesh/mesh_core/friend.c index 67a9ef04c..894e88cf5 100644 --- a/components/bt/esp_ble_mesh/mesh_core/friend.c +++ b/components/bt/esp_ble_mesh/mesh_core/friend.c @@ -26,6 +26,8 @@ #include "access.h" #include "foundation.h" #include "friend.h" +#include "client_common.h" +#include "provisioner_main.h" #ifdef CONFIG_BLE_MESH_FRIEND @@ -72,7 +74,18 @@ enum { static void (*friend_cb)(bool establish, u16_t lpn_addr, u8_t reason); +static struct bt_mesh_subnet *friend_subnet_get(u16_t net_idx) +{ + struct bt_mesh_subnet *sub = NULL; + if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { + sub = bt_mesh_subnet_get(net_idx); + } else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) { + sub = provisioner_subnet_get(net_idx); + } + + return sub; +} static struct bt_mesh_adv *adv_alloc(int id) { @@ -357,20 +370,31 @@ static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd, struct unseg_app_sdu_meta *meta) { u16_t app_idx = FRIEND_ADV(buf)->app_idx; + u8_t role; int err; - meta->subnet = bt_mesh_subnet_get(frnd->net_idx); + meta->subnet = friend_subnet_get(frnd->net_idx); + if (!meta->subnet) { + BT_ERR("Invalid subnet for unseg app sdu"); + return -EINVAL; + } + + role = (IS_ENABLED(CONFIG_BLE_MESH_NODE) && + bt_mesh_is_provisioned()) ? NODE : PROVISIONER; + meta->is_dev_key = (app_idx == BLE_MESH_KEY_DEV); bt_mesh_net_header_parse(&buf->b, &meta->net); err = bt_mesh_app_key_get(meta->subnet, app_idx, &meta->key, - &meta->aid, 0x0, meta->net.ctx.addr); + &meta->aid, role, meta->net.ctx.addr); if (err) { + BT_ERR("Failed to get AppKey"); return err; } if (BLE_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) { meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst); if (!meta->ad) { + BT_ERR("Failed to get label uuid"); return -ENOENT; } } else { @@ -451,13 +475,18 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf, bool master_cred) { - struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx); + struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx); const u8_t *enc, *priv; u32_t iv_index; u16_t src; u8_t nid; int err; + if (!sub) { + BT_ERR("Invalid subnet to encrypt friend pdu"); + return -EINVAL; + } + if (master_cred) { enc = sub->keys[sub->kr_flag].enc; priv = sub->keys[sub->kr_flag].privacy; @@ -534,7 +563,7 @@ static struct net_buf *encode_update(struct bt_mesh_friend *frnd, u8_t md) { struct bt_mesh_ctl_friend_update *upd; NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*upd)); - struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx); + struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx); __ASSERT_NO_MSG(sub != NULL); @@ -774,7 +803,7 @@ static void send_friend_clear(struct bt_mesh_friend *frnd) .send_ttl = BLE_MESH_TTL_MAX, }; struct bt_mesh_net_tx tx = { - .sub = bt_mesh_subnet_get(frnd->net_idx), + .sub = friend_subnet_get(frnd->net_idx), .ctx = &ctx, .src = bt_mesh_primary_addr(), .xmit = bt_mesh_net_transmit_get(), @@ -786,6 +815,11 @@ static void send_friend_clear(struct bt_mesh_friend *frnd) BT_DBG("%s", __func__); + if (!tx.sub) { + BT_ERR("Invalid subnet for Friend Clear"); + return; + } + bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req, sizeof(req), NULL, &clear_sent_cb, frnd); } @@ -1647,4 +1681,14 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src, } } +void bt_mesh_friend_remove_lpn(u16_t lpn_addr) +{ + struct bt_mesh_friend *frnd; + + frnd = bt_mesh_friend_find(BLE_MESH_KEY_ANY, lpn_addr, false, false); + if (frnd) { + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE); + } +} + #endif /* CONFIG_BLE_MESH_FRIEND */ diff --git a/components/bt/esp_ble_mesh/mesh_core/friend.h b/components/bt/esp_ble_mesh/mesh_core/friend.h index c6ecf7e6c..8c1fbe57b 100644 --- a/components/bt/esp_ble_mesh/mesh_core/friend.h +++ b/components/bt/esp_ble_mesh/mesh_core/friend.h @@ -51,4 +51,6 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, int bt_mesh_friend_init(void); +void bt_mesh_friend_remove_lpn(u16_t lpn_addr); + #endif /* _FRIEND_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_core/main.c b/components/bt/esp_ble_mesh/mesh_core/main.c index 13dc03610..90b00e635 100644 --- a/components/bt/esp_ble_mesh/mesh_core/main.c +++ b/components/bt/esp_ble_mesh/mesh_core/main.c @@ -413,6 +413,10 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers) provisioner_pb_gatt_enable(); } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + bt_mesh_friend_init(); + } + provisioner_en = true; return 0; @@ -437,6 +441,10 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers) bt_mesh_scan_disable(); } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + bt_mesh_friend_clear_net_idx(BLE_MESH_KEY_ANY); + } + provisioner_en = false; return 0; diff --git a/components/bt/esp_ble_mesh/mesh_core/net.c b/components/bt/esp_ble_mesh/mesh_core/net.c index 55ba8afb1..640ad61ae 100644 --- a/components/bt/esp_ble_mesh/mesh_core/net.c +++ b/components/bt/esp_ble_mesh/mesh_core/net.c @@ -1123,18 +1123,14 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len, continue; } -#if CONFIG_BLE_MESH_NODE - if (bt_mesh_is_provisioned()) { #if (defined(CONFIG_BLE_MESH_LOW_POWER) || defined(CONFIG_BLE_MESH_FRIEND)) - if (!friend_decrypt(sub, data, data_len, rx, buf)) { - rx->friend_cred = 1; - rx->ctx.net_idx = sub->net_idx; - rx->sub = sub; - return true; - } -#endif + if (!friend_decrypt(sub, data, data_len, rx, buf)) { + rx->friend_cred = 1; + rx->ctx.net_idx = sub->net_idx; + rx->sub = sub; + return true; } -#endif /* CONFIG_BLE_MESH_NODE */ +#endif if (NID(data) == sub->keys[0].nid && !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy, diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c index 7b40331a0..8fc1d4b3c 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c @@ -28,6 +28,7 @@ #include "adv.h" #include "net.h" #include "access.h" +#include "friend.h" #include "provisioner_prov.h" #include "proxy_client.h" @@ -142,6 +143,10 @@ int provisioner_node_reset(int node_index) } } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + bt_mesh_friend_remove_lpn(node->unicast_addr); + } + osi_free(mesh_nodes[node_index]); mesh_nodes[node_index] = NULL; diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.c b/components/bt/esp_ble_mesh/mesh_core/transport.c index bedfbe3f6..2235f7719 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.c +++ b/components/bt/esp_ble_mesh/mesh_core/transport.c @@ -139,32 +139,30 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu, net_buf_add_mem(buf, sdu->data, sdu->len); - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { - if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, - tx->src, tx->ctx->addr, - NULL, 1)) { - if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - BT_ERR("Not enough space in Friend Queue"); - net_buf_unref(buf); - return -ENOBUFS; - } else { - BT_WARN("No space in Friend Queue"); - goto send; - } - } - - if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE, - NULL, 1, &buf->b) && - BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - /* PDUs for a specific Friend should only go - * out through the Friend Queue. - */ + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx, + tx->src, tx->ctx->addr, + NULL, 1)) { + if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + BT_ERR("Not enough space in Friend Queue"); net_buf_unref(buf); - send_cb_finalize(cb, cb_data); - return 0; + return -ENOBUFS; + } else { + BT_WARN("No space in Friend Queue"); + goto send; } } + + if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE, + NULL, 1, &buf->b) && + BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + /* PDUs for a specific Friend should only go + * out through the Friend Queue. + */ + net_buf_unref(buf); + send_cb_finalize(cb, cb_data); + return 0; + } } send: @@ -413,27 +411,25 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, net_buf_add_mem(seg, sdu->data, len); net_buf_simple_pull(sdu, len); - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { - enum bt_mesh_friend_pdu_type type; + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + enum bt_mesh_friend_pdu_type type; - if (seg_o == tx->seg_n) { - type = BLE_MESH_FRIEND_PDU_COMPLETE; - } else { - type = BLE_MESH_FRIEND_PDU_PARTIAL; - } + if (seg_o == tx->seg_n) { + type = BLE_MESH_FRIEND_PDU_COMPLETE; + } else { + type = BLE_MESH_FRIEND_PDU_PARTIAL; + } - if (bt_mesh_friend_enqueue_tx(net_tx, type, - &tx->seq_auth, - tx->seg_n + 1, - &seg->b) && - BLE_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) { - /* PDUs for a specific Friend should only go - * out through the Friend Queue. - */ - net_buf_unref(seg); - continue; - } + if (bt_mesh_friend_enqueue_tx(net_tx, type, + &tx->seq_auth, + tx->seg_n + 1, + &seg->b) && + BLE_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) { + /* PDUs for a specific Friend should only go + * out through the Friend Queue. + */ + net_buf_unref(seg); + continue; } } @@ -904,24 +900,24 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr, return 0; } - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { - switch (ctl_op) { - case TRANS_CTL_OP_FRIEND_POLL: - return bt_mesh_friend_poll(rx, buf); - case TRANS_CTL_OP_FRIEND_REQ: - return bt_mesh_friend_req(rx, buf); - case TRANS_CTL_OP_FRIEND_CLEAR: - return bt_mesh_friend_clear(rx, buf); - case TRANS_CTL_OP_FRIEND_CLEAR_CFM: - return bt_mesh_friend_clear_cfm(rx, buf); - case TRANS_CTL_OP_FRIEND_SUB_ADD: - return bt_mesh_friend_sub_add(rx, buf); - case TRANS_CTL_OP_FRIEND_SUB_REM: - return bt_mesh_friend_sub_rem(rx, buf); - } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { + switch (ctl_op) { + case TRANS_CTL_OP_FRIEND_POLL: + return bt_mesh_friend_poll(rx, buf); + case TRANS_CTL_OP_FRIEND_REQ: + return bt_mesh_friend_req(rx, buf); + case TRANS_CTL_OP_FRIEND_CLEAR: + return bt_mesh_friend_clear(rx, buf); + case TRANS_CTL_OP_FRIEND_CLEAR_CFM: + return bt_mesh_friend_clear_cfm(rx, buf); + case TRANS_CTL_OP_FRIEND_SUB_ADD: + return bt_mesh_friend_sub_add(rx, buf); + case TRANS_CTL_OP_FRIEND_SUB_REM: + return bt_mesh_friend_sub_rem(rx, buf); } + } + if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { #if defined(CONFIG_BLE_MESH_LOW_POWER) if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) { return bt_mesh_lpn_friend_offer(rx, buf); @@ -1530,15 +1526,13 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) net_buf_simple_restore(buf, &state); - if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) { - if (seq_auth == TRANS_SEQ_AUTH_NVAL) { - bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL, - seg_count, buf); - } else { - bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth, - seg_count, buf); - } + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) { + if (seq_auth == TRANS_SEQ_AUTH_NVAL) { + bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL, + seg_count, buf); + } else { + bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth, + seg_count, buf); } }