From c6286529eb6f50047fdf4e1d3fd79e9cae2a8875 Mon Sep 17 00:00:00 2001 From: lly Date: Tue, 17 Sep 2019 16:56:52 +0800 Subject: [PATCH] ble_mesh: add ble mesh friend node event --- components/bt/esp_ble_mesh/Kconfig.in | 1 + .../bt/esp_ble_mesh/api/esp_ble_mesh_defs.h | 24 +++++++++- .../bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c | 40 +++++++++++++++++ components/bt/esp_ble_mesh/mesh_core/friend.c | 45 ++++++++++++++++--- .../mesh_core/include/mesh_main.h | 9 ++++ 5 files changed, 112 insertions(+), 7 deletions(-) diff --git a/components/bt/esp_ble_mesh/Kconfig.in b/components/bt/esp_ble_mesh/Kconfig.in index f051988fe..7aac6ff67 100644 --- a/components/bt/esp_ble_mesh/Kconfig.in +++ b/components/bt/esp_ble_mesh/Kconfig.in @@ -578,6 +578,7 @@ if BLE_MESH config BLE_MESH_FRIEND bool "Support for acting as a Friend Node" + select BLE_MESH_NODE help Enable this option to be able to act as a Friend Node. diff --git a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index 3ecdf0548..f6905289b 100644 --- a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -1246,6 +1246,8 @@ typedef enum { ESP_BLE_MESH_LPN_POLL_COMP_EVT, /*!< Low Power Node send Friend Poll completion event */ ESP_BLE_MESH_LPN_FRIENDSHIP_ESTABLISH_EVT, /*!< Low Power Node establishes friendship event */ ESP_BLE_MESH_LPN_FRIENDSHIP_TERMINATE_EVT, /*!< Low Power Node terminates friendship event */ + ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT, /*!< Friend Node establishes friendship event */ + ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT, /*!< Friend Node terminates friendship event */ ESP_BLE_MESH_PROV_EVT_MAX, } esp_ble_mesh_prov_cb_event_t; @@ -1536,7 +1538,7 @@ typedef union { uint8_t hops; /*!< Heartbeat hops (InitTTL - RxTTL + 1) */ uint16_t feature; /*!< Bit field of currently active features of the node */ } heartbeat_msg_recv; /*!< Event parameter of ESP_BLE_MESH_HEARTBEAT_MESSAGE_RECV_EVT */ - /* + /** * @brief ESP_BLE_MESH_LPN_ENABLE_COMP_EVT */ struct ble_mesh_lpn_enable_comp_param { @@ -1566,6 +1568,26 @@ typedef union { struct ble_mesh_lpn_friendship_terminate_param { uint16_t friend_addr; /*!< Friend Node unicast address */ } lpn_friendship_terminate; /*!< Event parameter of ESP_BLE_MESH_LPN_FRIENDSHIP_TERMINATE_EVT */ + /** + * @brief ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT + */ + struct ble_mesh_friend_friendship_establish_param { + uint16_t lpn_addr; /*!< Low Power Node unciast address */ + } frnd_friendship_establish; /*!< Event parameter of ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT */ + /** + * @brief ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT + */ + struct ble_mesh_friend_friendship_terminate_param { + uint16_t lpn_addr; /*!< Low Power Node unicast address */ + /** This enum value is the reason of friendship termination on the friend node side */ + enum { + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL, /*!< Friend Offer has been sent, but Friend Offer is not received within 1 second, friendship fails to be established */ + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_POLL_TIMEOUT, /*!< Friendship is established, PollTimeout timer expires and no Friend Poll/Sub Add/Sub Remove is received */ + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_RECV_FRND_REQ, /*!< Receive Friend Request from existing Low Power Node */ + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_RECV_FRND_CLEAR, /*!< Receive Friend Clear from other friend node */ + ESP_BLE_MESH_FRND_FRIENDSHIP_TERMINATE_DISABLE, /*!< Friend feature disabled or corresponding NetKey is deleted */ + } reason; /*!< Friendship terminated reason */ + } frnd_friendship_terminate; /*!< Event parameter of ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT */ } esp_ble_mesh_prov_cb_param_t; /** 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 4af196b9f..09b33aa45 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 @@ -599,6 +599,43 @@ static void btc_ble_mesh_lpn_cb(u16_t friend_addr, bool established) } #endif /* CONFIG_BLE_MESH_LOW_POWER */ +#if CONFIG_BLE_MESH_FRIEND +void btc_ble_mesh_friend_cb(bool establish, u16_t lpn_addr, u8_t reason) +{ + esp_ble_mesh_prov_cb_param_t mesh_param = {0}; + btc_msg_t msg = {0}; + bt_status_t ret; + u8_t act; + + LOG_DEBUG("%s", __func__); + + if (!BLE_MESH_ADDR_IS_UNICAST(lpn_addr)) { + LOG_ERROR("%s, Not a unicast address", __func__); + return; + } + + if (establish) { + mesh_param.frnd_friendship_establish.lpn_addr = lpn_addr; + act = ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT; + } else { + mesh_param.frnd_friendship_terminate.lpn_addr = lpn_addr; + mesh_param.frnd_friendship_terminate.reason = reason; + act = ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT; + } + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_PROV; + msg.act = act; + + ret = btc_transfer_context(&msg, &mesh_param, + sizeof(esp_ble_mesh_prov_cb_param_t), NULL); + if (ret != BT_STATUS_SUCCESS) { + LOG_ERROR("%s btc_transfer_context failed", __func__); + } + return; +} +#endif /* CONFIG_BLE_MESH_FRIEND */ + #endif /* CONFIG_BLE_MESH_NODE */ static void btc_ble_mesh_prov_register_complete_cb(int err_code) @@ -1259,6 +1296,9 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) #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; diff --git a/components/bt/esp_ble_mesh/mesh_core/friend.c b/components/bt/esp_ble_mesh/mesh_core/friend.c index 3d637d9bd..870235e45 100644 --- a/components/bt/esp_ble_mesh/mesh_core/friend.c +++ b/components/bt/esp_ble_mesh/mesh_core/friend.c @@ -65,6 +65,18 @@ static struct friend_adv { u64_t seq_auth; } adv_pool[FRIEND_BUF_COUNT]; +enum { + BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL, + BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT, + BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_REQ, + BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_CLEAR, + BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE, +}; + +static void (*friend_cb)(bool establish, u16_t lpn_addr, u8_t reason); + + + static struct bt_mesh_adv *adv_alloc(int id) { return &adv_pool[id].adv; @@ -137,7 +149,7 @@ static s32_t recv_delay(struct bt_mesh_friend *frnd) #endif } -static void friend_clear(struct bt_mesh_friend *frnd) +static void friend_clear(struct bt_mesh_friend *frnd, u8_t reason) { int i; @@ -145,6 +157,12 @@ static void friend_clear(struct bt_mesh_friend *frnd) k_delayed_work_cancel(&frnd->timer); + if (frnd->established) { + if (friend_cb) { + friend_cb(false, frnd->lpn, reason); + } + } + friend_cred_del(frnd->net_idx, frnd->lpn); if (frnd->last) { @@ -189,7 +207,7 @@ void bt_mesh_friend_clear_net_idx(u16_t net_idx) } if (net_idx == BLE_MESH_KEY_ANY || frnd->net_idx == net_idx) { - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE); } } } @@ -262,7 +280,7 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm, sizeof(cfm), NULL, NULL, NULL); - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_CLEAR); return 0; } @@ -568,6 +586,9 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) if (!frnd->established) { BT_DBG("Friendship established with 0x%04x", frnd->lpn); frnd->established = 1U; + if (friend_cb) { + friend_cb(true, frnd->lpn, 0); + } } if (msg->fsn == frnd->fsn && frnd->last) { @@ -828,7 +849,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false); if (frnd) { BT_WARN("%s, Existing LPN re-requesting Friendship", __func__); - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_RECV_FRND_REQ); goto init_friend; } @@ -857,6 +878,13 @@ init_friend: BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums", frnd->lpn, rx->rssi, frnd->recv_delay, frnd->poll_to); + /** + * Spec says: + * After a friendship has been established, if the PreviousAddress field + * of the Friend Request message contains a valid unicast address that is + * not the Friend node’s own unicast address, then the Friend node shall + * begin sending Friend Clear messages to that unicast address. + */ if (BLE_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) && !bt_mesh_elem_find(frnd->clear.frnd)) { clear_procedure_start(frnd); @@ -1010,14 +1038,14 @@ static void friend_timeout(struct k_work *work) if (frnd->established && !frnd->pending_req) { BT_WARN("%s, Friendship lost with 0x%04x", __func__, frnd->lpn); - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT); return; } frnd->last = (void *)sys_slist_get(&frnd->queue); if (!frnd->last) { BT_WARN("%s, Friendship not established with 0x%04x", __func__, frnd->lpn); - friend_clear(frnd); + friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL); return; } @@ -1035,6 +1063,11 @@ send_last: bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd); } +void bt_mesh_friend_set_cb(void (*cb)(bool establish, u16_t lpn_addr, u8_t reason)) +{ + friend_cb = cb; +} + int bt_mesh_friend_init(void) { int i; diff --git a/components/bt/esp_ble_mesh/mesh_core/include/mesh_main.h b/components/bt/esp_ble_mesh/mesh_core/include/mesh_main.h index d92adc609..f74c68d4f 100644 --- a/components/bt/esp_ble_mesh/mesh_core/include/mesh_main.h +++ b/components/bt/esp_ble_mesh/mesh_core/include/mesh_main.h @@ -581,6 +581,15 @@ int bt_mesh_lpn_poll(void); */ void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established)); +/** @brief Register a callback for Friendship changes of friend node. + * + * Registers a callback that will be called whenever Friendship gets + * established or is terminated. + * + * @param cb Function to call when the Friendship status of friend node changes. + */ +void bt_mesh_friend_set_cb(void (*cb)(bool establish, u16_t lpn_addr, u8_t reason)); + /** * @} */