summaryrefslogtreecommitdiff
path: root/src/libs/mynewt-nimble/nimble/host
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/mynewt-nimble/nimble/host')
-rw-r--r--src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h52
-rw-r--r--src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h1
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h109
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h409
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h267
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h485
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h244
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h42
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h196
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h42
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h20
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h123
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h198
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h5
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h18
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h24
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h22
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/access.c188
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/access.h23
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c47
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h19
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c224
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c507
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h86
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c281
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h1
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c389
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c267
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h9
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c901
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c1792
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c546
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h143
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h42
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c440
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h20
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c91
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c68
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c38
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c351
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h40
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c22
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h12
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c195
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h6
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c231
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h22
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c30
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c16
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/net.c1146
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/net.h245
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c888
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c158
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c1892
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h133
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h116
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c569
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c746
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h10
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c271
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h15
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c162
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h30
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c1290
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h17
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c1226
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.c666
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.h197
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c67
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h12
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c1193
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h80
-rw-r--r--src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml280
-rw-r--r--src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h2
-rw-r--r--src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h1
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c7
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c2
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c2
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_gap.c128
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h3
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_hs.c13
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c111
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c40
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h2
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c4
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c8
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h6
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c65
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c24
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c8
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c3
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_sm.c5
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c2
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c11
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h8
-rw-r--r--src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c16
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c1
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h5
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c5
-rw-r--r--src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml9
-rw-r--r--src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c67
101 files changed, 13581 insertions, 7690 deletions
diff --git a/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h b/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h
index 20e7dab7..20f9e30d 100644
--- a/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h
+++ b/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h
@@ -39,41 +39,47 @@ extern "C" {
struct hci_le_conn_complete;
struct hci_conn_update;
+#define BLE_GAP_ADV_ITVL_MS(t) ((t) * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_SCAN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_SCAN_WIN_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_CONN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_CONN_ITVL)
+#define BLE_GAP_SUPERVISION_TIMEOUT_MS(t) ((t) / 10)
+
/** 30 ms. */
-#define BLE_GAP_ADV_FAST_INTERVAL1_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_ADV_FAST_INTERVAL1_MIN BLE_GAP_ADV_ITVL_MS(30)
/** 60 ms. */
-#define BLE_GAP_ADV_FAST_INTERVAL1_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_ADV_FAST_INTERVAL1_MAX BLE_GAP_ADV_ITVL_MS(60)
/** 100 ms. */
-#define BLE_GAP_ADV_FAST_INTERVAL2_MIN (100 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_ADV_FAST_INTERVAL2_MIN BLE_GAP_ADV_ITVL_MS(100)
/** 150 ms. */
-#define BLE_GAP_ADV_FAST_INTERVAL2_MAX (150 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_ADV_FAST_INTERVAL2_MAX BLE_GAP_ADV_ITVL_MS(150)
/** 30 ms; active scanning. */
-#define BLE_GAP_SCAN_FAST_INTERVAL_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_SCAN_FAST_INTERVAL_MIN BLE_GAP_SCAN_ITVL_MS(30)
/** 60 ms; active scanning. */
-#define BLE_GAP_SCAN_FAST_INTERVAL_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_SCAN_FAST_INTERVAL_MAX BLE_GAP_SCAN_ITVL_MS(60)
/** 11.25 ms; limited discovery interval. */
-#define BLE_GAP_LIM_DISC_SCAN_INT (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_LIM_DISC_SCAN_INT BLE_GAP_SCAN_ITVL_MS(11.25)
/** 11.25 ms; limited discovery window (not from the spec). */
-#define BLE_GAP_LIM_DISC_SCAN_WINDOW (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_LIM_DISC_SCAN_WINDOW BLE_GAP_SCAN_WIN_MS(11.25)
/** 30 ms; active scanning. */
-#define BLE_GAP_SCAN_FAST_WINDOW (30 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_SCAN_FAST_WINDOW BLE_GAP_SCAN_WIN_MS(30)
/* 30.72 seconds; active scanning. */
-#define BLE_GAP_SCAN_FAST_PERIOD (30.72 * 1000)
+#define BLE_GAP_SCAN_FAST_PERIOD BLE_GAP_SCAN_ITVL_MS(30.72)
/** 1.28 seconds; background scanning. */
-#define BLE_GAP_SCAN_SLOW_INTERVAL1 (1280 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_SCAN_SLOW_INTERVAL1 BLE_GAP_SCAN_ITVL_MS(1280)
/** 11.25 ms; background scanning. */
-#define BLE_GAP_SCAN_SLOW_WINDOW1 (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_SCAN_SLOW_WINDOW1 BLE_GAP_SCAN_WIN_MS(11.25)
/** 10.24 seconds. */
#define BLE_GAP_DISC_DUR_DFLT (10.24 * 1000)
@@ -88,18 +94,18 @@ struct hci_conn_update;
#define BLE_GAP_CONN_PAUSE_PERIPHERAL (5 * 1000)
/* 30 ms. */
-#define BLE_GAP_INITIAL_CONN_ITVL_MIN (30 * 1000 / BLE_HCI_CONN_ITVL)
+#define BLE_GAP_INITIAL_CONN_ITVL_MIN BLE_GAP_CONN_ITVL_MS(30)
/* 50 ms. */
-#define BLE_GAP_INITIAL_CONN_ITVL_MAX (50 * 1000 / BLE_HCI_CONN_ITVL)
+#define BLE_GAP_INITIAL_CONN_ITVL_MAX BLE_GAP_CONN_ITVL_MS(50)
/** Default channels mask: all three channels are used. */
#define BLE_GAP_ADV_DFLT_CHANNEL_MAP 0x07
#define BLE_GAP_INITIAL_CONN_LATENCY 0
#define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100
-#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0010
-#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0300
+#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0000
+#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0000
#define BLE_GAP_ROLE_MASTER 0
#define BLE_GAP_ROLE_SLAVE 1
@@ -1896,6 +1902,20 @@ int ble_gap_unpair(const ble_addr_t *peer_addr);
*/
int ble_gap_unpair_oldest_peer(void);
+/**
+ * Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that the
+ * peer received in input parameters is not deleted.
+ *
+ * @param peer_addr Address of the peer (not to be deleted)
+ *
+ * @return 0 on success;
+ * A BLE host HCI return code if the controller
+ * rejected the request;
+ * A BLE host core return code on unexpected
+ * error.
+ */
+int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr);
+
#define BLE_GAP_PRIVATE_MODE_NETWORK 0
#define BLE_GAP_PRIVATE_MODE_DEVICE 1
diff --git a/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h b/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h
index 8d0a4596..7b90eaf9 100644
--- a/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h
+++ b/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h
@@ -21,6 +21,7 @@
#define H_BLE_HS_LOG_
#include "modlog/modlog.h"
+#include "log/log.h"
/* Only include the logcfg header if this version of newt can generate it. */
#if MYNEWT_VAL(NEWT_FEATURE_LOGCFG)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h
index 1f99f412..9f923cb9 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h
@@ -28,14 +28,23 @@ extern "C" {
#define BT_MESH_ADDR_RELAYS 0xfffe
#define BT_MESH_KEY_UNUSED 0xffff
+#define BT_MESH_KEY_ANY 0xffff
#define BT_MESH_KEY_DEV 0xfffe
#define BT_MESH_KEY_DEV_LOCAL BT_MESH_KEY_DEV
#define BT_MESH_KEY_DEV_REMOTE 0xfffd
#define BT_MESH_KEY_DEV_ANY 0xfffc
+#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
+#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
+#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
+#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
+
#define BT_MESH_IS_DEV_KEY(key) (key == BT_MESH_KEY_DEV_LOCAL || \
key == BT_MESH_KEY_DEV_REMOTE)
+#define BT_MESH_APP_SEG_SDU_MAX 12
+#define BT_MESH_TX_SDU_MAX (CONFIG_BT_MESH_TX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
+#define BT_MESH_RX_SDU_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
/** Helper to define a mesh element within an array.
*
* In case the element has no SIG or Vendor models the helper
@@ -57,13 +66,13 @@ extern "C" {
/** Abstraction that describes a Mesh Element */
struct bt_mesh_elem {
/* Unicast Address. Set at runtime during provisioning. */
- u16_t addr;
+ uint16_t addr;
/* Location Descriptor (GATT Bluetooth Namespace Descriptors) */
- const u16_t loc;
+ const uint16_t loc;
- const u8_t model_count;
- const u8_t vnd_model_count;
+ const uint8_t model_count;
+ const uint8_t vnd_model_count;
struct bt_mesh_model * const models;
struct bt_mesh_model * const vnd_models;
@@ -132,33 +141,33 @@ struct bt_mesh_elem {
/** Message sending context. */
struct bt_mesh_msg_ctx {
/** NetKey Index of the subnet to send the message on. */
- u16_t net_idx;
+ uint16_t net_idx;
/** AppKey Index to encrypt the message with. */
- u16_t app_idx;
+ uint16_t app_idx;
/** Remote address. */
- u16_t addr;
+ uint16_t addr;
/** Destination address of a received message. Not used for sending. */
- u16_t recv_dst;
+ uint16_t recv_dst;
/** RSSI of received packet. Not used for sending. */
- s8_t recv_rssi;
+ int8_t recv_rssi;
/** Received TTL value. Not used for sending. */
- u8_t recv_ttl;
+ uint8_t recv_ttl;
/** Force sending reliably by using segment acknowledgement */
bool send_rel;
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
- u8_t send_ttl;
+ uint8_t send_ttl;
};
struct bt_mesh_model_op {
/* OpCode encoded using the BT_MESH_MODEL_OP_* macros */
- const u32_t opcode;
+ const uint32_t opcode;
/* Minimum required message length */
const size_t min_len;
@@ -324,7 +333,7 @@ struct bt_mesh_model_op {
*
* @return Transmission count (actual transmissions is N + 1).
*/
-#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (u8_t)BIT_MASK(3)))
+#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (uint8_t)BIT_MASK(3)))
/** @def BT_MESH_TRANSMIT_INT
*
@@ -375,23 +384,24 @@ struct bt_mesh_model_pub {
/** The model the context belongs to. Initialized by the stack. */
struct bt_mesh_model *mod;
- u16_t addr; /**< Publish Address. */
- u16_t key; /**< Publish AppKey Index. */
+ uint16_t addr; /**< Publish Address. */
+ uint16_t key; /**< Publish AppKey Index. */
- u8_t ttl; /**< Publish Time to Live. */
- u8_t retransmit; /**< Retransmit Count & Interval Steps. */
- u8_t period; /**< Publish Period. */
- u8_t period_div:4, /**< Divisor for the Period. */
+ uint8_t ttl; /**< Publish Time to Live. */
+ uint8_t retransmit; /**< Retransmit Count & Interval Steps. */
+ uint8_t period; /**< Publish Period. */
+ uint8_t period_div:4, /**< Divisor for the Period. */
cred:1, /**< Friendship Credentials Flag. */
+ send_rel:1,
fast_period:1,/**< Use FastPeriodDivisor */
count:3; /**< Retransmissions left. */
- u32_t period_start; /**< Start of the current period. */
+ uint32_t period_start; /**< Start of the current period. */
/** @brief Publication buffer, containing the publication message.
*
* The application is expected to initialize this with
- * a valid net_buf_simple pointer, with the help of e.g.
+ * a valid os_mbuf pointer, with the help of e.g.
* the NET_BUF_SIMPLE() macro. The publication buffer must
* contain a valid publication message before calling the
* bt_mesh_model_publish() API or after the publication's
@@ -414,6 +424,10 @@ struct bt_mesh_model_pub {
* will be called periodically and is expected to update
* @ref bt_mesh_model_pub.msg with a valid publication
* message.
+ *
+ * If the callback returns non-zero, the publication is skipped
+ * and will resume on the next periodic publishing interval.
+ *
*
* @param mod The Model the Publication Context belogs to.
*
@@ -432,16 +446,18 @@ struct bt_mesh_model_cb {
* @sa settings_handler::h_set
*
* @param model Model to set the persistent data of.
+ * @param name Name/key of the settings item.
* @param val Data from the backend.
*
* @return 0 on success, error otherwise.
*/
- int (*const settings_set)(struct bt_mesh_model *model, char *val);
+ int (*const settings_set)(struct bt_mesh_model *model,
+ const char *name, char *val);
- /** @brief Callback called when all settings have been loaded.
+ /** @brief Callback called when the mesh is started.
*
- * This handler gets called after the settings have been loaded in
- * full.
+ * This handler gets called after the node has been provisioned, or
+ * after all mesh data has been loaded from persistent storage.
*
* @sa settings_handler::h_commit
*
@@ -449,12 +465,17 @@ struct bt_mesh_model_cb {
*
* @return 0 on success, error otherwise.
*/
- int (*const settings_commit)(struct bt_mesh_model *model);
+ int (*const start)(struct bt_mesh_model *model);
/** @brief Model init callback.
*
* Called on every model instance during mesh initialization.
*
+ *
+ * If any of the model init callbacks return an error, the Mesh
+ * subsystem initialization will be aborted, and the error will be
+ * returned to the caller of @ref bt_mesh_init.
+ *
* @param model Model to be initialized.
*
* @return 0 on success, error otherwise.
@@ -466,6 +487,9 @@ struct bt_mesh_model_cb {
* Called when the mesh node is reset. All model data is deleted on
* reset, and the model should clear its state.
*
+ * @note If the model stores any persistent data, this needs to be
+ * erased manually.
+ *
* @param model Model this callback belongs to.
*/
void (*const reset)(struct bt_mesh_model *model);
@@ -474,26 +498,26 @@ struct bt_mesh_model_cb {
/** Abstraction that describes a Mesh Model instance */
struct bt_mesh_model {
union {
- const u16_t id;
+ const uint16_t id;
struct {
- u16_t company;
- u16_t id;
+ uint16_t company;
+ uint16_t id;
} vnd;
};
/* Internal information, mainly for persistent storage */
- u8_t elem_idx; /* Belongs to Nth element */
- u8_t mod_idx; /* Is the Nth model in the element */
- u16_t flags; /* Model flags for internal bookkeeping */
+ uint8_t elem_idx; /* Belongs to Nth element */
+ uint8_t mod_idx; /* Is the Nth model in the element */
+ uint16_t flags; /* Model flags for internal bookkeeping */
/* Model Publication */
struct bt_mesh_model_pub * const pub;
/* AppKey List */
- u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
+ uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
/* Subscription List (group or virtual addresses) */
- u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
+ uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
const struct bt_mesh_model_op * const op;
@@ -511,11 +535,11 @@ struct bt_mesh_model {
};
struct bt_mesh_send_cb {
- void (*start)(u16_t duration, int err, void *cb_data);
+ void (*start)(uint16_t duration, int err, void *cb_data);
void (*end)(int err, void *cb_data);
};
-void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode);
+void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode);
/** Special TTL value to request using configured default TTL */
#define BT_MESH_TTL_DEFAULT 0xff
@@ -574,7 +598,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
* if no SIG model with the given ID exists in the given element.
*/
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
- u16_t id);
+ uint16_t id);
/** @brief Find a vendor model.
*
@@ -586,7 +610,7 @@ struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
* if no vendor model with the given ID exists in the given element.
*/
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
- u16_t company, u16_t id);
+ uint16_t company, uint16_t id);
/** @brief Get whether the model is in the primary element of the device.
*
@@ -603,13 +627,14 @@ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod)
*
* @param mod Mesh model.
* @param vnd This is a vendor model.
+ * @param name Name/key of the settings item.
* @param data Model data to store, or NULL to delete any model data.
* @param data_len Length of the model data.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
- const void *data, size_t data_len);
+ const char *name, const void *data, size_t data_len);
/** @brief Let a model extend another.
*
@@ -637,9 +662,9 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod,
/** Node Composition */
struct bt_mesh_comp {
- u16_t cid;
- u16_t pid;
- u16_t vid;
+ uint16_t cid;
+ uint16_t pid;
+ uint16_t vid;
size_t elem_count;
struct bt_mesh_elem *elem;
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h
new file mode 100644
index 00000000..2c731794
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h
@@ -0,0 +1,409 @@
+/* atomic operations */
+
+/*
+ * Copyright (c) 1997-2015, Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ATOMIC_H__
+#define __ATOMIC_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef int atomic_t;
+typedef atomic_t atomic_val_t;
+
+/**
+ * @defgroup atomic_apis Atomic Services APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Atomic compare-and-set.
+ *
+ * This routine performs an atomic compare-and-set on @a target. If the current
+ * value of @a target equals @a old_value, @a target is set to @a new_value.
+ * If the current value of @a target does not equal @a old_value, @a target
+ * is left unchanged.
+ *
+ * @param target Address of atomic variable.
+ * @param old_value Original value to compare against.
+ * @param new_value New value to store.
+ * @return 1 if @a new_value is written, 0 otherwise.
+ */
+static inline int atomic_cas(atomic_t *target, atomic_val_t old_value,
+ atomic_val_t new_value)
+{
+ return __atomic_compare_exchange_n(target, &old_value, new_value,
+ 0, __ATOMIC_SEQ_CST,
+ __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic addition.
+ *
+ * This routine performs an atomic addition on @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to add.
+ *
+ * @return Previous value of @a target.
+ */
+static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic subtraction.
+ *
+ * This routine performs an atomic subtraction on @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to subtract.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic increment.
+ *
+ * This routine performs an atomic increment by 1 on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_inc(atomic_t *target)
+{
+ return atomic_add(target, 1);
+}
+
+/**
+ *
+ * @brief Atomic decrement.
+ *
+ * This routine performs an atomic decrement by 1 on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_dec(atomic_t *target)
+{
+ return atomic_sub(target, 1);
+}
+
+/**
+ *
+ * @brief Atomic get.
+ *
+ * This routine performs an atomic read on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Value of @a target.
+ */
+
+static inline atomic_val_t atomic_get(const atomic_t *target)
+{
+ return __atomic_load_n(target, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic get-and-set.
+ *
+ * This routine atomically sets @a target to @a value and returns
+ * the previous value of @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to write to @a target.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
+{
+ /* This builtin, as described by Intel, is not a traditional
+ * test-and-set operation, but rather an atomic exchange operation. It
+ * writes value into *ptr, and returns the previous contents of *ptr.
+ */
+ return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic clear.
+ *
+ * This routine atomically sets @a target to zero and returns its previous
+ * value. (Hence, it is equivalent to atomic_set(target, 0).)
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_clear(atomic_t *target)
+{
+ return atomic_set(target, 0);
+}
+
+/**
+ *
+ * @brief Atomic bitwise inclusive OR.
+ *
+ * This routine atomically sets @a target to the bitwise inclusive OR of
+ * @a target and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to OR.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic bitwise exclusive OR (XOR).
+ *
+ * This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
+ * @a target and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to XOR
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic bitwise AND.
+ *
+ * This routine atomically sets @a target to the bitwise AND of @a target
+ * and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to AND.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic bitwise NAND.
+ *
+ * This routine atomically sets @a target to the bitwise NAND of @a target
+ * and @a value. (This operation is equivalent to target = ~(target & value).)
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to NAND.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
+}
+
+ /**
+ * @brief Initialize an atomic variable.
+ *
+ * This macro can be used to initialize an atomic variable. For example,
+ * @code atomic_t my_var = ATOMIC_INIT(75); @endcode
+ *
+ * @param i Value to assign to atomic variable.
+ */
+#define ATOMIC_INIT(i) (i)
+
+ /**
+ * @cond INTERNAL_HIDDEN
+ */
+
+#define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
+#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1)))
+#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
+
+ /**
+ * INTERNAL_HIDDEN @endcond
+ */
+
+ /**
+ * @brief Define an array of atomic variables.
+ *
+ * This macro defines an array of atomic variables containing at least
+ * @a num_bits bits.
+ *
+ * @note
+ * If used from file scope, the bits of the array are initialized to zero;
+ * if used from within a function, the bits are left uninitialized.
+ *
+ * @param name Name of array of atomic variables.
+ * @param num_bits Number of bits needed.
+ */
+#define ATOMIC_DEFINE(name, num_bits) \
+ atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS]
+
+ /**
+ * @brief Atomically test a bit.
+ *
+ * This routine tests whether bit number @a bit of @a target is set or not.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return 1 if the bit was set, 0 if it wasn't.
+ */
+ static inline int
+ atomic_test_bit(const atomic_t *target, int bit)
+ {
+ atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
+
+ return (1 & (val >> (bit & (ATOMIC_BITS - 1))));
+ }
+
+ /**
+ * @brief Atomically test and clear a bit.
+ *
+ * Atomically clear bit number @a bit of @a target and return its old value.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return 1 if the bit was set, 0 if it wasn't.
+ */
+ static inline int
+ atomic_test_and_clear_bit(atomic_t *target, int bit)
+ {
+ atomic_val_t mask = ATOMIC_MASK(bit);
+ atomic_val_t old;
+
+ old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+
+ return (old & mask) != 0;
+ }
+
+ /**
+ * @brief Atomically set a bit.
+ *
+ * Atomically set bit number @a bit of @a target and return its old value.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return 1 if the bit was set, 0 if it wasn't.
+ */
+ static inline int
+ atomic_test_and_set_bit(atomic_t *target, int bit)
+ {
+ atomic_val_t mask = ATOMIC_MASK(bit);
+ atomic_val_t old;
+
+ old = atomic_or(ATOMIC_ELEM(target, bit), mask);
+
+ return (old & mask) != 0;
+ }
+
+ /**
+ * @brief Atomically clear a bit.
+ *
+ * Atomically clear bit number @a bit of @a target.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return N/A
+ */
+ static inline void
+ atomic_clear_bit(atomic_t *target, int bit)
+ {
+ atomic_val_t mask = ATOMIC_MASK(bit);
+
+ atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+ }
+
+ /**
+ * @brief Atomically set a bit.
+ *
+ * Atomically set bit number @a bit of @a target.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return N/A
+ */
+ static inline void
+ atomic_set_bit(atomic_t *target, int bit)
+ {
+ atomic_val_t mask = ATOMIC_MASK(bit);
+
+ atomic_or(ATOMIC_ELEM(target, bit), mask);
+ }
+
+/**
+* @brief Atomically set a bit to a given value.
+*
+* Atomically set bit number @a bit of @a target to value @a val.
+* The target may be a single atomic variable or an array of them.
+*
+* @param target Address of atomic variable or array.
+* @param bit Bit number (starting from 0).
+* @param val true for 1, false for 0.
+*
+* @return N/A
+*/
+static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
+{
+ atomic_val_t mask = ATOMIC_MASK(bit);
+
+ if (val) {
+ (void)atomic_or(ATOMIC_ELEM(target, bit), mask);
+ } else {
+ (void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+ }
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ATOMIC_H__ */
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h
new file mode 100644
index 00000000..8f9a6bc9
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2019 Tobias Svehagen
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _BLUETOOTH_MESH_CDB_H_
+#define _BLUETOOTH_MESH_CDB_H_
+
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(BLE_MESH_CDB)
+#define NODE_COUNT CONFIG_BT_MESH_NODE_COUNT
+#define SUBNET_COUNT CONFIG_BT_MESH_SUBNET_COUNT
+#define APP_KEY_COUNT CONFIG_BT_MESH_APP_KEY_COUNT
+#else
+#define NODE_COUNT 0
+#define SUBNET_COUNT 0
+#define APP_KEY_COUNT 0
+#endif
+
+#include "atomic.h"
+
+enum {
+ BT_MESH_CDB_NODE_CONFIGURED,
+ BT_MESH_CDB_NODE_BLACKLISTED,
+
+ BT_MESH_CDB_NODE_FLAG_COUNT
+};
+
+struct bt_mesh_cdb_node {
+ uint8_t uuid[16];
+ uint16_t addr;
+ uint16_t net_idx;
+ uint8_t num_elem;
+ uint8_t dev_key[16];
+
+ ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT);
+};
+
+struct bt_mesh_cdb_subnet {
+ uint16_t net_idx;
+
+ bool kr_flag;
+ uint8_t kr_phase;
+
+ struct {
+ uint8_t net_key[16];
+ } keys[2];
+};
+
+struct bt_mesh_cdb_app_key {
+ uint16_t net_idx;
+ uint16_t app_idx;
+
+ struct {
+ uint8_t app_key[16];
+ } keys[2];
+};
+
+enum {
+ BT_MESH_CDB_VALID,
+ BT_MESH_CDB_SUBNET_PENDING,
+ BT_MESH_CDB_KEYS_PENDING,
+ BT_MESH_CDB_NODES_PENDING,
+ BT_MESH_CDB_IVU_IN_PROGRESS,
+
+ BT_MESH_CDB_FLAG_COUNT,
+};
+
+struct bt_mesh_cdb {
+ uint32_t iv_index;
+
+ ATOMIC_DEFINE(flags, BT_MESH_CDB_FLAG_COUNT);
+
+ struct bt_mesh_cdb_node nodes[NODE_COUNT];
+ struct bt_mesh_cdb_subnet subnets[SUBNET_COUNT];
+ struct bt_mesh_cdb_app_key app_keys[APP_KEY_COUNT];
+};
+
+extern struct bt_mesh_cdb bt_mesh_cdb;
+
+/** @brief Create the Mesh Configuration Database.
+ *
+ * Create and initialize the Mesh Configuration Database. A primary subnet,
+ * ie one with NetIdx 0, will be added and the provided key will be used as
+ * NetKey for that subnet.
+ *
+ * @param key The NetKey to be used for the primary subnet.
+ *
+ * @return 0 on success or negative error code on failure.
+ */
+int bt_mesh_cdb_create(const uint8_t key[16]);
+
+/** @brief Clear the Mesh Configuration Database.
+ *
+ * Remove all nodes, subnets and app-keys stored in the database and mark
+ * the database as invalid. The data will be cleared from persistent storage
+ * if CONFIG_BT_SETTINGS is enabled.
+ */
+void bt_mesh_cdb_clear(void);
+
+/** @brief Set and store the IV Index and IV Update flag.
+ *
+ * The IV Index stored in the CDB will be the one used during provisioning
+ * of new nodes. This function is generally only used from inside the stack.
+ *
+ * This function will store the data to persistent storage if
+ * CONFIG_BT_SETTINGS is enabled.
+ *
+ * @param iv_index The new IV Index to use.
+ * @param iv_update True if there is an ongoing IV Update procedure.
+ */
+void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update);
+
+/** @brief Allocate a node.
+ *
+ * Allocate a new node in the CDB.
+ *
+ * @param uuid UUID of the node.
+ * @param addr Address of the node's primary element. If 0, the lowest
+ * possible address available will be assigned to the node.
+ * @param num_elem Number of elements that the node has.
+ * @param net_idx NetIdx that the node was provisioned to.
+ *
+ * @return The new node or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem, uint16_t net_idx);
+
+/** @brief Delete a node.
+ *
+ * Delete a node from the CDB.
+ *
+ * @param node The node to be deleted.
+ * @param store If true, the node will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store);
+
+/** @brief Get a node by address.
+ *
+ * Try to find the node that has the provided address assigned to one of its
+ * elements.
+ *
+ * @param addr Address of the element to look for.
+ *
+ * @return The node that has an element with address addr or NULL if no such
+ * node exists.
+ */
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr);
+
+/** @brief Store node to persistent storage.
+ *
+ * @param node Node to be stored.
+ */
+void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node);
+
+enum {
+ BT_MESH_CDB_ITER_STOP = 0,
+ BT_MESH_CDB_ITER_CONTINUE,
+};
+
+/** @typedef bt_mesh_cdb_node_func_t
+ * @brief Node iterator callback.
+ *
+ * @param node Node found.
+ * @param user_data Data given.
+ *
+ * @return BT_MESH_CDB_ITER_CONTINUE to continue to iterate through the nodes
+ * or BT_MESH_CDB_ITER_STOP to stop.
+ */
+typedef uint8_t (*bt_mesh_cdb_node_func_t)(struct bt_mesh_cdb_node *node,
+ void *user_data);
+
+/** @brief Node iterator.
+ *
+ * Iterate nodes in the Mesh Configuration Database. The callback function
+ * will only be called for valid, ie allocated, nodes.
+ *
+ * @param func Callback function.
+ * @param user_data Data to pass to the callback.
+ */
+void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data);
+
+/** @brief Allocate a subnet.
+ *
+ * Allocate a new subnet in the CDB.
+ *
+ * @param net_idx NetIdx of the subnet.
+ *
+ * @return The new subnet or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx);
+
+/** @brief Delete a subnet.
+ *
+ * Delete a subnet from the CDB.
+ *
+ * @param sub The subnet to be deleted.
+ * @param store If true, the subnet will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store);
+
+/** @brief Get a subnet by NetIdx
+ *
+ * Try to find the subnet with the specified NetIdx.
+ *
+ * @param net_idx NetIdx of the subnet to look for.
+ *
+ * @return The subnet with the specified NetIdx or NULL if no such subnet
+ * exists.
+ */
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx);
+
+/** @brief Store subnet to persistent storage.
+ *
+ * @param sub Subnet to be stored.
+ */
+void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub);
+
+/** @brief Get the flags for a subnet
+ *
+ * @param sub The subnet to get flags for.
+ *
+ * @return The flags for the subnet.
+ */
+uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub);
+
+
+/** @brief Allocate an application key.
+ *
+ * Allocate a new application key in the CDB.
+ *
+ * @param net_idx NetIdx of NetKey that the application key is bound to.
+ * @param app_idx AppIdx of the application key.
+ *
+ * @return The new application key or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
+ uint16_t app_idx);
+
+/** @brief Delete an application key.
+ *
+ * Delete an application key from the CDB.
+ *
+ * @param key The application key to be deleted.
+ * @param store If true, the key will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store);
+
+/** @brief Get an application key by AppIdx
+ *
+ * Try to find the application key with the specified AppIdx.
+ *
+ * @param app_idx AppIdx of the application key to look for.
+ *
+ * @return The application key with the specified AppIdx or NULL if no such key
+ * exists.
+ */
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx);
+
+/** @brief Store application key to persistent storage.
+ *
+ * @param key Application key to be stored.
+ */
+void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key);
+
+#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */ \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h
new file mode 100644
index 00000000..378f0a0a
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h
@@ -0,0 +1,485 @@
+/** @file
+ * @brief Bluetooth Mesh Runtime Configuration APIs.
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _BT_MESH_CFG_H_
+#define _BT_MESH_CFG_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <sys/types.h>
+
+/**
+ * @brief Bluetooth Mesh Runtime Configuration API
+ * @defgroup bt_mesh_cfg Bluetooth Mesh Runtime Configuration
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Bluetooth Mesh Feature states */
+enum bt_mesh_feat_state {
+ /** Feature is supported, but disabled. */
+ BT_MESH_FEATURE_DISABLED,
+ /** Feature is supported and enabled. */
+ BT_MESH_FEATURE_ENABLED,
+ /** Feature is not supported, and cannot be enabled. */
+ BT_MESH_FEATURE_NOT_SUPPORTED,
+};
+
+/* Legacy feature defines */
+#define BT_MESH_RELAY_DISABLED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_RELAY_ENABLED BT_MESH_FEATURE_ENABLED
+#define BT_MESH_RELAY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_BEACON_DISABLED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_BEACON_ENABLED BT_MESH_FEATURE_ENABLED
+
+#define BT_MESH_GATT_PROXY_DISABLED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_GATT_PROXY_ENABLED BT_MESH_FEATURE_ENABLED
+#define BT_MESH_GATT_PROXY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_FRIEND_DISABLED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_FRIEND_ENABLED BT_MESH_FEATURE_ENABLED
+#define BT_MESH_FRIEND_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_NODE_IDENTITY_STOPPED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_NODE_IDENTITY_RUNNING BT_MESH_FEATURE_ENABLED
+#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+/** @brief Enable or disable sending of the Secure Network Beacon.
+ *
+ * @param beacon New Secure Network Beacon state.
+ */
+void bt_mesh_beacon_set(bool beacon);
+
+/** @brief Get the current Secure Network Beacon state.
+ *
+ * @returns Whether the Secure Network Beacon feature is enabled.
+ */
+bool bt_mesh_beacon_enabled(void);
+
+/** @brief Set the default TTL value.
+ *
+ * The default TTL value is used when no explicit TTL value is set. Models will
+ * use the default TTL value when @ref bt_mesh_msg_ctx::send_ttl is
+ * @ref BT_MESH_TTL_DEFAULT.
+ *
+ * @param default_ttl The new default TTL value. Valid values are 0x00 and 0x02
+ * to @ref BT_MESH_TTL_MAX.
+ *
+ * @retval 0 Successfully set the default TTL value.
+ * @retval -EINVAL Invalid TTL value.
+ */
+int bt_mesh_default_ttl_set(uint8_t default_ttl);
+
+/** @brief Get the current default TTL value.
+ *
+ * @return The current default TTL value.
+ */
+uint8_t bt_mesh_default_ttl_get(void);
+
+/** @brief Set the Network Transmit parameters.
+ *
+ * The Network Transmit parameters determine the parameters local messages are
+ * transmitted with.
+ *
+ * @see BT_MESH_TRANSMIT
+ *
+ * @param xmit New Network Transmit parameters. Use @ref BT_MESH_TRANSMIT for
+ * encoding.
+ */
+void bt_mesh_net_transmit_set(uint8_t xmit);
+
+/** @brief Get the current Network Transmit parameters.
+ *
+ * The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
+ * used to decode the Network Transmit parameters.
+ *
+ * @return The current Network Transmit parameters.
+ */
+uint8_t bt_mesh_net_transmit_get(void);
+
+/** @brief Configure the Relay feature.
+ *
+ * Enable or disable the Relay feature, and configure the parameters to
+ * transmit relayed messages with.
+ *
+ * Support for the Relay feature must be enabled through the
+ * @c CONFIG_BT_MESH_RELAY configuration option.
+ *
+ * @see BT_MESH_TRANSMIT
+ *
+ * @param relay New Relay feature state. Must be one of
+ * @ref BT_MESH_FEATURE_ENABLED and
+ * @ref BT_MESH_FEATURE_DISABLED.
+ * @param xmit New Relay retransmit parameters. Use @ref BT_MESH_TRANSMIT for
+ * encoding.
+ *
+ * @retval 0 Successfully changed the Relay configuration.
+ * @retval -ENOTSUP The Relay feature is not supported.
+ * @retval -EINVAL Invalid parameter.
+ * @retval -EALREADY Already using the given parameters.
+ */
+int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit);
+
+/** @brief Get the current Relay feature state.
+ *
+ * @returns The Relay feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_relay_get(void);
+
+/** @brief Get the current Relay Retransmit parameters.
+ *
+ * The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
+ * used to decode the Relay Retransmit parameters.
+ *
+ * @return The current Relay Retransmit parameters, or 0 if relay is not
+ * supported.
+ */
+uint8_t bt_mesh_relay_retransmit_get(void);
+
+/** @brief Enable or disable the GATT Proxy feature.
+ *
+ * Support for the GATT Proxy feature must be enabled through the
+ * @c CONFIG_BT_MESH_GATT_PROXY configuration option.
+ *
+ * @note The GATT Proxy feature only controls a Proxy node's ability to relay
+ * messages to the mesh network. A node that supports GATT Proxy will
+ * still advertise Connectable Proxy beacons, even if the feature is
+ * disabled. The Proxy feature can only be fully disabled through compile
+ * time configuration.
+ *
+ * @param gatt_proxy New GATT Proxy state. Must be one of
+ * @ref BT_MESH_FEATURE_ENABLED and
+ * @ref BT_MESH_FEATURE_DISABLED.
+ *
+ * @retval 0 Successfully changed the GATT Proxy feature state.
+ * @retval -ENOTSUP The GATT Proxy feature is not supported.
+ * @retval -EINVAL Invalid parameter.
+ * @retval -EALREADY Already in the given state.
+ */
+int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy);
+
+/** @brief Get the current GATT Proxy state.
+ *
+ * @returns The GATT Proxy feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void);
+
+/** @brief Enable or disable the Friend feature.
+ *
+ * Any active friendships will be terminated immediately if the Friend feature
+ * is disabled.
+ *
+ * Support for the Friend feature must be enabled through the
+ * @c CONFIG_BT_MESH_FRIEND configuration option.
+ *
+ * @param friendship New Friend feature state. Must be one of
+ * @ref BT_MESH_FEATURE_ENABLED and
+ * @ref BT_MESH_FEATURE_DISABLED.
+ *
+ * @retval 0 Successfully changed the Friend feature state.
+ * @retval -ENOTSUP The Friend feature is not supported.
+ * @retval -EINVAL Invalid parameter.
+ * @retval -EALREADY Already in the given state.
+ */
+int bt_mesh_friend_set(enum bt_mesh_feat_state friendship);
+
+/** @brief Get the current Friend state.
+ *
+ * @returns The Friend feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_friend_get(void);
+
+/**
+ * @brief Bluetooth Mesh Subnet Configuration
+ * @defgroup bt_mesh_cfg_subnet Bluetooth Mesh Subnet Configuration
+ * @{
+ */
+
+/** @brief Add a Subnet.
+ *
+ * Adds a subnet with the given network index and network key to the list of
+ * known Subnets. All messages sent on the given Subnet will be processed by
+ * this node, and the node may send and receive Network Beacons on the given
+ * Subnet.
+ *
+ * @param net_idx Network index.
+ * @param key Root network key of the Subnet. All other keys are derived
+ * from this.
+ *
+ * @retval STATUS_SUCCESS The Subnet was successfully added.
+ * @retval STATUS_INSUFF_RESOURCES No room for this Subnet.
+ * @retval STATUS_UNSPECIFIED The Subnet couldn't be created for some reason.
+ */
+uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16]);
+
+/** @brief Update the given Subnet.
+ *
+ * Starts the Key Refresh procedure for this Subnet by adding a second set of
+ * encryption keys. The Subnet will continue sending with the old key (but
+ * receiving messages using both) until the Subnet enters Key Refresh phase 2.
+ *
+ * This allows a network configurator to replace old network and application
+ * keys for the entire network, effectively removing access for all nodes that
+ * aren't given the new keys.
+ *
+ * @param net_idx Network index.
+ * @param key New root network key of the Subnet.
+ *
+ * @retval STATUS_SUCCESS The Subnet was updated with a second key.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_IDX_ALREADY_STORED The @c key value is the same as the
+ * current key.
+ * @retval STATUS_CANNOT_UPDATE The Subnet cannot be updated for some reason.
+ */
+uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16]);
+
+/** @brief Delete a Subnet.
+ *
+ * Removes the Subnet with the given network index from the node. The node will
+ * stop sending Network Beacons with the given Subnet, and can no longer
+ * process messages on this Subnet.
+ *
+ * All Applications bound to this Subnet are also deleted.
+ *
+ * @param net_idx Network index.
+ *
+ * @retval STATUS_SUCCESS The Subnet was deleted.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_del(uint16_t net_idx);
+
+/** @brief Check whether a Subnet is known.
+ *
+ * @param net_idx Network index
+ *
+ * @return true if a Subnet with the given index exists, false otherwise.
+ */
+bool bt_mesh_subnet_exists(uint16_t net_idx);
+
+/** @brief Set the Subnet's Key Refresh phase.
+ *
+ * The Key Refresh procedure is started by updating the Subnet keys through
+ * @ref bt_mesh_subnet_update. This puts the Subnet in Key Refresh Phase 1.
+ * Once all nodes have received the new Subnet key, Key Refresh Phase 2 can be
+ * activated through this function to start transmitting with the new network
+ * key. Finally, to revoke the old key, set the Key Refresh Phase to 3. This
+ * removes the old keys from the node, and returns the Subnet back to normal
+ * single-key operation with the new key set.
+ *
+ * @param net_idx Network index.
+ * @param phase Pointer to the new Key Refresh phase. Will return the actual
+ * Key Refresh phase after updating.
+ *
+ * @retval STATUS_SUCCESS The Key Refresh phase of the Subnet was successfully
+ * changed.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_CANNOT_UPDATE The given phase change is invalid.
+ */
+uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase);
+
+/** @brief Get the Subnet's Key Refresh phase.
+ *
+ * @param net_idx Network index.
+ * @param phase Pointer to the Key Refresh variable to fill.
+ *
+ * @retval STATUS_SUCCESS Successfully populated the @c phase variable.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase);
+
+/** @brief Set the Node Identity state of the Subnet.
+ *
+ * The Node Identity state of a Subnet determines whether the Subnet advertises
+ * connectable Node Identity beacons for Proxy Clients to connect to.
+ * Once started, the Node Identity beacon runs for 60 seconds, or until it is
+ * stopped.
+ *
+ * This function serves the same purpose as @ref bt_mesh_proxy_identity_enable,
+ * but only acts on a single Subnet.
+ *
+ * GATT Proxy support must be enabled through
+ * @option{CONFIG_BT_MESH_GATT_PROXY}.
+ *
+ * @param net_idx Network index.
+ * @param node_id New Node Identity state, must be either @ref
+ * BT_MESH_FEATURE_ENABLED or @ref BT_MESH_FEATURE_DISABLED.
+ *
+ * @retval STATUS_SUCCESS Successfully set the Node Identity state of the
+ * Subnet.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_FEAT_NOT_SUPP The Node Identity feature is not supported.
+ * @retval STATUS_CANNOT_SET Couldn't set the Node Identity state.
+ */
+uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
+ enum bt_mesh_feat_state node_id);
+
+/** @brief Get the Node Identity state of the Subnet.
+ *
+ * @param net_idx Network index.
+ * @param node_id Node Identity variable to fill.
+ *
+ * @retval STATUS_SUCCESS Successfully populated the @c node_id variable.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
+ enum bt_mesh_feat_state *node_id);
+
+/** @brief Get a list of all known Subnet indexes.
+ *
+ * Builds a list of all known Subnet indexes in the @c net_idxs array.
+ * If the @c net_idxs array is smaller than the list of known Subnets, this
+ * function fills all available entries and returns @c -ENOMEM. In this
+ * case, the next @c max entries of the list can be read out by calling
+ * @code
+ * bt_mesh_subnets_get(list, max, max);
+ * @endcode
+ *
+ * Note that any changes to the Subnet list between calls to this function
+ * could change the order and number of entries in the list.
+ *
+ * @param net_idxs Array to fill.
+ * @param max Max number of indexes to return.
+ * @param skip Number of indexes to skip. Enables batched processing of the
+ * list.
+ *
+ * @return The number of indexes added to the @c net_idxs array, or @c -ENOMEM
+ * if the number of known Subnets exceeds the @c max parameter.
+ */
+ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip);
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Bluetooth Mesh Application Configuration
+ * @defgroup bt_mesh_cfg_app Bluetooth Mesh Application Configuration
+ * @{
+ */
+
+/** @brief Add an Application key.
+ *
+ * Adds the Application with the given index to the list of known applications.
+ * Allows the node to send and receive model messages encrypted with this
+ * Application key.
+ *
+ * Every Application is bound to a specific Subnet. The node must know the
+ * Subnet the Application is bound to before it can add the Application.
+ *
+ * @param app_idx Application index.
+ * @param net_idx Network index the Application is bound to.
+ * @param key Application key value.
+ *
+ * @retval STATUS_SUCCESS The Application was successfully added.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_INSUFF_RESOURCES There's no room for storing this
+ * Application.
+ * @retval STATUS_INVALID_BINDING This AppIdx is already bound to another
+ * Subnet.
+ * @retval STATUS_IDX_ALREADY_STORED This AppIdx is already stored with a
+ * different key value.
+ * @retval STATUS_CANNOT_SET Cannot set the Application key for some reason.
+ */
+uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t key[16]);
+
+/** @brief Update an Application key.
+ *
+ * Update an Application with a second Application key, as part of the
+ * Key Refresh procedure of the bound Subnet. The node will continue
+ * transmitting with the old application key (but receiving on both) until the
+ * Subnet enters Key Refresh phase 2. Once the Subnet enters Key Refresh phase
+ * 3, the old application key will be deleted.
+ *
+ * @note The Application key can only be updated if the bound Subnet is in Key
+ * Refresh phase 1.
+ *
+ * @param app_idx Application index.
+ * @param net_idx Network index the Application is bound to, or
+ * @ref BT_MESH_KEY_ANY to skip the binding check.
+ * @param key New key value.
+ *
+ * @retval STATUS_SUCCESS The Application key was successfully updated.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
+ * @retval STATUS_CANNOT_UPDATE The Application key cannot be updated for some
+ * reason.
+ * @retval STATUS_IDX_ALREADY_STORED This AppIdx is already updated with a
+ * different key value.
+ */
+uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t key[16]);
+
+/** @brief Delete an Application key.
+ *
+ * All models bound to this application will remove this binding.
+ * All models publishing with this application will stop publishing.
+ *
+ * @param app_idx Application index.
+ * @param net_idx Network index.
+ *
+ * @retval STATUS_SUCCESS The Application key was successfully deleted.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
+ */
+uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx);
+
+/** @brief Check if an Application key is known.
+ *
+ * @param app_idx Application index.
+ *
+ * @return true if the Application is known, false otherwise.
+ */
+bool bt_mesh_app_key_exists(uint16_t app_idx);
+
+/** @brief Get a list of all known Application key indexes.
+ *
+ * Builds a list of all Application indexes for the given network index in the
+ * @c app_idxs array. If the @c app_idxs array cannot fit all bound
+ * Applications, this function fills all available entries and returns @c
+ * -ENOMEM. In this case, the next @c max entries of the list can be read out
+ * by calling
+ * @code
+ * bt_mesh_app_keys_get(net_idx, list, max, max);
+ * @endcode
+ *
+ * Note that any changes to the Application key list between calls to this
+ * function could change the order and number of entries in the list.
+ *
+ * @param net_idx Network Index to get the Applications of, or @ref
+ * BT_MESH_KEY_ANY to get all Applications.
+ * @param app_idxs Array to fill.
+ * @param max Max number of indexes to return.
+ * @param skip Number of indexes to skip. Enables batched processing of the
+ * list.
+ *
+ * @return The number of indexes added to the @c app_idxs array, or @c -ENOMEM
+ * if the number of known Applications exceeds the @c max parameter.
+ */
+ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
+ off_t skip);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* _BT_MESH_CFG_H_ */ \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h
index 7dc237be..bd2f9fe5 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h
@@ -26,7 +26,7 @@ struct bt_mesh_cfg_cli {
struct bt_mesh_model *model;
struct k_sem op_sync;
- u32_t op_pending;
+ uint32_t op_pending;
void *op_param;
};
@@ -37,45 +37,81 @@ extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb;
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_op, NULL, \
cli_data, &bt_mesh_cfg_cli_cb)
-int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
- u8_t *status, struct os_mbuf *comp);
+int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status);
-int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status);
+int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
+ uint8_t *status, struct os_mbuf *comp);
-int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
+int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
-int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl);
+int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
-int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl);
+int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl);
-int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status);
+int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl);
-int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
+int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
-int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status);
+int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
-int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
- u8_t *status);
+int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
-int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
- u8_t *transmit);
+int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
+ uint8_t *status);
-int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
- u8_t new_transmit, u8_t *status, u8_t *transmit);
+int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
+ uint8_t *transmit);
-int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
- const u8_t net_key[16], u8_t *status);
+int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
+ uint8_t val, uint8_t *transmit);
-int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
- u16_t key_app_idx, const u8_t app_key[16],
- u8_t *status);
+int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
+ uint8_t *transmit);
-int bt_mesh_cfg_mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u8_t *status);
+int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
+ uint8_t new_transmit, uint8_t *status, uint8_t *transmit);
-int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u16_t cid,
- u8_t *status);
+int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ const uint8_t net_key[16], uint8_t *status);
+
+int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
+ size_t *key_cnt);
+
+int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint8_t *status);
+
+int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ uint16_t key_app_idx, const uint8_t app_key[16],
+ uint8_t *status);
+
+int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ uint8_t *status, uint16_t *keys, size_t *key_cnt);
+
+int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status);
+
+int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status);
+
+int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t mod_app_idx,
+ uint16_t mod_id, uint8_t *status);
+
+int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+ uint8_t *status);
+
+int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t mod_app_idx, uint16_t mod_id,
+ uint16_t cid, uint8_t *status);
+
+int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint8_t *status, uint16_t *apps,
+ size_t *app_cnt);
+
+int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status,
+ uint16_t *apps, size_t *app_cnt);
/** @def BT_MESH_PUB_PERIOD_100MS
*
@@ -120,109 +156,117 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
#define BT_MESH_PUB_PERIOD_10MIN(steps) (((steps) & BIT_MASK(6)) | (3 << 6))
struct bt_mesh_cfg_mod_pub {
- u16_t addr;
- u16_t app_idx;
+ uint16_t addr;
+ uint16_t app_idx;
bool cred_flag;
- u8_t ttl;
- u8_t period;
- u8_t transmit;
+ uint8_t ttl;
+ uint8_t period;
+ uint8_t transmit;
};
-int bt_mesh_cfg_mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
- u8_t *status);
+int bt_mesh_cfg_mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
+ uint8_t *status);
+
+int bt_mesh_cfg_mod_pub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid,
+ struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
+
+int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
+ uint8_t *status);
-int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
+int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid,
+ struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
-int bt_mesh_cfg_mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
- u8_t *status);
+int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
-int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
+int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
+ uint8_t *status);
-int bt_mesh_cfg_mod_sub_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status);
+int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
-int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid,
- u8_t *status);
+int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
+ uint8_t *status);
-int bt_mesh_cfg_mod_sub_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status);
+int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
-int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid,
- u8_t *status);
+int bt_mesh_cfg_mod_sub_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t sub_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status);
-int bt_mesh_cfg_mod_sub_overwrite(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
- u16_t elem_addr, u16_t sub_addr,
- u16_t mod_id, u16_t cid, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t cid, uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t cid, u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t cid, uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, const uint8_t label[16],
+ uint16_t mod_id, uint16_t *virt_addr,
+ uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t cid, u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, const uint8_t label[16],
+ uint16_t mod_id, uint16_t cid,
+ uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_overwrite(u16_t net_idx, u16_t addr,
- u16_t elem_addr, const u8_t label[16],
- u16_t mod_id, u16_t *virt_addr,
- u8_t *status);
+int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint8_t *status, uint16_t *subs,
+ size_t *sub_cnt);
-int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
- u16_t elem_addr, const u8_t label[16],
- u16_t mod_id, u16_t cid,
- u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status,
+ uint16_t *subs, size_t *sub_cnt);
struct bt_mesh_cfg_hb_sub {
- u16_t src;
- u16_t dst;
- u8_t period;
- u8_t count;
- u8_t min;
- u8_t max;
+ uint16_t src;
+ uint16_t dst;
+ uint8_t period;
+ uint8_t count;
+ uint8_t min;
+ uint8_t max;
};
-int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
+int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
-int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
+int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
struct bt_mesh_cfg_hb_pub {
- u16_t dst;
- u8_t count;
- u8_t period;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx;
+ uint16_t dst;
+ uint8_t count;
+ uint8_t period;
+ uint8_t ttl;
+ uint16_t feat;
+ uint16_t net_idx;
};
-int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
- const struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
+int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
+ const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
-int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
+int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
-s32_t bt_mesh_cfg_cli_timeout_get(void);
-void bt_mesh_cfg_cli_timeout_set(s32_t timeout);
+int32_t bt_mesh_cfg_cli_timeout_get(void);
+void bt_mesh_cfg_cli_timeout_set(int32_t timeout);
#ifdef __cplusplus
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h
index 14d8a295..5bf3f439 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h
@@ -21,51 +21,13 @@
extern "C" {
#endif
-/** Mesh Configuration Server Model Context */
-struct bt_mesh_cfg_srv {
- struct bt_mesh_model *model;
-
- u8_t net_transmit; /* Network Transmit state */
- u8_t relay; /* Relay Mode state */
- u8_t relay_retransmit; /* Relay Retransmit state */
- u8_t beacon; /* Secure Network Beacon state */
- u8_t gatt_proxy; /* GATT Proxy state */
- u8_t frnd; /* Friend state */
- u8_t default_ttl; /* Default TTL */
-
- /* Heartbeat Publication */
- struct bt_mesh_hb_pub {
- struct k_delayed_work timer;
-
- u16_t dst;
- u16_t count;
- u8_t period;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx;
- } hb_pub;
-
- /* Heartbeat Subscription */
- struct bt_mesh_hb_sub {
- s64_t expiry;
-
- u16_t src;
- u16_t dst;
- u16_t count;
- u8_t min_hops;
- u8_t max_hops;
-
- /* Optional subscription tracking function */
- void (*func)(u8_t hops, u16_t feat);
- } hb_sub;
-};
extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[];
extern const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb;
-#define BT_MESH_MODEL_CFG_SRV(srv_data) \
+#define BT_MESH_MODEL_CFG_SRV \
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \
- srv_data, &bt_mesh_cfg_srv_cb)
+ NULL, &bt_mesh_cfg_srv_cb)
#ifdef __cplusplus
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h
index e37fcfbc..abe3dd53 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h
@@ -51,15 +51,6 @@
extern "C" {
#endif
-#define u8_t uint8_t
-#define s8_t int8_t
-#define u16_t uint16_t
-#define s16_t int16_t
-#define u32_t uint32_t
-#define u64_t uint64_t
-#define s64_t int64_t
-#define s32_t int32_t
-
/** @brief Helper to declare elements of bt_data arrays
*
* This macro is mainly for creating an array of struct bt_data
@@ -73,7 +64,7 @@ extern "C" {
{ \
.type = (_type), \
.data_len = (_data_len), \
- .data = (const u8_t *)(_data), \
+ .data = (const uint8_t *)(_data), \
}
/** @brief Helper to declare elements of bt_data arrays
@@ -85,8 +76,8 @@ extern "C" {
* @param _bytes Variable number of single-byte parameters
*/
#define BT_DATA_BYTES(_type, _bytes...) \
- BT_DATA(_type, ((u8_t []) { _bytes }), \
- sizeof((u8_t []) { _bytes }))
+ BT_DATA(_type, ((uint8_t []) { _bytes }), \
+ sizeof((uint8_t []) { _bytes }))
/* EIR/AD data type definitions */
#define BT_DATA_FLAGS 0x01 /* AD flags */
@@ -119,9 +110,13 @@ extern "C" {
#define sys_put_be16(a,b) put_be16(b, a)
#define sys_put_le16(a,b) put_le16(b, a)
+#define sys_put_le24(a,b) put_le24(b, a)
+#define sys_put_be24(a,b) put_be24(b, a)
#define sys_put_be32(a,b) put_be32(b, a)
#define sys_get_be16(a) get_be16(a)
+#define sys_get_be24(a) get_be24(a)
#define sys_get_le16(a) get_le16(a)
+#define sys_get_le24(a) get_le24(a)
#define sys_get_be32(a) get_be32(a)
#define sys_cpu_to_be16(a) htobe16(a)
#define sys_cpu_to_be32(a) htobe32(a)
@@ -196,9 +191,9 @@ typedef ble_addr_t bt_addr_le_t;
struct net_buf_simple_state {
/** Offset of the data pointer from the beginning of the storage */
- u16_t offset;
+ uint16_t offset;
/** Length of data */
- u16_t len;
+ uint16_t len;
};
static inline struct os_mbuf * NET_BUF_SIMPLE(uint16_t size)
@@ -238,6 +233,14 @@ static inline void net_buf_simple_init(struct os_mbuf *buf,
buf->om_len = 0;
}
+#define net_buf_simple_init_with_data(buf, data, size) \
+ os_mbuf_copyinto(buf, 0, data, size);
+
+static inline void net_buf_simple_reset(struct os_mbuf *om)
+{
+ net_buf_simple_init(om, 0);
+}
+
void net_buf_put(struct ble_npl_eventq *fifo, struct os_mbuf *buf);
void * net_buf_ref(struct os_mbuf *om);
void net_buf_unref(struct os_mbuf *om);
@@ -248,18 +251,20 @@ uint32_t net_buf_simple_pull_le32(struct os_mbuf *om);
uint8_t net_buf_simple_pull_u8(struct os_mbuf *om);
void net_buf_simple_add_le16(struct os_mbuf *om, uint16_t val);
void net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val);
+void net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val);
void net_buf_simple_add_u8(struct os_mbuf *om, uint8_t val);
void net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val);
void net_buf_simple_add_le32(struct os_mbuf *om, uint32_t val);
void net_buf_add_zeros(struct os_mbuf *om, uint8_t len);
void net_buf_simple_push_le16(struct os_mbuf *om, uint16_t val);
void net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val);
+void net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val);
void net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val);
void *net_buf_simple_pull(struct os_mbuf *om, uint8_t len);
void *net_buf_simple_pull_mem(struct os_mbuf *om, uint8_t len);
void *net_buf_simple_add(struct os_mbuf *om, uint8_t len);
bool k_fifo_is_empty(struct ble_npl_eventq *q);
-void *net_buf_get(struct ble_npl_eventq *fifo,s32_t t);
+void *net_buf_get(struct ble_npl_eventq *fifo,int32_t t);
uint8_t *net_buf_simple_push(struct os_mbuf *om, uint8_t len);
void net_buf_reserve(struct os_mbuf *om, size_t reserve);
@@ -271,7 +276,7 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
#define net_buf_clone(a, b) os_mbuf_dup(a)
#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 net_buf_pull(a, b) net_buf_simple_pull(a, b)
+#define net_buf_pull(a, b) net_buf_simple_pull_mem(a, b)
#define net_buf_pull_mem(a, b) net_buf_simple_pull_mem(a, b)
#define net_buf_pull_u8(a) net_buf_simple_pull_u8(a)
#define net_buf_pull_be16(a) net_buf_simple_pull_be16(a)
@@ -279,14 +284,16 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
#define BT_GATT_CCC_NOTIFY BLE_GATT_CHR_PROP_NOTIFY
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
/** Description of different data types that can be encoded into
* advertising data. Used to form arrays that are passed to the
* bt_le_adv_start() function.
*/
struct bt_data {
- u8_t type;
- u8_t data_len;
- const u8_t *data;
+ uint8_t type;
+ uint8_t data_len;
+ const uint8_t *data;
};
struct bt_pub_key_cb {
@@ -298,18 +305,24 @@ struct bt_pub_key_cb {
*
* @param key The local public key, or NULL in case of no key.
*/
- void (*func)(const u8_t key[64]);
+ void (*func)(const uint8_t key[64]);
struct bt_pub_key_cb *_next;
};
-typedef void (*bt_dh_key_cb_t)(const u8_t key[32]);
-int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb);
+typedef void (*bt_dh_key_cb_t)(const uint8_t key[32]);
+int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb);
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb);
uint8_t *bt_pub_key_get(void);
int bt_rand(void *buf, size_t len);
const char * bt_hex(const void *buf, size_t len);
int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data);
+int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
+ size_t len, const uint8_t *aad, size_t aad_len,
+ uint8_t *plaintext, size_t mic_size);
+int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
+ size_t len, const uint8_t *aad, size_t aad_len,
+ uint8_t *plaintext, size_t mic_size);
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,
@@ -323,9 +336,10 @@ struct k_delayed_work {
void k_work_init(struct ble_npl_callout *work, ble_npl_event_fn handler);
void k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f);
void k_delayed_work_cancel(struct k_delayed_work *w);
+bool k_delayed_work_pending(struct k_delayed_work *w);
void k_delayed_work_submit(struct k_delayed_work *w, uint32_t ms);
int64_t k_uptime_get(void);
-u32_t k_uptime_get_32(void);
+uint32_t k_uptime_get_32(void);
void k_sleep(int32_t duration);
void k_work_submit(struct ble_npl_callout *w);
void k_work_add_arg(struct ble_npl_callout *w, void *arg);
@@ -355,18 +369,18 @@ static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
src += length - 1;
for (; length > 0; length--) {
- *((u8_t *)dst++) = *((u8_t *)src--);
+ *((uint8_t *)dst++) = *((uint8_t *)src--);
}
}
#define popcount(x) __builtin_popcount(x)
-static inline unsigned int find_lsb_set(u32_t op)
+static inline unsigned int find_lsb_set(uint32_t op)
{
return __builtin_ffs(op);
}
-static inline unsigned int find_msb_set(u32_t op)
+static inline unsigned int find_msb_set(uint32_t op)
{
if (!op)
return 0;
@@ -374,43 +388,61 @@ static inline unsigned int find_msb_set(u32_t op)
return 32 - __builtin_clz(op);
}
-#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND
-#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
-#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
-#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
-#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
-#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
-#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
-#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
-#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
-#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
-#define CONFIG_BT_TESTING BLE_MESH_TESTING
-#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
-#define CONFIG_SETTINGS BLE_MESH_SETTINGS
-#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
+#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND
+#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
+#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
+#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
+#define CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR BLE_MESH_LPN_SUB_ALL_NODES_ADDR
+#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
+#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
+#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
+#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
+#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
+#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
+#define CONFIG_BT_TESTING BLE_MESH_TESTING
+#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
+#define CONFIG_SETTINGS BLE_MESH_SETTINGS
+#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
+#define CONFIG_BT_MESH_PROV_DEVICE BLE_MESH_PROV_DEVICE
/* Above flags are used with IS_ENABLED macro */
#define IS_ENABLED(config) MYNEWT_VAL(config)
-#define CONFIG_BT_MESH_LPN_GROUPS MYNEWT_VAL(BLE_MESH_LPN_GROUPS)
-#define CONFIG_BT_MESH_ADV_BUF_COUNT MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)
-#define CONFIG_BT_MESH_FRIEND_QUEUE_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE)
-#define CONFIG_BT_MESH_FRIEND_RECV_WIN MYNEWT_VAL(BLE_MESH_FRIEND_RECV_WIN)
-#define CONFIG_BT_MESH_LPN_POLL_TIMEOUT MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT)
-#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT)
-#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT)
-#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT)
-#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS)
-#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE)
-#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT)
-#define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)
-#define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
-#define CONFIG_BT_MESH_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_STORE_TIMEOUT)
-#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
-#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
-#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
-#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
-#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_NODE_COUNT)
+#define CONFIG_BT_MESH_LPN_GROUPS MYNEWT_VAL(BLE_MESH_LPN_GROUPS)
+#define CONFIG_BT_MESH_ADV_BUF_COUNT MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)
+#define CONFIG_BT_MESH_SEG_BUFS MYNEWT_VAL(BLE_MESH_SEG_BUFS )
+#define CONFIG_BT_MESH_FRIEND_QUEUE_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE)
+#define CONFIG_BT_MESH_FRIEND_RECV_WIN MYNEWT_VAL(BLE_MESH_FRIEND_RECV_WIN)
+#define CONFIG_BT_MESH_LPN_POLL_TIMEOUT MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT)
+#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT)
+#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT)
+#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT)
+#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS)
+#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE)
+#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT)
+#define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)
+#define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
+#define CONFIG_BT_MESH_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_STORE_TIMEOUT)
+#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
+#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
+#define CONFIG_BT_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX)
+#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
+#define CONFIG_BT_MESH_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX)
+#define CONFIG_BT_MESH_RX_SEG_MSG_COUNT MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT)
+#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
+#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)
+#define CONFIG_BT_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED)
+#define CONFIG_BT_MESH_DEFAULT_TTL MYNEWT_VAL(BLE_MESH_DEFAULT_TTL)
+#define CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_COUNT)
+#define CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_INTERVAL)
+#define CONFIG_BT_MESH_RELAY_ENABLED MYNEWT_VAL(BLE_MESH_RELAY_ENABLED)
+#define CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_INTERVAL)
+#define CONFIG_BT_MESH_BEACON_ENABLED MYNEWT_VAL(BLE_MESH_BEACON_ENABLED)
+#define CONFIG_BT_MESH_FRIEND_ENABLED MYNEWT_VAL(BLE_MESH_FRIEND_ENABLED)
+#define CONFIG_BT_MESH_RELAY MYNEWT_VAL(BLE_MESH_RELAY)
+#define CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_COUNT)
+#define CONFIG_BT_MESH_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED)
+#define CONFIG_BT_MESH_CDB BLE_MESH_CDB
#define printk console_printf
@@ -426,7 +458,7 @@ static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count,
ble_npl_sem_init(sem, initial_count);
}
-static inline int k_sem_take(struct k_sem *sem, s32_t timeout)
+static inline int k_sem_take(struct k_sem *sem, int32_t timeout)
{
uint32_t ticks;
@@ -448,8 +480,8 @@ static inline void k_sem_give(struct k_sem *sem)
static inline int net_buf_id(struct os_mbuf *buf)
{
struct os_mbuf_pool *pool = buf->om_omp;
- u8_t *pool_start = (u8_t *)pool->omp_pool->mp_membuf_addr;
- u8_t *buf_ptr = (u8_t *)buf;
+ uint8_t *pool_start = (uint8_t *)pool->omp_pool->mp_membuf_addr;
+ uint8_t *buf_ptr = (uint8_t *)buf;
return (buf_ptr - pool_start) / BUF_SIZE(pool);
}
@@ -495,6 +527,46 @@ settings_load(void)
#define BUILD_ASSERT(cond) _Static_assert(cond, "")
+
+/* Memory slabs/blocks */
+
+/** Memory slab structure */
+struct k_mem_slab {
+ /**
+ * _wait_q_t is not required now, as we don't implement zephyr timeouts -
+ * if slab couldn't be allocated, we simply return error
+ */
+ uint32_t num_blocks; /** number of memory blocks available for allocation */
+ size_t block_size; /** size of single block */
+ /**
+ * buffer for blocks - must be alligned to N-byte, where N is a power of 2.
+ * Minimal size of buffer is num_blocks * block_size
+ */
+ char *buffer;
+ char *free_list; /** list of free memory blocks */
+ uint32_t num_used; /** count of used memory blocks */
+};
+
+struct k_mem_block_id {
+ uint32_t pool : 8;
+ uint32_t level : 4;
+ uint32_t block : 20;
+};
+
+struct k_mem_block {
+ void *data;
+ struct k_mem_block_id id;
+};
+
+extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem);
+extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem);
+static inline uint32_t k_mem_slab_num_free_get(struct k_mem_slab *slab)
+{
+ return slab->num_blocks - slab->num_used;
+}
+
+int create_free_list(struct k_mem_slab *slab);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h
index 8ab8d6d5..e9efe4b1 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h
@@ -25,12 +25,12 @@ extern "C" {
struct bt_mesh_health_cli {
struct bt_mesh_model *model;
- void (*current_status)(struct bt_mesh_health_cli *cli, u16_t addr,
- u8_t test_id, u16_t cid, u8_t *faults,
+ void (*current_status)(struct bt_mesh_health_cli *cli, uint16_t addr,
+ uint8_t test_id, uint16_t cid, uint8_t *faults,
size_t fault_count);
struct k_sem op_sync;
- u32_t op_pending;
+ uint32_t op_pending;
void *op_param;
};
@@ -43,32 +43,30 @@ extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb;
int bt_mesh_health_cli_set(struct bt_mesh_model *model);
-int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t *test_id, u8_t *faults,
- size_t *fault_count);
+int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults,
+ size_t *fault_count);
-int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t *test_id, u8_t *faults,
- size_t *fault_count);
+int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults,
+ size_t *fault_count);
-int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t test_id, u8_t *faults,
- size_t *fault_count);
+int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t test_id, uint8_t *faults,
+ size_t *fault_count);
-int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *divisor);
+int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor);
-int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t divisor, u8_t *updated_divisor);
+int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
+ uint8_t *updated_divisor);
-int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *attention);
+int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention);
-int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t attention, u8_t *updated_attention);
+int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
+ uint8_t *updated_attention);
-s32_t bt_mesh_health_cli_timeout_get(void);
-void bt_mesh_health_cli_timeout_set(s32_t timeout);
+int32_t bt_mesh_health_cli_timeout_get(void);
+void bt_mesh_health_cli_timeout_set(int32_t timeout);
#ifdef __cplusplus
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h
index 83982376..ad79e368 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h
@@ -23,21 +23,21 @@ extern "C" {
struct bt_mesh_health_srv_cb {
/* Fetch current faults */
- int (*fault_get_cur)(struct bt_mesh_model *model, u8_t *test_id,
- u16_t *company_id, u8_t *faults,
- u8_t *fault_count);
+ int (*fault_get_cur)(struct bt_mesh_model *model, uint8_t *test_id,
+ uint16_t *company_id, uint8_t *faults,
+ uint8_t *fault_count);
/* Fetch registered faults */
- int (*fault_get_reg)(struct bt_mesh_model *model, u16_t company_id,
- u8_t *test_id, u8_t *faults,
- u8_t *fault_count);
+ int (*fault_get_reg)(struct bt_mesh_model *model, uint16_t company_id,
+ uint8_t *test_id, uint8_t *faults,
+ uint8_t *fault_count);
/* Clear registered faults */
- int (*fault_clear)(struct bt_mesh_model *model, u16_t company_id);
+ int (*fault_clear)(struct bt_mesh_model *model, uint16_t company_id);
/* Run a specific test */
- int (*fault_test)(struct bt_mesh_model *model, u8_t test_id,
- u16_t company_id);
+ int (*fault_test)(struct bt_mesh_model *model, uint8_t test_id,
+ uint16_t company_id);
/* Attention on */
void (*attn_on)(struct bt_mesh_model *model);
@@ -52,7 +52,7 @@ struct bt_mesh_health_srv_cb {
*
* @param max_faults Maximum number of faults the element can have.
*
- * @return a New net_buf_simple of the needed size.
+ * @return a New os_mbuf of the needed size.
*/
#define BT_MESH_HEALTH_FAULT_MSG(max_faults) \
NET_BUF_SIMPLE(1 + 3 + (max_faults))
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h
new file mode 100644
index 00000000..b9990f6f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h
@@ -0,0 +1,123 @@
+/** @file
+ * @brief Bluetooth Mesh Heartbeat API.
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _BLUETOOTH_MESH_HEARTBEAT_H_
+#define _BLUETOOTH_MESH_HEARTBEAT_H_
+
+/**
+ * @brief Bluetooth Mesh
+ * @defgroup bt_mesh_heartbeat Bluetooth Mesh Heartbeat
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Heartbeat Publication parameters */
+struct bt_mesh_hb_pub {
+ /** Destination address. */
+ uint16_t dst;
+ /** Remaining publish count. */
+ uint16_t count;
+ /** Time To Live value. */
+ uint8_t ttl;
+ /**
+ * Bitmap of features that trigger a Heartbeat publication if
+ * they change. Legal values are @ref BT_MESH_FEAT_RELAY,
+ * @ref BT_MESH_FEAT_PROXY, @ref BT_MESH_FEAT_FRIEND and
+ * @ref BT_MESH_FEAT_LOW_POWER.
+ */
+ uint16_t feat;
+ /** Network index used for publishing. */
+ uint16_t net_idx;
+ /** Publication period in seconds. */
+ uint32_t period;
+};
+
+/** Heartbeat Subscription parameters. */
+struct bt_mesh_hb_sub {
+ /** Subscription period in seconds. */
+ uint32_t period;
+ /** Remaining subscription time in seconds. */
+ uint32_t remaining;
+ /** Source address to receive Heartbeats from. */
+ uint16_t src;
+ /** Destination address to received Heartbeats on. */
+ uint16_t dst;
+ /** The number of received Heartbeat messages so far. */
+ uint16_t count;
+ /**
+ * Minimum hops in received messages, ie the shortest registered
+ * path from the publishing node to the subscribing node. A
+ * Heartbeat received from an immediate neighbor has hop
+ * count = 1.
+ */
+ uint8_t min_hops;
+ /**
+ * Maximum hops in received messages, ie the longest registered
+ * path from the publishing node to the subscribing node. A
+ * Heartbeat received from an immediate neighbor has hop
+ * count = 1.
+ */
+ uint8_t max_hops;
+};
+
+/** Heartbeat callback structure */
+struct bt_mesh_hb_cb {
+ /** @brief Receive callback for heartbeats.
+ *
+ * Gets called on every received Heartbeat that matches the current
+ * Heartbeat subscription parameters.
+ *
+ * @param sub Current Heartbeat subscription parameters.
+ * @param hops The number of hops the Heartbeat was received
+ * with.
+ * @param feat The feature set of the publishing node. The
+ * value is a bitmap of @ref BT_MESH_FEAT_RELAY,
+ * @ref BT_MESH_FEAT_PROXY,
+ * @ref BT_MESH_FEAT_FRIEND and
+ * @ref BT_MESH_FEAT_LOW_POWER.
+ */
+ void (*recv)(const struct bt_mesh_hb_sub *sub, uint8_t hops,
+ uint16_t feat);
+
+ /** @brief Subscription end callback for heartbeats.
+ *
+ * Gets called when the subscription period ends, providing a summary
+ * of the received heartbeat messages.
+ *
+ * @param sub Current Heartbeat subscription parameters.
+ */
+ void (*sub_end)(const struct bt_mesh_hb_sub *sub);
+};
+
+/** @brief Get the current Heartbeat publication parameters.
+ *
+ * @param get Heartbeat publication parameters return buffer.
+ */
+void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get);
+
+/** @brief Get the current Heartbeat subscription parameters.
+ *
+ * @param get Heartbeat subscription parameters return buffer.
+ */
+void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get);
+
+extern struct bt_mesh_hb_cb hb_cb;
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* _BLUETOOTH_MESH_HEARTBEAT_H_ */ \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h
index 4a5bedba..2bcb05c8 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h
@@ -59,10 +59,37 @@ typedef enum {
BT_MESH_PROV_OOB_ON_DEV = BIT(15),
} bt_mesh_prov_oob_info_t;
+/** Device Capabilities. */
+struct bt_mesh_dev_capabilities {
+ /** Number of elements supported by the device */
+ uint8_t elem_count;
+
+ /** Supported algorithms and other capabilities */
+ uint16_t algorithms;
+
+ /** Supported public key types */
+ uint8_t pub_key_type;
+
+ /** Supported static OOB Types */
+ uint8_t static_oob;
+
+ /** Supported Output OOB Actions */
+ bt_mesh_output_action_t output_actions;
+
+ /** Supported Input OOB Actions */
+ bt_mesh_input_action_t input_actions;
+
+ /** Maximum size of Output OOB supported */
+ uint8_t output_size;
+
+ /** Maximum size in octets of Input OOB supported */
+ uint8_t input_size;
+};
+
/** Provisioning properties & capabilities. */
struct bt_mesh_prov {
/** The UUID that's used when advertising as unprovisioned */
- const u8_t *uuid;
+ const uint8_t *uuid;
/** Optional URI. This will be advertised separately from the
* unprovisioned beacon, however the unprovisioned beacon will
@@ -75,19 +102,34 @@ struct bt_mesh_prov {
bt_mesh_prov_oob_info_t oob_info;
/** Static OOB value */
- const u8_t *static_val;
+ const uint8_t *static_val;
/** Static OOB value length */
- u8_t static_val_len;
+ uint8_t static_val_len;
/** Maximum size of Output OOB supported */
- u8_t output_size;
+ uint8_t output_size;
/** Supported Output OOB Actions */
- u16_t output_actions;
+ uint16_t output_actions;
/* Maximum size of Input OOB supported */
- u8_t input_size;
+ uint8_t input_size;
/** Supported Input OOB Actions */
- u16_t input_actions;
+ uint16_t input_actions;
+
+ /** @brief Provisioning Capabilities.
+ *
+ * This callback notifies the application that the provisioning capabilities
+ * of the unprovisioned device has been received.
+ *
+ * The application can consequently call bt_mesh_auth_method_set_<*> to
+ * select suitable provisioning oob authentication method.
+ *
+ * When this callback returns, the provisioner will start authentication with
+ * the chosen method.
+ *
+ * @param cap capabilities supported by device.
+ */
+ void (*capabilities)(const struct bt_mesh_dev_capabilities *cap);
/** @brief Output of a number is requested.
*
@@ -99,7 +141,7 @@ struct bt_mesh_prov {
*
* @return Zero on success or negative error code otherwise
*/
- int (*output_number)(bt_mesh_output_action_t act, u32_t num);
+ int (*output_number)(bt_mesh_output_action_t act, uint32_t num);
/** @brief Output of a string is requested.
*
@@ -126,7 +168,7 @@ struct bt_mesh_prov {
*
* @return Zero on success or negative error code otherwise
*/
- int (*input)(bt_mesh_input_action_t act, u8_t size);
+ int (*input)(bt_mesh_input_action_t act, uint8_t size);
/** @brief The other device finished their OOB input.
*
@@ -146,9 +188,9 @@ struct bt_mesh_prov {
* @param uri_hash Pointer to URI Hash value. NULL if no hash was
* present in the beacon.
*/
- void (*unprovisioned_beacon)(u8_t uuid[16],
+ void (*unprovisioned_beacon)(uint8_t uuid[16],
bt_mesh_prov_oob_info_t oob_info,
- u32_t *uri_hash);
+ uint32_t *uri_hash);
/** @brief Provisioning link has been opened.
*
@@ -177,7 +219,7 @@ struct bt_mesh_prov {
* @param net_idx NetKeyIndex given during provisioning.
* @param addr Primary element address.
*/
- void (*complete)(u16_t net_idx, u16_t addr);
+ void (*complete)(uint16_t net_idx, uint16_t addr);
/** @brief A new node has been added to the provisioning database.
*
@@ -186,10 +228,12 @@ struct bt_mesh_prov {
* the specified NetKeyIndex and primary element address.
*
* @param net_idx NetKeyIndex given during provisioning.
+ * @param uuid UUID of the added node
* @param addr Primary element address.
* @param num_elem Number of elements that this node has.
*/
- void (*node_added)(u16_t net_idx, u16_t addr, u8_t num_elem);
+ void (*node_added)(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem);
/** @brief Node has been reset.
*
@@ -222,7 +266,90 @@ int bt_mesh_input_string(const char *str);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_mesh_input_number(u32_t num);
+int bt_mesh_input_number(uint32_t num);
+
+/** @brief Provide Device public key.
+ *
+ * @param public_key Device public key.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]);
+
+/** @brief Use Input OOB authentication.
+ *
+ * Provisioner only.
+ *
+ * Instruct the unprovisioned device to use the specified Input OOB
+ * authentication action. When using @ref BT_MESH_PUSH, @ref BT_MESH_TWIST or
+ * @ref BT_MESH_ENTER_NUMBER, the @ref bt_mesh_prov::output_number callback is
+ * called with a random number that has to be entered on the unprovisioned
+ * device.
+ *
+ * When using @ref BT_MESH_ENTER_STRING, the @ref bt_mesh_prov::output_string
+ * callback is called with a random string that has to be entered on the
+ * unprovisioned device.
+ *
+ * @param action Authentication action used by the unprovisioned device.
+ * @param size Authentication size.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size);
+
+/** @brief Use Output OOB authentication.
+ *
+ * Provisioner only.
+ *
+ * Instruct the unprovisioned device to use the specified Output OOB
+ * authentication action. The @ref bt_mesh_prov::input callback will
+ * be called.
+ *
+ * When using @ref BT_MESH_BLINK, @ref BT_MESH_BEEP, @ref BT_MESH_VIBRATE
+ * or @ref BT_MESH_DISPLAY_NUMBER, and the application has to call
+ * @ref bt_mesh_input_number with the random number indicated by
+ * the unprovisioned device.
+ *
+ * When using @ref BT_MESH_DISPLAY_STRING, the application has to call
+ * @ref bt_mesh_input_string with the random string displayed by the
+ * unprovisioned device.
+ *
+ * @param action Authentication action used by the unprovisioned device.
+ * @param size Authentication size.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size);
+
+/** @brief Use static OOB authentication.
+ *
+ * Provisioner only.
+ *
+ * Instruct the unprovisioned device to use static OOB authentication, and use
+ * the given static authentication value when provisioning.
+ *
+ * @param static_val Static OOB value.
+ * @param size Static OOB value size.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size);
+
+/** @brief Don't use OOB authentication.
+ *
+ * Provisioner only.
+ *
+ * Don't use any authentication when provisioning new devices. This is the
+ * default behavior.
+ *
+ * @warning Not using any authentication exposes the mesh network to
+ * impersonation attacks, where attackers can pretend to be the
+ * unprovisioned device to gain access to the network. Authentication
+ * is strongly encouraged.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_auth_method_set_none(void);
/** @brief Enable specific provisioning bearers
*
@@ -258,25 +385,6 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
/* Primary Network Key index */
#define BT_MESH_NET_PRIMARY 0x000
-#define BT_MESH_RELAY_DISABLED 0x00
-#define BT_MESH_RELAY_ENABLED 0x01
-#define BT_MESH_RELAY_NOT_SUPPORTED 0x02
-
-#define BT_MESH_BEACON_DISABLED 0x00
-#define BT_MESH_BEACON_ENABLED 0x01
-
-#define BT_MESH_GATT_PROXY_DISABLED 0x00
-#define BT_MESH_GATT_PROXY_ENABLED 0x01
-#define BT_MESH_GATT_PROXY_NOT_SUPPORTED 0x02
-
-#define BT_MESH_FRIEND_DISABLED 0x00
-#define BT_MESH_FRIEND_ENABLED 0x01
-#define BT_MESH_FRIEND_NOT_SUPPORTED 0x02
-
-#define BT_MESH_NODE_IDENTITY_STOPPED 0x00
-#define BT_MESH_NODE_IDENTITY_RUNNING 0x01
-#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED 0x02
-
/* Features */
#define BT_MESH_FEAT_RELAY BIT(0)
#define BT_MESH_FEAT_PROXY BIT(1)
@@ -299,7 +407,7 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_mesh_init(u8_t own_addr_type,
+int bt_mesh_init(uint8_t own_addr_type,
const struct bt_mesh_prov *prov,
const struct bt_mesh_comp *comp);
@@ -351,9 +459,9 @@ int bt_mesh_resume(void);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
- u8_t flags, u32_t iv_index, u16_t addr,
- const u8_t dev_key[16]);
+int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx,
+ uint8_t flags, uint32_t iv_index, uint16_t addr,
+ const uint8_t dev_key[16]);
/** @brief Provision a Mesh Node using PB-ADV
*
@@ -365,8 +473,8 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration);
+int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration);
/** @brief Check if the local node has been provisioned.
*
@@ -428,7 +536,17 @@ int bt_mesh_lpn_poll(void);
*
* @param cb Function to call when the Friendship status changes.
*/
-void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established));
+void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established));
+
+/** @brief Terminate Friendship.
+ *
+ * Terminated Friendship for given LPN.
+ *
+ * @param lpn_addr Low Power Node address.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_friend_terminate(uint16_t lpn_addr);
#ifdef __cplusplus
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h
index 9ba63ef0..b9bc24fb 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h
@@ -17,10 +17,15 @@
#include "glue.h"
#include "access.h"
#include "main.h"
+#include "cfg.h"
#include "cfg_srv.h"
#include "health_srv.h"
#include "cfg_cli.h"
#include "health_cli.h"
#include "proxy.h"
+#include "cdb.h"
+#include "cfg.h"
+#include "heartbeat.h"
+#include "../src/app_keys.h"
#endif /* __BT_MESH_H */
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h
index f2e77a47..87e2dd2b 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h
@@ -15,7 +15,7 @@ struct bt_mesh_gen_model_cli {
struct bt_mesh_model *model;
struct k_sem op_sync;
- u32_t op_pending;
+ uint32_t op_pending;
void *op_param;
};
@@ -33,14 +33,14 @@ extern const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb;
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_LEVEL_CLI, gen_level_cli_op, pub,\
cli_data, &bt_mesh_gen_level_cli_cb)
-int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *state);
-int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t val, u8_t *state);
-int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- s16_t *level);
-int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- s16_t val, s16_t *state);
+int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t *state);
+int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t val, uint8_t *state);
+int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t *level);
+int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t val, int16_t *state);
#ifdef __cplusplus
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h
index e498ad34..a23296b8 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h
@@ -14,8 +14,8 @@ extern "C" {
struct bt_mesh_gen_onoff_srv {
struct bt_mesh_model *model;
- int (*get)(struct bt_mesh_model *model, u8_t *state);
- int (*set)(struct bt_mesh_model *model, u8_t state);
+ int (*get)(struct bt_mesh_model *model, uint8_t *state);
+ int (*set)(struct bt_mesh_model *model, uint8_t state);
};
extern const struct bt_mesh_model_op gen_onoff_srv_op[];
@@ -28,8 +28,8 @@ extern const struct bt_mesh_model_cb gen_onoff_srv_cb;
struct bt_mesh_gen_level_srv {
struct bt_mesh_model *model;
- int (*get)(struct bt_mesh_model *model, s16_t *level);
- int (*set)(struct bt_mesh_model *model, s16_t level);
+ int (*get)(struct bt_mesh_model *model, int16_t *level);
+ int (*set)(struct bt_mesh_model *model, int16_t level);
};
extern const struct bt_mesh_model_op gen_level_srv_op[];
@@ -42,8 +42,8 @@ extern const struct bt_mesh_model_cb gen_level_srv_cb;
struct bt_mesh_light_lightness_srv {
struct bt_mesh_model *model;
- int (*get)(struct bt_mesh_model *model, s16_t *level);
- int (*set)(struct bt_mesh_model *model, s16_t level);
+ int (*get)(struct bt_mesh_model *model, int16_t *level);
+ int (*set)(struct bt_mesh_model *model, int16_t level);
};
extern const struct bt_mesh_model_op light_lightness_srv_op[];
@@ -53,12 +53,12 @@ extern const struct bt_mesh_model_cb light_lightness_srv_cb;
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, \
light_lightness_srv_op, pub, srv, &light_lightness_srv_cb)
-void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
- int (*set)(struct bt_mesh_model *model, u8_t state));
-void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
- int (*set)(struct bt_mesh_model *model, s16_t level));
-void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
- int (*set)(struct bt_mesh_model *model, s16_t level));
+void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state),
+ int (*set)(struct bt_mesh_model *model, uint8_t state));
+void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level));
+void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level));
#ifdef __cplusplus
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h
index 4c2b2a61..580aafe4 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h
@@ -33,13 +33,13 @@ extern "C" {
* Allows access to Bluetooth stack internals, not exposed by public API.
*/
struct bt_test_cb {
- void (*mesh_net_recv)(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
+ void (*mesh_net_recv)(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
const void *payload, size_t payload_len);
- void (*mesh_model_bound)(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx);
- void (*mesh_model_unbound)(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx);
- void (*mesh_prov_invalid_bearer)(u8_t opcode);
+ void (*mesh_model_bound)(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx);
+ void (*mesh_model_unbound)(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx);
+ void (*mesh_prov_invalid_bearer)(uint8_t opcode);
void (*mesh_trans_incomp_timer_exp)(void);
sys_snode_t node;
@@ -66,7 +66,7 @@ void bt_test_cb_unregister(struct bt_test_cb *cb);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_test_mesh_lpn_group_add(u16_t group);
+int bt_test_mesh_lpn_group_add(uint16_t group);
/** Send Friend Subscription List Remove message.
*
@@ -79,7 +79,7 @@ int bt_test_mesh_lpn_group_add(u16_t group);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count);
+int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count);
/** Clear replay protection list cache.
*
@@ -87,12 +87,12 @@ int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count);
*/
int bt_test_mesh_rpl_clear(void);
-u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx);
-u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store);
+uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx);
+uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store);
int cmd_mesh_init(int argc, char *argv[]);
int bt_test_shell_init(void);
-int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, u16_t key_idx, u16_t id);
+int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, uint16_t key_idx, uint16_t id);
/**
* @}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
index ff8e9999..da077182 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c
@@ -26,7 +26,7 @@
#endif
static const struct bt_mesh_comp *dev_comp;
-static u16_t dev_primary_addr;
+static uint16_t dev_primary_addr;
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
struct bt_mesh_elem *elem,
@@ -53,7 +53,7 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
}
}
-s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
+int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
{
int period;
@@ -89,10 +89,10 @@ s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
}
}
-static s32_t next_period(struct bt_mesh_model *mod)
+static int32_t next_period(struct bt_mesh_model *mod)
{
struct bt_mesh_model_pub *pub = mod->pub;
- u32_t elapsed, period;
+ uint32_t elapsed, period;
period = bt_mesh_model_pub_period_get(mod);
if (!period) {
@@ -115,7 +115,7 @@ static s32_t next_period(struct bt_mesh_model *mod)
static void publish_sent(int err, void *user_data)
{
struct bt_mesh_model *mod = user_data;
- s32_t delay;
+ int32_t delay;
BT_DBG("err %d", err);
@@ -131,7 +131,7 @@ static void publish_sent(int err, void *user_data)
}
}
-static void publish_start(u16_t duration, int err, void *user_data)
+static void publish_start(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_model *mod = user_data;
struct bt_mesh_model_pub *pub = mod->pub;
@@ -156,30 +156,18 @@ static int publish_retransmit(struct bt_mesh_model *mod)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_model_pub *pub = mod->pub;
- struct bt_mesh_app_key *key;
struct bt_mesh_msg_ctx ctx = {
.addr = pub->addr,
.send_ttl = pub->ttl,
+ .app_idx = pub->key,
};
struct bt_mesh_net_tx tx = {
.ctx = &ctx,
.src = bt_mesh_model_elem(mod)->addr,
- .xmit = bt_mesh_net_transmit_get(),
.friend_cred = pub->cred,
};
int err;
- key = bt_mesh_app_key_find(pub->key);
- if (!key) {
- err = -EADDRNOTAVAIL;
- goto done;
- }
-
- tx.sub = bt_mesh_subnet_get(key->net_idx);
-
- ctx.net_idx = key->net_idx;
- ctx.app_idx = key->app_idx;
-
net_buf_simple_init(sdu, 0);
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
@@ -187,15 +175,22 @@ static int publish_retransmit(struct bt_mesh_model *mod)
err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod);
-done:
os_mbuf_free_chain(sdu);
return err;
}
+static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub)
+{
+ /* Cancel all retransmits for this publish attempt */
+ pub->count = 0U;
+ /* Make sure the publish timer gets reset */
+ publish_sent(err, pub->mod);
+}
+
static void mod_publish(struct ble_npl_event *work)
{
struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work);
- s32_t period_ms;
+ int32_t period_ms;
int err;
BT_DBG("");
@@ -227,7 +222,10 @@ static void mod_publish(struct ble_npl_event *work)
err = pub->update(pub->mod);
if (err) {
- BT_ERR("Failed to update publication message");
+ /* Cancel this publish attempt. */
+ BT_DBG("Update failed, skipping publish (err: %d)", err);
+ pub->period_start = k_uptime_get_32();
+ publish_retransmit_end(err, pub);
return;
}
@@ -242,7 +240,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
return &dev_comp->elem[mod->elem_idx];
}
-struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx)
+struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx)
{
struct bt_mesh_elem *elem;
@@ -274,6 +272,11 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
int i;
+ int *err = user_data;
+
+ if (*err) {
+ return;
+ }
if (mod->pub) {
mod->pub->mod = mod;
@@ -293,12 +296,14 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
}
if (mod->cb && mod->cb->init) {
- mod->cb->init(mod);
+ *err = mod->cb->init(mod);
}
}
int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
{
+ int err;
+
/* There must be at least one element */
if (!comp->elem_count) {
return -EINVAL;
@@ -306,12 +311,13 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
dev_comp = comp;
- bt_mesh_model_foreach(mod_init, NULL);
+ err = 0;
+ bt_mesh_model_foreach(mod_init, &err);
- return 0;
+ return err;
}
-void bt_mesh_comp_provision(u16_t addr)
+void bt_mesh_comp_provision(uint16_t addr)
{
int i;
@@ -334,16 +340,14 @@ void bt_mesh_comp_unprovision(void)
BT_DBG("");
dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
-
- bt_mesh_model_foreach(mod_init, NULL);
}
-u16_t bt_mesh_primary_addr(void)
+uint16_t bt_mesh_primary_addr(void)
{
return dev_primary_addr;
}
-static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
+static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr)
{
int i;
@@ -357,13 +361,13 @@ static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
}
struct find_group_visitor_ctx {
- u16_t *entry;
+ uint16_t *entry;
struct bt_mesh_model *mod;
- u16_t addr;
+ uint16_t addr;
};
static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *user_data)
+ uint32_t depth, void *user_data)
{
struct find_group_visitor_ctx *ctx = user_data;
@@ -380,7 +384,7 @@ static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
return BT_MESH_WALK_CONTINUE;
}
-u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
+uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr)
{
struct find_group_visitor_ctx ctx = {
.mod = *mod,
@@ -396,10 +400,10 @@ u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
}
static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
- u16_t group_addr)
+ uint16_t group_addr)
{
struct bt_mesh_model *model;
- u16_t *match;
+ uint16_t *match;
int i;
for (i = 0; i < elem->model_count; i++) {
@@ -423,9 +427,9 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
return NULL;
}
-struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
+struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
{
- u16_t index;
+ uint16_t index;
if (BT_MESH_ADDR_IS_UNICAST(addr)) {
index = (addr - dev_comp->elem[0].addr);
@@ -447,12 +451,12 @@ struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
return NULL;
}
-u8_t bt_mesh_elem_count(void)
+uint8_t bt_mesh_elem_count(void)
{
return dev_comp->elem_count;
}
-static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
+static bool model_has_key(struct bt_mesh_model *mod, uint16_t key)
{
int i;
@@ -467,22 +471,26 @@ static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
return false;
}
-static bool model_has_dst(struct bt_mesh_model *mod, u16_t dst)
+static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst)
{
if (BT_MESH_ADDR_IS_UNICAST(dst)) {
return (dev_comp->elem[mod->elem_idx].addr == dst);
} else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst)) {
- return bt_mesh_model_find_group(&mod, dst);
+ return !!bt_mesh_model_find_group(&mod, dst);
}
- return (mod->elem_idx == 0 && bt_mesh_fixed_group_match(dst));
+ /* If a message with a fixed group address is sent to the access layer,
+ * the lower layers have already confirmed that we are subscribing to
+ * it. All models on the primary element should receive the message.
+ */
+ return mod->elem_idx == 0;
}
static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
- u8_t model_count, u32_t opcode,
+ uint8_t model_count, uint32_t opcode,
struct bt_mesh_model **model)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < model_count; i++) {
const struct bt_mesh_model_op *op;
@@ -500,7 +508,7 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
return NULL;
}
-static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
+static int get_opcode(struct os_mbuf *buf, uint32_t *opcode)
{
switch (buf->om_data[0] >> 6) {
case 0x00:
@@ -527,6 +535,10 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
}
*opcode = net_buf_simple_pull_u8(buf) << 16;
+ /* Using LE for the CID since the model layer is defined as
+ * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
+ * will declare the opcode in this way.
+ */
*opcode |= net_buf_simple_pull_le16(buf);
return 0;
}
@@ -534,29 +546,12 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
CODE_UNREACHABLE;
}
-bool bt_mesh_fixed_group_match(u16_t addr)
-{
- /* Check for fixed group addresses */
- switch (addr) {
- case BT_MESH_ADDR_ALL_NODES:
- return true;
- case BT_MESH_ADDR_PROXIES:
- return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
- case BT_MESH_ADDR_FRIENDS:
- return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
- case BT_MESH_ADDR_RELAYS:
- return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
- default:
- return false;
- }
-}
-
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_model *models, *model;
const struct bt_mesh_model_op *op;
- u32_t opcode;
- u8_t count;
+ uint32_t opcode;
+ uint8_t count;
int i;
BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
@@ -615,7 +610,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
}
}
-void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
+void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode)
{
net_buf_simple_init(msg, 0);
@@ -628,6 +623,10 @@ void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode)
break;
case 3:
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
+ /* Using LE for the CID since the model layer is defined as
+ * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
+ * will declare the opcode in this way.
+ */
net_buf_simple_add_le16(msg, opcode & 0xffff);
break;
default:
@@ -674,11 +673,8 @@ int bt_mesh_model_send(struct bt_mesh_model *model,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
struct bt_mesh_net_tx tx = {
- .sub = bt_mesh_subnet_get(ctx->net_idx),
.ctx = ctx,
.src = bt_mesh_model_elem(model)->addr,
- .xmit = bt_mesh_net_transmit_get(),
- .friend_cred = 0,
};
return model_send(model, &tx, false, msg, cb, cb_data);
@@ -688,13 +684,15 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_model_pub *pub = model->pub;
- struct bt_mesh_app_key *key;
struct bt_mesh_msg_ctx ctx = {
+ .addr = pub->addr,
+ .send_ttl = pub->ttl,
+ .send_rel = pub->send_rel,
+ .app_idx = pub->key,
};
struct bt_mesh_net_tx tx = {
.ctx = &ctx,
.src = bt_mesh_model_elem(model)->addr,
- .xmit = bt_mesh_net_transmit_get(),
};
int err;
@@ -710,12 +708,6 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
goto done;
}
- key = bt_mesh_app_key_find(pub->key);
- if (!key) {
- err = -EADDRNOTAVAIL;
- goto done;
- }
-
if (pub->msg->om_len + 4 > BT_MESH_TX_SDU_MAX) {
BT_ERR("Message does not fit maximum SDU size");
err = -EMSGSIZE;
@@ -730,13 +722,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
net_buf_simple_init(sdu, 0);
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
- ctx.addr = pub->addr;
- ctx.send_ttl = pub->ttl;
- ctx.net_idx = key->net_idx;
- ctx.app_idx = key->app_idx;
-
tx.friend_cred = pub->cred;
- tx.sub = bt_mesh_subnet_get(ctx.net_idx),
pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
@@ -745,10 +731,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
if (err) {
- /* Don't try retransmissions for this publish attempt */
- pub->count = 0;
- /* Make sure the publish timer gets reset */
- publish_sent(err, model);
+ publish_retransmit_end(err, pub);
}
done:
@@ -757,9 +740,9 @@ done:
}
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
- u16_t company, u16_t id)
+ uint16_t company, uint16_t id)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < elem->vnd_model_count; i++) {
if (elem->vnd_models[i].vnd.company == company &&
@@ -772,9 +755,9 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
}
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
- u16_t id)
+ uint16_t id)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < elem->model_count; i++) {
if (elem->models[i].id == id) {
@@ -802,29 +785,38 @@ struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod)
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
- u32_t depth,
+ uint32_t depth,
void *user_data),
void *user_data)
{
struct bt_mesh_model *m = root;
- u32_t depth = 0;
+ int depth = 0;
+ /* 'skip' is set to true when we ascend from child to parent node.
+ * In that case, we want to skip calling the callback on the parent
+ * node and we don't want to descend onto a child node as those
+ * nodes have already been visited.
+ */
+ bool skip = false;
do {
- if (cb(m, depth, user_data) == BT_MESH_WALK_STOP) {
+ if (!skip &&
+ cb(m, (uint32_t)depth, user_data) == BT_MESH_WALK_STOP) {
return;
}
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
- if (m->extends) {
+ if (!skip && m->extends) {
m = m->extends;
depth++;
} else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) {
- m = m->next->next;
+ m = m->next;
depth--;
+ skip = true;
} else {
m = m->next;
+ skip = false;
}
#endif
- } while (m && m != root);
+ } while (m && depth > 0);
}
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h
index 48514983..affba538 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h
@@ -16,8 +16,7 @@ enum {
BT_MESH_MOD_BIND_PENDING = BIT(0),
BT_MESH_MOD_SUB_PENDING = BIT(1),
BT_MESH_MOD_PUB_PENDING = BIT(2),
- BT_MESH_MOD_DATA_PRESENT = BIT(3),
- BT_MESH_MOD_NEXT_IS_PARENT = BIT(4),
+ BT_MESH_MOD_NEXT_IS_PARENT = BIT(3),
};
/* Tree walk return codes */
@@ -26,23 +25,21 @@ enum bt_mesh_walk {
BT_MESH_WALK_CONTINUE,
};
-void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count);
+void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count);
-u8_t bt_mesh_elem_count(void);
+uint8_t bt_mesh_elem_count(void);
/* Find local element based on unicast or group address */
-struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr);
+struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr);
struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod);
void bt_mesh_model_tree_walk(struct bt_mesh_model *root,
enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod,
- u32_t depth,
+ uint32_t depth,
void *user_data),
void *user_data);
-u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr);
-
-bool bt_mesh_fixed_group_match(u16_t addr);
+uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr);
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
struct bt_mesh_elem *elem,
@@ -50,16 +47,16 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
void *user_data),
void *user_data);
-s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
+int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
-void bt_mesh_comp_provision(u16_t addr);
+void bt_mesh_comp_provision(uint16_t addr);
void bt_mesh_comp_unprovision(void);
-u16_t bt_mesh_primary_addr(void);
+uint16_t bt_mesh_primary_addr(void);
const struct bt_mesh_comp *bt_mesh_comp_get(void);
-struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx);
+struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx);
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c
index 4bd51cc1..4b372991 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c
@@ -38,19 +38,18 @@
#define ADV_INT_DEFAULT_MS 100
#define ADV_INT_FAST_MS 20
-static s32_t adv_int_min = ADV_INT_DEFAULT_MS;
+static int32_t adv_int_min = ADV_INT_DEFAULT_MS;
/* TinyCrypt PRNG consumes a lot of stack space, so we need to have
* an increased call stack whenever it's used.
*/
#if MYNEWT
-#define ADV_STACK_SIZE 768
-OS_TASK_STACK_DEFINE(g_blemesh_stack, ADV_STACK_SIZE);
+OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE));
struct os_task adv_task;
#endif
static struct ble_npl_eventq adv_queue;
-extern u8_t g_mesh_addr_type;
+extern uint8_t g_mesh_addr_type;
static int adv_initialized = false;
static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE(
@@ -60,14 +59,6 @@ static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE(
struct os_mbuf_pool adv_os_mbuf_pool;
static struct os_mempool adv_buf_mempool;
-static const u8_t adv_type[] = {
- [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV,
- [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE,
- [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON,
- [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI,
-};
-
-
static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT];
static struct bt_mesh_adv *adv_alloc(int id)
@@ -75,7 +66,7 @@ static struct bt_mesh_adv *adv_alloc(int id)
return &adv_pool[id];
}
-static inline void adv_send_start(u16_t duration, int err,
+static inline void adv_send_start(uint16_t duration, int err,
const struct bt_mesh_send_cb *cb,
void *cb_data)
{
@@ -94,10 +85,17 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
static inline void adv_send(struct os_mbuf *buf)
{
+ static const uint8_t adv_type[] = {
+ [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV,
+ [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE,
+ [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON,
+ [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI,
+} ;
+
const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb;
void *cb_data = BT_MESH_ADV(buf)->cb_data;
struct ble_gap_adv_params param = { 0 };
- u16_t duration, adv_int;
+ uint16_t duration, adv_int;
struct bt_data ad;
int err;
@@ -154,7 +152,7 @@ mesh_adv_thread(void *args)
static struct ble_npl_event *ev;
struct os_mbuf *buf;
#if (MYNEWT_VAL(BLE_MESH_PROXY))
- s32_t timeout;
+ int32_t timeout;
#endif
BT_DBG("started");
@@ -208,7 +206,7 @@ void bt_mesh_adv_update(void)
struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
bt_mesh_adv_alloc_t get_id,
enum bt_mesh_adv_type type,
- u8_t xmit, s32_t timeout)
+ uint8_t xmit, int32_t timeout)
{
struct bt_mesh_adv *adv;
struct os_mbuf *buf;
@@ -235,10 +233,11 @@ struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
ble_npl_event_set_arg(&adv->ev, buf);
return buf;
+ os_mbuf_free_chain(buf);
}
-struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
- s32_t timeout)
+struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
+ int32_t timeout)
{
return bt_mesh_adv_create_from_pool(&adv_os_mbuf_pool, adv_alloc, type,
xmit, timeout);
@@ -257,8 +256,8 @@ void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb,
net_buf_put(&adv_queue, net_buf_ref(buf));
}
-static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
- u8_t adv_type, struct os_mbuf *buf)
+static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi,
+ uint8_t adv_type, struct os_mbuf *buf)
{
if (adv_type != BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
return;
@@ -270,7 +269,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
while (buf->om_len > 1) {
struct net_buf_simple_state state;
- u8_t len, type;
+ uint8_t len, type;
len = net_buf_simple_pull_u8(buf);
/* Check for early termination */
@@ -304,7 +303,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
}
net_buf_simple_restore(buf, &state);
- net_buf_simple_pull(buf, len);
+ net_buf_simple_pull_mem(buf, len);
}
}
@@ -333,7 +332,7 @@ void bt_mesh_adv_init(void)
#if MYNEWT
os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL,
MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER,
- g_blemesh_stack, ADV_STACK_SIZE);
+ g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE));
#endif
/* For BT5 controllers we can have fast advertising interval */
@@ -362,7 +361,7 @@ ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_EXT_DISC:
ext_desc = &event->ext_disc;
buf = os_mbuf_get_pkthdr(&adv_os_mbuf_pool, 0);
- if (!buf || os_mbuf_append(buf, ext_desc->data, ext_desc->length_data)) {
+ if (!buf || os_mbuf_append(buf, ext_desc->om_data, ext_desc->length_data)) {
BT_ERR("Could not append data");
goto done;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h
index 4d0f7d8b..779ee58e 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h
@@ -31,23 +31,18 @@ enum bt_mesh_adv_type
BT_MESH_ADV_URI,
};
-typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, u16_t duration,
+typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration,
int err, void *user_data);
struct bt_mesh_adv {
const struct bt_mesh_send_cb *cb;
void *cb_data;
- u8_t type:2,
+ uint8_t type:2,
busy:1;
- u8_t xmit;
+ uint8_t xmit;
- /* For transport layer segment sending */
- struct {
- u8_t attempts;
- } seg;
-
- u8_t flags;
+ uint8_t flags;
int ref_cnt;
struct ble_npl_event ev;
@@ -56,13 +51,13 @@ struct bt_mesh_adv {
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
/* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */
-struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
- s32_t timeout);
+struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
+ int32_t timeout);
struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
bt_mesh_adv_alloc_t get_id,
enum bt_mesh_adv_type type,
- u8_t xmit, s32_t timeout);
+ uint8_t xmit, int32_t timeout);
void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb,
void *cb_data);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c
new file mode 100644
index 00000000..ab23c264
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "crypto.h"
+#define MESH_LOG_MODULE BLE_MESH_LOG
+
+static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
+{
+ dst[0] = a[0] ^ b[0];
+ dst[1] = a[1] ^ b[1];
+ dst[2] = a[2] ^ b[2];
+ dst[3] = a[3] ^ b[3];
+ dst[4] = a[4] ^ b[4];
+ dst[5] = a[5] ^ b[5];
+ dst[6] = a[6] ^ b[6];
+ dst[7] = a[7] ^ b[7];
+ dst[8] = a[8] ^ b[8];
+ dst[9] = a[9] ^ b[9];
+ dst[10] = a[10] ^ b[10];
+ dst[11] = a[11] ^ b[11];
+ dst[12] = a[12] ^ b[12];
+ dst[13] = a[13] ^ b[13];
+ dst[14] = a[14] ^ b[14];
+ dst[15] = a[15] ^ b[15];
+}
+
+/* pmsg is assumed to have the nonce already present in bytes 1-13 */
+static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
+ size_t mic_size, uint8_t msg_len, uint8_t b[16],
+ uint8_t X0[16])
+{
+ int i, j, err;
+
+ /* X_0 = e(AppKey, flags || nonce || length) */
+ b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;
+
+ sys_put_be16(msg_len, b + 14);
+
+ err = bt_encrypt_be(key, b, X0);
+ if (err) {
+ return err;
+ }
+
+ /* If AAD is being used to authenticate, include it here */
+ if (aad_len) {
+ sys_put_be16(aad_len, b);
+
+ for (i = 0; i < sizeof(uint16_t); i++) {
+ b[i] = X0[i] ^ b[i];
+ }
+
+ j = 0;
+ aad_len += sizeof(uint16_t);
+ while (aad_len > 16) {
+ do {
+ b[i] = X0[i] ^ aad[j];
+ i++, j++;
+ } while (i < 16);
+
+ aad_len -= 16;
+ i = 0;
+
+ err = bt_encrypt_be(key, b, X0);
+ if (err) {
+ return err;
+ }
+ }
+
+ for (; i < aad_len; i++, j++) {
+ b[i] = X0[i] ^ aad[j];
+ }
+
+ for (i = aad_len; i < 16; i++) {
+ b[i] = X0[i];
+ }
+
+ err = bt_encrypt_be(key, b, X0);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int ccm_auth(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t *cleartext_msg, size_t msg_len, const uint8_t *aad,
+ size_t aad_len, uint8_t *mic, size_t mic_size)
+{
+ uint8_t b[16], Xn[16], s0[16];
+ uint16_t blk_cnt, last_blk;
+ int err, j, i;
+
+ last_blk = msg_len % 16;
+ blk_cnt = (msg_len + 15) / 16;
+ if (!last_blk) {
+ last_blk = 16U;
+ }
+
+ b[0] = 0x01;
+ memcpy(b + 1, nonce, 13);
+
+ /* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
+ sys_put_be16(0x0000, &b[14]);
+
+ err = bt_encrypt_be(key, b, s0);
+ if (err) {
+ return err;
+ }
+
+ ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);
+
+ for (j = 0; j < blk_cnt; j++) {
+ /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
+ if (j + 1 == blk_cnt) {
+ for (i = 0; i < last_blk; i++) {
+ b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
+ }
+
+ memcpy(&b[i], &Xn[i], 16 - i);
+ } else {
+ xor16(b, Xn, &cleartext_msg[j * 16]);
+ }
+
+ err = bt_encrypt_be(key, b, Xn);
+ if (err) {
+ return err;
+ }
+ }
+
+ /* MIC = C_mic ^ X_1 */
+ for (i = 0; i < mic_size; i++) {
+ mic[i] = s0[i] ^ Xn[i];
+ }
+
+ return 0;
+}
+
+static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
+ const uint8_t *in_msg, uint8_t *out_msg, size_t msg_len)
+{
+ uint8_t a_i[16], s_i[16];
+ uint16_t last_blk, blk_cnt;
+ size_t i, j;
+ int err;
+
+ last_blk = msg_len % 16;
+ blk_cnt = (msg_len + 15) / 16;
+ if (!last_blk) {
+ last_blk = 16U;
+ }
+
+ a_i[0] = 0x01;
+ memcpy(&a_i[1], nonce, 13);
+
+ for (j = 0; j < blk_cnt; j++) {
+ /* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
+ sys_put_be16(j + 1, &a_i[14]);
+
+ err = bt_encrypt_be(key, a_i, s_i);
+ if (err) {
+ return err;
+ }
+
+ /* Encrypted = Payload[0-15] ^ C_1 */
+ if (j < blk_cnt - 1) {
+ xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
+ } else {
+ for (i = 0; i < last_blk; i++) {
+ out_msg[(j * 16) + i] =
+ in_msg[(j * 16) + i] ^ s_i[i];
+ }
+ }
+ }
+ return 0;
+}
+
+int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_msg,
+ size_t msg_len, const uint8_t *aad, size_t aad_len,
+ uint8_t *out_msg, size_t mic_size)
+{
+ uint8_t mic[16];
+
+ if (aad_len >= 0xff00 || mic_size > sizeof(mic)) {
+ return -EINVAL;
+ }
+
+ ccm_crypt(key, nonce, enc_msg, out_msg, msg_len);
+
+ ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
+
+ if (memcmp(mic, enc_msg + msg_len, mic_size)) {
+ return -EBADMSG;
+ }
+
+ return 0;
+}
+
+int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *msg,
+ size_t msg_len, const uint8_t *aad, size_t aad_len,
+ uint8_t *out_msg, size_t mic_size)
+{
+ uint8_t *mic = out_msg + msg_len;
+
+ BT_DBG("key %s", bt_hex(key, 16));
+ BT_DBG("nonce %s", bt_hex(nonce, 13));
+ BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
+ BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
+
+ /* Unsupported AAD size */
+ if (aad_len >= 0xff00 || mic_size > 16) {
+ return -EINVAL;
+ }
+
+ ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
+
+ ccm_crypt(key, nonce, msg, out_msg, msg_len);
+
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c
new file mode 100644
index 00000000..a6c32bf3
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "mesh/mesh.h"
+#include "mesh_priv.h"
+#include "net.h"
+#include "app_keys.h"
+#include "rpl.h"
+#include "settings.h"
+#include "crypto.h"
+#include "adv.h"
+#include "proxy.h"
+#include "friend.h"
+#include "foundation.h"
+#include "access.h"
+#include "subnet.h"
+
+#define MESH_LOG_MODULE BLE_MESH_LOG
+#include "log/log.h"
+
+static struct bt_mesh_app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = {
+ [0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
+ .app_idx = BT_MESH_KEY_UNUSED,
+ .net_idx = BT_MESH_KEY_UNUSED,
+ }
+};
+
+static void app_key_evt(struct bt_mesh_app_key *app, enum bt_mesh_key_evt evt)
+{
+ int i;
+
+ for (i = 0; i < (sizeof(bt_mesh_app_key_cb_list)/sizeof(void *)); i++) {
+ if (bt_mesh_app_key_cb_list[i]) {
+ BT_DBG("app_key_evt %d", i);
+ bt_mesh_app_key_cb_list[i] (app->app_idx, app->net_idx, evt);
+ }
+ }
+}
+
+struct bt_mesh_app_key *app_get(uint16_t app_idx)
+{
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ if (apps[i].app_idx == app_idx) {
+ return &apps[i];
+ }
+ }
+
+ return NULL;
+}
+
+static struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx)
+{
+ struct bt_mesh_app_key *app = NULL;
+
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ /* Check for already existing app_key */
+ if (apps[i].app_idx == app_idx) {
+ return &apps[i];
+ }
+
+ if (!app && apps[i].app_idx == BT_MESH_KEY_UNUSED) {
+ app = &apps[i];
+ }
+ }
+
+ return app;
+}
+
+static void app_key_del(struct bt_mesh_app_key *app)
+{
+ BT_DBG("AppIdx 0x%03x", app->app_idx);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_clear_app_key(app->app_idx);
+ }
+
+ app_key_evt(app, BT_MESH_KEY_DELETED);
+
+ app->net_idx = BT_MESH_KEY_UNUSED;
+ app->app_idx = BT_MESH_KEY_UNUSED;
+ (void)memset(app->keys, 0, sizeof(app->keys));
+}
+
+static void app_key_revoke(struct bt_mesh_app_key *app)
+{
+ if (!app->updated) {
+ return;
+ }
+
+ memcpy(&app->keys[0], &app->keys[1], sizeof(app->keys[0]));
+ memset(&app->keys[1], 0, sizeof(app->keys[1]));
+ app->updated = false;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_app_key(app->app_idx);
+ }
+
+ app_key_evt(app, BT_MESH_KEY_REVOKED);
+}
+
+
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ if (evt == BT_MESH_KEY_UPDATED || evt == BT_MESH_KEY_ADDED) {
+ return;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ struct bt_mesh_app_key *app = &apps[i];
+
+ if (app->app_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (app->net_idx != sub->net_idx) {
+ continue;
+ }
+
+ if (evt == BT_MESH_KEY_DELETED) {
+ app_key_del(app);
+ } else if (evt == BT_MESH_KEY_REVOKED) {
+ app_key_revoke(app);
+ } else if (evt == BT_MESH_KEY_SWAPPED && app->updated) {
+ app_key_evt(app, BT_MESH_KEY_SWAPPED);
+ }
+ }
+}
+
+
+uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t key[16])
+{
+ if (!bt_mesh_subnet_cb_list[0]) {
+ bt_mesh_subnet_cb_list[0] = subnet_evt;
+ }
+
+ struct bt_mesh_app_key *app;
+
+ BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
+ bt_hex(key, 16));
+
+ if (!bt_mesh_subnet_get(net_idx)) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ app = app_key_alloc(app_idx);
+ if (!app) {
+ return STATUS_INSUFF_RESOURCES;
+ }
+
+ if (app->app_idx == app_idx) {
+ if (app->net_idx != net_idx) {
+ return STATUS_INVALID_BINDING;
+ }
+
+ if (memcmp(key, app->keys[0].val, 16)) {
+ return STATUS_IDX_ALREADY_STORED;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ if (bt_mesh_app_id(key, &app->keys[0].id)) {
+ return STATUS_CANNOT_SET;
+ }
+
+ BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
+
+ app->net_idx = net_idx;
+ app->app_idx = app_idx;
+ app->updated = false;
+ memcpy(app->keys[0].val, key, 16);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing AppKey persistently");
+ bt_mesh_store_app_key(app->app_idx);
+ }
+
+ app_key_evt(app, BT_MESH_KEY_ADDED);
+
+ return STATUS_SUCCESS;
+}
+
+struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx)
+{
+ struct bt_mesh_app_key *app;
+
+ app = app_get(app_idx);
+ if (app) {
+ return app;
+ }
+
+ return NULL;
+}
+
+uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t key[16])
+{
+ struct bt_mesh_app_key *app;
+ struct bt_mesh_subnet *sub;
+
+ BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
+ bt_hex(key, 16));
+
+ app = app_get(app_idx);
+ if (!app) {
+ return STATUS_INVALID_APPKEY;
+ }
+
+ if (net_idx != BT_MESH_KEY_UNUSED && app->net_idx != net_idx) {
+ return STATUS_INVALID_BINDING;
+ }
+
+ sub = bt_mesh_subnet_get(app->net_idx);
+ if (!sub) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ /* The AppKey Update message shall generate an error when node
+ * is in normal operation, Phase 2, or Phase 3 or in Phase 1
+ * when the AppKey Update message on a valid AppKeyIndex when
+ * the AppKey value is different.
+ */
+ if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
+ return STATUS_CANNOT_UPDATE;
+ }
+
+ if (app->updated) {
+ if (memcmp(app->keys[1].val, key, 16)) {
+ return STATUS_IDX_ALREADY_STORED;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ if (bt_mesh_app_id(key, &app->keys[1].id)) {
+ return STATUS_CANNOT_UPDATE;
+ }
+
+ BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, app->keys[1].id);
+
+ app->updated = true;
+ memcpy(app->keys[1].val, key, 16);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing AppKey persistently");
+ bt_mesh_store_app_key(app->app_idx);
+ }
+
+ app_key_evt(app, BT_MESH_KEY_UPDATED);
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx)
+{
+ struct bt_mesh_app_key *app;
+
+ BT_DBG("AppIdx 0x%03x", app_idx);
+
+ if (net_idx != BT_MESH_KEY_UNUSED && !bt_mesh_subnet_get(net_idx)) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ app = app_get(app_idx);
+ if (!app) {
+ /* This could be a retry of a previous attempt that had its
+ * response lost, so pretend that it was a success.
+ */
+ return STATUS_SUCCESS;
+ }
+
+ if (net_idx != BT_MESH_KEY_UNUSED && net_idx != app->net_idx) {
+ return STATUS_INVALID_BINDING;
+ }
+
+ app_key_del(app);
+
+ return STATUS_SUCCESS;
+}
+
+int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t old_key[16], const uint8_t new_key[16])
+{
+ struct bt_mesh_app_key *app;
+
+ app = app_key_alloc(app_idx);
+ if (!app) {
+ return -ENOMEM;
+ }
+
+ if (app->app_idx == app_idx) {
+ return 0;
+ }
+
+ BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
+
+ memcpy(app->keys[0].val, old_key, 16);
+ if (bt_mesh_app_id(old_key, &app->keys[0].id)) {
+ return -EIO;
+ }
+
+ if (new_key) {
+ memcpy(app->keys[1].val, new_key, 16);
+ if (bt_mesh_app_id(new_key, &app->keys[1].id)) {
+ return -EIO;
+ }
+ }
+
+ app->net_idx = net_idx;
+ app->app_idx = app_idx;
+ app->updated = !!new_key;
+
+ return 0;
+}
+
+bool bt_mesh_app_key_exists(uint16_t app_idx)
+{
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ if (apps[i].app_idx == app_idx) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
+ off_t skip)
+{
+ size_t count = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ struct bt_mesh_app_key *app = &apps[i];
+
+ if (app->app_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (net_idx != BT_MESH_KEY_ANY && app->net_idx != net_idx) {
+ continue;
+ }
+
+ if (skip) {
+ skip--;
+ continue;
+ }
+
+ if (count >= max) {
+ return -ENOMEM;
+ }
+
+ app_idxs[count++] = app->app_idx;
+ }
+
+ return count;
+}
+
+int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
+ struct bt_mesh_subnet **sub,
+ const uint8_t *app_key[16], uint8_t *aid)
+{
+ struct bt_mesh_app_key *app = NULL;
+
+ if (BT_MESH_IS_DEV_KEY(ctx->app_idx)) {
+ /* With device keys, the application has to decide which subnet
+ * to send on.
+ */
+ *sub = bt_mesh_subnet_get(ctx->net_idx);
+ if (!*sub) {
+ BT_WARN("Unknown NetKey 0x%03x", ctx->net_idx);
+ return -EINVAL;
+ }
+
+ if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE &&
+ !bt_mesh_elem_find(ctx->addr)) {
+ struct bt_mesh_cdb_node *node;
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ BT_WARN("No DevKey for 0x%04x", ctx->addr);
+ return -EINVAL;
+ }
+
+ node = bt_mesh_cdb_node_get(ctx->addr);
+ if (!node) {
+ BT_WARN("No DevKey for 0x%04x", ctx->addr);
+ return -EINVAL;
+ }
+
+ *app_key = node->dev_key;
+ } else {
+ *app_key = bt_mesh.dev_key;
+ }
+
+ *aid = 0;
+ return 0;
+ }
+
+ app = app_get(ctx->app_idx);
+ if (!app) {
+ BT_WARN("Unknown AppKey 0x%03x", ctx->app_idx);
+ return -EINVAL;
+ }
+
+ *sub = bt_mesh_subnet_get(app->net_idx);
+ if (!*sub) {
+ BT_WARN("Unknown NetKey 0x%03x", app->net_idx);
+ return -EINVAL;
+ }
+
+ if ((*sub)->kr_phase == BT_MESH_KR_PHASE_2 && app->updated) {
+ *aid = app->keys[1].id;
+ *app_key = app->keys[1].val;
+ } else {
+ *aid = app->keys[0].id;
+ *app_key = app->keys[0].val;
+ }
+
+ return 0;
+}
+
+uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
+ struct bt_mesh_net_rx *rx,
+ int (*cb)(struct bt_mesh_net_rx *rx,
+ const uint8_t key[16], void *cb_data),
+ void *cb_data)
+{
+ int err, i;
+
+ if (dev_key) {
+ /* Attempt remote dev key first, as that is only available for
+ * provisioner devices, which normally don't interact with nodes
+ * that know their local dev key.
+ */
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB) &&
+ rx->net_if != BT_MESH_NET_IF_LOCAL) {
+ struct bt_mesh_cdb_node *node;
+
+ node = bt_mesh_cdb_node_get(rx->ctx.addr);
+ if (node && !cb(rx, node->dev_key, cb_data)) {
+ return BT_MESH_KEY_DEV_REMOTE;
+ }
+ }
+
+ /** Bluetooth Mesh Specification v1.0.1, section 3.4.3:
+ * The Device key is only valid for unicast addresses.
+ */
+ if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
+ err = cb(rx, bt_mesh.dev_key, cb_data);
+ if (!err) {
+ return BT_MESH_KEY_DEV_LOCAL;
+ }
+ }
+
+ return BT_MESH_KEY_UNUSED;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(apps); i++) {
+ const struct bt_mesh_app_key *app = &apps[i];
+ const struct bt_mesh_app_cred *cred;
+
+ if (app->app_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (app->net_idx != rx->sub->net_idx) {
+ continue;
+ }
+
+ if (rx->new_key && app->updated) {
+ cred = &app->keys[1];
+ } else {
+ cred = &app->keys[0];
+ }
+
+ if (cred->id != aid) {
+ continue;
+ }
+
+ err = cb(rx, cred->val, cb_data);
+ if (err) {
+ continue;
+ }
+
+ return app->app_idx;
+ }
+
+ return BT_MESH_KEY_UNUSED;
+}
+
+
+void bt_mesh_app_keys_reset(void)
+{
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ struct bt_mesh_app_key *app = &apps[i];
+
+ if (app->app_idx != BT_MESH_KEY_UNUSED) {
+ app_key_del(app);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h
new file mode 100644
index 00000000..d007b785
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _BT_MESH_APP_KEYS_H_
+#define _BT_MESH_APP_KEYS_H_
+
+#include "mesh/mesh.h"
+#include "subnet.h"
+
+/** Mesh Application. */
+struct bt_mesh_app_key {
+ uint16_t net_idx;
+ uint16_t app_idx;
+ bool updated;
+ struct bt_mesh_app_cred {
+ uint8_t id;
+ uint8_t val[16];
+ } keys[2];
+};
+
+/** @brief Reset the app keys module. */
+void bt_mesh_app_keys_reset(void);
+
+/** @brief Get the application key with the given AppIdx.
+ *
+ * @param app_idx App index.
+ *
+ * @return The matching application, or NULL if the application isn't known.
+ */
+struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx);
+
+/** @brief Initialize a new application key with the given parameters.
+ *
+ * @param app_idx AppIndex.
+ * @param net_idx NetIndex the application is bound to.
+ * @param old_key Current application key.
+ * @param new_key Updated application key, or NULL if not known.
+ *
+ * @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t old_key[16], const uint8_t new_key[16]);
+
+/** @brief Resolve the message encryption keys, given a message context.
+ *
+ * Will use the @c ctx::app_idx and @c ctx::net_idx fields to find a pair of
+ * message encryption keys. If @c ctx::app_idx represents a device key, the
+ * @c ctx::net_idx will be used to determine the net key. Otherwise, the
+ * @c ctx::net_idx parameter will be ignored.
+ *
+ * @param ctx Message context.
+ * @param sub Subnet return parameter.
+ * @param app_key Application return parameter.
+ * @param aid Application ID return parameter.
+ *
+ * @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
+ struct bt_mesh_subnet **sub,
+ const uint8_t *app_key[16], uint8_t *aid);
+
+/** @brief Iterate through all matching application keys and call @c cb on each.
+ *
+ * @param dev_key Whether to return device keys.
+ * @param aid 7 bit application ID to match.
+ * @param rx RX structure to match against.
+ * @param cb Callback to call for every valid app key.
+ * @param cb_data Callback data to pass to the callback.
+ *
+ * @return The AppIdx that yielded a 0-return from the callback.
+ */
+uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
+ struct bt_mesh_net_rx *rx,
+ int (*cb)(struct bt_mesh_net_rx *rx,
+ const uint8_t key[16], void *cb_data),
+ void *cb_data);
+
+struct bt_mesh_app_key *app_get(uint16_t app_idx);
+
+extern void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt);
+
+#endif /* _BT_MESH_APP_KEYS_H_ */ \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c
index cd540aa8..6a5fc5a1 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c
@@ -21,8 +21,8 @@
#include "crypto.h"
#include "beacon.h"
#include "foundation.h"
+#include "atomic.h"
-#define UNPROVISIONED_INTERVAL (K_SECONDS(5))
#define PROVISIONED_INTERVAL (K_SECONDS(10))
#define BEACON_TYPE_UNPROVISIONED 0x00
@@ -36,26 +36,12 @@
static struct k_delayed_work beacon_timer;
-static struct bt_mesh_subnet *cache_check(u8_t data[21])
+static int cache_check(struct bt_mesh_subnet *sub, void *beacon_data)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (!memcmp(sub->beacon_cache, data, 21)) {
- return sub;
- }
- }
-
- return NULL;
+ return !memcmp(sub->beacon_cache, beacon_data, 21);
}
-static void cache_add(u8_t data[21], struct bt_mesh_subnet *sub)
+static void cache_add(uint8_t data[21], struct bt_mesh_subnet *sub)
{
memcpy(sub->beacon_cache, data, 21);
}
@@ -72,16 +58,12 @@ static void beacon_complete(int err, void *user_data)
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
struct os_mbuf *buf)
{
- u8_t flags = bt_mesh_net_flags(sub);
+ uint8_t flags = bt_mesh_net_flags(sub);
struct bt_mesh_subnet_keys *keys;
net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE);
- if (sub->kr_flag) {
- keys = &sub->keys[1];
- } else {
- keys = &sub->keys[0];
- }
+ keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)];
net_buf_simple_add_u8(buf, flags);
@@ -103,43 +85,33 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
#define BEACON_THRESHOLD(sub) (K_SECONDS(10 * ((sub)->beacons_last + 1)) - \
K_SECONDS(5))
-static int secure_beacon_send(void)
+static int secure_beacon_send(struct bt_mesh_subnet *sub, void *cb_data)
{
static const struct bt_mesh_send_cb send_cb = {
.end = beacon_complete,
};
- u32_t now = k_uptime_get_32();
- int i;
+ uint32_t now = k_uptime_get_32();
+ struct os_mbuf *buf;
+ uint32_t time_diff;
BT_DBG("");
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
- struct os_mbuf *buf;
- u32_t time_diff;
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- time_diff = now - sub->beacon_sent;
- if (time_diff < K_SECONDS(600) &&
- time_diff < BEACON_THRESHOLD(sub)) {
- continue;
- }
+ time_diff = now - sub->beacon_sent;
+ if (time_diff < (600 * MSEC_PER_SEC) &&
+ time_diff < BEACON_THRESHOLD(sub)) {
+ return 0;
+ }
- buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT,
- K_NO_WAIT);
- if (!buf) {
- BT_ERR("Unable to allocate beacon buffer");
- return -ENOBUFS;
- }
+ buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT, K_NO_WAIT);
+ if (!buf) {
+ BT_ERR("Unable to allocate beacon buffer");
+ return -ENOMEM;
+ }
- bt_mesh_beacon_create(sub, buf);
+ bt_mesh_beacon_create(sub, buf);
- bt_mesh_adv_send(buf, &send_cb, sub);
- net_buf_unref(buf);
- }
+ bt_mesh_adv_send(buf, &send_cb, sub);
+ net_buf_unref(buf);
return 0;
}
@@ -147,9 +119,9 @@ static int secure_beacon_send(void)
static int unprovisioned_beacon_send(void)
{
const struct bt_mesh_prov *prov;
- u8_t uri_hash[16] = { 0 };
+ uint8_t uri_hash[16] = { 0 };
struct os_mbuf *buf;
- u16_t oob_info;
+ uint16_t oob_info;
BT_DBG("unprovisioned_beacon_send");
@@ -202,12 +174,11 @@ static int unprovisioned_beacon_send(void)
static void unprovisioned_beacon_recv(struct os_mbuf *buf)
{
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
const struct bt_mesh_prov *prov;
- u8_t *uuid;
- u16_t oob_info;
- u32_t uri_hash_val;
- u32_t *uri_hash = NULL;
+ uint8_t *uuid;
+ uint16_t oob_info;
+ uint32_t uri_hash_val;
+ uint32_t *uri_hash = NULL;
if (buf->om_len != 18 && buf->om_len != 22) {
BT_ERR("Invalid unprovisioned beacon length (%u)", buf->om_len);
@@ -231,13 +202,17 @@ static void unprovisioned_beacon_recv(struct os_mbuf *buf)
(bt_mesh_prov_oob_info_t)oob_info,
uri_hash);
}
-#endif
+}
+
+static void sub_update_beacon_observation(struct bt_mesh_subnet *sub)
+{
+ sub->beacons_last = sub->beacons_cur;
+ sub->beacons_cur = 0U;
}
static void update_beacon_observation(void)
{
static bool first_half;
- int i;
/* Observation period is 20 seconds, whereas the beacon timer
* runs every 10 seconds. We process what's happened during the
@@ -248,23 +223,15 @@ static void update_beacon_observation(void)
return;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- sub->beacons_last = sub->beacons_cur;
- sub->beacons_cur = 0;
- }
+ bt_mesh_subnet_foreach(sub_update_beacon_observation);
}
static void beacon_send(struct ble_npl_event *work)
{
/* Don't send anything if we have an active provisioning link */
- if ((MYNEWT_VAL(BLE_MESH_PROV)) && bt_prov_active()) {
- k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && bt_mesh_prov_active()) {
+ k_delayed_work_submit(&beacon_timer,
+ K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT)));
return;
}
@@ -272,34 +239,81 @@ static void beacon_send(struct ble_npl_event *work)
if (bt_mesh_is_provisioned()) {
update_beacon_observation();
- secure_beacon_send();
+ (void)bt_mesh_subnet_find(secure_beacon_send, NULL);
/* Only resubmit if beaconing is still enabled */
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED ||
+ if (bt_mesh_beacon_enabled() ||
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) {
k_delayed_work_submit(&beacon_timer,
PROVISIONED_INTERVAL);
}
- } else if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+
+ return;
+ }
+
+ if (IS_ENABLED(BLE_MESH_PB_ADV)) {
unprovisioned_beacon_send();
- k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
+ k_delayed_work_submit(&beacon_timer,
+ K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT)));
+ }
+}
+
+struct beacon_params {
+ const uint8_t *net_id;
+ const uint8_t *auth;
+ uint32_t iv_index;
+ uint8_t flags;
+
+ bool new_key;
+};
+
+static bool auth_match(struct bt_mesh_subnet_keys *keys,
+ const struct beacon_params *params)
+{
+ uint8_t net_auth[8];
+
+ if (memcmp(params->net_id, keys->net_id, 8)) {
+ return false;
+ }
+
+ bt_mesh_beacon_auth(keys->beacon, params->flags, keys->net_id,
+ params->iv_index, net_auth);
+
+ if (memcmp(params->auth, net_auth, 8)) {
+ BT_WARN("Authentication Value %s != %s",
+ bt_hex(params->auth, 8), bt_hex(net_auth, 8));
+ return false;
}
+
+ return true;
+}
+
+static int subnet_by_id(struct bt_mesh_subnet *sub, void *cb_data)
+{
+ struct beacon_params *params = cb_data;
+
+ for (int i = 0; i < ARRAY_SIZE(sub->keys); i++) {
+ if (sub->keys[i].valid && auth_match(&sub->keys[i], params)) {
+ params->new_key = (i > 0);
+ return true;
+ }
+ }
+
+ return false;
}
static void secure_beacon_recv(struct os_mbuf *buf)
{
- u8_t *data, *net_id, *auth;
+ struct beacon_params params;
struct bt_mesh_subnet *sub;
- u32_t iv_index;
- bool new_key, kr_change, iv_change;
- u8_t flags;
+ uint8_t *data;
if (buf->om_len < 21) {
BT_ERR("Too short secure beacon (len %u)", buf->om_len);
return;
}
- sub = cache_check(buf->om_data);
+ sub = bt_mesh_subnet_find(cache_check, buf->om_data);
if (sub) {
/* We've seen this beacon before - just update the stats */
goto update_stats;
@@ -308,27 +322,30 @@ static void secure_beacon_recv(struct os_mbuf *buf)
/* So we can add to the cache if auth matches */
data = buf->om_data;
- flags = net_buf_simple_pull_u8(buf);
- net_id = net_buf_simple_pull_mem(buf, 8);
- iv_index = net_buf_simple_pull_be32(buf);
- auth = buf->om_data;
+ params.flags = net_buf_simple_pull_u8(buf);
+ params.net_id = net_buf_simple_pull_mem(buf, 8);
+ params.iv_index = net_buf_simple_pull_be32(buf);
+ params.auth = buf->om_data;
BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
- flags, bt_hex(net_id, 8), (unsigned) iv_index);
+ params.flags, bt_hex(params.net_id, 8), params.iv_index);
- sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
+ sub = bt_mesh_subnet_find(subnet_by_id, &params);
if (!sub) {
BT_DBG("No subnet that matched beacon");
return;
}
- if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
+ if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !params.new_key) {
BT_WARN("Ignoring Phase 2 KR Update secured using old key");
return;
}
cache_add(data, sub);
+ bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(params.flags),
+ params.new_key);
+
/* If we have NetKey0 accept initiation only from it */
if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
sub->net_idx != BT_MESH_KEY_PRIMARY) {
@@ -337,31 +354,18 @@ static void secure_beacon_recv(struct os_mbuf *buf)
}
BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
- sub->net_idx, (unsigned) iv_index, (unsigned) bt_mesh.iv_index);
+ sub->net_idx, params.iv_index, bt_mesh.iv_index);
if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) &&
(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ==
- BT_MESH_IV_UPDATE(flags))) {
+ BT_MESH_IV_UPDATE(params.flags))) {
bt_mesh_beacon_ivu_initiator(false);
}
- iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));
-
- kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
- if (kr_change) {
- bt_mesh_net_beacon_update(sub);
- }
-
- if (iv_change) {
- /* Update all subnets */
- bt_mesh_net_sec_update(NULL);
- } else if (kr_change) {
- /* Key Refresh without IV Update only impacts one subnet */
- bt_mesh_net_sec_update(sub);
- }
+ bt_mesh_net_iv_update(params.iv_index, BT_MESH_IV_UPDATE(params.flags));
update_stats:
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
+ if (bt_mesh_beacon_enabled() &&
sub->beacons_cur < 0xff) {
sub->beacons_cur++;
}
@@ -369,7 +373,7 @@ update_stats:
void bt_mesh_beacon_recv(struct os_mbuf *buf)
{
- u8_t type;
+ uint8_t type;
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
@@ -381,7 +385,9 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
type = net_buf_simple_pull_u8(buf);
switch (type) {
case BEACON_TYPE_UNPROVISIONED:
- unprovisioned_beacon_recv(buf);
+ if (IS_ENABLED(BLE_MESH_PB_ADV)) {
+ unprovisioned_beacon_recv(buf);
+ }
break;
case BEACON_TYPE_SECURE:
secure_beacon_recv(buf);
@@ -392,8 +398,38 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
}
}
+void bt_mesh_beacon_update(struct bt_mesh_subnet *sub)
+{
+ uint8_t flags = bt_mesh_net_flags(sub);
+ struct bt_mesh_subnet_keys *keys;
+ int err;
+
+ keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)];
+
+ BT_DBG("NetIndex 0x%03x Using %s key", sub->net_idx,
+ SUBNET_KEY_TX_IDX(sub) ? "new" : "current");
+ BT_DBG("flags 0x%02x, IVI 0x%08x", flags, bt_mesh.iv_index);
+
+ err = bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
+ bt_mesh.iv_index, sub->auth);
+ if (err) {
+ BT_ERR("Failed updating net beacon for 0x%03x", sub->net_idx);
+ }
+}
+
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ if (evt != BT_MESH_KEY_DELETED) {
+ bt_mesh_beacon_update(sub);
+ }
+}
+
void bt_mesh_beacon_init(void)
{
+ if (!bt_mesh_subnet_cb_list[1]) {
+ bt_mesh_subnet_cb_list[1] = subnet_evt;
+ }
+
k_delayed_work_init(&beacon_timer, beacon_send);
}
@@ -402,35 +438,30 @@ void bt_mesh_beacon_ivu_initiator(bool enable)
atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable);
if (enable) {
- k_work_submit(&beacon_timer.work);
- } else if (bt_mesh_beacon_get() == BT_MESH_BEACON_DISABLED) {
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
+ } else if (!bt_mesh_beacon_enabled()) {
k_delayed_work_cancel(&beacon_timer);
}
}
-void bt_mesh_beacon_enable(void)
+static void subnet_beacon_enable(struct bt_mesh_subnet *sub)
{
- int i;
+ sub->beacons_last = 0U;
+ sub->beacons_cur = 0U;
+
+ bt_mesh_beacon_update(sub);
+}
+void bt_mesh_beacon_enable(void)
+{
if (!bt_mesh_is_provisioned()) {
- k_work_submit(&beacon_timer.work);
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
return;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- sub->beacons_last = 0;
- sub->beacons_cur = 0;
-
- bt_mesh_net_beacon_update(sub);
- }
+ bt_mesh_subnet_foreach(subnet_beacon_enable);
- k_work_submit(&beacon_timer.work);
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
}
void bt_mesh_beacon_disable(void)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h
index ac4bfed8..a6aa8cbb 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h
@@ -22,5 +22,6 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
struct os_mbuf *buf);
void bt_mesh_beacon_init(void);
+void bt_mesh_beacon_update(struct bt_mesh_subnet *sub);
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c
new file mode 100644
index 00000000..bcca3b90
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2019 Tobias Svehagen
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if BLE_MESH_CDB
+#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_CDB)
+#define LOG_MODULE_NAME bt_mesh_cdb
+#include "log/log.h"
+
+#include "mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "settings.h"
+#include "mesh_priv.h"
+#include "mesh/glue.h"
+
+
+struct bt_mesh_cdb bt_mesh_cdb = {
+ .nodes = {
+ [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
+ .addr = BT_MESH_ADDR_UNASSIGNED,
+ }
+ },
+ .subnets = {
+ [0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = {
+ .net_idx = BT_MESH_KEY_UNUSED,
+ }
+ },
+ .app_keys = {
+ [0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
+ .net_idx = BT_MESH_KEY_UNUSED,
+ }
+ },
+};
+
+/*
+ * Check if an address range from addr_start for addr_start + num_elem - 1 is
+ * free for use. When a conflict is found, next will be set to the next address
+ * available after the conflicting range and -EAGAIN will be returned.
+ */
+static int addr_is_free(uint16_t addr_start, uint8_t num_elem, uint16_t *next)
+{
+ uint16_t addr_end = addr_start + num_elem - 1;
+ uint16_t other_start, other_end;
+ int i;
+
+ if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
+ !BT_MESH_ADDR_IS_UNICAST(addr_end) ||
+ num_elem == 0) {
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+ continue;
+ }
+
+ other_start = node->addr;
+ other_end = other_start + node->num_elem - 1;
+
+ if (!(addr_end < other_start || addr_start > other_end)) {
+ if (next) {
+ *next = other_end + 1;
+ }
+
+ return -EAGAIN;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Find the lowest possible starting address that can fit num_elem elements. If
+ * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
+ * returned. Otherwise the first address in the range is returned.
+ *
+ * NOTE: This is quite an ineffective algorithm as it might need to look
+ * through the array of nodes N+2 times. A more effective algorithm
+ * could be used if the nodes were stored in a sorted list.
+ */
+static uint16_t find_lowest_free_addr(uint8_t num_elem)
+{
+ uint16_t addr = 1, next = 0;
+ int err, i;
+
+ /*
+ * It takes a maximum of node count + 2 to find a free address if there
+ * is any. +1 for our own address and +1 for making sure that the
+ * address range is valid.
+ */
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) {
+ err = addr_is_free(addr, num_elem, &next);
+ if (err == 0) {
+ break;
+ } else if (err != -EAGAIN) {
+ addr = BT_MESH_ADDR_UNASSIGNED;
+ break;
+ }
+
+ addr = next;
+ }
+
+ return addr;
+}
+
+int bt_mesh_cdb_create(const uint8_t key[16])
+{
+ struct bt_mesh_cdb_subnet *sub;
+
+ if (atomic_test_and_set_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_VALID)) {
+ return -EALREADY;
+ }
+
+ sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY);
+ if (sub == NULL) {
+ return -ENOMEM;
+ }
+
+ memcpy(sub->keys[0].net_key, key, 16);
+ bt_mesh_cdb.iv_index = 0;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ bt_mesh_store_cdb_subnet(sub);
+ }
+
+ return 0;
+}
+
+void bt_mesh_cdb_clear(void)
+{
+ int i;
+
+ atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+ if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) {
+ bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) {
+ bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+ if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) {
+ bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true);
+ }
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ }
+}
+
+void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update)
+{
+ BT_DBG("Updating IV index to %d\n", iv_index);
+
+ bt_mesh_cdb.iv_index = iv_index;
+
+ atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS,
+ iv_update);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ }
+}
+
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx)
+{
+ struct bt_mesh_cdb_subnet *sub;
+ int i;
+
+ if (bt_mesh_cdb_subnet_get(net_idx) != NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ sub = &bt_mesh_cdb.subnets[i];
+
+ if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ sub->net_idx = net_idx;
+
+ return sub;
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store)
+{
+ BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+ bt_mesh_clear_cdb_subnet(sub);
+ }
+
+ sub->net_idx = BT_MESH_KEY_UNUSED;
+ memset(sub->keys, 0, sizeof(sub->keys));
+}
+
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ if (bt_mesh_cdb.subnets[i].net_idx == net_idx) {
+ return &bt_mesh_cdb.subnets[i];
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub)
+{
+ if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
+ bt_mesh_store_cdb_subnet(sub);
+ }
+}
+
+uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub)
+{
+ uint8_t flags = 0x00;
+
+ if (sub && sub->kr_flag) {
+ flags |= BT_MESH_NET_FLAG_KR;
+ }
+
+ if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) {
+ flags |= BT_MESH_NET_FLAG_IVU;
+ }
+
+ return flags;
+}
+
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem, uint16_t net_idx)
+{
+ int i;
+
+ if (addr == BT_MESH_ADDR_UNASSIGNED) {
+ addr = find_lowest_free_addr(num_elem);
+ if (addr == BT_MESH_ADDR_UNASSIGNED) {
+ return NULL;
+ }
+ } else if (addr_is_free(addr, num_elem, NULL) < 0) {
+ BT_DBG("Address range 0x%04x-0x%04x is not free", addr,
+ addr + num_elem - 1);
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+ memcpy(node->uuid, uuid, 16);
+ node->addr = addr;
+ node->num_elem = num_elem;
+ node->net_idx = net_idx;
+ atomic_set(node->flags, 0);
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store)
+{
+ BT_DBG("Node addr 0x%04x store %u", node->addr, store);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+ bt_mesh_clear_cdb_node(node);
+ }
+
+ node->addr = BT_MESH_ADDR_UNASSIGNED;
+ memset(node->dev_key, 0, sizeof(node->dev_key));
+}
+
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (addr >= node->addr &&
+ addr <= node->addr + node->num_elem - 1) {
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node)
+{
+ if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+}
+
+void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+ if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) {
+ continue;
+ }
+
+ if (func(&bt_mesh_cdb.nodes[i], user_data) ==
+ BT_MESH_CDB_ITER_STOP) {
+ break;
+ }
+ }
+}
+
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
+ uint16_t app_idx)
+{
+ struct bt_mesh_cdb_app_key *key;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+ key = &bt_mesh_cdb.app_keys[i];
+
+ if (key->net_idx != BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ key->net_idx = net_idx;
+ key->app_idx = app_idx;
+
+ return key;
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store)
+{
+ BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
+ bt_mesh_clear_cdb_app_key(key);
+ }
+
+ key->net_idx = BT_MESH_ADDR_UNASSIGNED;
+ memset(key->keys, 0, sizeof(key->keys));
+}
+
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) {
+ struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i];
+
+ if (key->net_idx != BT_MESH_KEY_UNUSED &&
+ key->app_idx == app_idx) {
+ return key;
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key)
+{
+ if (MYNEWT_VAL(BLE_MESH_SETTINGS)) {
+ bt_mesh_store_cdb_app_key(key);
+ }
+}
+#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c
new file mode 100644
index 00000000..4e149255
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mesh/mesh.h"
+#include "mesh_priv.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "settings.h"
+#include "heartbeat.h"
+#include "friend.h"
+#include "cfg.h"
+#include "mesh/glue.h"
+
+void bt_mesh_beacon_set(bool beacon)
+{
+ if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) {
+ return;
+ }
+
+ atomic_set_bit_to(bt_mesh.flags, BT_MESH_BEACON, beacon);
+
+ if (beacon) {
+ bt_mesh_beacon_enable();
+ } else {
+ bt_mesh_beacon_disable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+}
+
+bool bt_mesh_beacon_enabled(void)
+{
+ return atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON);
+}
+
+static int feature_set(int feature_flag, enum bt_mesh_feat_state state)
+{
+ if (state != BT_MESH_FEATURE_DISABLED &&
+ state != BT_MESH_FEATURE_ENABLED) {
+ return -EINVAL;
+ }
+
+ if (atomic_test_bit(bt_mesh.flags, feature_flag) ==
+ (state == BT_MESH_FEATURE_ENABLED)) {
+ return -EALREADY;
+ }
+
+ atomic_set_bit_to(bt_mesh.flags, feature_flag,
+ (state == BT_MESH_FEATURE_ENABLED));
+
+ return 0;
+}
+
+static enum bt_mesh_feat_state feature_get(int feature_flag)
+{
+ return atomic_test_bit(bt_mesh.flags, feature_flag) ?
+ BT_MESH_FEATURE_ENABLED :
+ BT_MESH_FEATURE_DISABLED;
+}
+
+int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy)
+{
+ int err;
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_GATT_PROXY, gatt_proxy);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_PROXY);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void)
+{
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ return BT_MESH_FEATURE_NOT_SUPPORTED;
+ }
+
+ return feature_get(BT_MESH_GATT_PROXY);
+}
+
+int bt_mesh_default_ttl_set(uint8_t default_ttl)
+{
+ if (default_ttl == 1 || default_ttl > BT_MESH_TTL_MAX) {
+ return -EINVAL;
+ }
+
+ if (default_ttl == bt_mesh.default_ttl) {
+ return 0;
+ }
+
+ bt_mesh.default_ttl = default_ttl;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+uint8_t bt_mesh_default_ttl_get(void)
+{
+ return bt_mesh.default_ttl;
+}
+
+int bt_mesh_friend_set(enum bt_mesh_feat_state friendship)
+{
+ int err;
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_FRIEND, friendship);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_FRIEND);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ if (friendship == BT_MESH_FEATURE_DISABLED) {
+ bt_mesh_friends_clear();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_friend_get(void)
+{
+ if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ return BT_MESH_FEATURE_NOT_SUPPORTED;
+ }
+
+ return feature_get(BT_MESH_FRIEND);
+}
+
+void bt_mesh_net_transmit_set(uint8_t xmit)
+{
+ if (bt_mesh.net_xmit == xmit) {
+ return;
+ }
+
+ bt_mesh.net_xmit = xmit;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+}
+
+uint8_t bt_mesh_net_transmit_get(void)
+{
+ return bt_mesh.net_xmit;
+}
+
+int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit)
+{
+ int err;
+
+ if (!CONFIG_BT_MESH_RELAY) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_RELAY, relay);
+ if (err == -EINVAL) {
+ return err;
+ }
+
+ if (err == -EALREADY && bt_mesh.relay_xmit == xmit) {
+ return -EALREADY;
+ }
+
+ bt_mesh.relay_xmit = xmit;
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_RELAY);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_relay_get(void)
+{
+ return feature_get(BT_MESH_RELAY);
+}
+
+uint8_t bt_mesh_relay_retransmit_get(void)
+{
+ if (!CONFIG_BT_MESH_RELAY) {
+ return 0;
+ }
+
+ return bt_mesh.relay_xmit;
+}
+
+bool bt_mesh_fixed_group_match(uint16_t addr)
+{
+ /* Check for fixed group addresses */
+ switch (addr) {
+ case BT_MESH_ADDR_ALL_NODES:
+ return true;
+ case BT_MESH_ADDR_PROXIES:
+ return (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED);
+ case BT_MESH_ADDR_FRIENDS:
+ return (bt_mesh_friend_get() == BT_MESH_FEATURE_ENABLED);
+ case BT_MESH_ADDR_RELAYS:
+ return (bt_mesh_relay_get() == BT_MESH_FEATURE_ENABLED);
+ default:
+ return false;
+ }
+}
+
+void bt_mesh_cfg_init(void)
+{
+ bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL;
+ bt_mesh.net_xmit =
+ BT_MESH_TRANSMIT(CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT,
+ CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL);
+
+#if defined(CONFIG_BT_MESH_RELAY)
+ bt_mesh.relay_xmit =
+ BT_MESH_TRANSMIT(CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT,
+ CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL);
+#endif
+
+ if (CONFIG_BT_MESH_RELAY_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_RELAY);
+ }
+
+ if (CONFIG_BT_MESH_BEACON_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_BEACON);
+ }
+
+ if (CONFIG_BT_MESH_GATT_PROXY_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_GATT_PROXY);
+ }
+
+ if (CONFIG_BT_MESH_FRIEND_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND);
+ }
+} \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h
new file mode 100644
index 00000000..6f58acf8
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void bt_mesh_cfg_init(void);
+
+bool bt_mesh_fixed_group_match(uint16_t addr); \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c
index 2c2f6c3f..a87cd7bb 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c
@@ -25,11 +25,11 @@
#define DUMMY_2_BYTE_OP BT_MESH_MODEL_OP_2(0xff, 0xff)
struct comp_data {
- u8_t *status;
+ uint8_t *status;
struct os_mbuf *comp;
};
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_cfg_cli *cli;
@@ -61,9 +61,9 @@ static void comp_data_status(struct bt_mesh_model *model,
static void state_status_u8(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf,
- u32_t expect_status)
+ uint32_t expect_status)
{
- u8_t *status;
+ uint8_t *status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -110,8 +110,8 @@ static void gatt_proxy_status(struct bt_mesh_model *model,
}
struct relay_param {
- u8_t *status;
- u8_t *transmit;
+ uint8_t *status;
+ uint8_t *transmit;
};
static void relay_status(struct bt_mesh_model *model,
@@ -137,8 +137,8 @@ static void relay_status(struct bt_mesh_model *model,
}
struct net_key_param {
- u8_t *status;
- u16_t net_idx;
+ uint8_t *status;
+ uint16_t net_idx;
};
static void net_key_status(struct bt_mesh_model *model,
@@ -146,8 +146,8 @@ static void net_key_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct net_key_param *param;
- u16_t net_idx, app_idx;
- u8_t status;
+ uint16_t net_idx;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -159,7 +159,7 @@ static void net_key_status(struct bt_mesh_model *model,
}
status = net_buf_simple_pull_u8(buf);
- key_idx_unpack(buf, &net_idx, &app_idx);
+ net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
param = cli->op_param;
if (param->net_idx != net_idx) {
@@ -174,10 +174,66 @@ static void net_key_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct net_key_list_param {
+ uint16_t *keys;
+ size_t *key_cnt;
+};
+
+static void net_key_list(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct net_key_list_param *param;
+ int i;
+
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_NET_KEY_LIST) {
+ BT_WARN("Unexpected Net Key List message");
+ return;
+ }
+
+ param = cli->op_param;
+
+ for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) {
+ key_idx_unpack(buf, &param->keys[i], &param->keys[i + 1]);
+ }
+
+ if (i < *param->key_cnt && buf->om_len >= 2) {
+ param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff;
+ }
+
+ *param->key_cnt = i;
+
+ k_sem_give(&cli->op_sync);
+}
+
+static void node_reset_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf)
+{
+ bool *param = NULL;
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x",
+ ctx->net_idx, ctx->app_idx, ctx->addr);
+
+ if (cli->op_pending != OP_NODE_RESET_STATUS) {
+ BT_WARN("Unexpected Node Reset Status message");
+ return;
+ }
+
+ param = cli->op_param;
+
+ if (param) {
+ *param = true;
+ }
+ k_sem_give(&cli->op_sync);
+}
+
struct app_key_param {
- u8_t *status;
- u16_t net_idx;
- u16_t app_idx;
+ uint8_t *status;
+ uint16_t net_idx;
+ uint16_t app_idx;
};
static void app_key_status(struct bt_mesh_model *model,
@@ -185,8 +241,8 @@ static void app_key_status(struct bt_mesh_model *model,
struct os_mbuf*buf)
{
struct app_key_param *param;
- u16_t net_idx, app_idx;
- u8_t status;
+ uint16_t net_idx, app_idx;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -213,21 +269,71 @@ static void app_key_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct app_key_list_param {
+ uint16_t net_idx;
+ uint8_t *status;
+ uint16_t *keys;
+ size_t *key_cnt;
+};
+
+static void app_key_list(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ struct app_key_list_param *param;
+ uint16_t net_idx;
+ uint8_t status;
+ int i;
+
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_APP_KEY_LIST) {
+ BT_WARN("Unexpected App Key List message");
+ return;
+ }
+
+ status = net_buf_simple_pull_u8(buf);
+ net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
+
+ param = cli->op_param;
+ if (param->net_idx != net_idx) {
+ BT_WARN("App Key List Net Key index did not match");
+ return;
+ }
+
+ for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) {
+ key_idx_unpack(buf, &param->keys[i], &param->keys[i + 1]);
+ }
+
+ if (i < *param->key_cnt && buf->om_len >= 2) {
+ param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff;
+ }
+
+ *param->key_cnt = i;
+ if (param->status) {
+ *param->status = status;
+ }
+
+ k_sem_give(&cli->op_sync);
+}
+
struct mod_app_param {
- u8_t *status;
- u16_t elem_addr;
- u16_t mod_app_idx;
- u16_t mod_id;
- u16_t cid;
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t mod_app_idx;
+ uint16_t mod_id;
+ uint16_t cid;
};
static void mod_app_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
struct mod_app_param *param;
- u8_t status;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -265,11 +371,92 @@ static void mod_app_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct mod_member_list_param {
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t mod_id;
+ uint16_t cid;
+ uint16_t *members;
+ size_t *member_cnt;
+};
+
+static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf, bool vnd)
+{
+ struct mod_member_list_param *param;
+ uint16_t elem_addr, mod_id, cid;
+ uint8_t status;
+ int i;
+
+ status = net_buf_simple_pull_u8(buf);
+ elem_addr = net_buf_simple_pull_le16(buf);
+ if (vnd) {
+ cid = net_buf_simple_pull_le16(buf);
+ }
+
+ mod_id = net_buf_simple_pull_le16(buf);
+
+ param = cli->op_param;
+ if (param->elem_addr != elem_addr || param->mod_id != mod_id ||
+ (vnd && param->cid != cid)) {
+ BT_WARN("Model Member List parameters did not match");
+ return;
+ }
+
+ if (buf->om_len % 2) {
+ BT_WARN("Model Member List invalid length");
+ return;
+ }
+
+ for (i = 0; i < *param->member_cnt && buf->om_len; i++) {
+ param->members[i] = net_buf_simple_pull_le16(buf);
+ }
+
+ *param->member_cnt = i;
+ if (param->status) {
+ *param->status = status;
+ }
+
+ k_sem_give(&cli->op_sync);
+}
+
+static void mod_app_list(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_SIG_MOD_APP_LIST) {
+ BT_WARN("Unexpected Model App List message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, false);
+}
+
+static void mod_app_list_vnd(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_VND_MOD_APP_LIST) {
+ BT_WARN("Unexpected Model App List Vendor message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, true);
+}
+
struct mod_pub_param {
- u16_t mod_id;
- u16_t cid;
- u16_t elem_addr;
- u8_t *status;
+ uint16_t mod_id;
+ uint16_t cid;
+ uint16_t elem_addr;
+ uint8_t *status;
struct bt_mesh_cfg_mod_pub *pub;
};
@@ -277,9 +464,9 @@ static void mod_pub_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t mod_id, cid, elem_addr;
+ uint16_t mod_id, cid, elem_addr;
struct mod_pub_param *param;
- u8_t status;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -341,21 +528,21 @@ static void mod_pub_status(struct bt_mesh_model *model,
}
struct mod_sub_param {
- u8_t *status;
- u16_t elem_addr;
- u16_t *sub_addr;
- u16_t *expect_sub;
- u16_t mod_id;
- u16_t cid;
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t *sub_addr;
+ uint16_t *expect_sub;
+ uint16_t mod_id;
+ uint16_t cid;
};
static void mod_sub_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t elem_addr, sub_addr, mod_id, cid;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
struct mod_sub_param *param;
- u8_t status;
+ uint8_t status;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -397,8 +584,40 @@ static void mod_sub_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+static void mod_sub_list(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_MOD_SUB_LIST) {
+ BT_WARN("Unexpected Model Subscription List message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, false);
+}
+
+static void mod_sub_list_vnd(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ struct os_mbuf *buf)
+{
+ BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
+ ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
+ bt_hex(buf->om_data, buf->om_len));
+
+ if (cli->op_pending != OP_MOD_SUB_LIST_VND) {
+ BT_WARN("Unexpected Model Subscription List Vendor message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, true);
+}
+
struct hb_sub_param {
- u8_t *status;
+ uint8_t *status;
struct bt_mesh_cfg_hb_sub *sub;
};
@@ -432,7 +651,7 @@ static void hb_sub_status(struct bt_mesh_model *model,
}
struct hb_pub_param {
- u8_t *status;
+ uint8_t *status;
struct bt_mesh_cfg_hb_pub *pub;
};
@@ -475,12 +694,19 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = {
{ OP_GATT_PROXY_STATUS, 1, gatt_proxy_status },
{ OP_RELAY_STATUS, 2, relay_status },
{ OP_NET_KEY_STATUS, 3, net_key_status },
+ { OP_NET_KEY_LIST, 0, net_key_list },
{ OP_APP_KEY_STATUS, 4, app_key_status },
+ { OP_APP_KEY_LIST, 3, app_key_list },
{ OP_MOD_APP_STATUS, 7, mod_app_status },
+ { OP_SIG_MOD_APP_LIST, 5, mod_app_list},
+ { OP_VND_MOD_APP_LIST, 7, mod_app_list_vnd},
{ OP_MOD_PUB_STATUS, 12, mod_pub_status },
{ OP_MOD_SUB_STATUS, 7, mod_sub_status },
+ { OP_MOD_SUB_LIST, 5, mod_sub_list},
+ { OP_MOD_SUB_LIST_VND, 7, mod_sub_list_vnd},
{ OP_HEARTBEAT_SUB_STATUS, 9, hb_sub_status },
{ OP_HEARTBEAT_PUB_STATUS, 10, hb_pub_status },
+ { OP_NODE_RESET_STATUS, 0, node_reset_status},
BT_MESH_MODEL_OP_END,
};
@@ -516,7 +742,7 @@ const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = {
.init = cfg_cli_init,
};
-static int cli_prepare(void *param, u32_t op)
+static int cli_prepare(void *param, uint32_t op)
{
if (!cli) {
BT_ERR("No available Configuration Client context!");
@@ -551,8 +777,8 @@ static int cli_wait(void)
return err;
}
-int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
- u8_t *status, struct os_mbuf *comp)
+int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
+ uint8_t *status, struct os_mbuf *comp)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEV_COMP_DATA_GET, 1);
struct bt_mesh_msg_ctx ctx = {
@@ -588,8 +814,8 @@ done:
return err;
}
-static int get_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
- u8_t *val)
+static int get_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp,
+ uint8_t *val)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -620,8 +846,8 @@ done:
return err;
}
-static int set_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
- u8_t new_val, u8_t *val)
+static int set_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp,
+ uint8_t new_val, uint8_t *val)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 1);
struct bt_mesh_msg_ctx ctx = {
@@ -653,57 +879,71 @@ done:
return err;
}
-int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_BEACON_GET, OP_BEACON_STATUS,
status);
}
-int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status)
+int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status)
{
return set_state_u8(net_idx, addr, OP_BEACON_SET, OP_BEACON_STATUS,
val, status);
}
-int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl)
+int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl)
{
return get_state_u8(net_idx, addr, OP_DEFAULT_TTL_GET,
OP_DEFAULT_TTL_STATUS, ttl);
}
-int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl)
+int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl)
{
return set_state_u8(net_idx, addr, OP_DEFAULT_TTL_SET,
OP_DEFAULT_TTL_STATUS, val, ttl);
}
-int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_FRIEND_GET,
OP_FRIEND_STATUS, status);
}
-int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status)
+int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status)
{
return set_state_u8(net_idx, addr, OP_FRIEND_SET, OP_FRIEND_STATUS,
val, status);
}
-int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_GATT_PROXY_GET,
OP_GATT_PROXY_STATUS, status);
}
-int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
- u8_t *status)
+int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
+ uint8_t *status)
{
return set_state_u8(net_idx, addr, OP_GATT_PROXY_SET,
OP_GATT_PROXY_STATUS, val, status);
}
-int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
- u8_t *transmit)
+int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
+ uint8_t val, uint8_t *transmit)
+{
+ return set_state_u8(net_idx, addr, OP_NET_TRANSMIT_SET,
+ OP_NET_TRANSMIT_STATUS, val, transmit);
+}
+
+int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
+ uint8_t *transmit)
+{
+ return get_state_u8(net_idx, addr, OP_NET_TRANSMIT_GET,
+ OP_NET_TRANSMIT_STATUS, transmit);
+}
+
+int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
+ uint8_t *transmit)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -738,8 +978,8 @@ done:
return err;
}
-int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
- u8_t new_transmit, u8_t *status, u8_t *transmit)
+int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
+ uint8_t new_transmit, uint8_t *status, uint8_t *transmit)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_SET, 2);
struct bt_mesh_msg_ctx ctx = {
@@ -776,8 +1016,8 @@ done:
return err;
}
-int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
- const u8_t net_key[16], u8_t *status)
+int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ const uint8_t net_key[16], uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_ADD, 18);
struct bt_mesh_msg_ctx ctx = {
@@ -819,9 +1059,85 @@ done:
return err;
}
-int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
- u16_t key_app_idx, const u8_t app_key[16],
- u8_t *status)
+int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
+ size_t *key_cnt)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_GET, 0);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct net_key_list_param param = {
+ .keys = keys,
+ .key_cnt = key_cnt,
+ };
+ int err;
+
+ err = cli_prepare(&param, OP_NET_KEY_LIST);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NET_KEY_GET);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ return err;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint8_t *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_DEL, 2);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct net_key_param param = {
+ .status = status,
+ .net_idx = key_net_idx,
+ };
+ int err;
+
+ err = cli_prepare(&param, OP_NET_KEY_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NET_KEY_DEL);
+ net_buf_simple_add_le16(msg, key_net_idx);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ return err;
+}
+
+int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ uint16_t key_app_idx, const uint8_t app_key[16],
+ uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_ADD, 19);
struct bt_mesh_msg_ctx ctx = {
@@ -864,9 +1180,137 @@ done:
return err;
}
-static int mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u16_t cid,
- u8_t *status)
+int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET, 0);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+
+ int err;
+
+ if (status) {
+ *status = false;
+ }
+
+ err = cli_prepare(status, OP_NODE_RESET_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NODE_RESET);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ if (err) {
+ return err;
+ } else {
+ return 0;
+ }
+}
+
+int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ uint8_t *status, uint16_t *keys, size_t *key_cnt)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_GET, 2);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct app_key_list_param param = {
+ .net_idx = key_net_idx,
+ .status = status,
+ .keys = keys,
+ .key_cnt = key_cnt,
+ };
+ int err;
+
+ err = cli_prepare(&param, OP_APP_KEY_LIST);
+ if (err) {
+ os_mbuf_free_chain(msg);
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_GET);
+ net_buf_simple_add_le16(msg, key_net_idx);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ os_mbuf_free_chain(msg);
+ cli_reset();
+ return err;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_DEL, 3);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct app_key_param param = {
+ .status = status,
+ .net_idx = key_net_idx,
+ .app_idx = key_app_idx,
+ };
+ int err;
+
+ err = cli_prepare(&param, OP_APP_KEY_STATUS);
+ if (err) {
+ os_mbuf_free_chain(msg);
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_DEL);
+ key_idx_pack(msg, key_net_idx, key_app_idx);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ os_mbuf_free_chain(msg);
+ cli_reset();
+ return err;
+ }
+
+ if (!status) {
+ cli_reset();
+ os_mbuf_free_chain(msg);
+ return 0;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+static int mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+ uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_BIND, 8);
struct bt_mesh_msg_ctx ctx = {
@@ -917,16 +1361,16 @@ done:
return err;
}
-int bt_mesh_cfg_mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u8_t *status)
+int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status)
{
return mod_app_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
CID_NVAL, status);
}
-int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u16_t cid,
- u8_t *status)
+int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+ uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -936,8 +1380,160 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
status);
}
-static int mod_sub(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid, u8_t *status)
+static int mod_app_unbind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+ uint8_t *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_UNBIND, 8);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct mod_app_param param = {
+ .status = status,
+ .elem_addr = elem_addr,
+ .mod_app_idx = mod_app_idx,
+ .mod_id = mod_id,
+ .cid = cid,
+ };
+ int err;
+
+ err = cli_prepare(&param, OP_MOD_APP_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_MOD_APP_UNBIND);
+ net_buf_simple_add_le16(msg, elem_addr);
+ net_buf_simple_add_le16(msg, mod_app_idx);
+
+ if (cid != CID_NVAL) {
+ net_buf_simple_add_le16(msg, cid);
+ }
+
+ net_buf_simple_add_le16(msg, mod_id);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ err = 0;
+ goto done;
+ }
+
+done:
+ os_mbuf_free_chain(msg);
+ if (err) {
+ return err;
+ } else {
+ return cli_wait();
+ }
+}
+
+int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t mod_app_idx,
+ uint16_t mod_id, uint8_t *status)
+{
+ return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
+ CID_NVAL, status);
+}
+
+int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t mod_app_idx,
+ uint16_t mod_id, uint16_t cid, uint8_t *status)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx,
+ mod_id, cid, status);
+}
+
+static int mod_member_list_get(uint32_t op, uint32_t expect_op, uint16_t net_idx,
+ uint16_t addr, uint16_t elem_addr, uint16_t mod_id,
+ uint16_t cid, uint8_t *status, uint16_t *apps,
+ size_t *app_cnt)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 6);
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = net_idx,
+ .app_idx = BT_MESH_KEY_DEV_REMOTE,
+ .addr = addr,
+ .send_ttl = BT_MESH_TTL_DEFAULT,
+ };
+ struct mod_member_list_param param = {
+ .status = status,
+ .elem_addr = elem_addr,
+ .mod_id = mod_id,
+ .cid = cid,
+ .members = apps,
+ .member_cnt = app_cnt,
+ };
+ int err;
+
+ err = cli_prepare(&param, expect_op);
+ if (err) {
+ goto done;
+ }
+
+ BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x",
+ net_idx, addr, elem_addr);
+ BT_DBG("mod_id 0x%04x cid 0x%04x op: %x", mod_id, cid, op);
+
+ bt_mesh_model_msg_init(msg, op);
+ net_buf_simple_add_le16(msg, elem_addr);
+
+ if (cid != CID_NVAL) {
+ net_buf_simple_add_le16(msg, cid);
+ }
+
+ net_buf_simple_add_le16(msg, mod_id);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ return err;
+}
+
+int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint8_t *status, uint16_t *apps,
+ size_t *app_cnt)
+{
+ return mod_member_list_get(OP_SIG_MOD_APP_GET, OP_SIG_MOD_APP_LIST,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, apps, app_cnt);
+}
+
+int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status,
+ uint16_t *apps, size_t *app_cnt)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_member_list_get(OP_VND_MOD_APP_GET, OP_VND_MOD_APP_LIST,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, apps, app_cnt);
+}
+
+static int mod_sub(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint16_t cid, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 8);
struct bt_mesh_msg_ctx ctx = {
@@ -979,6 +1575,7 @@ static int mod_sub(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
if (!status) {
cli_reset();
+ err = 0;
goto done;
}
@@ -988,16 +1585,16 @@ done:
return err;
}
-int bt_mesh_cfg_mod_sub_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status)
+int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint8_t *status)
{
return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr,
mod_id, CID_NVAL, status);
}
-int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid,
- u8_t *status)
+int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
+ uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1007,16 +1604,16 @@ int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, status);
}
-int bt_mesh_cfg_mod_sub_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status)
+int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint8_t *status)
{
return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr,
mod_id, CID_NVAL, status);
}
-int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid,
- u8_t *status)
+int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
+ uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1026,16 +1623,16 @@ int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, status);
}
-int bt_mesh_cfg_mod_sub_overwrite(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status)
+int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t sub_addr, uint16_t mod_id, uint8_t *status)
{
return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr,
sub_addr, mod_id, CID_NVAL, status);
}
-int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
- u16_t elem_addr, u16_t sub_addr,
- u16_t mod_id, u16_t cid, u8_t *status)
+int bt_mesh_cfg_mod_sub_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t sub_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1045,9 +1642,9 @@ int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
sub_addr, mod_id, cid, status);
}
-static int mod_sub_va(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id, u16_t cid,
- u16_t *virt_addr, u8_t *status)
+static int mod_sub_va(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id, uint16_t cid,
+ uint16_t *virt_addr, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 22);
struct bt_mesh_msg_ctx ctx = {
@@ -1102,17 +1699,17 @@ done:
return err;
}
-int bt_mesh_cfg_mod_sub_va_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t *virt_addr, uint8_t *status)
{
return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label,
mod_id, CID_NVAL, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t cid, u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t cid, uint16_t *virt_addr, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1122,17 +1719,17 @@ int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t *virt_addr, uint8_t *status)
{
return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label,
mod_id, CID_NVAL, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t cid, u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t cid, uint16_t *virt_addr, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1142,19 +1739,19 @@ int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_overwrite(u16_t net_idx, u16_t addr,
- u16_t elem_addr, const u8_t label[16],
- u16_t mod_id, u16_t *virt_addr,
- u8_t *status)
+int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, const uint8_t label[16],
+ uint16_t mod_id, uint16_t *virt_addr,
+ uint8_t *status)
{
return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr,
label, mod_id, CID_NVAL, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
- u16_t elem_addr, const u8_t label[16],
- u16_t mod_id, u16_t cid,
- u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, const uint8_t label[16],
+ uint16_t mod_id, uint16_t cid,
+ uint16_t *virt_addr, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1164,9 +1761,31 @@ int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
label, mod_id, cid, virt_addr, status);
}
-static int mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
+int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint8_t *status, uint16_t *subs,
+ size_t *sub_cnt)
+{
+ return mod_member_list_get(OP_MOD_SUB_GET, OP_MOD_SUB_LIST, net_idx,
+ addr, elem_addr, mod_id, CID_NVAL, status,
+ subs, sub_cnt);
+}
+
+int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status,
+ uint16_t *subs, size_t *sub_cnt)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_member_list_get(OP_MOD_SUB_GET_VND, OP_MOD_SUB_LIST_VND,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, subs, sub_cnt);
+}
+
+static int mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid,
+ struct bt_mesh_cfg_mod_pub *pub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_GET, 6);
struct bt_mesh_msg_ctx ctx = {
@@ -1217,17 +1836,17 @@ done:
return err;
}
-int bt_mesh_cfg_mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
- u8_t *status)
+int bt_mesh_cfg_mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
+ uint8_t *status)
{
return mod_pub_get(net_idx, addr, elem_addr, mod_id, CID_NVAL,
pub, status);
}
-int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
+int bt_mesh_cfg_mod_pub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid,
+ struct bt_mesh_cfg_mod_pub *pub, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1236,9 +1855,9 @@ int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
return mod_pub_get(net_idx, addr, elem_addr, mod_id, cid, pub, status);
}
-static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
+static int mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid,
+ struct bt_mesh_cfg_mod_pub *pub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_SET, 13);
struct bt_mesh_msg_ctx ctx = {
@@ -1265,7 +1884,7 @@ static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
net_buf_simple_add_le16(msg, elem_addr);
net_buf_simple_add_le16(msg, pub->addr);
- net_buf_simple_add_le16(msg, (pub->app_idx | (pub->cred_flag << 12)));
+ net_buf_simple_add_le16(msg, (pub->app_idx & (pub->cred_flag << 12)));
net_buf_simple_add_u8(msg, pub->ttl);
net_buf_simple_add_u8(msg, pub->period);
net_buf_simple_add_u8(msg, pub->transmit);
@@ -1294,17 +1913,17 @@ done:
return err;
}
-int bt_mesh_cfg_mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
- u8_t *status)
+int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
+ uint8_t *status)
{
return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL,
pub, status);
}
-int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
+int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid,
+ struct bt_mesh_cfg_mod_pub *pub, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1313,8 +1932,8 @@ int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status);
}
-int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_sub *sub, u8_t *status)
+int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_sub *sub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_SET, 5);
struct bt_mesh_msg_ctx ctx = {
@@ -1357,8 +1976,8 @@ done:
return err;
}
-int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_sub *sub, u8_t *status)
+int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_sub *sub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -1398,8 +2017,8 @@ done:
return err;
}
-int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
- const struct bt_mesh_cfg_hb_pub *pub, u8_t *status)
+int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
+ const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_SET, 9);
struct bt_mesh_msg_ctx ctx = {
@@ -1444,8 +2063,8 @@ done:
return err;
}
-int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_pub *pub, u8_t *status)
+int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_pub *pub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -1485,12 +2104,12 @@ done:
return err;
}
-s32_t bt_mesh_cfg_cli_timeout_get(void)
+int32_t bt_mesh_cfg_cli_timeout_get(void)
{
return msg_timeout;
}
-void bt_mesh_cfg_cli_timeout_set(s32_t timeout)
+void bt_mesh_cfg_cli_timeout_set(int32_t timeout)
{
msg_timeout = timeout;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c
index 57aac90a..8a085bd7 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c
@@ -17,9 +17,12 @@
#include "mesh_priv.h"
#include "adv.h"
+#include "app_keys.h"
#include "net.h"
+#include "rpl.h"
#include "lpn.h"
#include "transport.h"
+#include "heartbeat.h"
#include "crypto.h"
#include "access.h"
#include "beacon.h"
@@ -28,12 +31,10 @@
#include "friend.h"
#include "testing.h"
#include "settings.h"
+#include "cfg.h"
-#define DEFAULT_TTL 7
-
-static struct bt_mesh_cfg_srv *conf;
-
-static struct label labels[CONFIG_BT_MESH_LABEL_COUNT];
+void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt);
static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
bool primary)
@@ -42,7 +43,7 @@ static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
int i;
if (net_buf_simple_tailroom(buf) <
- 4 + (elem->model_count * 2) + (elem->vnd_model_count * 2)) {
+ 4 + (elem->model_count * 2) + (elem->vnd_model_count * 4)) {
BT_ERR("Too large device composition");
return -E2BIG;
}
@@ -68,7 +69,7 @@ static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
static int comp_get_page_0(struct os_mbuf *buf)
{
- u16_t feat = 0;
+ uint16_t feat = 0;
const struct bt_mesh_comp *comp;
int i;
@@ -113,7 +114,7 @@ static void dev_comp_data_get(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
- u8_t page;
+ uint8_t page;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -145,7 +146,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
struct os_mbuf *buf, bool *vnd)
{
if (buf->om_len < 4) {
- u16_t id;
+ uint16_t id;
id = net_buf_simple_pull_le16(buf);
@@ -155,7 +156,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
return bt_mesh_model_find(elem, id);
} else {
- u16_t company, id;
+ uint16_t company, id;
company = net_buf_simple_pull_le16(buf);
id = net_buf_simple_pull_le16(buf);
@@ -169,25 +170,9 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
}
}
-static bool app_key_is_valid(u16_t app_idx)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != BT_MESH_KEY_UNUSED &&
- key->app_idx == app_idx) {
- return true;
- }
- }
-
- return false;
-}
-
-static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
- u16_t app_idx, u8_t cred_flag, u8_t ttl, u8_t period,
- u8_t retransmit, bool store)
+static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr,
+ uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period,
+ uint8_t retransmit, bool store)
{
if (!model->pub) {
return STATUS_NVAL_PUB_PARAM;
@@ -225,10 +210,20 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
return STATUS_SUCCESS;
}
- if (!bt_mesh_app_key_find(app_idx)) {
+ if (!bt_mesh_app_key_exists(app_idx)) {
return STATUS_INVALID_APPKEY;
}
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+ if (BT_MESH_ADDR_IS_VIRTUAL(model->pub->addr)) {
+ uint8_t *uuid = bt_mesh_va_label_get(model->pub->addr);
+
+ if (uuid) {
+ bt_mesh_va_del(uuid, NULL);
+ }
+ }
+#endif
+
model->pub->addr = pub_addr;
model->pub->key = app_idx;
model->pub->cred = cred_flag;
@@ -237,12 +232,12 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
model->pub->retransmit = retransmit;
if (model->pub->update) {
- s32_t period_ms;
+ int32_t period_ms;
period_ms = bt_mesh_model_pub_period_get(model);
BT_DBG("period %u ms", (unsigned) period_ms);
- if (period_ms) {
+ if (period_ms > 0) {
k_delayed_work_submit(&model->pub->timer, period_ms);
} else {
k_delayed_work_cancel(&model->pub->timer);
@@ -256,13 +251,13 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
return STATUS_SUCCESS;
}
-u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx)
+uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx)
{
int i;
BT_DBG("model %p key_idx 0x%03x", model, key_idx);
- if (!app_key_is_valid(key_idx)) {
+ if (!bt_mesh_app_key_exists(key_idx)) {
return STATUS_INVALID_APPKEY;
}
@@ -288,13 +283,13 @@ u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx)
return STATUS_INSUFF_RESOURCES;
}
-u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store)
+uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store)
{
int i;
BT_DBG("model %p key_idx 0x%03x store %u", model, key_idx, store);
- if (!app_key_is_valid(key_idx)) {
+ if (!bt_mesh_app_key_exists(key_idx)) {
return STATUS_INVALID_APPKEY;
}
@@ -318,240 +313,88 @@ u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store)
return STATUS_SUCCESS;
}
-struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx == BT_MESH_KEY_UNUSED) {
- return key;
- }
- }
-
- return NULL;
-}
-
-static u8_t app_key_set(u16_t net_idx, u16_t app_idx, const u8_t val[16],
- bool update)
+static void send_app_key_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ uint8_t status,
+ uint16_t app_idx, uint16_t net_idx)
{
- struct bt_mesh_app_keys *keys;
- struct bt_mesh_app_key *key;
- struct bt_mesh_subnet *sub;
-
- BT_DBG("net_idx 0x%04x app_idx %04x update %u val %s",
- net_idx, app_idx, update, bt_hex(val, 16));
-
- sub = bt_mesh_subnet_get(net_idx);
- if (!sub) {
- return STATUS_INVALID_NETKEY;
- }
-
- key = bt_mesh_app_key_find(app_idx);
- if (update) {
- if (!key) {
- return STATUS_INVALID_APPKEY;
- }
-
- if (key->net_idx != net_idx) {
- return STATUS_INVALID_BINDING;
- }
-
- keys = &key->keys[1];
-
- /* The AppKey Update message shall generate an error when node
- * is in normal operation, Phase 2, or Phase 3 or in Phase 1
- * when the AppKey Update message on a valid AppKeyIndex when
- * the AppKey value is different.
- */
- if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
- return STATUS_CANNOT_UPDATE;
- }
-
- if (key->updated) {
- if (memcmp(keys->val, val, 16)) {
- return STATUS_CANNOT_UPDATE;
- } else {
- return STATUS_SUCCESS;
- }
- }
-
- key->updated = true;
- } else {
- if (key) {
- if (key->net_idx == net_idx &&
- !memcmp(key->keys[0].val, val, 16)) {
- return STATUS_SUCCESS;
- }
-
- if (key->net_idx == net_idx) {
- return STATUS_IDX_ALREADY_STORED;
- } else {
- return STATUS_INVALID_NETKEY;
- }
- }
-
- key = bt_mesh_app_key_alloc(app_idx);
- if (!key) {
- return STATUS_INSUFF_RESOURCES;
- }
+ struct os_mbuf *msg = NET_BUF_SIMPLE(
+ BT_MESH_MODEL_BUF_LEN(OP_APP_KEY_STATUS, 4));
- keys = &key->keys[0];
- }
-
- if (bt_mesh_app_id(val, &keys->id)) {
- if (update) {
- key->updated = false;
- }
-
- return STATUS_STORAGE_FAIL;
- }
-
- BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, keys->id);
-
- key->net_idx = net_idx;
- key->app_idx = app_idx;
- memcpy(keys->val, val, 16);
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
+ net_buf_simple_add_u8(msg, status);
+ key_idx_pack(msg, net_idx, app_idx);
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing AppKey persistently");
- bt_mesh_store_app_key(key);
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ BT_ERR("Unable to send App Key Status response");
}
- return STATUS_SUCCESS;
+ os_mbuf_free_chain(msg);
}
static void app_key_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
-
- status = app_key_set(key_net_idx, key_app_idx, buf->om_data, false);
- BT_DBG("status 0x%02x", status);
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
+ status = bt_mesh_app_key_add(key_app_idx, key_net_idx, buf->om_data);
- os_mbuf_free_chain(msg);
+ send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
static void app_key_update(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
-
- status = app_key_set(key_net_idx, key_app_idx, buf->om_data, true);
+ status = bt_mesh_app_key_update(key_app_idx, key_net_idx, buf->om_data);
BT_DBG("status 0x%02x", status);
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
-
- os_mbuf_free_chain(msg);
+ send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
-struct unbind_data {
- u16_t app_idx;
- bool store;
-};
-
-static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
- bool vnd, bool primary, void *user_data)
+static void mod_app_key_del(struct bt_mesh_model *mod,
+ struct bt_mesh_elem *elem, bool vnd, bool primary,
+ void *user_data)
{
- struct unbind_data *data = user_data;
+ uint16_t *app_idx = user_data;
- mod_unbind(mod, data->app_idx, data->store);
+ mod_unbind(mod, *app_idx, true);
}
-void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store)
+static void app_key_evt(uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt)
{
- struct unbind_data data = { .app_idx = key->app_idx, .store = store };
-
- BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
-
- bt_mesh_model_foreach(_mod_unbind, &data);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_clear_app_key(key);
+ if (evt == BT_MESH_KEY_DELETED) {
+ bt_mesh_model_foreach(&mod_app_key_del, &app_idx);
}
-
- key->net_idx = BT_MESH_KEY_UNUSED;
- memset(key->keys, 0, sizeof(key->keys));
}
static void app_key_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- struct bt_mesh_app_key *key;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- if (!bt_mesh_subnet_get(key_net_idx)) {
- status = STATUS_INVALID_NETKEY;
- goto send_status;
- }
+ status = bt_mesh_app_key_del(key_app_idx, key_net_idx);
- key = bt_mesh_app_key_find(key_app_idx);
- if (!key) {
- /* Treat as success since the client might have missed a
- * previous response and is resending the request.
- */
- status = STATUS_SUCCESS;
- goto send_status;
- }
-
- if (key->net_idx != key_net_idx) {
- status = STATUS_INVALID_BINDING;
- goto send_status;
- }
-
- bt_mesh_app_key_del(key, true);
- status = STATUS_SUCCESS;
-
-send_status:
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
-
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
-
- os_mbuf_free_chain(msg);
+ send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
/* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */
@@ -564,8 +407,11 @@ static void app_key_get(struct bt_mesh_model *model,
struct os_mbuf *msg =
BT_MESH_MODEL_BUF(OP_APP_KEY_LIST,
3 + IDX_LEN(CONFIG_BT_MESH_APP_KEY_COUNT));
- u16_t get_idx, i, prev;
- u8_t status;
+ uint16_t app_idx[CONFIG_BT_MESH_APP_KEY_COUNT];
+ uint16_t get_idx;
+ uint8_t status;
+ ssize_t count;
+ int i;
get_idx = net_buf_simple_pull_le16(buf);
if (get_idx > 0xfff) {
@@ -577,7 +423,7 @@ static void app_key_get(struct bt_mesh_model *model,
bt_mesh_model_msg_init(msg, OP_APP_KEY_LIST);
- if (!bt_mesh_subnet_get(get_idx)) {
+ if (!bt_mesh_subnet_exists(get_idx)) {
status = STATUS_INVALID_NETKEY;
} else {
status = STATUS_SUCCESS;
@@ -590,25 +436,17 @@ static void app_key_get(struct bt_mesh_model *model,
goto send_status;
}
- prev = BT_MESH_KEY_UNUSED;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != get_idx) {
- continue;
- }
-
- if (prev == BT_MESH_KEY_UNUSED) {
- prev = key->app_idx;
- continue;
- }
+ count = bt_mesh_app_keys_get(get_idx, app_idx, ARRAY_SIZE(app_idx), 0);
+ if (count < 0 || count > ARRAY_SIZE(app_idx)) {
+ count = ARRAY_SIZE(app_idx);
+ }
- key_idx_pack(msg, prev, key->app_idx);
- prev = BT_MESH_KEY_UNUSED;
+ for (i = 0; i < count - 1; i += 2) {
+ key_idx_pack(msg, app_idx[i], app_idx[i + 1]);
}
- if (prev != BT_MESH_KEY_UNUSED) {
- net_buf_simple_add_le16(msg, prev);
+ if (i < count) {
+ net_buf_simple_add_le16(msg, app_idx[i]);
}
send_status:
@@ -631,7 +469,7 @@ static void beacon_get(struct bt_mesh_model *model,
bt_hex(buf->om_data, buf->om_len));
bt_mesh_model_msg_init(msg, OP_BEACON_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_beacon_get());
+ net_buf_simple_add_u8(msg, bt_mesh_beacon_enabled());
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Config Beacon Status response");
@@ -644,35 +482,20 @@ static void beacon_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_BEACON_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) {
- if (buf->om_data[0] != cfg->beacon) {
- cfg->beacon = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
-
- if (cfg->beacon) {
- bt_mesh_beacon_enable();
- } else {
- bt_mesh_beacon_disable();
- }
- }
- } else {
+ if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) {
BT_WARN("Invalid Config Beacon value 0x%02x", buf->om_data[0]);
goto done;
}
+ bt_mesh_beacon_set(buf->om_data[0]);
+
bt_mesh_model_msg_init(msg, OP_BEACON_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_beacon_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Config Beacon Status response");
@@ -709,29 +532,20 @@ static void default_ttl_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
+ int err;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] <= BT_MESH_TTL_MAX && buf->om_data[0] != 0x01) {
- if (cfg->default_ttl != buf->om_data[0]) {
- cfg->default_ttl = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
- } else {
+ err = bt_mesh_default_ttl_set(buf->om_data[0]);
+ if (err) {
BT_WARN("Prohibited Default TTL value 0x%02x", buf->om_data[0]);
goto done;
}
bt_mesh_model_msg_init(msg, OP_DEFAULT_TTL_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_default_ttl_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Default TTL Status response");
@@ -772,8 +586,6 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
-
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
@@ -783,35 +595,8 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
return;
}
- if (!(MYNEWT_VAL(BLE_MESH_GATT_PROXY)) ||
- bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
- goto send_status;
- }
-
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- goto send_status;
- }
+ (void)bt_mesh_gatt_proxy_set(buf->om_data[0]);
- BT_DBG("GATT Proxy 0x%02x -> 0x%02x", cfg->gatt_proxy, buf->om_data[0]);
-
- if (cfg->gatt_proxy == buf->om_data[0]) {
- goto send_status;
- }
-
- cfg->gatt_proxy = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
-
- bt_mesh_adv_update();
-
- if (cfg->hb_pub.feat & BT_MESH_FEAT_PROXY) {
- bt_mesh_heartbeat_send();
- }
-
-send_status:
send_gatt_proxy_status(model, ctx);
}
@@ -841,7 +626,6 @@ static void net_transmit_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -851,18 +635,10 @@ static void net_transmit_set(struct bt_mesh_model *model,
BT_MESH_TRANSMIT_COUNT(buf->om_data[0]),
BT_MESH_TRANSMIT_INT(buf->om_data[0]));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else {
- cfg->net_transmit = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
+ bt_mesh_net_transmit_set(buf->om_data[0]);
bt_mesh_model_msg_init(msg, OP_NET_TRANSMIT_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_net_transmit_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Network Transmit Status");
@@ -898,43 +674,18 @@ static void relay_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_STATUS, 2);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) {
- bool change;
-
- if (cfg->relay == BT_MESH_RELAY_NOT_SUPPORTED) {
- change = false;
- } else {
- change = (cfg->relay != buf->om_data[0]);
- cfg->relay = buf->om_data[0];
- cfg->relay_retransmit = buf->om_data[1];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
-
- BT_DBG("Relay 0x%02x (%s) xmit 0x%02x (count %u interval %u)",
- cfg->relay, change ? "changed" : "not changed",
- cfg->relay_retransmit,
- BT_MESH_TRANSMIT_COUNT(cfg->relay_retransmit),
- BT_MESH_TRANSMIT_INT(cfg->relay_retransmit));
-
- if ((cfg->hb_pub.feat & BT_MESH_FEAT_RELAY) && change) {
- bt_mesh_heartbeat_send();
- }
- } else {
+ if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) {
BT_WARN("Invalid Relay value 0x%02x", buf->om_data[0]);
goto done;
}
+ (void)bt_mesh_relay_set(buf->om_data[0], buf->om_data[1]);
+
bt_mesh_model_msg_init(msg, OP_RELAY_STATUS);
net_buf_simple_add_u8(msg, bt_mesh_relay_get());
net_buf_simple_add_u8(msg, bt_mesh_relay_retransmit_get());
@@ -950,9 +701,9 @@ done:
static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
struct bt_mesh_msg_ctx *ctx,
- u16_t elem_addr, u16_t pub_addr,
+ uint16_t elem_addr, uint16_t pub_addr,
bool vnd, struct bt_mesh_model *mod,
- u8_t status, u8_t *mod_id)
+ uint8_t status, uint8_t *mod_id)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_STATUS, 14);
@@ -964,11 +715,11 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
if (status != STATUS_SUCCESS) {
memset(net_buf_simple_add(msg, 7), 0, 7);
} else {
- u16_t idx_cred;
+ uint16_t idx_cred;
net_buf_simple_add_le16(msg, pub_addr);
- idx_cred = mod->pub->key | (u16_t)mod->pub->cred << 12;
+ idx_cred = mod->pub->key | (uint16_t)mod->pub->cred << 12;
net_buf_simple_add_le16(msg, idx_cred);
net_buf_simple_add_u8(msg, mod->pub->ttl);
net_buf_simple_add_u8(msg, mod->pub->period);
@@ -992,10 +743,10 @@ static void mod_pub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, pub_addr = 0;
+ uint16_t elem_addr, pub_addr = 0;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1039,11 +790,11 @@ static void mod_pub_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t retransmit, status, pub_ttl, pub_period, cred_flag;
- u16_t elem_addr, pub_addr, pub_app_idx;
+ uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
+ uint16_t elem_addr, pub_addr, pub_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
+ uint8_t *mod_id;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1097,102 +848,9 @@ send_status:
status, mod_id);
}
-struct label *get_label(u16_t index)
-{
- if (index >= ARRAY_SIZE(labels)) {
- return NULL;
- }
-
- return &labels[index];
-}
-
-#if CONFIG_BT_MESH_LABEL_COUNT > 0
-static inline void va_store(struct label *store)
-{
- atomic_set_bit(store->flags, BT_MESH_VA_CHANGED);
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_label();
- }
-}
-
-static struct label *va_find(const u8_t *label_uuid,
- struct label **free_slot)
-{
- struct label *match = NULL;
- int i;
-
- if (free_slot != NULL) {
- *free_slot = NULL;
- }
-
- for (i = 0; i < ARRAY_SIZE(labels); i++) {
- if (labels[i].ref == 0) {
- if (free_slot != NULL) {
- *free_slot = &labels[i];
- }
- continue;
- }
-
- if (!memcmp(labels[i].uuid, label_uuid, 16)) {
- match = &labels[i];
- }
- }
-
- return match;
-}
-
-static u8_t va_add(u8_t *label_uuid, u16_t *addr)
-{
- struct label *update, *free_slot = NULL;
-
- update = va_find(label_uuid, &free_slot);
- if (update) {
- update->ref++;
- va_store(update);
- return 0;
- }
-
- if (!free_slot) {
- return STATUS_INSUFF_RESOURCES;
- }
-
- if (bt_mesh_virtual_addr(label_uuid, addr) < 0) {
- return STATUS_UNSPECIFIED;
- }
-
- free_slot->ref = 1;
- free_slot->addr = *addr;
- memcpy(free_slot->uuid, label_uuid, 16);
- va_store(free_slot);
-
- return STATUS_SUCCESS;
-}
-
-static u8_t va_del(u8_t *label_uuid, u16_t *addr)
-{
- struct label *update;
-
- update = va_find(label_uuid, NULL);
- if (update) {
- update->ref--;
-
- if (addr) {
- *addr = update->addr;
- }
-
- va_store(update);
- }
-
- if (addr) {
- *addr = BT_MESH_ADDR_UNASSIGNED;
- }
-
- return STATUS_CANNOT_REMOVE;
-}
-
static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
{
- u8_t *label_uuid;
+ uint8_t *label_uuid;
size_t clear_count;
int i;
@@ -1207,13 +865,13 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
continue;
}
- label_uuid = bt_mesh_label_uuid_get(mod->groups[i]);
+ label_uuid = bt_mesh_va_label_get(mod->groups[i]);
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
clear_count++;
if (label_uuid) {
- va_del(label_uuid, NULL);
+ bt_mesh_va_del(label_uuid, NULL);
} else {
BT_ERR("Label UUID not found");
}
@@ -1226,12 +884,12 @@ static void mod_pub_va_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t retransmit, status, pub_ttl, pub_period, cred_flag;
- u16_t elem_addr, pub_addr, pub_app_idx;
+ uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
+ uint16_t elem_addr, pub_addr, pub_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1277,85 +935,25 @@ static void mod_pub_va_set(struct bt_mesh_model *model,
goto send_status;
}
- status = va_add(label_uuid, &pub_addr);
- if (status == STATUS_SUCCESS) {
- status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag,
- pub_ttl, pub_period, retransmit, true);
- }
-
-send_status:
- send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
- status, mod_id);
-}
-#else
-static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
-{
- size_t clear_count;
- int i;
-
- /* Unref stored labels related to this model */
- for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) {
- if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
- mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
- clear_count++;
- }
- }
-
- return clear_count;
-}
-
-static void mod_pub_va_set(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- u8_t *mod_id, status;
- struct bt_mesh_model *mod;
- struct bt_mesh_elem *elem;
- u16_t elem_addr, pub_addr = 0;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
- mod_id = net_buf_simple_pull(buf, 4);
-
- BT_DBG("elem_addr 0x%04x", elem_addr);
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- mod = NULL;
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- mod = get_model(elem, buf, &vnd);
- if (!mod) {
- status = STATUS_INVALID_MODEL;
+ status = bt_mesh_va_add(label_uuid, &pub_addr);
+ if (status != STATUS_SUCCESS) {
goto send_status;
}
- if (!mod->pub) {
- status = STATUS_NVAL_PUB_PARAM;
- goto send_status;
+ status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl,
+ pub_period, retransmit, true);
+ if (status != STATUS_SUCCESS) {
+ bt_mesh_va_del(label_uuid, NULL);
}
- pub_addr = mod->pub->addr;
- status = STATUS_INSUFF_RESOURCES;
-
send_status:
send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
status, mod_id);
}
-#endif /* MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 */
static void send_mod_sub_status(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx, u8_t status,
- u16_t elem_addr, u16_t sub_addr, u8_t *mod_id,
+ struct bt_mesh_msg_ctx *ctx, uint8_t status,
+ uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id,
bool vnd)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_SUB_STATUS, 9);
@@ -1386,12 +984,12 @@ static void mod_sub_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u8_t status;
- u16_t *entry;
+ uint8_t *mod_id;
+ uint8_t status;
+ uint16_t *entry;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1459,12 +1057,12 @@ static void mod_sub_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u16_t *match;
- u8_t status;
+ uint8_t *mod_id;
+ uint16_t *match;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1522,7 +1120,7 @@ send_status:
}
static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *user_data)
+ uint32_t depth, void *user_data)
{
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups));
@@ -1537,11 +1135,11 @@ static void mod_sub_overwrite(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u8_t status;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1605,9 +1203,9 @@ static void mod_sub_del_all(struct bt_mesh_model *model,
{
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
+ uint16_t elem_addr;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1649,12 +1247,12 @@ send_status:
}
struct mod_sub_list_ctx {
- u16_t elem_idx;
+ uint16_t elem_idx;
struct os_mbuf *msg;
};
static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *ctx)
+ uint32_t depth, void *ctx)
{
struct mod_sub_list_ctx *visit = ctx;
int count = 0;
@@ -1693,7 +1291,7 @@ static void mod_sub_get(struct bt_mesh_model *model,
struct mod_sub_list_ctx visit_ctx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u16_t addr, id;
+ uint16_t addr, id;
addr = net_buf_simple_pull_le16(buf);
if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
@@ -1748,9 +1346,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
+ struct mod_sub_list_ctx visit_ctx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u16_t company, addr, id;
+ uint16_t company, addr, id;
addr = net_buf_simple_pull_le16(buf);
if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
@@ -1789,8 +1388,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
net_buf_simple_add_le16(msg, company);
net_buf_simple_add_le16(msg, id);
+ visit_ctx.msg = msg;
+ visit_ctx.elem_idx = mod->elem_idx;
bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor,
- msg);
+ &visit_ctx);
send_list:
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -1802,18 +1403,17 @@ done:
}
-#if MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0
static void mod_sub_va_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u16_t *entry;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint16_t *entry;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1843,7 +1443,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
goto send_status;
}
- status = va_add(label_uuid, &sub_addr);
+ status = bt_mesh_va_add(label_uuid, &sub_addr);
if (status != STATUS_SUCCESS) {
goto send_status;
}
@@ -1851,6 +1451,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
if (bt_mesh_model_find_group(&mod, sub_addr)) {
/* Tried to add existing subscription */
status = STATUS_SUCCESS;
+ bt_mesh_va_del(label_uuid, NULL);
goto send_status;
}
@@ -1858,6 +1459,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED);
if (!entry) {
status = STATUS_INSUFF_RESOURCES;
+ bt_mesh_va_del(label_uuid, NULL);
goto send_status;
}
@@ -1882,13 +1484,13 @@ static void mod_sub_va_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u16_t *match;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint16_t *match;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1919,7 +1521,7 @@ static void mod_sub_va_del(struct bt_mesh_model *model,
goto send_status;
}
- status = va_del(label_uuid, &sub_addr);
+ status = bt_mesh_va_del(label_uuid, &sub_addr);
if (sub_addr == BT_MESH_ADDR_UNASSIGNED) {
goto send_status;
}
@@ -1950,12 +1552,12 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
+ uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1985,11 +1587,10 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model,
}
if (ARRAY_SIZE(mod->groups) > 0) {
- bt_mesh_model_tree_walk(bt_mesh_model_root(mod),
- mod_sub_clear_visitor, NULL);
-
- status = va_add(label_uuid, &sub_addr);
+ status = bt_mesh_va_add(label_uuid, &sub_addr);
if (status == STATUS_SUCCESS) {
+ bt_mesh_model_tree_walk(bt_mesh_model_root(mod),
+ mod_sub_clear_visitor, NULL);
mod->groups[0] = sub_addr;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
@@ -2008,131 +1609,10 @@ send_status:
send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
mod_id, vnd);
}
-#else
-static void mod_sub_va_add(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_model *mod;
- struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- mod = NULL;
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- mod = get_model(elem, buf, &vnd);
- if (!mod) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-
-static void mod_sub_va_del(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- if (!get_model(elem, buf, &vnd)) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-
-static void mod_sub_va_overwrite(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 18);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- if (!get_model(elem, buf, &vnd)) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-#endif /* MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 */
static void send_net_key_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
- u16_t idx, u8_t status)
+ uint16_t idx, uint8_t status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_STATUS, 3);
@@ -2152,9 +1632,8 @@ static void net_key_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
- int err;
+ uint8_t status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2164,72 +1643,16 @@ static void net_key_add(struct bt_mesh_model *model,
BT_DBG("idx 0x%04x", idx);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
- sub = &bt_mesh.sub[i];
- break;
- }
- }
-
- if (!sub) {
- send_net_key_status(model, ctx, idx,
- STATUS_INSUFF_RESOURCES);
- return;
- }
- }
-
- /* Check for already existing subnet */
- if (sub->net_idx == idx) {
- u8_t status;
-
- if (memcmp(buf->om_data, sub->keys[0].net, 16)) {
- status = STATUS_IDX_ALREADY_STORED;
- } else {
- status = STATUS_SUCCESS;
- }
-
- send_net_key_status(model, ctx, idx, status);
- return;
- }
-
- err = bt_mesh_net_keys_create(&sub->keys[0], buf->om_data);
- if (err) {
- send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
- return;
- }
-
- sub->net_idx = idx;
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing NetKey persistently");
- bt_mesh_store_subnet(sub);
- }
-
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
-
- if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- bt_mesh_proxy_beacon_send(sub);
- bt_mesh_adv_update();
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
+ status = bt_mesh_subnet_add(idx, buf->om_data);
+ send_net_key_status(model, ctx, idx, status);
}
static void net_key_update(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
- int err;
+ uint8_t status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2237,80 +1660,16 @@ static void net_key_update(struct bt_mesh_model *model,
return;
}
- BT_DBG("idx 0x%04x", idx);
-
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_net_key_status(model, ctx, idx, STATUS_INVALID_NETKEY);
- return;
- }
-
- /* The node shall successfully process a NetKey Update message on a
- * valid NetKeyIndex when the NetKey value is different and the Key
- * Refresh procedure has not been started, or when the NetKey value is
- * the same in Phase 1. The NetKey Update message shall generate an
- * error when the node is in Phase 2, or Phase 3.
- */
- switch (sub->kr_phase) {
- case BT_MESH_KR_NORMAL:
- if (!memcmp(buf->om_data, sub->keys[0].net, 16)) {
- return;
- }
- break;
- case BT_MESH_KR_PHASE_1:
- if (!memcmp(buf->om_data, sub->keys[1].net, 16)) {
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
- return;
- }
- /* fall through */
- case BT_MESH_KR_PHASE_2:
- case BT_MESH_KR_PHASE_3:
- send_net_key_status(model, ctx, idx, STATUS_CANNOT_UPDATE);
- return;
- }
-
- err = bt_mesh_net_keys_create(&sub->keys[1], buf->om_data);
- if (!err && ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND)))) {
- err = friend_cred_update(sub);
- }
-
- if (err) {
- send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
- return;
- }
-
- sub->kr_phase = BT_MESH_KR_PHASE_1;
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing NetKey persistently");
- bt_mesh_store_subnet(sub);
- }
-
- bt_mesh_net_beacon_update(sub);
-
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
-}
-
-static void hb_pub_disable(struct bt_mesh_cfg_srv *cfg)
-{
- BT_DBG("");
-
- cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_pub.count = 0;
- cfg->hb_pub.ttl = 0;
- cfg->hb_pub.period = 0;
+ status = bt_mesh_subnet_update(idx, buf->om_data);
- k_delayed_work_cancel(&cfg->hb_pub.timer);
+ send_net_key_status(model, ctx, idx, status);
}
static void net_key_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t del_idx;
- u8_t status;
+ uint16_t del_idx;
del_idx = net_buf_simple_pull_le16(buf);
if (del_idx > 0xfff) {
@@ -2320,28 +1679,18 @@ static void net_key_del(struct bt_mesh_model *model,
BT_DBG("idx 0x%04x", del_idx);
- sub = bt_mesh_subnet_get(del_idx);
- if (!sub) {
- /* This could be a retry of a previous attempt that had its
- * response lost, so pretend that it was a success.
- */
- status = STATUS_SUCCESS;
- goto send_status;
- }
-
/* The key that the message was encrypted with cannot be removed.
* The NetKey List must contain a minimum of one NetKey.
*/
if (ctx->net_idx == del_idx) {
- status = STATUS_CANNOT_REMOVE;
- goto send_status;
+ send_net_key_status(model, ctx, del_idx,
+ STATUS_CANNOT_REMOVE);
+ return;
}
- bt_mesh_subnet_del(sub, true);
- status = STATUS_SUCCESS;
+ bt_mesh_subnet_del(del_idx);
-send_status:
- send_net_key_status(model, ctx, del_idx, status);
+ send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS);
}
static void net_key_get(struct bt_mesh_model *model,
@@ -2351,29 +1700,23 @@ static void net_key_get(struct bt_mesh_model *model,
struct os_mbuf *msg =
BT_MESH_MODEL_BUF(OP_NET_KEY_LIST,
IDX_LEN(CONFIG_BT_MESH_SUBNET_COUNT));
- u16_t prev, i;
+ uint16_t net_idx[CONFIG_BT_MESH_SUBNET_COUNT];
+ ssize_t count;
+ int i;
bt_mesh_model_msg_init(msg, OP_NET_KEY_LIST);
- prev = BT_MESH_KEY_UNUSED;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (prev == BT_MESH_KEY_UNUSED) {
- prev = sub->net_idx;
- continue;
- }
+ count = bt_mesh_subnets_get(net_idx, ARRAY_SIZE(net_idx), 0);
+ if (count < 0 || count > ARRAY_SIZE(net_idx)) {
+ count = ARRAY_SIZE(net_idx);
+ }
- key_idx_pack(msg, prev, sub->net_idx);
- prev = BT_MESH_KEY_UNUSED;
+ for (i = 0; i < count - 1; i += 2) {
+ key_idx_pack(msg, net_idx[i], net_idx[i + 1]);
}
- if (prev != BT_MESH_KEY_UNUSED) {
- net_buf_simple_add_le16(msg, prev);
+ if (i < count) {
+ net_buf_simple_add_le16(msg, net_idx[i]);
}
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -2383,14 +1726,32 @@ static void net_key_get(struct bt_mesh_model *model,
os_mbuf_free_chain(msg);
}
+static void send_node_id_status(struct bt_mesh_model *model,
+ struct bt_mesh_msg_ctx *ctx,
+ uint8_t status,
+ uint16_t net_idx, uint8_t node_id)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
+
+ bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
+ net_buf_simple_add_u8(msg, status);
+ net_buf_simple_add_le16(msg, net_idx);
+ net_buf_simple_add_u8(msg, node_id);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ BT_ERR("Unable to send Node Identity Status");
+ }
+
+ os_mbuf_free_chain(msg);
+}
+
static void node_identity_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
- struct bt_mesh_subnet *sub;
- u8_t node_id;
- u16_t idx;
+ enum bt_mesh_feat_state node_id;
+ uint8_t status;
+ uint16_t idx;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -2399,39 +1760,20 @@ static void node_identity_get(struct bt_mesh_model *model,
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
- goto done;
- }
-
- bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
-
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- net_buf_simple_add_u8(msg, STATUS_INVALID_NETKEY);
- node_id = 0x00;
- } else {
- net_buf_simple_add_u8(msg, STATUS_SUCCESS);
- node_id = sub->node_id;
+ return;
}
- net_buf_simple_add_le16(msg, idx);
- net_buf_simple_add_u8(msg, node_id);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send Node Identity Status");
- }
+ status = bt_mesh_subnet_node_id_get(idx, &node_id);
-done:
- os_mbuf_free_chain(msg);
+ send_node_id_status(model, ctx, status, idx, node_id);
}
static void node_identity_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
- struct bt_mesh_subnet *sub;
- u8_t node_id;
- u16_t idx;
+ uint8_t node_id, status;
+ uint16_t idx;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -2440,51 +1782,36 @@ static void node_identity_set(struct bt_mesh_model *model,
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
BT_WARN("Invalid NetKeyIndex 0x%04x", idx);
- goto done;
+ return;
}
node_id = net_buf_simple_pull_u8(buf);
if (node_id != 0x00 && node_id != 0x01) {
BT_WARN("Invalid Node ID value 0x%02x", node_id);
- goto done;
+ return;
}
- bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
-
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- net_buf_simple_add_u8(msg, STATUS_INVALID_NETKEY);
- net_buf_simple_add_le16(msg, idx);
- net_buf_simple_add_u8(msg, node_id);
- } else {
- net_buf_simple_add_u8(msg, STATUS_SUCCESS);
- net_buf_simple_add_le16(msg, idx);
-
- if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) {
- if (node_id) {
- bt_mesh_proxy_identity_start(sub);
- } else {
- bt_mesh_proxy_identity_stop(sub);
- }
- bt_mesh_adv_update();
- }
-
- net_buf_simple_add_u8(msg, sub->node_id);
+ status = bt_mesh_subnet_node_id_set(idx, node_id);
+ if (status == STATUS_INVALID_NETKEY) {
+ send_node_id_status(model, ctx, status, idx,
+ BT_MESH_NODE_IDENTITY_STOPPED);
+ return;
}
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send Node Identity Status");
+ if (status == STATUS_FEAT_NOT_SUPP) {
+ /* Should return success, even if feature isn't supported: */
+ send_node_id_status(model, ctx, STATUS_SUCCESS, idx,
+ BT_MESH_NODE_IDENTITY_NOT_SUPPORTED);
+ return;
}
-done:
- os_mbuf_free_chain(msg);
-
+ send_node_id_status(model, ctx, status, idx, node_id);
}
static void create_mod_app_status(struct os_mbuf *msg,
struct bt_mesh_model *mod, bool vnd,
- u16_t elem_addr, u16_t app_idx,
- u8_t status, u8_t *mod_id)
+ uint16_t elem_addr, uint16_t app_idx,
+ uint8_t status, uint8_t *mod_id)
{
bt_mesh_model_msg_init(msg, OP_MOD_APP_STATUS);
@@ -2504,10 +1831,10 @@ static void mod_app_bind(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9);
- u16_t elem_addr, key_app_idx;
+ uint16_t elem_addr, key_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2565,10 +1892,10 @@ static void mod_app_unbind(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9);
- u16_t elem_addr, key_app_idx;
+ uint16_t elem_addr, key_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2626,8 +1953,8 @@ static void mod_app_get(struct bt_mesh_model *model,
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
- u16_t elem_addr;
+ uint8_t *mod_id, status;
+ uint16_t elem_addr;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2694,6 +2021,8 @@ static void node_reset(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
+ static struct bt_mesh_proxy_idle_cb proxy_idle = {.cb = bt_mesh_reset};
+
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET_STATUS, 0);
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -2710,7 +2039,15 @@ static void node_reset(struct bt_mesh_model *model,
BT_ERR("Unable to send Node Reset Status");
}
- bt_mesh_reset();
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ bt_mesh_reset();
+ return;
+ }
+
+ /* If the response goes to a proxy node, we'll wait for the sending to
+ * complete before moving on.
+ */
+ bt_mesh_proxy_on_idle(&proxy_idle);
os_mbuf_free_chain(msg);
}
@@ -2718,10 +2055,9 @@ static void send_friend_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_FRIEND_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
bt_mesh_model_msg_init(msg, OP_FRIEND_STATUS);
- net_buf_simple_add_u8(msg, cfg->frnd);
+ net_buf_simple_add_u8(msg, bt_mesh_friend_get());
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Friend Status");
@@ -2744,8 +2080,6 @@ static void friend_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
-
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
bt_hex(buf->om_data, buf->om_len));
@@ -2755,34 +2089,8 @@ static void friend_set(struct bt_mesh_model *model,
return;
}
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- goto send_status;
- }
-
- BT_DBG("Friend 0x%02x -> 0x%02x", cfg->frnd, buf->om_data[0]);
-
- if (cfg->frnd == buf->om_data[0]) {
- goto send_status;
- }
-
- if (MYNEWT_VAL(BLE_MESH_FRIEND)) {
- cfg->frnd = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
+ (void)bt_mesh_friend_set(buf->om_data[0]);
- if (cfg->frnd == BT_MESH_FRIEND_DISABLED) {
- bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
- }
- }
-
- if (cfg->hb_pub.feat & BT_MESH_FEAT_FRIEND) {
- bt_mesh_heartbeat_send();
- }
-
-send_status:
send_friend_status(model, ctx);
}
@@ -2792,8 +2100,8 @@ static void lpn_timeout_get(struct bt_mesh_model *model,
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_STATUS, 5);
struct bt_mesh_friend *frnd;
- u16_t lpn_addr;
- s32_t timeout;
+ uint16_t lpn_addr;
+ int32_t timeout;
lpn_addr = net_buf_simple_pull_le16(buf);
@@ -2823,9 +2131,7 @@ static void lpn_timeout_get(struct bt_mesh_model *model,
timeout = k_delayed_work_remaining_get(&frnd->timer) / 100;
send_rsp:
- net_buf_simple_add_u8(msg, timeout);
- net_buf_simple_add_u8(msg, timeout >> 8);
- net_buf_simple_add_u8(msg, timeout >> 16);
+ net_buf_simple_add_le24(msg, timeout);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send LPN PollTimeout Status");
@@ -2837,7 +2143,7 @@ done:
static void send_krp_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
- u16_t idx, u8_t phase, u8_t status)
+ uint16_t idx, uint8_t phase, uint8_t status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_STATUS, 4);
@@ -2857,8 +2163,8 @@ static void send_krp_status(struct bt_mesh_model *model,
static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
+ uint8_t kr_phase, status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2868,21 +2174,16 @@ static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
BT_DBG("idx 0x%04x", idx);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
- } else {
- send_krp_status(model, ctx, idx, sub->kr_phase,
- STATUS_SUCCESS);
- }
+ status = bt_mesh_subnet_kr_phase_get(idx, &kr_phase);
+
+ send_krp_status(model, ctx, idx, kr_phase, status);
}
static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u8_t phase;
- u16_t idx;
+ uint8_t phase, status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
phase = net_buf_simple_pull_u8(buf);
@@ -2892,56 +2193,16 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
return;
}
- BT_DBG("idx 0x%04x transition 0x%02x", idx, phase);
-
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
- return;
- }
-
- BT_DBG("%u -> %u", sub->kr_phase, phase);
-
- if (phase < BT_MESH_KR_PHASE_2 || phase > BT_MESH_KR_PHASE_3 ||
- (sub->kr_phase == BT_MESH_KR_NORMAL &&
- phase == BT_MESH_KR_PHASE_2)) {
- BT_WARN("Prohibited transition %u -> %u", sub->kr_phase, phase);
+ status = bt_mesh_subnet_kr_phase_set(idx, &phase);
+ if (status == STATUS_CANNOT_UPDATE) {
+ BT_ERR("Invalid kr phase transition 0x%02x", phase);
return;
}
- if (sub->kr_phase == BT_MESH_KR_PHASE_1 &&
- phase == BT_MESH_KR_PHASE_2) {
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- sub->kr_flag = 1;
- bt_mesh_net_beacon_update(sub);
- } else if ((sub->kr_phase == BT_MESH_KR_PHASE_1 ||
- sub->kr_phase == BT_MESH_KR_PHASE_2) &&
- phase == BT_MESH_KR_PHASE_3) {
- bt_mesh_net_revoke_keys(sub);
- if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND))) {
- friend_cred_refresh(ctx->net_idx);
- }
- sub->kr_phase = BT_MESH_KR_NORMAL;
- sub->kr_flag = 0;
- bt_mesh_net_beacon_update(sub);
- }
-
- send_krp_status(model, ctx, idx, sub->kr_phase, STATUS_SUCCESS);
+ send_krp_status(model, ctx, idx, phase, status);
}
-static u8_t hb_log(u16_t val)
-{
- if (!val) {
- return 0x00;
- } else if (val == 0xffff) {
- return 0xff;
- } else {
- return 32 - __builtin_clz(val);
- }
-}
-
-static u8_t hb_pub_count_log(u16_t val)
+static uint8_t hb_pub_count_log(uint16_t val)
{
if (!val) {
return 0x00;
@@ -2954,32 +2215,20 @@ static u8_t hb_pub_count_log(u16_t val)
}
}
-static u16_t hb_pwr2(u8_t val, u8_t sub)
-{
- if (!val) {
- return 0x0000;
- } else if (val == 0xff || val == 0x11) {
- return 0xffff;
- } else {
- return (1 << (val - sub));
- }
-}
-
struct hb_pub_param {
- u16_t dst;
- u8_t count_log;
- u8_t period_log;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx;
+ uint16_t dst;
+ uint8_t count_log;
+ uint8_t period_log;
+ uint8_t ttl;
+ uint16_t feat;
+ uint16_t net_idx;
} __packed;
static void hb_pub_send_status(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx, u8_t status,
- struct hb_pub_param *orig_msg)
+ struct bt_mesh_msg_ctx *ctx, uint8_t status,
+ const struct bt_mesh_hb_pub *pub)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_STATUS, 10);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
@@ -2987,20 +2236,13 @@ static void hb_pub_send_status(struct bt_mesh_model *model,
net_buf_simple_add_u8(msg, status);
- if (orig_msg) {
- memcpy(net_buf_simple_add(msg, sizeof(*orig_msg)), orig_msg,
- sizeof(*orig_msg));
- goto send;
- }
-
- net_buf_simple_add_le16(msg, cfg->hb_pub.dst);
- net_buf_simple_add_u8(msg, hb_pub_count_log(cfg->hb_pub.count));
- net_buf_simple_add_u8(msg, cfg->hb_pub.period);
- net_buf_simple_add_u8(msg, cfg->hb_pub.ttl);
- net_buf_simple_add_le16(msg, cfg->hb_pub.feat);
- net_buf_simple_add_le16(msg, cfg->hb_pub.net_idx);
+ net_buf_simple_add_le16(msg, pub->dst);
+ net_buf_simple_add_u8(msg, hb_pub_count_log(pub->count));
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(pub->period));
+ net_buf_simple_add_u8(msg, pub->ttl);
+ net_buf_simple_add_le16(msg, pub->feat);
+ net_buf_simple_add_le16(msg, pub->net_idx);
-send:
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Heartbeat Publication Status");
}
@@ -3012,9 +2254,13 @@ static void heartbeat_pub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
+ struct bt_mesh_hb_pub pub;
+
BT_DBG("src 0x%04x", ctx->addr);
- hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
+ bt_mesh_hb_pub_get(&pub);
+
+ hb_pub_send_status(model, ctx, STATUS_SUCCESS, &pub);
}
static void heartbeat_pub_set(struct bt_mesh_model *model,
@@ -3022,27 +2268,32 @@ static void heartbeat_pub_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct hb_pub_param *param = (void *)buf->om_data;
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t dst, feat, idx;
- u8_t status;
+ struct bt_mesh_hb_pub pub;
+ uint8_t status;
BT_DBG("src 0x%04x", ctx->addr);
- dst = sys_le16_to_cpu(param->dst);
+ pub.dst = sys_le16_to_cpu(param->dst);
+ pub.count = bt_mesh_hb_pwr2(param->count_log);
+ pub.period = bt_mesh_hb_pwr2(param->period_log);
+ pub.ttl = param->ttl;
+ pub.feat = sys_le16_to_cpu(param->feat);
+ pub.net_idx = sys_le16_to_cpu(param->net_idx);
+
/* All other address types but virtual are valid */
- if (BT_MESH_ADDR_IS_VIRTUAL(dst)) {
+ if (BT_MESH_ADDR_IS_VIRTUAL(pub.dst)) {
status = STATUS_INVALID_ADDRESS;
- goto failed;
+ goto rsp;
}
if (param->count_log > 0x11 && param->count_log != 0xff) {
status = STATUS_CANNOT_SET;
- goto failed;
+ goto rsp;
}
if (param->period_log > 0x10) {
status = STATUS_CANNOT_SET;
- goto failed;
+ goto rsp;
}
if (param->ttl > BT_MESH_TTL_MAX && param->ttl != BT_MESH_TTL_DEFAULT) {
@@ -3050,84 +2301,32 @@ static void heartbeat_pub_set(struct bt_mesh_model *model,
return;
}
- feat = sys_le16_to_cpu(param->feat);
-
- idx = sys_le16_to_cpu(param->net_idx);
- if (idx > 0xfff) {
- BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+ if (pub.net_idx > 0xfff) {
+ BT_ERR("Invalid NetKeyIndex 0x%04x", pub.net_idx);
return;
}
- if (!bt_mesh_subnet_get(idx)) {
- status = STATUS_INVALID_NETKEY;
- goto failed;
- }
-
- cfg->hb_pub.dst = dst;
- cfg->hb_pub.period = param->period_log;
- cfg->hb_pub.feat = feat & BT_MESH_FEAT_SUPPORTED;
- cfg->hb_pub.net_idx = idx;
-
- if (dst == BT_MESH_ADDR_UNASSIGNED) {
- hb_pub_disable(cfg);
- } else {
- /* 2^(n-1) */
- cfg->hb_pub.count = hb_pwr2(param->count_log, 1);
- cfg->hb_pub.ttl = param->ttl;
-
- BT_DBG("period %u ms", hb_pwr2(param->period_log, 1) * 1000);
-
- /* The first Heartbeat message shall be published as soon
- * as possible after the Heartbeat Publication Period state
- * has been configured for periodic publishing.
- */
- if (param->period_log && param->count_log) {
- k_work_submit(&cfg->hb_pub.timer.work);
- } else {
- k_delayed_work_cancel(&cfg->hb_pub.timer);
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_hb_pub();
- }
-
- hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
-
- return;
-
-failed:
- hb_pub_send_status(model, ctx, status, param);
+ status = bt_mesh_hb_pub_set(&pub);
+rsp:
+ hb_pub_send_status(model, ctx, status, &pub);
}
static void hb_sub_send_status(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx, u8_t status)
+ struct bt_mesh_msg_ctx *ctx,
+ const struct bt_mesh_hb_sub *sub)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_STATUS, 9);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t period;
- s64_t uptime;
-
- BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
-
- uptime = k_uptime_get();
- if (uptime > cfg->hb_sub.expiry) {
- period = 0;
- } else {
- period = (cfg->hb_sub.expiry - uptime) / 1000;
- }
+ BT_DBG("src 0x%04x ", ctx->addr);
bt_mesh_model_msg_init(msg, OP_HEARTBEAT_SUB_STATUS);
- net_buf_simple_add_u8(msg, status);
-
- net_buf_simple_add_le16(msg, cfg->hb_sub.src);
- net_buf_simple_add_le16(msg, cfg->hb_sub.dst);
-
- net_buf_simple_add_u8(msg, hb_log(period));
- net_buf_simple_add_u8(msg, hb_log(cfg->hb_sub.count));
- net_buf_simple_add_u8(msg, cfg->hb_sub.min_hops);
- net_buf_simple_add_u8(msg, cfg->hb_sub.max_hops);
+ net_buf_simple_add_u8(msg, STATUS_SUCCESS);
+ net_buf_simple_add_le16(msg, sub->src);
+ net_buf_simple_add_le16(msg, sub->dst);
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(sub->remaining));
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(sub->count));
+ net_buf_simple_add_u8(msg, sub->min_hops);
+ net_buf_simple_add_u8(msg, sub->max_hops);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -3141,92 +2340,58 @@ static void heartbeat_sub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
+ struct bt_mesh_hb_sub sub;
+
BT_DBG("src 0x%04x", ctx->addr);
- hb_sub_send_status(model, ctx, STATUS_SUCCESS);
+ bt_mesh_hb_sub_get(&sub);
+
+ hb_sub_send_status(model, ctx, &sub);
}
static void heartbeat_sub_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t sub_src, sub_dst;
- u8_t sub_period;
- s32_t period_ms;
+ uint8_t period_log, status;
+ struct bt_mesh_hb_sub sub;
+ uint16_t sub_src, sub_dst;
+ uint32_t period;
BT_DBG("src 0x%04x", ctx->addr);
sub_src = net_buf_simple_pull_le16(buf);
sub_dst = net_buf_simple_pull_le16(buf);
- sub_period = net_buf_simple_pull_u8(buf);
+ period_log = net_buf_simple_pull_u8(buf);
BT_DBG("sub_src 0x%04x sub_dst 0x%04x period 0x%02x",
- sub_src, sub_dst, sub_period);
-
- if (sub_src != BT_MESH_ADDR_UNASSIGNED &&
- !BT_MESH_ADDR_IS_UNICAST(sub_src)) {
- BT_WARN("Prohibited source address");
- return;
- }
+ sub_src, sub_dst, period_log);
- if (BT_MESH_ADDR_IS_VIRTUAL(sub_dst) || BT_MESH_ADDR_IS_RFU(sub_dst) ||
- (BT_MESH_ADDR_IS_UNICAST(sub_dst) &&
- sub_dst != bt_mesh_primary_addr())) {
- BT_WARN("Prohibited destination address");
+ if (period_log > 0x11) {
+ BT_WARN("Prohibited subscription period 0x%02x", period_log);
return;
}
- if (sub_period > 0x11) {
- BT_WARN("Prohibited subscription period 0x%02x", sub_period);
- return;
- }
+ period = bt_mesh_hb_pwr2(period_log);
- if (sub_src == BT_MESH_ADDR_UNASSIGNED ||
- sub_dst == BT_MESH_ADDR_UNASSIGNED ||
- sub_period == 0x00) {
- /* Only an explicit address change to unassigned should
- * trigger clearing of the values according to
- * MESH/NODE/CFG/HBS/BV-02-C.
+ status = bt_mesh_hb_sub_set(sub_src, sub_dst, period);
+ if (status != STATUS_SUCCESS) {
+ /* All errors are caused by invalid packets, which should be
+ * ignored.
*/
- if (sub_src == BT_MESH_ADDR_UNASSIGNED ||
- sub_dst == BT_MESH_ADDR_UNASSIGNED) {
- cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.min_hops = BT_MESH_TTL_MAX;
- cfg->hb_sub.max_hops = 0;
- cfg->hb_sub.count = 0;
- }
-
- period_ms = 0;
- } else {
- cfg->hb_sub.src = sub_src;
- cfg->hb_sub.dst = sub_dst;
- cfg->hb_sub.min_hops = BT_MESH_TTL_MAX;
- cfg->hb_sub.max_hops = 0;
- cfg->hb_sub.count = 0;
- period_ms = hb_pwr2(sub_period, 1) * 1000;
- }
-
- /* Let the transport layer know it needs to handle this address */
- bt_mesh_set_hb_sub_dst(cfg->hb_sub.dst);
-
- BT_DBG("period_ms %u", (unsigned) period_ms);
-
- if (period_ms) {
- cfg->hb_sub.expiry = k_uptime_get() + period_ms;
- } else {
- cfg->hb_sub.expiry = 0;
+ return;
}
- hb_sub_send_status(model, ctx, STATUS_SUCCESS);
+ bt_mesh_hb_sub_get(&sub);
/* MESH/NODE/CFG/HBS/BV-01-C expects the MinHops to be 0x7f after
* disabling subscription, but 0x00 for subsequent Get requests.
*/
- if (!period_ms) {
- cfg->hb_sub.min_hops = 0;
+ if (!period_log) {
+ sub.min_hops = BT_MESH_TTL_MAX;
}
+
+ hb_sub_send_status(model, ctx, &sub);
}
const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
@@ -3280,58 +2445,9 @@ const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
BT_MESH_MODEL_OP_END,
};
-static void hb_publish(struct ble_npl_event *work)
-{
- struct bt_mesh_cfg_srv *cfg = ble_npl_event_get_arg(work);
- struct bt_mesh_subnet *sub;
- u16_t period_ms;
-
- BT_DBG("hb_pub.count: %u", cfg->hb_pub.count);
-
- sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx);
- if (!sub) {
- BT_ERR("No matching subnet for idx 0x%02x",
- cfg->hb_pub.net_idx);
- cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED;
- return;
- }
-
- if (cfg->hb_pub.count == 0) {
- return;
- }
-
- period_ms = hb_pwr2(cfg->hb_pub.period, 1) * 1000;
- if (period_ms && cfg->hb_pub.count > 1) {
- k_delayed_work_submit(&cfg->hb_pub.timer, period_ms);
- }
-
- bt_mesh_heartbeat_send();
-
- if (cfg->hb_pub.count != 0xffff) {
- cfg->hb_pub.count--;
- }
-}
-
-static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg)
-{
- if (cfg->relay > 0x02) {
- return false;
- }
-
- if (cfg->beacon > 0x01) {
- return false;
- }
-
- if (cfg->default_ttl > BT_MESH_TTL_MAX) {
- return false;
- }
-
- return true;
-}
-
static int cfg_srv_init(struct bt_mesh_model *model)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
+ bt_mesh_app_key_cb_list[0] = app_key_evt;
BT_DBG("");
@@ -3340,43 +2456,12 @@ static int cfg_srv_init(struct bt_mesh_model *model)
return -EINVAL;
}
- if (!cfg) {
- BT_ERR("No Configuration Server context provided");
- return -EINVAL;
- }
-
- if (!conf_is_valid(cfg)) {
- BT_ERR("Invalid values in configuration");
- return -EINVAL;
- }
-
/*
* Configuration Model security is device-key based and only the local
* device-key is allowed to access this model.
*/
model->keys[0] = BT_MESH_KEY_DEV_LOCAL;
- if (!(MYNEWT_VAL(BLE_MESH_RELAY))) {
- cfg->relay = BT_MESH_RELAY_NOT_SUPPORTED;
- }
-
- if (!(MYNEWT_VAL(BLE_MESH_FRIEND))) {
- cfg->frnd = BT_MESH_FRIEND_NOT_SUPPORTED;
- }
-
- if (!(MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- cfg->gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED;
- }
-
- k_delayed_work_init(&cfg->hb_pub.timer, hb_publish);
- k_delayed_work_add_arg(&cfg->hb_pub.timer, cfg);
- cfg->hb_pub.net_idx = BT_MESH_KEY_UNUSED;
- cfg->hb_sub.expiry = 0;
-
- cfg->model = model;
-
- conf = cfg;
-
return 0;
}
@@ -3401,8 +2486,6 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
if (clear_count) {
bt_mesh_store_mod_sub(mod);
}
-
- bt_mesh_model_data_store(mod, vnd, NULL, 0);
}
if (mod->cb && mod->cb->reset) {
@@ -3412,208 +2495,5 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
void bt_mesh_cfg_reset(void)
{
- struct bt_mesh_cfg_srv *cfg = conf;
- int i;
-
- BT_DBG("");
-
- if (!cfg) {
- return;
- }
-
- bt_mesh_set_hb_sub_dst(BT_MESH_ADDR_UNASSIGNED);
-
- cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.expiry = 0;
-
- /* Delete all net keys, which also takes care of all app keys which
- * are associated with each net key.
- */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_subnet_del(sub, true);
- }
- }
-
bt_mesh_model_foreach(mod_reset, NULL);
-
- memset(labels, 0, sizeof(labels));
-}
-
-void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat)
-{
- struct bt_mesh_cfg_srv *cfg = conf;
-
- if (!cfg) {
- BT_WARN("No configuaration server context available");
- return;
- }
-
- if (src != cfg->hb_sub.src || dst != cfg->hb_sub.dst) {
- BT_WARN("No subscription for received heartbeat");
- return;
- }
-
- if (k_uptime_get() > cfg->hb_sub.expiry) {
- BT_WARN("Heartbeat subscription period expired");
- return;
- }
-
- cfg->hb_sub.min_hops = min(cfg->hb_sub.min_hops, hops);
- cfg->hb_sub.max_hops = max(cfg->hb_sub.max_hops, hops);
-
- if (cfg->hb_sub.count < 0xffff) {
- cfg->hb_sub.count++;
- }
-
- BT_DBG("src 0x%04x dst 0x%04x hops %u min %u max %u count %u", src,
- dst, hops, cfg->hb_sub.min_hops, cfg->hb_sub.max_hops,
- cfg->hb_sub.count);
-
- if (cfg->hb_sub.func) {
- cfg->hb_sub.func(hops, feat);
- }
-}
-
-u8_t bt_mesh_net_transmit_get(void)
-{
- if (conf) {
- return conf->net_transmit;
- }
-
- return 0;
-}
-
-u8_t bt_mesh_relay_get(void)
-{
- if (conf) {
- return conf->relay;
- }
-
- return BT_MESH_RELAY_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_friend_get(void)
-{
- BT_DBG("conf %p conf->frnd 0x%02x", conf, conf->frnd);
-
- if (conf) {
- return conf->frnd;
- }
-
- return BT_MESH_FRIEND_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_relay_retransmit_get(void)
-{
- if (conf) {
- return conf->relay_retransmit;
- }
-
- return 0;
-}
-
-u8_t bt_mesh_beacon_get(void)
-{
- if (conf) {
- return conf->beacon;
- }
-
- return BT_MESH_BEACON_DISABLED;
-}
-
-u8_t bt_mesh_gatt_proxy_get(void)
-{
- if (conf) {
- return conf->gatt_proxy;
- }
-
- return BT_MESH_GATT_PROXY_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_default_ttl_get(void)
-{
- if (conf) {
- return conf->default_ttl;
- }
-
- return DEFAULT_TTL;
-}
-
-u8_t *bt_mesh_label_uuid_get(u16_t addr)
-{
- int i;
-
- BT_DBG("addr 0x%04x", addr);
-
- for (i = 0; i < ARRAY_SIZE(labels); i++) {
- if (labels[i].addr == addr) {
- BT_DBG("Found Label UUID for 0x%04x: %s", addr,
- bt_hex(labels[i].uuid, 16));
- return labels[i].uuid;
- }
- }
-
- BT_WARN("No matching Label UUID for 0x%04x", addr);
-
- return NULL;
-}
-
-struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void)
-{
- if (!conf) {
- return NULL;
- }
-
- return &conf->hb_pub;
-}
-
-void bt_mesh_hb_pub_disable(void)
-{
- if (conf) {
- hb_pub_disable(conf);
- }
-}
-
-struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void)
-{
- return conf;
-}
-
-void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store)
-{
- int i;
-
- BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
-
- if (conf && conf->hb_pub.net_idx == sub->net_idx) {
- hb_pub_disable(conf);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_store_hb_pub();
- }
- }
-
- /* Delete any app keys bound to this NetKey index */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx == sub->net_idx) {
- bt_mesh_app_key_del(key, store);
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_clear_net_idx(sub->net_idx);
- }
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_clear_subnet(sub);
- }
-
- memset(sub, 0, sizeof(*sub));
- sub->net_idx = BT_MESH_KEY_UNUSED;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c
index b6a0ba21..3111a6ef 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c
@@ -24,8 +24,8 @@
#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4)
#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
-int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
- size_t sg_len, u8_t mac[16])
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+ size_t sg_len, uint8_t mac[16])
{
struct tc_aes_key_sched_struct sched;
struct tc_cmac_struct state;
@@ -48,8 +48,8 @@ int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
return 0;
}
-int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
- const char *info, u8_t okm[16])
+int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
+ const char *info, uint8_t okm[16])
{
int err;
@@ -61,14 +61,14 @@ int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
return bt_mesh_aes_cmac_one(okm, info, strlen(info), okm);
}
-int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
- u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16])
+int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
+ uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16])
{
struct bt_mesh_sg sg[3];
- u8_t salt[16];
- u8_t out[16];
- u8_t t[16];
- u8_t pad;
+ uint8_t salt[16];
+ uint8_t out[16];
+ uint8_t t[16];
+ uint8_t pad;
int err;
BT_DBG("n %s", bt_hex(n, 16));
@@ -126,11 +126,11 @@ int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
return 0;
}
-int bt_mesh_k3(const u8_t n[16], u8_t out[8])
+int bt_mesh_k3(const uint8_t n[16], uint8_t out[8])
{
- u8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
- u8_t tmp[16];
- u8_t t[16];
+ uint8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
+ uint8_t tmp[16];
+ uint8_t t[16];
int err;
err = bt_mesh_s1("smk3", tmp);
@@ -153,11 +153,11 @@ int bt_mesh_k3(const u8_t n[16], u8_t out[8])
return 0;
}
-int bt_mesh_k4(const u8_t n[16], u8_t out[1])
+int bt_mesh_k4(const uint8_t n[16], uint8_t out[1])
{
- u8_t id6[] = { 'i', 'd', '6', 0x01 };
- u8_t tmp[16];
- u8_t t[16];
+ uint8_t id6[] = { 'i', 'd', '6', 0x01 };
+ uint8_t tmp[16];
+ uint8_t t[16];
int err;
err = bt_mesh_s1("smk4", tmp);
@@ -180,10 +180,10 @@ int bt_mesh_k4(const u8_t n[16], u8_t out[1])
return 0;
}
-int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
+int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16])
{
const char *id128 = "id128\x01";
- u8_t salt[16];
+ uint8_t salt[16];
int err;
err = bt_mesh_s1(s, salt);
@@ -194,326 +194,8 @@ int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
return bt_mesh_k1(n, 16, salt, id128, out);
}
-static int bt_mesh_ccm_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t *enc_msg, size_t msg_len,
- const u8_t *aad, size_t aad_len,
- u8_t *out_msg, size_t mic_size)
-{
- u8_t msg[16], pmsg[16], cmic[16], cmsg[16], Xn[16], mic[16];
- u16_t last_blk, blk_cnt;
- size_t i, j;
- int err;
-
- if (msg_len < 1 || aad_len >= 0xff00) {
- return -EINVAL;
- }
-
- /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(0x0000, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmic);
- if (err) {
- return err;
- }
-
- /* X_0 = e(AppKey, 0x09 || nonce || length) */
- if (mic_size == sizeof(u64_t)) {
- pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
- } else {
- pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
- }
-
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(msg_len, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* If AAD is being used to authenticate, include it here */
- if (aad_len) {
- sys_put_be16(aad_len, pmsg);
-
- for (i = 0; i < sizeof(u16_t); i++) {
- pmsg[i] = Xn[i] ^ pmsg[i];
- }
-
- j = 0;
- aad_len += sizeof(u16_t);
- while (aad_len > 16) {
- do {
- pmsg[i] = Xn[i] ^ aad[j];
- i++, j++;
- } while (i < 16);
-
- aad_len -= 16;
- i = 0;
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- for (; i < aad_len; i++, j++) {
- pmsg[i] = Xn[i] ^ aad[j];
- }
-
- for (i = aad_len; i < 16; i++) {
- pmsg[i] = Xn[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- last_blk = msg_len % 16;
- blk_cnt = (msg_len + 15) / 16;
- if (!last_blk) {
- last_blk = 16;
- }
-
- for (j = 0; j < blk_cnt; j++) {
- if (j + 1 == blk_cnt) {
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < last_blk; i++) {
- msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
- }
-
- memcpy(out_msg + (j * 16), msg, last_blk);
-
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < last_blk; i++) {
- pmsg[i] = Xn[i] ^ msg[i];
- }
-
- for (i = last_blk; i < 16; i++) {
- pmsg[i] = Xn[i] ^ 0x00;
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* MIC = C_mic ^ X_1 */
- for (i = 0; i < sizeof(mic); i++) {
- mic[i] = cmic[i] ^ Xn[i];
- }
- } else {
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < 16; i++) {
- msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
- }
-
- memcpy(out_msg + (j * 16), msg, 16);
-
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < 16; i++) {
- pmsg[i] = Xn[i] ^ msg[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
- }
-
- if (memcmp(mic, enc_msg + msg_len, mic_size)) {
- return -EBADMSG;
- }
-
- return 0;
-}
-
-static int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t *msg, size_t msg_len,
- const u8_t *aad, size_t aad_len,
- u8_t *out_msg, size_t mic_size)
-{
- u8_t pmsg[16], cmic[16], cmsg[16], mic[16], Xn[16];
- u16_t blk_cnt, last_blk;
- size_t i, j;
- int err;
-
- BT_DBG("key %s", bt_hex(key, 16));
- BT_DBG("nonce %s", bt_hex(nonce, 13));
- BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
- BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
-
- /* Unsupported AAD size */
- if (aad_len >= 0xff00) {
- return -EINVAL;
- }
-
- /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(0x0000, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmic);
- if (err) {
- return err;
- }
-
- /* X_0 = e(AppKey, 0x09 || nonce || length) */
- if (mic_size == sizeof(u64_t)) {
- pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
- } else {
- pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
- }
-
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(msg_len, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* If AAD is being used to authenticate, include it here */
- if (aad_len) {
- sys_put_be16(aad_len, pmsg);
-
- for (i = 0; i < sizeof(u16_t); i++) {
- pmsg[i] = Xn[i] ^ pmsg[i];
- }
-
- j = 0;
- aad_len += sizeof(u16_t);
- while (aad_len > 16) {
- do {
- pmsg[i] = Xn[i] ^ aad[j];
- i++, j++;
- } while (i < 16);
-
- aad_len -= 16;
- i = 0;
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- for (; i < aad_len; i++, j++) {
- pmsg[i] = Xn[i] ^ aad[j];
- }
-
- for (i = aad_len; i < 16; i++) {
- pmsg[i] = Xn[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- last_blk = msg_len % 16;
- blk_cnt = (msg_len + 15) / 16;
- if (!last_blk) {
- last_blk = 16;
- }
-
- for (j = 0; j < blk_cnt; j++) {
- if (j + 1 == blk_cnt) {
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < last_blk; i++) {
- pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
- }
- for (i = last_blk; i < 16; i++) {
- pmsg[i] = Xn[i] ^ 0x00;
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* MIC = C_mic ^ X_1 */
- for (i = 0; i < sizeof(mic); i++) {
- mic[i] = cmic[i] ^ Xn[i];
- }
-
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < last_blk; i++) {
- out_msg[(j * 16) + i] =
- msg[(j * 16) + i] ^ cmsg[i];
- }
- } else {
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < 16; i++) {
- pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_N */
- for (i = 0; i < 16; i++) {
- out_msg[(j * 16) + i] =
- msg[(j * 16) + i] ^ cmsg[i];
- }
-
- }
- }
-
- memcpy(out_msg + msg_len, mic, mic_size);
-
- return 0;
-}
-
-static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
- u32_t iv_index)
+static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu,
+ uint32_t iv_index)
{
/* Nonce Type */
nonce[0] = 0x03;
@@ -538,8 +220,8 @@ static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
sys_put_be32(iv_index, &nonce[9]);
}
-static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
- u32_t iv_index)
+static void create_net_nonce(uint8_t nonce[13], const uint8_t *pdu,
+ uint32_t iv_index)
{
/* Nonce Type */
nonce[0] = 0x00;
@@ -564,11 +246,11 @@ static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
sys_put_be32(iv_index, &nonce[9]);
}
-int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
- const u8_t privacy_key[16])
+int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
+ const uint8_t privacy_key[16])
{
- u8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
- u8_t tmp[16];
+ uint8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
+ uint8_t tmp[16];
int err, i;
BT_DBG("IVIndex %u, PrivacyKey %s", (unsigned) iv_index,
@@ -591,11 +273,11 @@ int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
return 0;
}
-int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy)
+int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy)
{
- u8_t mic_len = NET_MIC_LEN(buf->om_data);
- u8_t nonce[13];
+ uint8_t mic_len = NET_MIC_LEN(buf->om_data);
+ uint8_t nonce[13];
int err;
BT_DBG("IVIndex %u EncKey %s mic_len %u", (unsigned) iv_index,
@@ -610,7 +292,7 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- err = bt_mesh_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
+ err = bt_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
NULL, 0, &buf->om_data[7], mic_len);
if (!err) {
net_buf_simple_add(buf, mic_len);
@@ -619,11 +301,11 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
return err;
}
-int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy)
+int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy)
{
- u8_t mic_len = NET_MIC_LEN(buf->om_data);
- u8_t nonce[13];
+ uint8_t mic_len = NET_MIC_LEN(buf->om_data);
+ uint8_t nonce[13];
BT_DBG("PDU (%u bytes) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
BT_DBG("iv_index %u, key %s mic_len %u", (unsigned) iv_index,
@@ -639,118 +321,74 @@ int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
buf->om_len -= mic_len;
- return bt_mesh_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
+ return bt_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
NULL, 0, &buf->om_data[7], mic_len);
}
-static void create_app_nonce(u8_t nonce[13], bool dev_key, u8_t aszmic,
- u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index)
+static void create_app_nonce(uint8_t nonce[13],
+ const struct bt_mesh_app_crypto_ctx *ctx)
{
- if (dev_key) {
+ if (ctx->dev_key) {
nonce[0] = 0x02;
} else {
nonce[0] = 0x01;
}
- sys_put_be32((seq_num | ((u32_t)aszmic << 31)), &nonce[1]);
+ sys_put_be32((ctx->seq_num | ((uint32_t)ctx->aszmic << 31)), &nonce[1]);
- sys_put_be16(src, &nonce[5]);
- sys_put_be16(dst, &nonce[7]);
+ sys_put_be16(ctx->src, &nonce[5]);
+ sys_put_be16(ctx->dst, &nonce[7]);
- sys_put_be32(iv_index, &nonce[9]);
+ sys_put_be32(ctx->iv_index, &nonce[9]);
}
-static int mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
+int bt_mesh_app_encrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf)
{
- u8_t nonce[13];
+ int err;
+ uint8_t nonce[13];
BT_DBG("AppKey %s", bt_hex(key, 16));
- BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst);
- BT_DBG("seq_num 0x%08x iv_index 0x%08x", (unsigned) seq_num,
- (unsigned) iv_index);
+ BT_DBG("dev_key %u src 0x%04x dst 0x%04x", ctx->dev_key, ctx->src,
+ ctx->dst);
+ BT_DBG("seq_num 0x%08x iv_index 0x%08x", ctx->seq_num, ctx->iv_index);
BT_DBG("Clear: %s", bt_hex(buf->om_data, buf->om_len));
- create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
+ create_app_nonce(nonce, ctx);
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- return bt_mesh_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ad,
- ad ? 16 : 0, buf->om_data,
- APP_MIC_LEN(aszmic));
-}
+ err = bt_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad,
+ ctx->ad ? 16 : 0, buf->om_data,
+ APP_MIC_LEN(ctx->aszmic));
-int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index)
-{
- int err;
-
- err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
- seq_num, iv_index);
if (!err) {
+ net_buf_simple_add(buf, APP_MIC_LEN(ctx->aszmic));
BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
}
return err;
}
-int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
+int bt_mesh_app_decrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf, struct os_mbuf *out)
{
+ uint8_t nonce[13];
int err;
- err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
- seq_num, iv_index);
-
- if (!err) {
- net_buf_simple_add(buf, APP_MIC_LEN(aszmic));
- BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
- }
-
- return err;
-}
-
-static int mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, struct os_mbuf *out,
- const u8_t *ad, u16_t src, u16_t dst,
- u32_t seq_num, u32_t iv_index)
-{
- u8_t nonce[13];
-
BT_DBG("EncData (len %u) %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
+ create_app_nonce(nonce, ctx);
BT_DBG("AppKey %s", bt_hex(key, 16));
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- return bt_mesh_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ad,
- ad ? 16 : 0, out->om_data,
- APP_MIC_LEN(aszmic));
-}
-
-int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index)
-{
- return mesh_app_decrypt(key, dev_key, aszmic, buf, buf,
- ad, src, dst, seq_num, iv_index);
-}
-
-int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, struct os_mbuf *out,
- const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index)
-{
- int err;
-
- err = mesh_app_decrypt(key, dev_key, aszmic, buf, out,
- ad, src, dst, seq_num, iv_index);
+ err = bt_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad,
+ ctx->ad ? 16 : 0, out->om_data,
+ APP_MIC_LEN(ctx->aszmic));
if (!err) {
net_buf_simple_add(out, buf->om_len);
}
@@ -759,7 +397,7 @@ int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
}
/* reversed, 8-bit, poly=0x07 */
-static const u8_t crc_table[256] = {
+static const uint8_t crc_table[256] = {
0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
@@ -801,9 +439,9 @@ static const u8_t crc_table[256] = {
0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
};
-u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
+uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len)
{
- u8_t fcs = 0xff;
+ uint8_t fcs = 0xff;
while (data_len--) {
fcs = crc_table[fcs ^ *data++];
@@ -814,11 +452,11 @@ u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
return 0xff - fcs;
}
-bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs)
+bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs)
{
- const u8_t *data = buf->om_data;
- u16_t data_len = buf->om_len;
- u8_t fcs = 0xff;
+ const uint8_t *data = buf->om_data;
+ uint16_t data_len = buf->om_len;
+ uint8_t fcs = 0xff;
while (data_len--) {
fcs = crc_table[fcs ^ *data++];
@@ -827,10 +465,10 @@ bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs)
return crc_table[fcs ^ received_fcs] == 0xcf;
}
-int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
+int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr)
{
- u8_t salt[16];
- u8_t tmp[16];
+ uint8_t salt[16];
+ uint8_t tmp[16];
int err;
err = bt_mesh_s1("vtad", salt);
@@ -848,21 +486,21 @@ int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
return 0;
}
-int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16])
+int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16])
{
- const u8_t conf_salt_key[16] = { 0 };
+ const uint8_t conf_salt_key[16] = { 0 };
return bt_mesh_aes_cmac_one(conf_salt_key, conf_inputs, 145, salt);
}
-int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
- u8_t conf_key[16])
+int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
+ uint8_t conf_key[16])
{
return bt_mesh_k1(dhkey, 32, conf_salt, "prck", conf_key);
}
-int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
- const u8_t auth[16], u8_t conf[16])
+int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
+ const uint8_t auth[16], uint8_t conf[16])
{
struct bt_mesh_sg sg[] = { { rand, 16 }, { auth, 16 } };
@@ -873,23 +511,23 @@ int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
return bt_mesh_aes_cmac(conf_key, sg, ARRAY_SIZE(sg), conf);
}
-int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25 + 8], u8_t out[25])
+int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25 + 8], uint8_t out[25])
{
- return bt_mesh_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
+ return bt_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
}
-int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25], u8_t out[25 + 8])
+int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25], uint8_t out[25 + 8])
{
- return bt_mesh_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
+ return bt_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
}
-int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
- const u8_t net_id[8], u32_t iv_index,
- u8_t auth[8])
+int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
+ const uint8_t net_id[8], uint32_t iv_index,
+ uint8_t auth[8])
{
- u8_t msg[13], tmp[16];
+ uint8_t msg[13], tmp[16];
int err;
BT_DBG("BeaconKey %s", bt_hex(beacon_key, 16));
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h
index 745cf324..637d13e7 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h
@@ -15,81 +15,81 @@ struct bt_mesh_sg {
size_t len;
};
-int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
- size_t sg_len, u8_t mac[16]);
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+ size_t sg_len, uint8_t mac[16]);
-static inline int bt_mesh_aes_cmac_one(const u8_t key[16], const void *m,
- size_t len, u8_t mac[16])
+static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
+ size_t len, uint8_t mac[16])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_aes_cmac(key, &sg, 1, mac);
}
-static inline bool bt_mesh_s1(const char *m, u8_t salt[16])
+static inline bool bt_mesh_s1(const char *m, uint8_t salt[16])
{
- const u8_t zero[16] = { 0 };
+ const uint8_t zero[16] = { 0 };
return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt);
}
-int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
- const char *info, u8_t okm[16]);
+int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
+ const char *info, uint8_t okm[16]);
#define bt_mesh_k1_str(ikm, ikm_len, salt_str, info, okm) \
({ \
- const u8_t salt[16] = salt_str; \
+ const uint8_t salt[16] = salt_str; \
bt_mesh_k1(ikm, ikm_len, salt, info, okm); \
})
-int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
- u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16]);
+int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
+ uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16]);
-int bt_mesh_k3(const u8_t n[16], u8_t out[8]);
+int bt_mesh_k3(const uint8_t n[16], uint8_t out[8]);
-int bt_mesh_k4(const u8_t n[16], u8_t out[1]);
+int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]);
-int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]);
+int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16]);
-static inline int bt_mesh_id_resolving_key(const u8_t net_key[16],
- u8_t resolving_key[16])
+static inline int bt_mesh_id_resolving_key(const uint8_t net_key[16],
+ uint8_t resolving_key[16])
{
return bt_mesh_k1_str(net_key, 16, "smbt", "smbi", resolving_key);
}
-static inline int bt_mesh_identity_key(const u8_t net_key[16],
- u8_t identity_key[16])
+static inline int bt_mesh_identity_key(const uint8_t net_key[16],
+ uint8_t identity_key[16])
{
return bt_mesh_id128(net_key, "nkik", identity_key);
}
-static inline int bt_mesh_beacon_key(const u8_t net_key[16],
- u8_t beacon_key[16])
+static inline int bt_mesh_beacon_key(const uint8_t net_key[16],
+ uint8_t beacon_key[16])
{
return bt_mesh_id128(net_key, "nkbk", beacon_key);
}
-int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
- const u8_t net_id[16], u32_t iv_index,
- u8_t auth[8]);
+int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
+ const uint8_t net_id[16], uint32_t iv_index,
+ uint8_t auth[8]);
-static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1])
+static inline int bt_mesh_app_id(const uint8_t app_key[16], uint8_t app_id[1])
{
return bt_mesh_k4(app_key, app_id);
}
-static inline int bt_mesh_session_key(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t session_key[16])
+static inline int bt_mesh_session_key(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t session_key[16])
{
return bt_mesh_k1(dhkey, 32, prov_salt, "prsk", session_key);
}
-static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t nonce[13])
+static inline int bt_mesh_prov_nonce(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t nonce[13])
{
- u8_t tmp[16];
+ uint8_t tmp[16];
int err;
err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp);
@@ -100,19 +100,19 @@ static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
return err;
}
-static inline int bt_mesh_dev_key(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t dev_key[16])
+static inline int bt_mesh_dev_key(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t dev_key[16])
{
return bt_mesh_k1(dhkey, 32, prov_salt, "prdk", dev_key);
}
-static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
- const u8_t prov_rand[16],
- const u8_t dev_rand[16],
- u8_t prov_salt[16])
+static inline int bt_mesh_prov_salt(const uint8_t conf_salt[16],
+ const uint8_t prov_rand[16],
+ const uint8_t dev_rand[16],
+ uint8_t prov_salt[16])
{
- const u8_t prov_salt_key[16] = { 0 };
+ const uint8_t prov_salt_key[16] = { 0 };
struct bt_mesh_sg sg[] = {
{ conf_salt, 16 },
{ prov_rand, 16 },
@@ -122,49 +122,50 @@ static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt);
}
-int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
- const u8_t privacy_key[16]);
+int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
+ const uint8_t privacy_key[16]);
-int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy);
+int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy);
-int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy);
+int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy);
-int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index);
-
-int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index);
+struct bt_mesh_app_crypto_ctx {
+ bool dev_key;
+ uint8_t aszmic;
+ uint16_t src;
+ uint16_t dst;
+ uint32_t seq_num;
+ uint32_t iv_index;
+ const uint8_t *ad;
+};
-int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index);
+int bt_mesh_app_encrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf);
-int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, struct os_mbuf*out,
- const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index);
+int bt_mesh_app_decrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf, struct os_mbuf *out);
-u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len);
+uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len);
-bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs);
+bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs);
-int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr);
+int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr);
-int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16]);
+int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16]);
-int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
- u8_t conf_key[16]);
+int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
+ uint8_t conf_key[16]);
-int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
- const u8_t auth[16], u8_t conf[16]);
+int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
+ const uint8_t auth[16], uint8_t conf[16]);
-int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25 + 8], u8_t out[25]);
+int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25 + 8], uint8_t out[25]);
-int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25], u8_t out[25 + 8]);
+int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25], uint8_t out[25 + 8]);
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h
index ee615ae9..012afbbb 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h
@@ -115,57 +115,23 @@
#define STATUS_UNSPECIFIED 0x10
#define STATUS_INVALID_BINDING 0x11
-enum {
- BT_MESH_VA_CHANGED, /* Label information changed */
-};
-
-struct label {
- u16_t ref;
- u16_t addr;
- u8_t uuid[16];
- atomic_t flags[1];
-};
-
void bt_mesh_cfg_reset(void);
-void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat);
-
-void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
-
-struct label *get_label(u16_t index);
-
-u8_t *bt_mesh_label_uuid_get(u16_t addr);
-
-struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
-void bt_mesh_hb_pub_disable(void);
-struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void);
-
-u8_t bt_mesh_net_transmit_get(void);
-u8_t bt_mesh_relay_get(void);
-u8_t bt_mesh_friend_get(void);
-u8_t bt_mesh_relay_retransmit_get(void);
-u8_t bt_mesh_beacon_get(void);
-u8_t bt_mesh_gatt_proxy_get(void);
-u8_t bt_mesh_default_ttl_get(void);
-
-void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store);
-
-struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx);
-void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store);
+void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time);
static inline void key_idx_pack(struct os_mbuf *buf,
- u16_t idx1, u16_t idx2)
+ uint16_t idx1, uint16_t idx2)
{
net_buf_simple_add_le16(buf, idx1 | ((idx2 & 0x00f) << 12));
net_buf_simple_add_u8(buf, idx2 >> 4);
}
static inline void key_idx_unpack(struct os_mbuf *buf,
- u16_t *idx1, u16_t *idx2)
+ uint16_t *idx1, uint16_t *idx2)
{
*idx1 = sys_get_le16(&buf->om_data[0]) & 0xfff;
*idx2 = sys_get_le16(&buf->om_data[1]) >> 4;
- net_buf_simple_pull(buf, 3);
+ net_buf_simple_pull_mem(buf, 3);
}
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c
index 9056a865..9a83c87f 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c
@@ -7,7 +7,7 @@
*/
#include "syscfg/syscfg.h"
-#define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG
+#define MESH_LOG_MODULE BLE_MESH_FRIEND_LOG
#if MYNEWT_VAL(BLE_MESH_FRIEND)
@@ -21,10 +21,12 @@
#include "crypto.h"
#include "adv.h"
#include "net.h"
+#include "app_keys.h"
#include "transport.h"
#include "access.h"
#include "foundation.h"
#include "friend.h"
+#include "subnet.h"
/* We reserve one extra buffer for each friendship, since we need to be able
* to resend the last sent PDU, which sits separately outside of the queue.
@@ -48,20 +50,20 @@ static struct os_mempool friend_buf_mempool;
#define FRIEND_XMIT BT_MESH_TRANSMIT(0, 20)
struct friend_pdu_info {
- u16_t src;
- u16_t dst;
+ uint16_t src;
+ uint16_t dst;
- u8_t seq[3];
+ uint8_t seq[3];
- u8_t ttl:7,
+ uint8_t ttl:7,
ctl:1;
- u32_t iv_index;
+ uint32_t iv_index;
};
static struct friend_adv {
struct bt_mesh_adv adv;
- u16_t app_idx;
+ uint16_t app_idx;
} adv_pool[FRIEND_BUF_COUNT];
static struct bt_mesh_adv *adv_alloc(int id)
@@ -70,7 +72,7 @@ static struct bt_mesh_adv *adv_alloc(int id)
return &adv_pool[id].adv;
}
-static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr)
+static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr)
{
if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) {
return false;
@@ -79,7 +81,7 @@ static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr)
return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem));
}
-struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
+struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
bool valid, bool established)
{
int i;
@@ -89,7 +91,7 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
- if (valid && !frnd->valid) {
+ if (valid && !frnd->subnet) {
continue;
}
@@ -97,7 +99,8 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
continue;
}
- if (net_idx != BT_MESH_KEY_ANY && frnd->net_idx != net_idx) {
+ if (net_idx != BT_MESH_KEY_ANY &&
+ (!frnd->subnet || frnd->subnet->net_idx != net_idx)) {
continue;
}
@@ -109,11 +112,18 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
return NULL;
}
-static void purge_buffers(struct net_buf_slist_t *list)
+static int friend_cred_create(struct bt_mesh_friend *frnd, uint8_t idx)
{
- struct os_mbuf *buf;
+ return bt_mesh_friend_cred_create(&frnd->cred[idx], frnd->lpn,
+ bt_mesh_primary_addr(),
+ frnd->lpn_counter, frnd->counter,
+ frnd->subnet->keys[idx].net);
+}
+static void purge_buffers(struct net_buf_slist_t *list)
+{
while (!net_buf_slist_is_empty(list)) {
+ struct os_mbuf *buf;
buf = (void *)net_buf_slist_get(list);
BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS;
net_buf_unref(buf);
@@ -125,10 +135,10 @@ static void purge_buffers(struct net_buf_slist_t *list)
* like the PTS, where the receiver might not have sufficiently compensated
* for internal latencies required to start scanning.
*/
-static s32_t recv_delay(struct bt_mesh_friend *frnd)
+static int32_t recv_delay(struct bt_mesh_friend *frnd)
{
#if CONFIG_BT_MESH_FRIEND_RECV_WIN > 50
- return (s32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
+ return (int32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
#else
return frnd->recv_delay;
#endif
@@ -142,7 +152,7 @@ static void friend_clear(struct bt_mesh_friend *frnd)
k_delayed_work_cancel(&frnd->timer);
- friend_cred_del(frnd->net_idx, frnd->lpn);
+ memset(frnd->cred, 0, sizeof(frnd->cred));
if (frnd->last) {
/* Cancel the sending if necessary */
@@ -163,7 +173,8 @@ static void friend_clear(struct bt_mesh_friend *frnd)
seg->seg_count = 0U;
}
- frnd->valid = 0;
+ frnd->counter++;
+ frnd->subnet = NULL;
frnd->established = 0;
frnd->pending_buf = 0;
frnd->fsn = 0;
@@ -172,26 +183,26 @@ static void friend_clear(struct bt_mesh_friend *frnd)
memset(frnd->sub_list, 0, sizeof(frnd->sub_list));
}
-void bt_mesh_friend_clear_net_idx(u16_t net_idx)
+void bt_mesh_friends_clear(void)
{
int i;
- BT_DBG("net_idx 0x%04x", net_idx);
+ BT_DBG("");
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
- if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
+ if (!frnd->subnet) {
continue;
}
- if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
- friend_clear(frnd);
- }
+ friend_clear(frnd);
}
}
-void bt_mesh_friend_sec_update(u16_t net_idx)
+static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md);
+
+void bt_mesh_friend_sec_update(uint16_t net_idx)
{
int i;
@@ -200,12 +211,13 @@ void bt_mesh_friend_sec_update(u16_t net_idx)
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
- if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
+ if (!frnd->subnet) {
continue;
}
- if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
- frnd->sec_update = 1;
+ if (net_idx == BT_MESH_KEY_ANY ||
+ frnd->subnet->net_idx == net_idx) {
+ enqueue_update(frnd, 0x00);
}
}
}
@@ -214,7 +226,7 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_clear *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd;
- u16_t lpn_addr, lpn_counter;
+ uint16_t lpn_addr, lpn_counter;
struct bt_mesh_net_tx tx = {
.sub = rx->sub,
.ctx = &rx->ctx,
@@ -257,14 +269,14 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
cfm.lpn_counter = msg->lpn_counter;
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm,
- sizeof(cfm), NULL, NULL, NULL);
+ sizeof(cfm), NULL, NULL);
friend_clear(frnd);
return 0;
}
-static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr)
+static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr)
{
int i;
@@ -278,7 +290,7 @@ static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr)
BT_WARN("No space in friend subscription list");
}
-static void friend_sub_rem(struct bt_mesh_friend *frnd, u16_t addr)
+static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr)
{
int i;
@@ -322,38 +334,41 @@ static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd,
}
struct unseg_app_sdu_meta {
- struct bt_mesh_net_rx net;
- const u8_t *key;
+ struct bt_mesh_app_crypto_ctx crypto;
+ const uint8_t *key;
struct bt_mesh_subnet *subnet;
- bool is_dev_key;
- u8_t aid;
- u8_t *ad;
+ uint8_t aid;
};
static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd,
struct os_mbuf *buf,
struct unseg_app_sdu_meta *meta)
{
- u16_t app_idx = FRIEND_ADV(buf)->app_idx;
+ uint16_t app_idx = FRIEND_ADV(buf)->app_idx;
+ struct bt_mesh_net_rx net;
int err;
- meta->subnet = bt_mesh_subnet_get(frnd->net_idx);
- meta->is_dev_key = (app_idx == BT_MESH_KEY_DEV);
- meta->is_dev_key = BT_MESH_IS_DEV_KEY(app_idx);
- bt_mesh_net_header_parse(buf, &meta->net);
- err = bt_mesh_app_key_get(meta->subnet, app_idx, meta->net.ctx.recv_dst,
- &meta->key, &meta->aid);
+ meta->subnet = frnd->subnet;
+ bt_mesh_net_header_parse(buf, &net);
+ err = bt_mesh_keys_resolve(&net.ctx, &net.sub, &meta->key, &meta->aid);
if (err) {
return err;
}
- if (BT_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) {
- meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst);
- if (!meta->ad) {
+ meta->crypto.src = net.ctx.addr;
+ meta->crypto.dst = net.ctx.recv_dst;
+ meta->crypto.iv_index = BT_MESH_NET_IVI_TX;
+ meta->crypto.dev_key = BT_MESH_IS_DEV_KEY(app_idx);
+ meta->crypto.seq_num = net.seq;
+ meta->crypto.aszmic = 0;
+
+ if (BT_MESH_ADDR_IS_VIRTUAL(meta->crypto.dst)) {
+ meta->crypto.ad = bt_mesh_va_label_get(meta->crypto.dst);
+ if (!meta->crypto.ad) {
return -ENOENT;
}
} else {
- meta->ad = NULL;
+ meta->crypto.ad = NULL;
}
return 0;
@@ -372,12 +387,10 @@ static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd,
net_buf_simple_pull_mem(buf, 10);
buf->om_len -= 4;
- err = bt_mesh_app_decrypt_in_place(meta->key, meta->is_dev_key,
- 0, buf, meta->ad, meta->net.ctx.addr,
- meta->net.ctx.recv_dst, meta->net.seq,
- BT_MESH_NET_IVI_TX);
+ err = bt_mesh_app_decrypt(meta->key, &meta->crypto, buf, buf);
net_buf_simple_restore(buf, &state);
+ net_buf_unref(buf);
return err;
}
@@ -394,10 +407,7 @@ static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd,
net_buf_simple_pull_mem(buf, 10);
buf->om_len -= 4;
- err = bt_mesh_app_encrypt_in_place(meta->key, meta->is_dev_key, 0, buf,
- meta->ad, meta->net.ctx.addr,
- meta->net.ctx.recv_dst, bt_mesh.seq,
- BT_MESH_NET_IVI_TX);
+ err = bt_mesh_app_encrypt(meta->key, &meta->crypto, buf);
net_buf_simple_restore(buf, &state);
return err;
@@ -423,7 +433,7 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
/* No need to reencrypt the message if the sequence number is
* unchanged.
*/
- if (meta.net.seq == bt_mesh.seq) {
+ if (meta.crypto.seq_num == bt_mesh.seq) {
return 0;
}
@@ -444,28 +454,22 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
bool master_cred)
{
- struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
- const u8_t *enc, *priv;
- u32_t iv_index;
- u16_t src;
- u8_t nid;
+ const struct bt_mesh_net_cred *cred;
+ uint32_t iv_index;
+ uint16_t src;
int err;
if (master_cred) {
- enc = sub->keys[sub->kr_flag].enc;
- priv = sub->keys[sub->kr_flag].privacy;
- nid = sub->keys[sub->kr_flag].nid;
+ cred = &frnd->subnet->keys[SUBNET_KEY_TX_IDX(frnd->subnet)]
+ .msg;
} else {
- if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
- BT_ERR("friend_cred_get failed");
- return -ENOENT;
- }
+ cred = &frnd->cred[SUBNET_KEY_TX_IDX(frnd->subnet)];
}
src = sys_get_be16(&buf->om_data[5]);
if (bt_mesh_elem_find(src)) {
- u32_t seq;
+ uint32_t seq;
if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) {
err = unseg_app_sdu_prepare(frnd, buf);
@@ -475,25 +479,23 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
}
seq = bt_mesh_next_seq();
- buf->om_data[2] = seq >> 16;
- buf->om_data[3] = seq >> 8;
- buf->om_data[4] = seq;
+ sys_put_be24(seq, &buf->om_data[2]);
iv_index = BT_MESH_NET_IVI_TX;
FRIEND_ADV(buf)->app_idx = BT_MESH_KEY_UNUSED;
} else {
- u8_t ivi = (buf->om_data[0] >> 7);
+ uint8_t ivi = (buf->om_data[0] >> 7);
iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi));
}
- buf->om_data[0] = (nid | (iv_index & 1) << 7);
+ buf->om_data[0] = (cred->nid | (iv_index & 1) << 7);
- if (bt_mesh_net_encrypt(enc, buf, iv_index, false)) {
+ if (bt_mesh_net_encrypt(cred->enc, buf, iv_index, false)) {
BT_ERR("Encrypting failed");
return -EINVAL;
}
- if (bt_mesh_net_obfuscate(buf->om_data, iv_index, priv)) {
+ if (bt_mesh_net_obfuscate(buf->om_data, iv_index, cred->privacy)) {
BT_ERR("Obfuscating failed");
return -EINVAL;
}
@@ -502,7 +504,7 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
}
static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
- u8_t ctl_op,
+ uint8_t ctl_op,
struct os_mbuf *sdu)
{
struct friend_pdu_info info;
@@ -524,21 +526,20 @@ static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
return create_friend_pdu(frnd, &info, sdu);
}
-static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
+static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, uint8_t md)
{
struct bt_mesh_ctl_friend_update *upd;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*upd));
- struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
struct os_mbuf *buf;
- __ASSERT_NO_MSG(sub != NULL);
+ __ASSERT_NO_MSG(frnd->subnet);
BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md);
net_buf_simple_init(sdu, 1);
upd = net_buf_simple_add(sdu, sizeof(*upd));
- upd->flags = bt_mesh_net_flags(sub);
+ upd->flags = bt_mesh_net_flags(frnd->subnet);
upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index);
upd->md = md;
@@ -548,7 +549,7 @@ static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
return buf;
}
-static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact)
+static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact)
{
struct bt_mesh_ctl_friend_sub_confirm *cfm;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*cfm));
@@ -585,16 +586,18 @@ done:
static void friend_recv_delay(struct bt_mesh_friend *frnd)
{
+ int32_t delay = recv_delay(frnd);
+
frnd->pending_req = 1;
- k_delayed_work_submit(&frnd->timer, recv_delay(frnd));
- BT_DBG("Waiting RecvDelay of %d ms", (int) recv_delay(frnd));
+ k_delayed_work_submit(&frnd->timer, K_MSEC(delay));
+ BT_DBG("Waiting RecvDelay of %d ms", delay);
}
int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_friend *frnd;
- u8_t xact;
+ uint8_t xact;
if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
BT_WARN("Too short Friend Subscription Add");
@@ -629,7 +632,7 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_friend *frnd;
- u8_t xact;
+ uint8_t xact;
if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
BT_WARN("Too short Friend Subscription Remove");
@@ -666,7 +669,7 @@ static void enqueue_buf(struct bt_mesh_friend *frnd, struct os_mbuf *buf)
frnd->queue_size++;
}
-static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md)
+static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md)
{
struct os_mbuf *buf;
@@ -676,7 +679,6 @@ static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md)
return;
}
- frnd->sec_update = 0;
enqueue_buf(frnd, buf);
}
@@ -735,7 +737,7 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
return 0;
}
-static struct bt_mesh_friend *find_clear(u16_t prev_friend)
+static struct bt_mesh_friend *find_clear(uint16_t prev_friend)
{
int i;
@@ -766,13 +768,13 @@ static const struct bt_mesh_send_cb clear_sent_cb = {
static void send_friend_clear(struct bt_mesh_friend *frnd)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = frnd->net_idx,
+ .net_idx = frnd->subnet->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = frnd->clear.frnd,
.send_ttl = BT_MESH_TTL_MAX,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = frnd->subnet,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = bt_mesh_net_transmit_get(),
@@ -785,13 +787,13 @@ static void send_friend_clear(struct bt_mesh_friend *frnd)
BT_DBG("");
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
- sizeof(req), NULL, &clear_sent_cb, frnd);
+ sizeof(req), &clear_sent_cb, frnd);
}
static void clear_timeout(struct ble_npl_event *work)
{
struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
- u32_t duration;
+ uint32_t duration;
BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
@@ -820,7 +822,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
{
struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd;
- u16_t lpn_addr, lpn_counter;
+ uint16_t lpn_addr, lpn_counter;
BT_DBG("");
@@ -855,7 +857,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
return 0;
}
-static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
+static void enqueue_offer(struct bt_mesh_friend *frnd, int8_t rssi)
{
struct bt_mesh_ctl_friend_offer *off;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*off));
@@ -880,11 +882,9 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
}
if (encrypt_friend_pdu(frnd, buf, true)) {
- return;
+ goto done;
}
- frnd->counter++;
-
if (frnd->last) {
net_buf_unref(frnd->last);
}
@@ -897,43 +897,45 @@ done:
}
#define RECV_WIN CONFIG_BT_MESH_FRIEND_RECV_WIN
-#define RSSI_FACT(crit) (((crit) >> 5) & (u8_t)BIT_MASK(2))
-#define RECV_WIN_FACT(crit) (((crit) >> 3) & (u8_t)BIT_MASK(2))
-#define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (u8_t)BIT_MASK(3))
-#define MIN_QUEUE_SIZE(crit) ((u32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
+#define RSSI_FACT(crit) (((crit) >> 5) & (uint8_t)BIT_MASK(2))
+#define RECV_WIN_FACT(crit) (((crit) >> 3) & (uint8_t)BIT_MASK(2))
+#define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (uint8_t)BIT_MASK(3))
+#define MIN_QUEUE_SIZE(crit) ((uint32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
-static s32_t offer_delay(struct bt_mesh_friend *frnd, s8_t rssi, u8_t crit)
+static int32_t offer_delay(struct bt_mesh_friend *frnd, int8_t rssi, uint8_t crit)
{
/* Scaling factors. The actual values are 1, 1.5, 2 & 2.5, but we
* want to avoid floating-point arithmetic.
*/
- static const u8_t fact[] = { 10, 15, 20, 25 };
- s32_t delay;
+ static const uint8_t fact[] = { 10, 15, 20, 25 };
+ int32_t delay;
BT_DBG("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d",
fact[RECV_WIN_FACT(crit)], RECV_WIN,
fact[RSSI_FACT(crit)], rssi);
/* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */
- delay = (s32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
- delay -= (s32_t)fact[RSSI_FACT(crit)] * rssi;
+ delay = (int32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
+ delay -= (int32_t)fact[RSSI_FACT(crit)] * rssi;
delay /= 10;
BT_DBG("Local Delay calculated as %d ms", (int) delay);
- if (delay < 100) {
- return K_MSEC(100);
- }
-
- return K_MSEC(delay);
+ return MAX(delay, 100);
}
int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_req *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd = NULL;
- u32_t poll_to;
- int i;
+ uint32_t poll_to;
+ int32_t delay;
+ int i, err;
+
+ if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+ BT_WARN("Ignoring Friend request from local interface");
+ return 0;
+ }
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Request");
@@ -945,9 +947,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
return -EINVAL;
}
- poll_to = (((u32_t)msg->poll_to[0] << 16) |
- ((u32_t)msg->poll_to[1] << 8) |
- ((u32_t)msg->poll_to[2]));
+ poll_to = sys_get_be24(msg->poll_to);
if (poll_to <= 0x000009 || poll_to >= 0x34bc00) {
BT_WARN("Prohibited PollTimeout (0x%06x)", (unsigned) poll_to);
@@ -984,9 +984,8 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
}
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
- if (!bt_mesh.frnd[i].valid) {
+ if (!bt_mesh.frnd[i].subnet) {
frnd = &bt_mesh.frnd[i];
- frnd->valid = 1;
break;
}
}
@@ -999,12 +998,19 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
init_friend:
frnd->lpn = rx->ctx.addr;
frnd->num_elem = msg->num_elem;
- frnd->net_idx = rx->sub->net_idx;
+ frnd->subnet = rx->sub;
frnd->recv_delay = msg->recv_delay;
frnd->poll_to = poll_to * 100;
frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
+ err = friend_cred_create(frnd, SUBNET_KEY_TX_IDX(frnd->subnet));
+ if (err) {
+ BT_ERR("Failed to create friend credentials");
+ friend_clear(frnd);
+ return -EIO;
+ }
+
BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay,
(unsigned) frnd->poll_to);
@@ -1014,24 +1020,20 @@ init_friend:
clear_procedure_start(frnd);
}
- k_delayed_work_submit(&frnd->timer,
- offer_delay(frnd, rx->ctx.recv_rssi,
- msg->criteria));
-
- friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
- frnd->counter);
+ delay = offer_delay(frnd, rx->ctx.recv_rssi, msg->criteria);
+ k_delayed_work_submit(&frnd->timer, K_MSEC(delay));
enqueue_offer(frnd, rx->ctx.recv_rssi);
return 0;
}
-static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero)
+static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_zero)
{
struct os_mbuf *buf = (void *)net_buf_slist_peek_head(&seg->queue);
struct net_buf_simple_state state;
- u16_t buf_seq_zero;
- u16_t buf_src;
+ uint16_t buf_seq_zero;
+ uint16_t buf_src;
if (!buf) {
return false;
@@ -1048,8 +1050,8 @@ static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero)
}
static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
- u16_t src, u16_t seq_zero,
- u8_t seg_count)
+ uint16_t src, uint16_t seq_zero,
+ uint8_t seg_count)
{
struct bt_mesh_friend_seg *unassigned = NULL;
int i;
@@ -1075,7 +1077,7 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
enum bt_mesh_friend_pdu_type type,
- u16_t src, u8_t seg_count,
+ uint16_t src, uint8_t seg_count,
struct os_mbuf *buf)
{
struct bt_mesh_friend_seg *seg;
@@ -1083,15 +1085,11 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
BT_DBG("type %u", type);
if (type == BT_MESH_FRIEND_PDU_SINGLE) {
- if (frnd->sec_update) {
- enqueue_update(frnd, 1);
- }
-
enqueue_buf(frnd, buf);
return;
}
- u16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
+ uint16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
seg = get_seg(frnd, src, seq_zero, seg_count);
if (!seg) {
@@ -1103,10 +1101,6 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
net_buf_slist_put(&seg->queue, buf);
if (type == BT_MESH_FRIEND_PDU_COMPLETE) {
- if (frnd->sec_update) {
- enqueue_update(frnd, 1);
- }
-
net_buf_slist_merge_slist(&frnd->queue, &seg->queue);
frnd->queue_size += seg->seg_count;
@@ -1117,7 +1111,7 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
}
}
-static void buf_send_start(u16_t duration, int err, void *user_data)
+static void buf_send_start(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_friend *frnd = user_data;
@@ -1126,7 +1120,7 @@ static void buf_send_start(u16_t duration, int err, void *user_data)
frnd->pending_buf = 0;
/* Friend Offer doesn't follow the re-sending semantics */
- if (!frnd->established) {
+ if (!frnd->established && frnd->last) {
net_buf_unref(frnd->last);
frnd->last = NULL;
}
@@ -1154,6 +1148,38 @@ static void buf_send_end(int err, void *user_data)
}
}
+static void update_overwrite(struct os_mbuf *buf, uint8_t md)
+{
+ struct net_buf_simple_state state;
+ struct bt_mesh_ctl_friend_update *upd;
+
+ if (buf->om_len != 16) {
+ return;
+ }
+
+ net_buf_simple_save(buf, &state);
+
+ net_buf_skip(buf, 1); /* skip IVI, NID */
+
+ if (!(net_buf_pull_u8(buf) >> 7)) {
+ goto end;
+ }
+
+ net_buf_skip(buf, 7); /* skip seqnum src dec*/
+
+ if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1))
+ != TRANS_CTL_OP_FRIEND_UPDATE) {
+ goto end;
+ }
+
+ upd = net_buf_pull_mem(buf, sizeof(*upd));
+ BT_DBG("Update Previous Friend Update MD 0x%02x -> 0x%02x", upd->md, md);
+ upd->md = md;
+
+end:
+ net_buf_simple_restore(buf, &state);
+}
+
static void friend_timeout(struct ble_npl_event *work)
{
struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
@@ -1162,6 +1188,8 @@ static void friend_timeout(struct ble_npl_event *work)
.end = buf_send_end,
};
+ uint8_t md;
+
__ASSERT_NO_MSG(frnd->pending_buf == 0);
BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn,
@@ -1187,12 +1215,17 @@ static void friend_timeout(struct ble_npl_event *work)
return;
}
+ md = (uint8_t)(net_buf_slist_peek_head(&frnd->queue) != NULL);
+
+ update_overwrite(frnd->last, md);
+
if (encrypt_friend_pdu(frnd, frnd->last, false)) {
return;
}
/* Clear the flag we use for segment tracking */
BT_MESH_ADV(frnd->last)->flags &= ~NET_BUF_FRAGS;
+ BT_MESH_ADV(frnd->last)->flags = 0;
BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
frnd->last, frnd->lpn);
@@ -1204,8 +1237,56 @@ send_last:
bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
}
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ int i, err;
+
+ if (evt == BT_MESH_KEY_ADDED) {
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+ struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+ if (frnd->subnet != sub) {
+ continue;
+ }
+
+ switch (evt) {
+ case BT_MESH_KEY_DELETED:
+ BT_DBG("Cleared network for 0x%04x", frnd->lpn);
+ friend_clear(frnd);
+ break;
+ case BT_MESH_KEY_UPDATED:
+ BT_DBG("Generating new keys for 0x%04x", frnd->lpn);
+ err = friend_cred_create(frnd, 1);
+ if (err) {
+ BT_ERR("Failed updating friend cred for 0x%04x",
+ frnd->lpn);
+ friend_clear(frnd);
+ }
+ break;
+ case BT_MESH_KEY_SWAPPED:
+ enqueue_update(frnd, 0);
+ break;
+ case BT_MESH_KEY_REVOKED:
+ BT_DBG("Revoking old keys for 0x%04x", frnd->lpn);
+ memcpy(&frnd->cred[0], &frnd->cred[1],
+ sizeof(frnd->cred[0]));
+ memset(&frnd->cred[1], 0, sizeof(frnd->cred[1]));
+ enqueue_update(frnd, 0);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
int bt_mesh_friend_init(void)
{
+ if (!bt_mesh_subnet_cb_list[3]) {
+ bt_mesh_subnet_cb_list[3] = subnet_evt;
+ }
int rc;
int i;
@@ -1223,8 +1304,6 @@ int bt_mesh_friend_init(void)
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
int j;
- frnd->net_idx = BT_MESH_KEY_UNUSED;
-
net_buf_slist_init(&frnd->queue);
k_delayed_work_init(&frnd->timer, friend_timeout);
@@ -1240,7 +1319,7 @@ int bt_mesh_friend_init(void)
return 0;
}
-static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src)
+static bool is_segack(struct os_mbuf *buf, uint64_t *seqauth, uint16_t src)
{
struct net_buf_simple_state state;
bool found = false;
@@ -1265,7 +1344,7 @@ static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src)
net_buf_skip(buf, 2); /* skip dst */
- if (TRANS_CTL_OP((u8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
+ if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
goto end;
}
@@ -1276,8 +1355,8 @@ end:
return found;
}
-static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
- u16_t src)
+static void friend_purge_old_ack(struct bt_mesh_friend *frnd, uint64_t *seq_auth,
+ uint16_t src)
{
struct os_mbuf *cur, *prev = NULL;
@@ -1302,7 +1381,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
struct friend_pdu_info info;
@@ -1334,9 +1413,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
info.ctl = rx->ctl;
- info.seq[0] = (rx->seq >> 16);
- info.seq[1] = (rx->seq >> 8);
- info.seq[2] = rx->seq;
+ sys_put_be24(rx->seq, info.seq);
info.iv_index = BT_MESH_NET_IVI_RX(rx);
@@ -1355,7 +1432,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
struct friend_pdu_info info;
@@ -1373,9 +1450,7 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
info.ttl = tx->ctx->send_ttl;
info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
- info.seq[0] = (bt_mesh.seq >> 16);
- info.seq[1] = (bt_mesh.seq >> 8);
- info.seq[2] = bt_mesh.seq;
+ sys_put_be24(bt_mesh.seq, info.seq);
info.iv_index = BT_MESH_NET_IVI_TX;
@@ -1398,8 +1473,8 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
}
-static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
- u16_t addr)
+static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx,
+ uint16_t addr)
{
int i;
@@ -1407,7 +1482,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
return false;
}
- if (net_idx != frnd->net_idx) {
+ if (net_idx != frnd->subnet->net_idx) {
return false;
}
@@ -1424,7 +1499,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
return false;
}
-bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
+bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr)
{
int i;
@@ -1443,10 +1518,10 @@ bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
return false;
}
-static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr,
- u64_t *seq_auth, u8_t seg_count)
+static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr,
+ uint64_t *seq_auth, uint8_t seg_count)
{
- u32_t total = 0;
+ uint32_t total = 0;
int i;
if (seg_count > CONFIG_BT_MESH_FRIEND_QUEUE_SIZE) {
@@ -1474,8 +1549,8 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr,
return (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - total) > seg_count;
}
-bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
- u64_t *seq_auth, u8_t seg_count)
+bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
+ uint64_t *seq_auth, uint8_t seg_count)
{
bool someone_has_space = false, friend_match = false;
int i;
@@ -1509,11 +1584,11 @@ bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
return someone_has_space;
}
-static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr,
- u64_t *seq_auth, u8_t seg_count)
+static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t addr,
+ uint64_t *seq_auth, uint8_t seg_count)
{
bool pending_segments;
- u8_t avail_space;
+ uint8_t avail_space;
if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) {
return false;
@@ -1547,7 +1622,7 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr,
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
int i;
@@ -1570,6 +1645,11 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
continue;
}
+ if (friend_lpn_matches(frnd, rx->sub->net_idx,
+ rx->ctx.addr)) {
+ continue;
+ }
+
if (!friend_queue_prepare_space(frnd, rx->ctx.addr, seq_auth,
seg_count)) {
continue;
@@ -1582,7 +1662,7 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
bool matched = false;
@@ -1617,8 +1697,22 @@ bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
return matched;
}
-void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
- u16_t dst, u64_t *seq_auth)
+int bt_mesh_friend_terminate(uint16_t lpn_addr)
+{
+ struct bt_mesh_friend *frnd;
+
+ frnd = bt_mesh_friend_find(BT_MESH_KEY_ANY, lpn_addr, false, false);
+ if (!frnd) {
+ return -ENOENT;
+ }
+
+ friend_clear(frnd);
+
+ return 0;
+}
+
+void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
+ uint16_t dst, uint64_t *seq_auth)
{
int i;
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h
index 10ffa819..ee783f33 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h
@@ -17,29 +17,29 @@ enum bt_mesh_friend_pdu_type {
BT_MESH_FRIEND_PDU_COMPLETE,
};
-bool bt_mesh_friend_match(u16_t net_idx, u16_t addr);
+bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr);
-struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
+struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
bool valid, bool established);
-bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
- u64_t *seq_auth, u8_t seg_count);
+bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
+ uint64_t *seq_auth, uint8_t seg_count);
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf);
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf);
-void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
- u16_t dst, u64_t *seq_auth);
+void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
+ uint16_t dst, uint64_t *seq_auth);
-void bt_mesh_friend_sec_update(u16_t net_idx);
+void bt_mesh_friend_sec_update(uint16_t net_idx);
-void bt_mesh_friend_clear_net_idx(u16_t net_idx);
+void bt_mesh_friends_clear(void);
int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c
index 896f3d1a..aab7f374 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c
@@ -30,7 +30,7 @@
#include "base64/base64.h"
#endif
-extern u8_t g_mesh_addr_type;
+extern uint8_t g_mesh_addr_type;
#if MYNEWT_VAL(BLE_EXT_ADV)
/* Store configuration for different bearers */
@@ -44,8 +44,8 @@ bt_hex(const void *buf, size_t len)
{
static const char hex[] = "0123456789abcdef";
static char hexbufs[4][137];
- static u8_t curbuf;
- const u8_t *b = buf;
+ static uint8_t curbuf;
+ const uint8_t *b = buf;
char *str;
int i;
@@ -215,6 +215,14 @@ net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val)
}
void
+net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val)
+{
+ val = htole32(val);
+ os_mbuf_append(om, &val, 3);
+ ASSERT_NOT_CHAIN(om);
+}
+
+void
net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val)
{
val = htobe32(val);
@@ -270,6 +278,22 @@ net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val)
}
void
+net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val)
+{
+ uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len];
+
+ assert(headroom >= 3);
+ om->om_data -= 3;
+ put_be24(om->om_data, val);
+ om->om_len += 3;
+
+ if (om->om_pkthdr_len) {
+ OS_MBUF_PKTHDR(om)->omp_len += 3;
+ }
+ ASSERT_NOT_CHAIN(om);
+}
+
+void
net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val)
{
uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len];
@@ -333,7 +357,7 @@ k_fifo_is_empty(struct ble_npl_eventq *q)
return ble_npl_eventq_is_empty(q);
}
-void * net_buf_get(struct ble_npl_eventq *fifo, s32_t t)
+void * net_buf_get(struct ble_npl_eventq *fifo, int32_t t)
{
struct ble_npl_event *ev = ble_npl_eventq_get(fifo, 0);
@@ -384,6 +408,12 @@ k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f)
#endif
}
+bool
+k_delayed_work_pending(struct k_delayed_work *w)
+{
+ return ble_npl_callout_is_active(&w->work);
+}
+
void
k_delayed_work_cancel(struct k_delayed_work *w)
{
@@ -440,7 +470,7 @@ int64_t k_uptime_get(void)
return ble_npl_time_ticks_to_ms32(ble_npl_time_get());
}
-u32_t k_uptime_get_32(void)
+uint32_t k_uptime_get_32(void)
{
return k_uptime_get();
}
@@ -459,7 +489,7 @@ static uint8_t priv[32];
static bool has_pub = false;
int
-bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb)
+bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb)
{
uint8_t dh[32];
@@ -510,7 +540,7 @@ bt_pub_key_get(void)
}
static int
-set_ad(const struct bt_data *ad, size_t ad_len, u8_t *buf, u8_t *buf_len)
+set_ad(const struct bt_data *ad, size_t ad_len, uint8_t *buf, uint8_t *buf_len)
{
int i;
@@ -846,6 +876,52 @@ void net_buf_slist_merge_slist(struct net_buf_slist_t *list,
}
}
+/** Memory slab methods */
+extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem)
+{
+ **(char ***)mem = slab->free_list;
+ slab->free_list = *(char **)mem;
+ slab->num_used--;
+}
+
+extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem)
+{
+ int result;
+
+ if (slab->free_list != NULL) {
+ /* take a free block */
+ *mem = slab->free_list;
+ slab->free_list = *(char **)(slab->free_list);
+ slab->num_used++;
+ result = 0;
+ } else {
+ *mem = NULL;
+ result = -ENOMEM;
+ }
+ return result;
+}
+
+int create_free_list(struct k_mem_slab *slab)
+{
+ uint32_t j;
+ char *p;
+
+ if(((slab->block_size | (uintptr_t)slab->buffer) &
+ (sizeof(void *) - 1)) != 0) {
+ return -EINVAL;
+ }
+
+ slab->free_list = NULL;
+ p = slab->buffer;
+
+ for (j = 0U; j < slab->num_blocks; j++) {
+ *(char **)p = slab->free_list;
+ slab->free_list = p;
+ p += slab->block_size;
+ }
+ return 0;
+}
+
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
int settings_bytes_from_str(char *val_str, void *vp, int *len)
@@ -867,4 +943,3 @@ char *settings_str_from_bytes(const void *vp, int vp_len,
}
#endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */
-
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c
index 193279c2..76d639c5 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c
@@ -21,15 +21,15 @@
#include "foundation.h"
#include "mesh/health_cli.h"
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_health_cli *health_cli;
struct health_fault_param {
- u16_t cid;
- u8_t *expect_test_id;
- u8_t *test_id;
- u8_t *faults;
+ uint16_t cid;
+ uint8_t *expect_test_id;
+ uint8_t *test_id;
+ uint8_t *faults;
size_t *fault_count;
};
@@ -38,8 +38,8 @@ static void health_fault_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct health_fault_param *param;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -84,8 +84,8 @@ static void health_current_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_cli *cli = model->user_data;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len,
@@ -106,7 +106,7 @@ static void health_current_status(struct bt_mesh_model *model,
}
struct health_period_param {
- u8_t *divisor;
+ uint8_t *divisor;
};
static void health_period_status(struct bt_mesh_model *model,
@@ -132,7 +132,7 @@ static void health_period_status(struct bt_mesh_model *model,
}
struct health_attention_param {
- u8_t *attention;
+ uint8_t *attention;
};
static void health_attention_status(struct bt_mesh_model *model,
@@ -167,7 +167,7 @@ const struct bt_mesh_model_op bt_mesh_health_cli_op[] = {
BT_MESH_MODEL_OP_END,
};
-static int cli_prepare(void *param, u32_t op)
+static int cli_prepare(void *param, uint32_t op)
{
if (!health_cli) {
BT_ERR("No available Health Client context!");
@@ -202,12 +202,10 @@ static int cli_wait(void)
return err;
}
-int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *attention)
+int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_GET, 0);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -237,12 +235,11 @@ done:
return err;
}
-int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t attention, u8_t *updated_attention)
+int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
+ uint8_t *updated_attention)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_SET, 1);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -283,12 +280,10 @@ done:
return err;
}
-int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *divisor)
+int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_GET, 0);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -318,12 +313,11 @@ done:
return err;
}
-int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t divisor, u8_t *updated_divisor)
+int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
+ uint8_t *updated_divisor)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_SET, 1);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -364,13 +358,12 @@ done:
return err;
}
-int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t test_id, u8_t *faults,
- size_t *fault_count)
+int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t test_id, uint8_t *faults,
+ size_t *fault_count)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_TEST, 3);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -415,13 +408,12 @@ done:
return err;
}
-int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t *test_id, u8_t *faults,
- size_t *fault_count)
+int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults,
+ size_t *fault_count)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_CLEAR, 2);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -465,13 +457,12 @@ done:
return err;
}
-int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t *test_id, u8_t *faults,
- size_t *fault_count)
+int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults,
+ size_t *fault_count)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_GET, 2);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -505,12 +496,12 @@ done:
return err;
}
-s32_t bt_mesh_health_cli_timeout_get(void)
+int32_t bt_mesh_health_cli_timeout_get(void)
{
return msg_timeout;
}
-void bt_mesh_health_cli_timeout_set(s32_t timeout)
+void bt_mesh_health_cli_timeout_set(int32_t timeout)
{
msg_timeout = timeout;
}
@@ -523,6 +514,7 @@ int bt_mesh_health_cli_set(struct bt_mesh_model *model)
}
health_cli = model->user_data;
+ msg_timeout = 2 * MSEC_PER_SEC;
return 0;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c
index 16de83a9..dd90533b 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c
@@ -27,11 +27,11 @@
struct bt_mesh_health_srv *health_srv;
static void health_get_registered(struct bt_mesh_model *mod,
- u16_t company_id,
+ uint16_t company_id,
struct os_mbuf *msg)
{
struct bt_mesh_health_srv *srv = mod->user_data;
- u8_t *test_id;
+ uint8_t *test_id;
BT_DBG("Company ID 0x%04x", company_id);
@@ -41,7 +41,7 @@ static void health_get_registered(struct bt_mesh_model *mod,
net_buf_simple_add_le16(msg, company_id);
if (srv->cb && srv->cb->fault_get_reg) {
- u8_t fault_count = net_buf_simple_tailroom(msg) - 4;
+ uint8_t fault_count = net_buf_simple_tailroom(msg) - 4;
int err;
err = srv->cb->fault_get_reg(mod, company_id, test_id,
@@ -64,9 +64,9 @@ static size_t health_get_current(struct bt_mesh_model *mod,
{
struct bt_mesh_health_srv *srv = mod->user_data;
const struct bt_mesh_comp *comp;
- u8_t *test_id, *company_ptr;
- u16_t company_id;
- u8_t fault_count;
+ uint8_t *test_id, *company_ptr;
+ uint16_t company_id;
+ uint8_t fault_count;
int err;
bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS);
@@ -104,7 +104,7 @@ static void health_fault_get(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -124,7 +124,7 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -141,7 +141,7 @@ static void health_fault_clear(struct bt_mesh_model *model,
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -165,8 +165,8 @@ static void health_fault_test_unrel(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
- u8_t test_id;
+ uint16_t company_id;
+ uint8_t test_id;
test_id = net_buf_simple_pull_u8(buf);
company_id = net_buf_simple_pull_le16(buf);
@@ -184,8 +184,8 @@ static void health_fault_test(struct bt_mesh_model *model,
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
- u8_t test_id;
+ uint16_t company_id;
+ uint8_t test_id;
BT_DBG("");
@@ -219,7 +219,7 @@ static void send_attention_status(struct bt_mesh_model *model,
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_STATUS, 1);
struct bt_mesh_health_srv *srv = model->user_data;
- u8_t time;
+ uint8_t time;
time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000;
BT_DBG("%u second%s", time, (time == 1) ? "" : "s");
@@ -248,7 +248,7 @@ static void attention_set_unrel(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t time;
+ uint8_t time;
time = net_buf_simple_pull_u8(buf);
@@ -297,7 +297,7 @@ static void health_period_set_unrel(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t period;
+ uint8_t period;
period = net_buf_simple_pull_u8(buf);
if (period > 15) {
@@ -389,10 +389,6 @@ static int health_srv_init(struct bt_mesh_model *model)
struct bt_mesh_health_srv *srv = model->user_data;
if (!srv) {
- if (!bt_mesh_model_in_primary(model)) {
- return 0;
- }
-
BT_ERR("No Health Server context provided");
return -EINVAL;
}
@@ -420,7 +416,7 @@ const struct bt_mesh_model_cb bt_mesh_health_srv_cb = {
.init = health_srv_init,
};
-void bt_mesh_attention(struct bt_mesh_model *model, u8_t time)
+void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time)
{
struct bt_mesh_health_srv *srv;
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c
new file mode 100644
index 00000000..538a1cb6
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_HEARTBEAT_LOG
+
+#include "mesh_priv.h"
+#include "net.h"
+#include "rpl.h"
+#include "access.h"
+#include "lpn.h"
+#include "settings.h"
+#include "transport.h"
+#include "heartbeat.h"
+#include "foundation.h"
+#include "mesh/glue.h"
+
+struct bt_mesh_hb_cb hb_cb;
+
+static struct bt_mesh_hb_pub pub;
+static struct bt_mesh_hb_sub sub;
+static struct k_delayed_work sub_timer;
+static struct k_delayed_work pub_timer;
+
+static int64_t sub_remaining(void)
+{
+ if (sub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return 0U;
+ }
+
+ return k_delayed_work_remaining_get(&sub_timer) / MSEC_PER_SEC;
+}
+
+static void hb_publish_end_cb(int err, void *cb_data)
+{
+ if (pub.period && pub.count > 1) {
+ k_delayed_work_submit(&pub_timer, K_SECONDS(pub.period));
+ }
+
+ if (pub.count != 0xffff) {
+ pub.count--;
+ }
+}
+
+static void notify_recv(uint8_t hops, uint16_t feat)
+{
+ sub.remaining = sub_remaining();
+
+ if (hb_cb.recv != NULL) {
+ hb_cb.recv(&sub, hops, feat);
+ }
+}
+
+static void notify_sub_end(void)
+{
+ sub.remaining = 0;
+
+ if (hb_cb.sub_end != NULL) {
+ hb_cb.sub_end(&sub);
+ }
+}
+
+static void sub_end(struct ble_npl_event *work)
+{
+ notify_sub_end();
+}
+
+static int heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+ uint16_t feat = 0U;
+ struct __packed {
+ uint8_t init_ttl;
+ uint16_t feat;
+ } hb;
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = pub.net_idx,
+ .app_idx = BT_MESH_KEY_UNUSED,
+ .addr = pub.dst,
+ .send_ttl = pub.ttl,
+ };
+ struct bt_mesh_net_tx tx = {
+ .sub = bt_mesh_subnet_get(pub.net_idx),
+ .ctx = &ctx,
+ .src = bt_mesh_primary_addr(),
+ .xmit = bt_mesh_net_transmit_get(),
+ };
+
+ /* Do nothing if heartbeat publication is not enabled */
+ if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return 0U;
+ }
+
+ hb.init_ttl = pub.ttl;
+
+ if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) {
+ feat |= BT_MESH_FEAT_RELAY;
+ }
+
+ if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
+ feat |= BT_MESH_FEAT_PROXY;
+ }
+
+ if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) {
+ feat |= BT_MESH_FEAT_FRIEND;
+ }
+
+ if (bt_mesh_lpn_established()) {
+ feat |= BT_MESH_FEAT_LOW_POWER;
+ }
+
+ hb.feat = sys_cpu_to_be16(feat);
+
+ BT_DBG("InitTTL %u feat 0x%04x", pub.ttl, feat);
+
+ return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
+ cb, cb_data);
+}
+
+static void hb_publish_start_cb(uint16_t duration, int err, void *cb_data)
+{
+ if (err) {
+ hb_publish_end_cb(err, cb_data);
+ }
+}
+
+static void hb_publish(struct ble_npl_event *work)
+{
+ static const struct bt_mesh_send_cb publish_cb = {
+ .start = hb_publish_start_cb,
+ .end = hb_publish_end_cb,
+ };
+ struct bt_mesh_subnet *sub;
+ int err;
+
+ BT_DBG("hb_pub.count: %u", pub.count);
+
+ sub = bt_mesh_subnet_get(pub.net_idx);
+ if (!sub) {
+ BT_ERR("No matching subnet for idx 0x%02x", pub.net_idx);
+ pub.dst = BT_MESH_ADDR_UNASSIGNED;
+ return;
+ }
+
+ if (pub.count == 0U) {
+ return;
+ }
+
+ err = heartbeat_send(&publish_cb, NULL);
+ if (err) {
+ hb_publish_end_cb(err, NULL);
+ }
+}
+
+int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t init_ttl, hops;
+ uint16_t feat;
+
+ if (buf->om_len < 3) {
+ BT_ERR("Too short heartbeat message");
+ return -EINVAL;
+ }
+
+ init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
+ feat = net_buf_simple_pull_be16(buf);
+
+ hops = (init_ttl - rx->ctx.recv_ttl + 1);
+
+ if (rx->ctx.addr != sub.src || rx->ctx.recv_dst != sub.dst) {
+ BT_DBG("No subscription for received heartbeat");
+ return 0;
+ }
+
+ if (!k_delayed_work_pending(&sub_timer)) {
+ BT_DBG("Heartbeat subscription period expired");
+ return 0;
+ }
+
+ sub.min_hops = MIN(sub.min_hops, hops);
+ sub.max_hops = MAX(sub.max_hops, hops);
+
+ if (sub.count < 0xffff) {
+ sub.count++;
+ }
+
+ BT_DBG("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x",
+ rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
+ (hops == 1U) ? "" : "s", feat);
+
+ notify_recv(hops, feat);
+
+ return 0;
+}
+
+static void pub_disable(void)
+{
+ BT_DBG("");
+
+ pub.dst = BT_MESH_ADDR_UNASSIGNED;
+ pub.count = 0U;
+ pub.ttl = 0U;
+ pub.period = 0U;
+
+ k_delayed_work_cancel(&pub_timer);
+}
+
+uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub)
+{
+ if (!new_pub || new_pub->dst == BT_MESH_ADDR_UNASSIGNED) {
+ pub_disable();
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ bt_mesh_is_provisioned()) {
+ bt_mesh_store_hb_pub();
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ if (!bt_mesh_subnet_get(new_pub->net_idx)) {
+ BT_ERR("Unknown NetKey 0x%04x", new_pub->net_idx);
+ return STATUS_INVALID_NETKEY;
+ }
+
+ new_pub->feat &= BT_MESH_FEAT_SUPPORTED;
+ pub = *new_pub;
+
+ if (!bt_mesh_is_provisioned()) {
+ return STATUS_SUCCESS;
+ }
+
+ /* The first Heartbeat message shall be published as soon as possible
+ * after the Heartbeat Publication Period state has been configured for
+ * periodic publishing.
+ */
+ if (pub.period && pub.count) {
+ k_delayed_work_submit(&pub_timer, K_NO_WAIT);
+ } else {
+ k_delayed_work_cancel(&pub_timer);
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_hb_pub();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get)
+{
+ *get = pub;
+}
+
+uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period)
+{
+ if (src != BT_MESH_ADDR_UNASSIGNED && !BT_MESH_ADDR_IS_UNICAST(src)) {
+ BT_WARN("Prohibited source address");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ if (BT_MESH_ADDR_IS_VIRTUAL(dst) || BT_MESH_ADDR_IS_RFU(dst) ||
+ (BT_MESH_ADDR_IS_UNICAST(dst) && dst != bt_mesh_primary_addr())) {
+ BT_WARN("Prohibited destination address");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ if (period > (1U << 16)) {
+ BT_WARN("Prohibited subscription period %u s", period);
+ return STATUS_CANNOT_SET;
+ }
+
+ /* Only an explicit address change to unassigned should trigger clearing
+ * of the values according to MESH/NODE/CFG/HBS/BV-02-C.
+ */
+ if (src == BT_MESH_ADDR_UNASSIGNED || dst == BT_MESH_ADDR_UNASSIGNED) {
+ sub.src = BT_MESH_ADDR_UNASSIGNED;
+ sub.dst = BT_MESH_ADDR_UNASSIGNED;
+ sub.min_hops = 0U;
+ sub.max_hops = 0U;
+ sub.count = 0U;
+ sub.period = sub.period - sub_remaining();
+ k_delayed_work_cancel(&sub_timer);
+ notify_sub_end();
+ } else if (period) {
+ sub.src = src;
+ sub.dst = dst;
+ sub.min_hops = BT_MESH_TTL_MAX;
+ sub.max_hops = 0U;
+ sub.count = 0U;
+ sub.period = period;
+ k_delayed_work_submit(&sub_timer, K_SECONDS(period));
+ } else {
+ /* Clearing the period should stop heartbeat subscription
+ * without clearing the parameters, so we can still read them.
+ */
+ sub.period = sub.period - sub_remaining();
+ k_delayed_work_cancel(&sub_timer);
+ notify_sub_end();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get)
+{
+ *get = sub;
+ get->remaining = sub_remaining();
+}
+
+void bt_mesh_hb_feature_changed(uint16_t features)
+{
+ if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return;
+ }
+
+ if (!(pub.feat & features)) {
+ return;
+ }
+
+ heartbeat_send(NULL, NULL);
+}
+
+void bt_mesh_hb_init(void)
+{
+ pub.net_idx = BT_MESH_KEY_UNUSED;
+ k_delayed_work_init(&pub_timer, hb_publish);
+ k_delayed_work_init(&sub_timer, sub_end);
+}
+
+void bt_mesh_hb_start(void)
+{
+ if (pub.count && pub.period) {
+ BT_DBG("Starting heartbeat publication");
+ k_delayed_work_submit(&pub_timer, K_NO_WAIT);
+ }
+}
+
+void bt_mesh_hb_suspend(void)
+{
+ k_delayed_work_cancel(&pub_timer);
+}
+
+void bt_mesh_hb_resume(void)
+{
+ if (pub.period && pub.count) {
+ BT_DBG("Starting heartbeat publication");
+ k_delayed_work_submit(&pub_timer, K_NO_WAIT);
+ }
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h
new file mode 100644
index 00000000..c43683fe
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mesh/heartbeat.h"
+
+static inline uint16_t bt_mesh_hb_pwr2(uint8_t val)
+{
+ if (!val) {
+ return 0x0000;
+ } else if (val == 0xff || val == 0x11) {
+ return 0xffff;
+ } else {
+ return (1 << (val - 1));
+ }
+}
+
+static inline uint8_t bt_mesh_hb_log(uint32_t val)
+{
+ if (!val) {
+ return 0x00;
+ } else if (val == 0xffff) {
+ return 0xff;
+ } else {
+ return 32 - __builtin_clz(val);
+ }
+}
+
+void bt_mesh_hb_init(void);
+void bt_mesh_hb_start(void);
+void bt_mesh_hb_suspend(void);
+void bt_mesh_hb_resume(void);
+
+int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
+void bt_mesh_hb_feature_changed(uint16_t features);
+
+uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *hb_pub);
+uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c
index b6d83818..bc4792c6 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c
@@ -6,52 +6,52 @@
#include "light_model.h"
-static u8_t gen_onoff_state;
-static s16_t gen_level_state;
+static uint8_t gen_onoff_state;
+static int16_t gen_level_state;
static void update_light_state(void)
{
- console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (u16_t)gen_level_state);
+ console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (uint16_t)gen_level_state);
}
-int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state)
+int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state)
{
*state = gen_onoff_state;
return 0;
}
-int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state)
+int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state)
{
gen_onoff_state = state;
update_light_state();
return 0;
}
-int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level)
+int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level)
{
*level = gen_level_state;
return 0;
}
-int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level)
+int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level)
{
gen_level_state = level;
- if ((u16_t)gen_level_state > 0x0000) {
+ if ((uint16_t)gen_level_state > 0x0000) {
gen_onoff_state = 1;
}
- if ((u16_t)gen_level_state == 0x0000) {
+ if ((uint16_t)gen_level_state == 0x0000) {
gen_onoff_state = 0;
}
update_light_state();
return 0;
}
-int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness)
+int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness)
{
return light_model_gen_level_get(model, lightness);
}
-int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness)
+int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness)
{
return light_model_gen_level_set(model, lightness);
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h
index 95fcdb78..d5f95943 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h
@@ -9,11 +9,11 @@
#include "syscfg/syscfg.h"
#include "mesh/mesh.h"
-int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state);
-int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state);
-int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level);
-int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level);
-int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness);
-int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness);
+int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state);
+int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state);
+int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level);
+int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level);
+int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness);
+int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness);
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c
index ec012a5f..bd48c088 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c
@@ -19,6 +19,7 @@
#include "adv.h"
#include "net.h"
#include "transport.h"
+#include "heartbeat.h"
#include "access.h"
#include "beacon.h"
#include "foundation.h"
@@ -42,27 +43,33 @@
#define POLL_RETRY_TIMEOUT K_MSEC(100)
-#define REQ_RETRY_DURATION(lpn) (4 * (LPN_RECV_DELAY + (lpn)->adv_duration + \
- (lpn)->recv_win + POLL_RETRY_TIMEOUT))
+#define REQ_RETRY_DURATION(lpn) (LPN_RECV_DELAY + (lpn)->adv_duration + \
+ (lpn)->recv_win + POLL_RETRY_TIMEOUT)
#define POLL_TIMEOUT_INIT (MYNEWT_VAL(BLE_MESH_LPN_INIT_POLL_TIMEOUT) * 100)
-#define POLL_TIMEOUT_MAX(lpn) ((MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT) * 100) - \
- REQ_RETRY_DURATION(lpn))
-#define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 4)
-#define CLEAR_ATTEMPTS 2
+#define POLL_TIMEOUT (MYNEWT_VAL(BLE_MESH_LPN_RECV_DELAY) * 100)
+
+#define REQ_ATTEMPTS_MAX 6
+#define REQ_ATTEMPTS(lpn) MIN(REQ_ATTEMPTS_MAX, \
+ POLL_TIMEOUT / REQ_RETRY_DURATION(lpn))
+
+#define POLL_TIMEOUT_MAX(lpn) (POLL_TIMEOUT - \
+ (REQ_ATTEMPTS(lpn) * REQ_RETRY_DURATION(lpn)))
+
+#define CLEAR_ATTEMPTS 3
#define LPN_CRITERIA ((MYNEWT_VAL(BLE_MESH_LPN_MIN_QUEUE_SIZE)) | \
(MYNEWT_VAL(BLE_MESH_LPN_RSSI_FACTOR) << 3) | \
(MYNEWT_VAL(BLE_MESH_LPN_RECV_WIN_FACTOR) << 5))
-#define POLL_TO(to) { (u8_t)((to) >> 16), (u8_t)((to) >> 8), (u8_t)(to) }
+#define POLL_TO(to) { (uint8_t)((to) >> 16), (uint8_t)((to) >> 8), (uint8_t)(to) }
#define LPN_POLL_TO POLL_TO(MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT))
/* 2 transmissions, 20ms interval */
#define POLL_XMIT BT_MESH_TRANSMIT(1, 20)
-static void (*lpn_cb)(u16_t friend_addr, bool established);
+static void (*lpn_cb)(uint16_t friend_addr, bool established);
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
static const char *state2str(int state)
@@ -145,10 +152,7 @@ static void friend_clear_sent(int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- /* We're switching away from Low Power behavior, so permanently
- * enable scanning.
- */
- bt_mesh_scan_enable();
+ /* Scanning will enable if lpn state still enabled */
lpn->req_attempts++;
@@ -170,31 +174,30 @@ static const struct bt_mesh_send_cb clear_sent_cb = {
static int send_friend_clear(void)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = bt_mesh.lpn.sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = bt_mesh.lpn.frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = bt_mesh.lpn.sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = bt_mesh_net_transmit_get(),
};
struct bt_mesh_ctl_friend_clear req = {
.lpn_addr = sys_cpu_to_be16(tx.src),
- .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter),
+ .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.lpn_counter),
};
BT_DBG("");
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
- sizeof(req), NULL, &clear_sent_cb, NULL);
+ sizeof(req), &clear_sent_cb, NULL);
}
static void clear_friendship(bool force, bool disable)
{
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
BT_DBG("force %u disable %u", force, disable);
@@ -210,8 +213,6 @@ static void clear_friendship(bool force, bool disable)
k_delayed_work_cancel(&lpn->timer);
- friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd);
-
if (lpn->clear_success) {
lpn->old_friend = BT_MESH_ADDR_UNASSIGNED;
} else {
@@ -231,6 +232,7 @@ static void clear_friendship(bool force, bool disable)
lpn->sent_req = 0;
lpn->established = 0;
lpn->clear_success = 0;
+ lpn->sub = NULL;
group_zero(lpn->added);
group_zero(lpn->pending);
@@ -242,9 +244,7 @@ static void clear_friendship(bool force, bool disable)
*/
lpn->groups_changed = 1;
- if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
- bt_mesh_heartbeat_send();
- }
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
if (disable) {
lpn_set_state(BT_MESH_LPN_DISABLED);
@@ -255,7 +255,7 @@ static void clear_friendship(bool force, bool disable)
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
}
-static void friend_req_sent(u16_t duration, int err, void *user_data)
+static void friend_req_sent(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
@@ -284,33 +284,43 @@ static int send_friend_req(struct bt_mesh_lpn *lpn)
{
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = BT_MESH_ADDR_FRIENDS,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
};
+
+ lpn->lpn_counter++;
+
struct bt_mesh_ctl_friend_req req = {
.criteria = LPN_CRITERIA,
.recv_delay = LPN_RECV_DELAY,
.poll_to = LPN_POLL_TO,
- .prev_addr = lpn->old_friend,
+ .prev_addr = sys_cpu_to_be16(lpn->old_friend),
.num_elem = comp->elem_count,
- .lpn_counter = sys_cpu_to_be16(lpn->counter),
+ .lpn_counter = sys_cpu_to_be16(lpn->lpn_counter),
};
BT_DBG("");
+ lpn->sub = bt_mesh_subnet_next(NULL);
+ if (!lpn->sub) {
+ BT_ERR("No subnets, can't start LPN mode");
+ return -ENOENT;
+ }
+
+ ctx.net_idx = lpn->sub->net_idx;
+ tx.sub = lpn->sub;
+
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
- sizeof(req), NULL, &friend_req_sent_cb, NULL);
+ sizeof(req), &friend_req_sent_cb, NULL);
}
-static void req_sent(u16_t duration, int err, void *user_data)
+static void req_sent(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
@@ -337,6 +347,7 @@ static void req_sent(u16_t duration, int err, void *user_data)
k_delayed_work_submit(&lpn->timer,
LPN_RECV_DELAY - SCAN_LATENCY);
} else {
+ lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
k_delayed_work_submit(&lpn->timer,
LPN_RECV_DELAY + duration +
lpn->recv_win);
@@ -350,20 +361,20 @@ static const struct bt_mesh_send_cb req_sent_cb = {
static int send_friend_poll(void)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = bt_mesh.lpn.sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = bt_mesh.lpn.frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = bt_mesh.lpn.sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
.friend_cred = true,
};
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u8_t fsn = lpn->fsn;
+ uint8_t fsn = lpn->fsn;
int err;
BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
@@ -377,7 +388,7 @@ static int send_friend_poll(void)
}
err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
- NULL, &req_sent_cb, NULL);
+ &req_sent_cb, NULL);
if (err == 0) {
lpn->pending_poll = 0;
lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
@@ -477,14 +488,22 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx)
send_friend_poll();
}
+static int friend_cred_create(struct bt_mesh_net_cred *cred,
+ const uint8_t key[16])
+{
+ struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+ return bt_mesh_friend_cred_create(cred, bt_mesh_primary_addr(),
+ lpn->frnd, lpn->lpn_counter,
+ lpn->frnd_counter, key);
+}
+
int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_offer *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- struct bt_mesh_subnet *sub = rx->sub;
- struct friend_cred *cred;
- u16_t frnd_counter;
+ uint16_t frnd_counter;
int err;
if (buf->om_len < sizeof(*msg)) {
@@ -508,16 +527,24 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi,
frnd_counter);
+ lpn->frnd_counter = frnd_counter;
lpn->frnd = rx->ctx.addr;
- cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter);
- if (!cred) {
- lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
- return -ENOMEM;
- }
+ /* Create friend credentials for each of the valid keys in the
+ * friendship subnet:
+ */
+ for (int i = 0; i < ARRAY_SIZE(lpn->cred); i++) {
+ if (!lpn->sub->keys[i].valid) {
+ continue;
+ }
+ err = friend_cred_create(&lpn->cred[i], lpn->sub->keys[i].net);
+ if (err) {
+ lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
+ return err;
+ }
+ }
/* TODO: Add offer acceptance criteria check */
-
k_delayed_work_cancel(&lpn->timer);
lpn->recv_win = msg->recv_win;
@@ -525,15 +552,13 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
err = send_friend_poll();
if (err) {
- friend_cred_clear(cred);
+ lpn->sub = NULL;
lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
lpn->recv_win = 0;
lpn->queue_size = 0;
return err;
}
- lpn->counter++;
-
return 0;
}
@@ -542,7 +567,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
{
struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u16_t addr, counter;
+ uint16_t addr, counter;
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Clear Confirm");
@@ -559,7 +584,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter);
- if (addr != bt_mesh_primary_addr() || counter != lpn->counter) {
+ if (addr != bt_mesh_primary_addr() || counter != lpn->lpn_counter) {
BT_WARN("Invalid parameters in Friend Clear Confirm");
return 0;
}
@@ -570,10 +595,10 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
return 0;
}
-static void lpn_group_add(u16_t group)
+static void lpn_group_add(uint16_t group)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u16_t *free_slot = NULL;
+ uint16_t *free_slot = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
@@ -596,7 +621,7 @@ static void lpn_group_add(u16_t group)
lpn->groups_changed = 1;
}
-static void lpn_group_del(u16_t group)
+static void lpn_group_del(uint16_t group)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
int i;
@@ -627,18 +652,18 @@ static inline int group_popcount(atomic_t *target)
#endif
}
-static bool sub_update(u8_t op)
+static bool sub_update(uint8_t op)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
int added_count = group_popcount(lpn->added);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = lpn->sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = lpn->frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = lpn->sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
@@ -688,8 +713,8 @@ static bool sub_update(u8_t op)
req.xact = lpn->xact_next++;
- if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, NULL,
- &req_sent_cb, NULL) < 0) {
+ if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2,
+ &req_sent_cb, NULL) < 0) {
group_zero(lpn->pending);
return false;
}
@@ -711,7 +736,7 @@ static void update_timeout(struct bt_mesh_lpn *lpn)
bt_mesh_scan_disable();
}
- if (lpn->req_attempts < 6) {
+ if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
BT_WARN("Retrying first Friend Poll");
lpn->sent_req = 0;
if (send_friend_poll() == 0) {
@@ -759,14 +784,14 @@ static void lpn_timeout(struct ble_npl_event *work)
if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
bt_mesh_scan_disable();
}
- lpn->counter++;
+ lpn->lpn_counter++;
lpn_set_state(BT_MESH_LPN_ENABLED);
lpn->sent_req = 0U;
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
break;
case BT_MESH_LPN_ESTABLISHED:
if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
- u8_t req = lpn->sent_req;
+ uint8_t req = lpn->sent_req;
lpn->sent_req = 0;
@@ -800,7 +825,7 @@ static void lpn_timeout(struct ble_npl_event *work)
}
}
-void bt_mesh_lpn_group_add(u16_t group)
+void bt_mesh_lpn_group_add(uint16_t group)
{
BT_DBG("group 0x%04x", group);
@@ -813,7 +838,7 @@ void bt_mesh_lpn_group_add(u16_t group)
sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
}
-void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
+void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count)
{
int i;
@@ -831,7 +856,7 @@ void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
}
-static s32_t poll_timeout(struct bt_mesh_lpn *lpn)
+static int32_t poll_timeout(struct bt_mesh_lpn *lpn)
{
/* If we're waiting for segment acks keep polling at high freq */
if (bt_mesh_tx_in_progress()) {
@@ -908,7 +933,9 @@ int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
}
if (!lpn->sent_req) {
- k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
+ int32_t timeout = poll_timeout(lpn);
+
+ k_delayed_work_submit(&lpn->timer, K_MSEC(timeout));
}
return 0;
@@ -920,7 +947,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
struct bt_mesh_ctl_friend_update *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
struct bt_mesh_subnet *sub = rx->sub;
- u32_t iv_index;
+ uint32_t iv_index;
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Update");
@@ -944,8 +971,6 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
}
if (!lpn->established) {
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
-
/* This is normally checked on the transport layer, however
* in this state we're also still accepting master
* credentials so we need to ensure the right ones (Friend
@@ -960,9 +985,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
BT_INFO("Friendship established with 0x%04x", lpn->frnd);
- if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
- bt_mesh_heartbeat_send();
- }
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
if (lpn_cb) {
lpn_cb(lpn->frnd, true);
@@ -980,11 +1003,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
BT_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags,
(unsigned) iv_index, msg->md);
- if (bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags),
- rx->new_key)) {
- bt_mesh_net_beacon_update(sub);
- }
-
+ bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags), rx->new_key);
bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(msg->flags));
if (lpn->groups_changed) {
@@ -1002,7 +1021,9 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
}
if (!lpn->sent_req) {
- k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
+ int32_t timeout = poll_timeout(lpn);
+
+ k_delayed_work_submit(&lpn->timer, K_MSEC(timeout));
}
return 0;
@@ -1019,17 +1040,41 @@ int bt_mesh_lpn_poll(void)
return send_friend_poll();
}
-void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established))
+void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established))
{
lpn_cb = cb;
}
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ switch (evt) {
+ case BT_MESH_KEY_DELETED:
+ if (sub == bt_mesh.lpn.sub) {
+ BT_DBG("NetKey deleted");
+ clear_friendship(true, false);
+ }
+ break;
+ case BT_MESH_KEY_UPDATED:
+ BT_DBG("NetKey updated");
+ friend_cred_create(&bt_mesh.lpn.cred[1], sub->keys[1].net);
+ break;
+ default:
+ break;
+ }
+}
+
int bt_mesh_lpn_init(void)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+ if (!bt_mesh_subnet_cb_list[2]) {
+ bt_mesh_subnet_cb_list[2] = subnet_evt;
+ }
+
BT_DBG("");
+ lpn->groups_changed = 0;
+
k_delayed_work_init(&lpn->timer, lpn_timeout);
if (lpn->state == BT_MESH_LPN_ENABLED) {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h
index 0ff6c9cf..90de2ca0 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h
@@ -28,7 +28,7 @@ static inline bool bt_mesh_lpn_established(void)
#endif
}
-static inline bool bt_mesh_lpn_match(u16_t addr)
+static inline bool bt_mesh_lpn_match(uint16_t addr)
{
#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
if (bt_mesh_lpn_established()) {
@@ -58,8 +58,8 @@ static inline bool bt_mesh_lpn_timer(void)
void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx);
-void bt_mesh_lpn_group_add(u16_t group);
-void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count);
+void bt_mesh_lpn_group_add(uint16_t group);
+void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count);
void bt_mesh_lpn_disable(bool force);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c
index 52fbdbf6..bfb0e1af 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c
@@ -18,7 +18,12 @@
#include "adv.h"
#include "prov.h"
+#include "provisioner.h"
#include "net.h"
+#include "subnet.h"
+#include "app_keys.h"
+#include "rpl.h"
+#include "cfg.h"
#include "beacon.h"
#include "lpn.h"
#include "friend.h"
@@ -26,16 +31,18 @@
#include "access.h"
#include "foundation.h"
#include "proxy.h"
+#include "heartbeat.h"
#include "shell.h"
#include "mesh_priv.h"
#include "settings.h"
-u8_t g_mesh_addr_type;
+
+uint8_t g_mesh_addr_type;
static struct ble_gap_event_listener mesh_event_listener;
-int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
- u8_t flags, u32_t iv_index, u16_t addr,
- const u8_t dev_key[16])
+int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx,
+ uint8_t flags, uint32_t iv_index, uint16_t addr,
+ const uint8_t dev_key[16])
{
bool pb_gatt_enabled;
int err;
@@ -58,6 +65,53 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
pb_gatt_enabled = false;
}
+ /*
+ * FIXME:
+ * Should net_key and iv_index be over-ridden?
+ */
+ if (IS_ENABLED(BLE_MESH_CDB)) {
+ const struct bt_mesh_comp *comp;
+ const struct bt_mesh_prov *prov;
+ struct bt_mesh_cdb_node *node;
+
+ if (!atomic_test_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_VALID)) {
+ BT_ERR("No valid network");
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -EINVAL;
+ }
+
+ comp = bt_mesh_comp_get();
+ if (comp == NULL) {
+ BT_ERR("Failed to get node composition");
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -EINVAL;
+ }
+
+ if (!bt_mesh_cdb_subnet_get(net_idx)) {
+ BT_ERR("No subnet with idx %d", net_idx);
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -ENOENT;
+ }
+
+ prov = bt_mesh_prov_get();
+ node = bt_mesh_cdb_node_alloc(prov->uuid, addr,
+ comp->elem_count, net_idx);
+ if (node == NULL) {
+ BT_ERR("Failed to allocate database node");
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -ENOMEM;
+ }
+
+ addr = node->addr;
+ iv_index = bt_mesh_cdb.iv_index;
+ memcpy(node->dev_key, dev_key, 16);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+ }
+
err = bt_mesh_net_create(net_idx, flags, net_key, iv_index);
if (err) {
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
@@ -75,20 +129,18 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
memcpy(bt_mesh.dev_key, dev_key, 16);
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing network information persistently");
- bt_mesh_store_net();
- bt_mesh_store_subnet(&bt_mesh.sub[0]);
- bt_mesh_store_iv(false);
+ if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
+ IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
+ bt_mesh_lpn_group_add(BT_MESH_ADDR_ALL_NODES);
}
- bt_mesh_net_start();
+ bt_mesh_start();
return 0;
}
-int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration)
+int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
{
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
return -EINVAL;
@@ -122,25 +174,30 @@ void bt_mesh_reset(void)
bt_mesh_cfg_reset();
- bt_mesh_rx_reset();
- bt_mesh_tx_reset();
+ bt_mesh_trans_reset();
+ bt_mesh_app_keys_reset();
+ bt_mesh_net_keys_reset();
+
+ bt_mesh_net_loopback_clear(BT_MESH_KEY_ANY);
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
+ if (IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
+ uint16_t group = BT_MESH_ADDR_ALL_NODES;
+
+ bt_mesh_lpn_group_del(&group, 1);
+ }
+
bt_mesh_lpn_disable(true);
}
if ((MYNEWT_VAL(BLE_MESH_FRIEND))) {
- bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
+ bt_mesh_friends_clear();
}
if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
bt_mesh_proxy_gatt_disable();
}
- if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) {
- bt_mesh_proxy_prov_enable();
- }
-
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_clear_net();
}
@@ -162,55 +219,6 @@ bool bt_mesh_is_provisioned(void)
return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID);
}
-int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
-{
- if (bt_mesh_is_provisioned()) {
- return -EALREADY;
- }
-
- char uuid_buf[BLE_UUID_STR_LEN];
- const struct bt_mesh_prov *prov = bt_mesh_prov_get();
- ble_uuid_t *uuid = BLE_UUID128_DECLARE();
-
- memcpy(BLE_UUID128(uuid)->value, prov->uuid, 16);
- BT_INFO("Device UUID: %s", ble_uuid_to_str(uuid, uuid_buf));
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
- (bearers & BT_MESH_PROV_ADV)) {
- /* Make sure we're scanning for provisioning inviations */
- bt_mesh_scan_enable();
- /* Enable unprovisioned beacon sending */
- bt_mesh_beacon_enable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
- (bearers & BT_MESH_PROV_GATT)) {
- bt_mesh_proxy_prov_enable();
- bt_mesh_adv_update();
- }
-
- return 0;
-}
-
-int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
-{
- if (bt_mesh_is_provisioned()) {
- return -EALREADY;
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
- (bearers & BT_MESH_PROV_ADV)) {
- bt_mesh_beacon_disable();
- bt_mesh_scan_disable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
- (bearers & BT_MESH_PROV_GATT)) {
- bt_mesh_proxy_prov_disable(true);
- }
-
- return 0;
-}
static int bt_mesh_gap_event(struct ble_gap_event *event, void *arg)
{
@@ -251,9 +259,9 @@ int bt_mesh_suspend(void)
return err;
}
- bt_mesh_hb_pub_disable();
+ bt_mesh_hb_suspend();
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+ if (bt_mesh_beacon_enabled()) {
bt_mesh_beacon_disable();
}
@@ -266,7 +274,7 @@ static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
if (mod->pub && mod->pub->update) {
- s32_t period_ms = bt_mesh_model_pub_period_get(mod);
+ int32_t period_ms = bt_mesh_model_pub_period_get(mod);
if (period_ms) {
k_delayed_work_submit(&mod->pub->timer, period_ms);
@@ -293,7 +301,9 @@ int bt_mesh_resume(void)
return err;
}
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+ bt_mesh_hb_resume();
+
+ if (bt_mesh_beacon_enabled()) {
bt_mesh_beacon_enable();
}
@@ -317,45 +327,76 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov,
return err;
}
-#if (MYNEWT_VAL(BLE_MESH_PROV))
- err = bt_mesh_prov_init(prov);
- if (err) {
- return err;
- }
-#endif
-
#if (MYNEWT_VAL(BLE_MESH_PROXY))
bt_mesh_proxy_init();
#endif
#if (MYNEWT_VAL(BLE_MESH_PROV))
- /* Need this to proper link.rx.buf allocation */
- bt_mesh_prov_reset_link();
+ err = bt_mesh_prov_init(prov);
+ if (err) {
+ return err;
+ }
#endif
+ bt_mesh_cfg_init();
bt_mesh_net_init();
bt_mesh_trans_init();
+ bt_mesh_hb_init();
bt_mesh_beacon_init();
bt_mesh_adv_init();
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- /* Make sure we're scanning for provisioning inviations */
- bt_mesh_scan_enable();
- /* Enable unprovisioned beacon sending */
-
- bt_mesh_beacon_enable();
-#endif
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- bt_mesh_proxy_prov_enable();
+#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
+ bt_mesh_settings_init();
#endif
ble_gap_event_listener_register(&mesh_event_listener,
bt_mesh_gap_event, NULL);
-#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
- bt_mesh_settings_init();
-#endif
-
return 0;
}
+
+static void model_start(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+ bool vnd, bool primary, void *user_data)
+{
+ if (mod->cb && mod->cb->start) {
+ mod->cb->start(mod);
+ }
+}
+
+int bt_mesh_start(void)
+{
+ if (bt_mesh_beacon_enabled()) {
+ bt_mesh_beacon_enable();
+ } else {
+ bt_mesh_beacon_disable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+ bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
+ bt_mesh_proxy_gatt_enable();
+ bt_mesh_adv_update();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+ bt_mesh_lpn_init();
+ } else {
+ bt_mesh_scan_enable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ bt_mesh_friend_init();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
+ struct bt_mesh_subnet *sub = bt_mesh_subnet_next(NULL);
+ uint16_t addr = bt_mesh_primary_addr();
+
+ bt_mesh_prov_complete(sub->net_idx, addr);
+ }
+
+ bt_mesh_hb_start();
+
+ bt_mesh_model_foreach(model_start, NULL);
+
+ return 0;
+} \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h
index f09bb230..213f5437 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h
@@ -8,14 +8,28 @@
#ifndef __MESH_PRIV_H
#define __MESH_PRIV_H
+#include <stdbool.h>
+#include <stdint.h>
+
#define BT_MESH_KEY_PRIMARY 0x0000
#define BT_MESH_KEY_ANY 0xffff
-#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
-#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
-#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
-#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
+enum bt_mesh_key_evt {
+ BT_MESH_KEY_ADDED, /* New key added */
+ BT_MESH_KEY_DELETED, /* Existing key deleted */
+ BT_MESH_KEY_UPDATED, /* KR phase 1, second key added */
+ BT_MESH_KEY_SWAPPED, /* KR phase 2, now sending on second key */
+ BT_MESH_KEY_REVOKED, /* KR phase 3, old key removed */
+};
+
+/** Appkey callback. Instantiate with @ref BT_MESH_APP_KEY_CB */
+struct bt_mesh_app_key_cb {
+ void (*evt_handler)(uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt);
+};
+
struct bt_mesh_net;
+int bt_mesh_start(void);
#define OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01)
#define OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c
index b00cfa52..9755ec1f 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c
@@ -11,19 +11,19 @@
#include "mesh/model_cli.h"
#include "mesh_priv.h"
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_gen_model_cli *gen_onoff_cli;
static struct bt_mesh_gen_model_cli *gen_level_cli;
-static u8_t transaction_id = 0;
+static uint8_t transaction_id = 0;
struct gen_onoff_param {
- u8_t *state;
+ uint8_t *state;
};
struct gen_level_param {
- s16_t *level;
+ int16_t *level;
};
static void gen_onoff_status(struct bt_mesh_model *model,
@@ -32,7 +32,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_model_cli *cli = model->user_data;
struct gen_onoff_param *param;
- u8_t state;
+ uint8_t state;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -62,7 +62,7 @@ static void gen_level_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_model_cli *cli = model->user_data;
struct gen_level_param *param;
- s16_t level;
+ int16_t level;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -138,7 +138,7 @@ const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb = {
.init = level_cli_init,
};
-static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
+static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, uint32_t op)
{
int err;
@@ -155,8 +155,8 @@ static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
return err;
}
-int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *state)
+int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -184,8 +184,8 @@ done:
return err;
}
-int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t val, u8_t *state)
+int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t val, uint8_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -227,8 +227,8 @@ done:
return err;
}
-int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- s16_t *level)
+int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t *level)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -256,8 +256,8 @@ done:
return err;
}
-int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- s16_t val, s16_t *state)
+int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t val, int16_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
struct bt_mesh_msg_ctx ctx = {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c
index 5f5a8df4..b6f34360 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c
@@ -20,7 +20,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(3);
- u8_t *state;
+ uint8_t *state;
bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_STATUS);
state = net_buf_simple_add(msg, 1);
@@ -51,7 +51,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
- u8_t state;
+ uint8_t state;
state = buf->om_data[0];
@@ -77,7 +77,7 @@ static void gen_level_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_level_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
- s16_t *level;
+ int16_t *level;
bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_STATUS);
level = net_buf_simple_add(msg, 2);
@@ -107,9 +107,9 @@ static void gen_level_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf) {
struct bt_mesh_gen_level_srv *cb = model->user_data;
- s16_t level;
+ int16_t level;
- level = (s16_t) net_buf_simple_pull_le16(buf);
+ level = (int16_t) net_buf_simple_pull_le16(buf);
BT_DBG("level: %d", level);
if (cb && cb->set) {
@@ -130,7 +130,7 @@ static void light_lightness_status(struct bt_mesh_model *model,
{
struct bt_mesh_light_lightness_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
- s16_t *lightness;
+ int16_t *lightness;
bt_mesh_model_msg_init(msg, OP_LIGHT_LIGHTNESS_STATUS);
lightness = net_buf_simple_add(msg, 2);
@@ -160,9 +160,9 @@ static void light_lightness_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf) {
struct bt_mesh_light_lightness_srv *cb = model->user_data;
- s16_t lightness;
+ int16_t lightness;
- lightness = (s16_t) net_buf_simple_pull_le16(buf);
+ lightness = (int16_t) net_buf_simple_pull_le16(buf);
BT_DBG("lightness: %d", lightness);
if (cb && cb->set) {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c
index 240314d4..8b86935d 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c
@@ -20,6 +20,7 @@
#include "adv.h"
#include "mesh_priv.h"
#include "net.h"
+#include "rpl.h"
#include "lpn.h"
#include "friend.h"
#include "proxy.h"
@@ -29,6 +30,9 @@
#include "beacon.h"
#include "settings.h"
#include "prov.h"
+#include "cfg.h"
+#include "mesh/glue.h"
+#include "mesh/slist.h"
/* Minimum valid Mesh Network PDU length. The Network headers
* themselves take up 9 bytes. After that there is a minumum of 1 byte
@@ -38,6 +42,10 @@
*/
#define BT_MESH_NET_MIN_PDU_LEN (BT_MESH_NET_HDR_LEN + 1 + 8)
+#define LOOPBACK_MAX_PDU_LEN (BT_MESH_NET_HDR_LEN + 16)
+#define LOOPBACK_USER_DATA_SIZE sizeof(struct bt_mesh_subnet *)
+#define LOOPBACK_BUF_SUB(buf) (*(struct bt_mesh_subnet **)net_buf_user_data(buf))
+
/* Seq limit after IV Update is triggered */
#define IV_UPDATE_SEQ_LIMIT 8000000
@@ -45,54 +53,34 @@
#define NID(pdu) ((pdu)[0] & 0x7f)
#define CTL(pdu) ((pdu)[1] >> 7)
#define TTL(pdu) ((pdu)[1] & 0x7f)
-#define SEQ(pdu) (((u32_t)(pdu)[2] << 16) | \
- ((u32_t)(pdu)[3] << 8) | (u32_t)(pdu)[4]);
+#define SEQ(pdu) (sys_get_be24(&pdu[2]))
#define SRC(pdu) (sys_get_be16(&(pdu)[5]))
#define DST(pdu) (sys_get_be16(&(pdu)[7]))
-/* Determine how many friendship credentials we need */
-#if (MYNEWT_VAL(BLE_MESH_FRIEND))
-#define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT)
-#elif (MYNEWT_VAL(BLE_MESH_LOW_POWER))
-#define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
-#else
-#define FRIEND_CRED_COUNT 0
-#endif
-
-static struct friend_cred friend_cred[FRIEND_CRED_COUNT];
-
-static u64_t msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
-static u16_t msg_cache_next;
+static struct {
+ uint32_t src : 15, /* MSb of source is always 0 */
+ seq : 17;
+} msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
+static uint16_t msg_cache_next;
/* Singleton network context (the implementation only supports one) */
struct bt_mesh_net bt_mesh = {
.local_queue = STAILQ_HEAD_INITIALIZER(bt_mesh.local_queue),
- .sub = {
- [0 ... (MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
- .app_keys = {
- [0 ... (MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT) - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- .nodes = {
- [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
-#endif
};
-static u32_t dup_cache[4];
+static struct os_mbuf_pool loopback_os_mbuf_pool;
+static struct os_mempool loopback_buf_mempool;
+os_membuf_t loopback_mbuf_membuf[
+ OS_MEMPOOL_SIZE(LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE,
+ MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS))];
+
+static uint32_t dup_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
static int dup_cache_next;
static bool check_dup(struct os_mbuf *data)
{
- const u8_t *tail = net_buf_simple_tail(data);
- u32_t val;
+ const uint8_t *tail = net_buf_simple_tail(data);
+ uint32_t val;
int i;
val = sys_get_be32(tail - 4) ^ sys_get_be32(tail - 8);
@@ -109,364 +97,52 @@ static bool check_dup(struct os_mbuf *data)
return false;
}
-static u64_t msg_hash(struct bt_mesh_net_rx *rx, struct os_mbuf *pdu)
-{
- u32_t hash1, hash2;
-
- /* Three least significant bytes of IVI + first byte of SEQ */
- hash1 = (BT_MESH_NET_IVI_RX(rx) << 8) | pdu->om_data[2];
-
- /* Two last bytes of SEQ + SRC */
- memcpy(&hash2, &pdu->om_data[3], 4);
-
- return (u64_t)hash1 << 32 | (u64_t)hash2;
-}
-
-static bool msg_cache_match(struct bt_mesh_net_rx *rx,
- struct os_mbuf *pdu)
+static bool msg_cache_match(struct os_mbuf *pdu)
{
- u64_t hash = msg_hash(rx, pdu);
- u16_t i;
+ uint16_t i;
for (i = 0; i < ARRAY_SIZE(msg_cache); i++) {
- if (msg_cache[i] == hash) {
+ if (msg_cache[i].src == SRC(pdu->om_data) &&
+ msg_cache[i].seq == (SEQ(pdu->om_data) & BIT_MASK(17))) {
return true;
}
}
- /* Add to the cache */
- rx->msg_cache_idx = msg_cache_next++;
- msg_cache[rx->msg_cache_idx] = hash;
- msg_cache_next %= ARRAY_SIZE(msg_cache);
-
return false;
}
-struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx)
+static void msg_cache_add(struct bt_mesh_net_rx *rx)
{
- int i;
-
- if (net_idx == BT_MESH_KEY_ANY) {
- return &bt_mesh.sub[0];
- }
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == net_idx) {
- return &bt_mesh.sub[i];
- }
- }
-
- return NULL;
+ /* Add to the cache */
+ rx->msg_cache_idx = msg_cache_next++;
+ msg_cache[rx->msg_cache_idx].src = rx->ctx.addr;
+ msg_cache[rx->msg_cache_idx].seq = rx->seq;
+ msg_cache_next %= ARRAY_SIZE(msg_cache);
}
-int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
- const u8_t key[16])
+int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
+ uint32_t iv_index)
{
- u8_t p[] = { 0 };
- u8_t nid;
int err;
- err = bt_mesh_k2(key, p, sizeof(p), &nid, keys->enc, keys->privacy);
- if (err) {
- BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
- return err;
- }
-
- memcpy(keys->net, key, 16);
-
- keys->nid = nid;
-
- BT_DBG("NID 0x%02x EncKey %s", keys->nid, bt_hex(keys->enc, 16));
- BT_DBG("PrivacyKey %s", bt_hex(keys->privacy, 16));
+ BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags, iv_index);
- err = bt_mesh_k3(key, keys->net_id);
- if (err) {
- BT_ERR("Unable to generate Net ID");
- return err;
- }
-
- BT_DBG("NetID %s", bt_hex(keys->net_id, 8));
-
-#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
- err = bt_mesh_identity_key(key, keys->identity);
- if (err) {
- BT_ERR("Unable to generate IdentityKey");
- return err;
- }
-
- BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16));
-#endif /* GATT_PROXY */
-
- err = bt_mesh_beacon_key(key, keys->beacon);
- if (err) {
- BT_ERR("Unable to generate beacon key");
- return err;
- }
-
- BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16));
-
- return 0;
-}
-
-int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16])
-{
- u16_t lpn_addr, frnd_addr;
- int err;
- u8_t p[9];
+ BT_DBG("NetKey %s", bt_hex(key, 16));
-#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
- if (cred->addr == bt_mesh.lpn.frnd) {
- lpn_addr = bt_mesh_primary_addr();
- frnd_addr = cred->addr;
+ if (BT_MESH_KEY_REFRESH(flags)) {
+ err = bt_mesh_subnet_set(idx, BT_MESH_KR_PHASE_2, NULL, key);
} else {
- lpn_addr = cred->addr;
- frnd_addr = bt_mesh_primary_addr();
+ err = bt_mesh_subnet_set(idx, BT_MESH_KR_NORMAL, key, NULL);
}
-#else
- lpn_addr = cred->addr;
- frnd_addr = bt_mesh_primary_addr();
-#endif
-
- BT_DBG("LPNAddress 0x%04x FriendAddress 0x%04x", lpn_addr, frnd_addr);
- BT_DBG("LPNCounter 0x%04x FriendCounter 0x%04x", cred->lpn_counter,
- cred->frnd_counter);
-
- p[0] = 0x01;
- sys_put_be16(lpn_addr, p + 1);
- sys_put_be16(frnd_addr, p + 3);
- sys_put_be16(cred->lpn_counter, p + 5);
- sys_put_be16(cred->frnd_counter, p + 7);
- err = bt_mesh_k2(net_key, p, sizeof(p), &cred->cred[idx].nid,
- cred->cred[idx].enc, cred->cred[idx].privacy);
if (err) {
- BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
+ BT_ERR("Failed creating subnet");
return err;
}
- BT_DBG("Friend NID 0x%02x EncKey %s", cred->cred[idx].nid,
- bt_hex(cred->cred[idx].enc, 16));
- BT_DBG("Friend PrivacyKey %s", bt_hex(cred->cred[idx].privacy, 16));
-
- return 0;
-}
-
-void friend_cred_refresh(u16_t net_idx)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr != BT_MESH_ADDR_UNASSIGNED &&
- cred->net_idx == net_idx) {
- memcpy(&cred->cred[0], &cred->cred[1],
- sizeof(cred->cred[0]));
- }
- }
-}
-
-int friend_cred_update(struct bt_mesh_subnet *sub)
-{
- int err, i;
-
- BT_DBG("net_idx 0x%04x", sub->net_idx);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr == BT_MESH_ADDR_UNASSIGNED ||
- cred->net_idx != sub->net_idx) {
- continue;
- }
-
- err = friend_cred_set(cred, 1, sub->keys[1].net);
- if (err) {
- return err;
- }
- }
-
- return 0;
-}
-
-struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
- u16_t lpn_counter, u16_t frnd_counter)
-{
- struct friend_cred *cred;
- int i, err;
-
- BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
-
- for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) ||
- (friend_cred[i].addr == addr &&
- friend_cred[i].net_idx == sub->net_idx)) {
- cred = &friend_cred[i];
- break;
- }
- }
-
- if (!cred) {
- BT_WARN("No free friend credential slots");
- return NULL;
- }
-
- cred->net_idx = sub->net_idx;
- cred->addr = addr;
- cred->lpn_counter = lpn_counter;
- cred->frnd_counter = frnd_counter;
-
- err = friend_cred_set(cred, 0, sub->keys[0].net);
- if (err) {
- friend_cred_clear(cred);
- return NULL;
- }
-
- if (sub->kr_flag) {
- err = friend_cred_set(cred, 1, sub->keys[1].net);
- if (err) {
- friend_cred_clear(cred);
- return NULL;
- }
- }
-
- return cred;
-}
-
-void friend_cred_clear(struct friend_cred *cred)
-{
- cred->net_idx = BT_MESH_KEY_UNUSED;
- cred->addr = BT_MESH_ADDR_UNASSIGNED;
- cred->lpn_counter = 0;
- cred->frnd_counter = 0;
- memset(cred->cred, 0, sizeof(cred->cred));
-}
-
-int friend_cred_del(u16_t net_idx, u16_t addr)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr == addr && cred->net_idx == net_idx) {
- friend_cred_clear(cred);
- return 0;
- }
- }
-
- return -ENOENT;
-}
-
-int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
- const u8_t **enc, const u8_t **priv)
-{
- int i;
-
- BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->net_idx != sub->net_idx) {
- continue;
- }
-
- if (addr != BT_MESH_ADDR_UNASSIGNED && cred->addr != addr) {
- continue;
- }
-
- if (nid) {
- *nid = cred->cred[sub->kr_flag].nid;
- }
-
- if (enc) {
- *enc = cred->cred[sub->kr_flag].enc;
- }
-
- if (priv) {
- *priv = cred->cred[sub->kr_flag].privacy;
- }
-
- return 0;
- }
-
- return -ENOENT;
-}
-
-u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
-{
- u8_t flags = 0x00;
-
- if (sub && sub->kr_flag) {
- flags |= BT_MESH_NET_FLAG_KR;
- }
-
- if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
- flags |= BT_MESH_NET_FLAG_IVU;
- }
-
- return flags;
-}
-
-int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub)
-{
- u8_t flags = bt_mesh_net_flags(sub);
- struct bt_mesh_subnet_keys *keys;
-
- if (sub->kr_flag) {
- BT_DBG("NetIndex %u Using new key", sub->net_idx);
- keys = &sub->keys[1];
- } else {
- BT_DBG("NetIndex %u Using current key", sub->net_idx);
- keys = &sub->keys[0];
- }
-
- BT_DBG("flags 0x%02x, IVI 0x%08x", flags, (unsigned) bt_mesh.iv_index);
-
- return bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
- bt_mesh.iv_index, sub->auth);
-}
-
-int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
- u32_t iv_index)
-{
- struct bt_mesh_subnet *sub;
- int err;
-
- BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags,
- (unsigned) iv_index);
-
- BT_DBG("NetKey %s", bt_hex(key, 16));
-
(void)memset(msg_cache, 0, sizeof(msg_cache));
msg_cache_next = 0U;
- sub = &bt_mesh.sub[0];
-
- sub->kr_flag = BT_MESH_KEY_REFRESH(flags);
- if (sub->kr_flag) {
- err = bt_mesh_net_keys_create(&sub->keys[1], key);
- if (err) {
- return -EIO;
- }
-
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- } else {
- err = bt_mesh_net_keys_create(&sub->keys[0], key);
- if (err) {
- return -EIO;
- }
- }
-
- sub->net_idx = idx;
-
- if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
bt_mesh.iv_index = iv_index;
atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS,
BT_MESH_IV_UPDATE(flags));
@@ -477,94 +153,14 @@ int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
*/
bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS;
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
-
- return 0;
-}
-
-void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub)
-{
- int i;
-
- BT_DBG("idx 0x%04x", sub->net_idx);
-
- memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0]));
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != sub->net_idx || !key->updated) {
- continue;
- }
-
- memcpy(&key->keys[0], &key->keys[1], sizeof(key->keys[0]));
- key->updated = false;
- }
-}
-
-bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key)
-{
- if (new_kr != sub->kr_flag && sub->kr_phase == BT_MESH_KR_NORMAL) {
- BT_WARN("KR change in normal operation. Are we blacklisted?");
- return false;
- }
-
- sub->kr_flag = new_kr;
-
- if (sub->kr_flag) {
- if (sub->kr_phase == BT_MESH_KR_PHASE_1) {
- BT_DBG("Phase 1 -> Phase 2");
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- return true;
- }
- } else {
- switch (sub->kr_phase) {
- case BT_MESH_KR_PHASE_1:
- if (!new_key) {
- /* Ignore */
- break;
- }
- /* Upon receiving a Secure Network beacon with the KR flag set
- * to 0 using the new NetKey in Phase 1, the node shall
- * immediately transition to Phase 3, which effectively skips
- * Phase 2.
- *
- * Intentional fall-through.
- */
- case BT_MESH_KR_PHASE_2:
- BT_DBG("KR Phase 0x%02x -> Normal", sub->kr_phase);
- bt_mesh_net_revoke_keys(sub);
- if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND))) {
- friend_cred_refresh(sub->net_idx);
- }
- sub->kr_phase = BT_MESH_KR_NORMAL;
- return true;
- }
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing network information persistently");
+ bt_mesh_store_net();
+ bt_mesh_store_subnet(idx);
+ bt_mesh_store_iv(false);
}
- return false;
-}
-
-void bt_mesh_rpl_reset(void)
-{
- int i;
-
- /* Discard "old old" IV Index entries from RPL and flag
- * any other ones (which are valid) as old.
- */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
- if (rpl->src) {
- if (rpl->old_iv) {
- memset(rpl, 0, sizeof(*rpl));
- } else {
- rpl->old_iv = true;
- }
- }
- }
+ return 0;
}
#if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST)
@@ -588,29 +184,12 @@ bool bt_mesh_iv_update(void)
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
}
- bt_mesh_net_sec_update(NULL);
-
return atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
}
#endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */
-/* Used for sending immediate beacons to Friend queues and GATT clients */
-void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub)
+bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update)
{
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_sec_update(sub ? sub->net_idx : BT_MESH_KEY_ANY);
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
- bt_mesh_proxy_beacon_send(sub);
- }
-}
-
-bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update)
-{
- int i;
-
if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
/* We're currently in IV Update mode */
@@ -644,7 +223,7 @@ bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update)
if (iv_index > bt_mesh.iv_index + 1) {
BT_WARN("Performing IV Index Recovery");
- memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
+ bt_mesh_rpl_clear();
bt_mesh.iv_index = iv_index;
bt_mesh.seq = 0;
goto do_update;
@@ -694,10 +273,20 @@ do_update:
k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_net_beacon_update(&bt_mesh.sub[i]);
- }
+ /* Notify other modules */
+ if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ bt_mesh_friend_sec_update(BT_MESH_KEY_ANY);
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+ bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
+ bt_mesh_proxy_beacon_send(NULL);
+ }
+
+ bt_mesh_subnet_foreach(bt_mesh_beacon_update);
+
+ if (MYNEWT_VAL(BLE_MESH_CDB)) {
+ bt_mesh_cdb_iv_update(iv_index, iv_update);
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
@@ -707,9 +296,9 @@ do_update:
return true;
}
-u32_t bt_mesh_next_seq(void)
+uint32_t bt_mesh_next_seq(void)
{
- u32_t seq = bt_mesh.seq++;
+ uint32_t seq = bt_mesh.seq++;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_seq();
@@ -720,89 +309,63 @@ u32_t bt_mesh_next_seq(void)
bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY)) {
bt_mesh_beacon_ivu_initiator(true);
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
- bt_mesh_net_sec_update(NULL);
}
return seq;
}
-int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
- bool new_key, const struct bt_mesh_send_cb *cb,
- void *cb_data)
-{
- const u8_t *enc, *priv;
- u32_t seq;
- u16_t dst;
- int err;
-
- BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key,
- buf->om_len);
-
- enc = sub->keys[new_key].enc;
- priv = sub->keys[new_key].privacy;
-
- err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
- if (err) {
- BT_ERR("deobfuscate failed (err %d)", err);
- return err;
- }
-
- err = bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
- if (err) {
- BT_ERR("decrypt failed (err %d)", err);
- return err;
- }
-
- seq = bt_mesh_next_seq();
- buf->om_data[2] = seq >> 16;
- buf->om_data[3] = seq >> 8;
- buf->om_data[4] = seq;
-
- /* Get destination, in case it's a proxy client */
- dst = DST(buf->om_data);
-
- err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
- if (err) {
- BT_ERR("encrypt failed (err %d)", err);
- return err;
- }
-
- err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
- if (err) {
- BT_ERR("obfuscate failed (err %d)", err);
- return err;
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- bt_mesh_proxy_relay(buf, dst)) {
- send_cb_finalize(cb, cb_data);
- } else {
- bt_mesh_adv_send(buf, cb, cb_data);
- }
-
- return 0;
-}
-
static void bt_mesh_net_local(struct ble_npl_event *work)
{
struct os_mbuf *buf;
while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
- BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
- bt_mesh_net_recv(buf, 0, BT_MESH_NET_IF_LOCAL);
+ struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf);
+ struct bt_mesh_net_rx rx = {
+ .ctx = {
+ .net_idx = sub->net_idx,
+ /* Initialize AppIdx to a sane value */
+ .app_idx = BT_MESH_KEY_UNUSED,
+ .recv_ttl = TTL(buf->om_data),
+ /* TTL=1 only goes to local IF */
+ .send_ttl = 1U,
+ .addr = SRC(buf->om_data),
+ .recv_dst = DST(buf->om_data),
+ .recv_rssi = 0,
+ },
+ .net_if = BT_MESH_NET_IF_LOCAL,
+ .sub = sub,
+ .old_iv = (IVI(buf->om_data) != (bt_mesh.iv_index & 0x01)),
+ .ctl = CTL(buf->om_data),
+ .seq = SEQ(buf->om_data),
+ .new_key = SUBNET_KEY_TX_IDX(sub),
+ .local_match = 1U,
+ .friend_match = 0U,
+ };
+
+ BT_DBG("src: 0x%04x dst: 0x%04x seq 0x%06x sub %p", rx.ctx.addr,
+ rx.ctx.addr, rx.seq, sub);
+
+ (void) bt_mesh_trans_recv(buf, &rx);
net_buf_unref(buf);
}
}
-int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
- bool proxy)
+static const struct bt_mesh_net_cred *net_tx_cred_get(struct bt_mesh_net_tx *tx)
+{
+#if defined(BLE_MESH_LOW_POWER)
+ if (tx->friend_cred && bt_mesh_lpn_established()) {
+ return &bt_mesh.lpn.cred[SUBNET_KEY_TX_IDX(tx->sub)];
+ }
+#endif
+
+ tx->friend_cred = 0U;
+ return &tx->sub->keys[SUBNET_KEY_TX_IDX(tx->sub)].msg;
+}
+
+static int net_header_encode(struct bt_mesh_net_tx *tx, uint8_t nid,
+ struct os_mbuf *buf)
{
const bool ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
- u32_t seq_val;
- u8_t nid;
- const u8_t *enc, *priv;
- u8_t *seq;
- int err;
if (ctl && net_buf_simple_tailroom(buf) < 8) {
BT_ERR("Insufficient MIC space for CTL PDU");
@@ -818,11 +381,7 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
net_buf_simple_push_be16(buf, tx->ctx->addr);
net_buf_simple_push_be16(buf, tx->src);
- seq = net_buf_simple_push(buf, 3);
- seq_val = bt_mesh_next_seq();
- seq[0] = seq_val >> 16;
- seq[1] = seq_val >> 8;
- seq[2] = seq_val;
+ net_buf_simple_push_be24(buf, bt_mesh_next_seq());
if (ctl) {
net_buf_simple_push_u8(buf, tx->ctx->send_ttl | 0x80);
@@ -830,37 +389,68 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
net_buf_simple_push_u8(buf, tx->ctx->send_ttl);
}
- if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && tx->friend_cred) {
- if (friend_cred_get(tx->sub, BT_MESH_ADDR_UNASSIGNED,
- &nid, &enc, &priv)) {
- BT_WARN("Falling back to master credentials");
+ net_buf_simple_push_u8(buf, (nid | (BT_MESH_NET_IVI_TX & 1) << 7));
- tx->friend_cred = 0;
+ return 0;
+}
- nid = tx->sub->keys[tx->sub->kr_flag].nid;
- enc = tx->sub->keys[tx->sub->kr_flag].enc;
- priv = tx->sub->keys[tx->sub->kr_flag].privacy;
- }
- } else {
- tx->friend_cred = 0;
- nid = tx->sub->keys[tx->sub->kr_flag].nid;
- enc = tx->sub->keys[tx->sub->kr_flag].enc;
- priv = tx->sub->keys[tx->sub->kr_flag].privacy;
+static int net_encrypt(struct os_mbuf *buf,
+ const struct bt_mesh_net_cred *cred, uint32_t iv_index,
+ bool proxy)
+{
+ int err;
+
+ err = bt_mesh_net_encrypt(cred->enc, buf, iv_index, proxy);
+ if (err) {
+ return err;
}
- net_buf_simple_push_u8(buf, (nid | (BT_MESH_NET_IVI_TX & 1) << 7));
+ return bt_mesh_net_obfuscate(buf->om_data, iv_index, cred->privacy);
+}
- err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, proxy);
+int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
+ bool proxy)
+{
+ const struct bt_mesh_net_cred *cred;
+ int err;
+
+ cred = net_tx_cred_get(tx);
+ err = net_header_encode(tx, cred->nid, buf);
if (err) {
return err;
}
- return bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
+ return net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, proxy);
+}
+
+static int loopback(const struct bt_mesh_net_tx *tx, const uint8_t *data,
+ size_t len)
+{
+ struct os_mbuf *buf;
+
+ buf = os_mbuf_get_pkthdr(&loopback_os_mbuf_pool, 0);
+ if (!buf) {
+ BT_WARN("Unable to allocate loopback");
+ return -ENOMEM;
+ }
+
+ BT_DBG("");
+
+ LOOPBACK_BUF_SUB(buf) = tx->sub;
+
+ net_buf_add_mem(buf, data, len);
+
+ net_buf_slist_put(&bt_mesh.local_queue, buf);
+
+ k_work_submit(&bt_mesh.local_work);
+
+ return 0;
}
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
+ const struct bt_mesh_net_cred *cred;
int err;
BT_DBG("src 0x%04x dst 0x%04x len %u headroom %zu tailroom %zu",
@@ -869,11 +459,8 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
BT_DBG("Payload len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
BT_DBG("Seq 0x%06x", bt_mesh.seq);
- if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
- tx->ctx->send_ttl = bt_mesh_default_ttl_get();
- }
-
- err = bt_mesh_net_encode(tx, buf, false);
+ cred = net_tx_cred_get(tx);
+ err = net_header_encode(tx, cred->nid, buf);
if (err) {
goto done;
}
@@ -881,225 +468,118 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
BT_DBG("encoded %u bytes: %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- /* Deliver to GATT Proxy Clients if necessary. Mesh spec 3.4.5.2:
- * "The output filter of the interface connected to advertising or
- * GATT bearers shall drop all messages with TTL value set to 1."
- */
- if (MYNEWT_VAL(BLE_MESH_GATT_PROXY) &&
- tx->ctx->send_ttl != 1) {
- if (bt_mesh_proxy_relay(buf, tx->ctx->addr) &&
- BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
- /* Notify completion if this only went
- * through the Mesh Proxy.
- */
- send_cb_finalize(cb, cb_data);
-
- err = 0;
- goto done;
- }
- }
-
/* Deliver to local network interface if necessary */
if (bt_mesh_fixed_group_match(tx->ctx->addr) ||
bt_mesh_elem_find(tx->ctx->addr)) {
- if (cb && cb->start) {
- cb->start(0, 0, cb_data);
- }
- net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
- if (cb && cb->end) {
- cb->end(0, cb_data);
- }
- k_work_submit(&bt_mesh.local_work);
- } else if (tx->ctx->send_ttl != 1) {
- /* Deliver to to the advertising network interface. Mesh spec
- * 3.4.5.2: "The output filter of the interface connected to
- * advertising or GATT bearers shall drop all messages with
- * TTL value set to 1."
- */
- bt_mesh_adv_send(buf, cb, cb_data);
- }
+ err = loopback(tx, buf->om_data, buf->om_len);
-done:
- net_buf_unref(buf);
- return err;
-}
+ /* Local unicast messages should not go out to network */
+ if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) ||
+ tx->ctx->send_ttl == 1U) {
+ if (!err) {
+ send_cb_finalize(cb, cb_data);
+ }
-static bool auth_match(struct bt_mesh_subnet_keys *keys,
- const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8])
-{
- u8_t net_auth[8];
+ goto done;
+ }
+ }
+ /* Mesh spec 3.4.5.2: "The output filter of the interface connected to
+ * advertising or GATT bearers shall drop all messages with TTL value
+ * set to 1." If a TTL=1 packet wasn't for a local interface, it is
+ * invalid.
+ */
+ if (tx->ctx->send_ttl == 1U) {
+ err = -EINVAL;
+ goto done;
+ }
- if (memcmp(net_id, keys->net_id, 8)) {
- return false;
+ err = net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, false);
+ if (err) {
+ goto done;
}
- bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, iv_index,
- net_auth);
+ /* Deliver to GATT Proxy Clients if necessary. */
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
+ bt_mesh_proxy_relay(buf, tx->ctx->addr) &&
+ BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
+ /* Notify completion if this only went through the Mesh Proxy */
+ send_cb_finalize(cb, cb_data);
- if (memcmp(auth, net_auth, 8)) {
- BT_WARN("Authentication Value %s != %s",
- bt_hex(auth, 8), bt_hex(net_auth, 8));
- return false;
+ err = 0;
+ goto done;
}
- return true;
+ bt_mesh_adv_send(buf, cb, cb_data);
+
+done:
+ net_buf_unref(buf);
+ return err;
}
-struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8],
- bool *new_key)
+void bt_mesh_net_loopback_clear(uint16_t net_idx)
{
- int i;
+ struct net_buf_slist_t new_list;
+ struct os_mbuf *buf;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+ BT_DBG("0x%04x", net_idx);
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
+ net_buf_slist_init(&new_list);
- if (auth_match(&sub->keys[0], net_id, flags, iv_index, auth)) {
- *new_key = false;
- return sub;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
+ while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
+ struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf);
- if (auth_match(&sub->keys[1], net_id, flags, iv_index, auth)) {
- *new_key = true;
- return sub;
+ if (net_idx == BT_MESH_KEY_ANY || net_idx == sub->net_idx) {
+ BT_DBG("Dropped 0x%06x", SEQ(buf->om_data));
+ net_buf_unref(buf);
+ } else {
+ net_buf_slist_put(&new_list, buf);
}
}
- return NULL;
+ bt_mesh.local_queue = new_list;
}
-static int net_decrypt(struct bt_mesh_subnet *sub, const u8_t *enc,
- const u8_t *priv, const u8_t *data,
- size_t data_len, struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
+static bool net_decrypt(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+ struct os_mbuf *out,
+ const struct bt_mesh_net_cred *cred)
{
- BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
- BT_DBG("IVI %u net->iv_index 0x%08x", IVI(data),
- (unsigned) bt_mesh.iv_index);
+ bool proxy = (rx->net_if == BT_MESH_NET_IF_PROXY_CFG);
- rx->old_iv = (IVI(data) != (bt_mesh.iv_index & 0x01));
+ if (NID(in->om_data) != cred->nid) {
+ return false;
+ }
- net_buf_simple_init(buf, 0);
- memcpy(net_buf_simple_add(buf, data_len), data, data_len);
+ BT_DBG("NID 0x%02x", NID(in->om_data));
+ BT_DBG("IVI %u net->iv_index 0x%08x", IVI(in->om_data), bt_mesh.iv_index);
- if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) {
- return -ENOENT;
- }
+ rx->old_iv = (IVI(in->om_data) != (bt_mesh.iv_index & 0x01));
+ net_buf_simple_reset(out);
+ net_buf_simple_add_mem(out, in->om_data, in->om_len);
- if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(rx, buf)) {
- BT_WARN("Duplicate found in Network Message Cache");
- return -EALREADY;
+ if (bt_mesh_net_obfuscate(out->om_data, BT_MESH_NET_IVI_RX(rx),
+ cred->privacy)) {
+ return false;
}
- rx->ctx.addr = SRC(buf->om_data);
+ rx->ctx.addr = SRC(out->om_data);
if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr)) {
- BT_WARN("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr);
- return -EINVAL;
- }
-
- BT_DBG("src 0x%04x", rx->ctx.addr);
-
- if ((MYNEWT_VAL(BLE_MESH_PROXY)) &&
- rx->net_if == BT_MESH_NET_IF_PROXY_CFG) {
- return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx),
- true);
+ BT_DBG("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr);
+ return false;
}
- return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false);
-}
-
-static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data,
- size_t data_len, struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- int i;
-
- BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->net_idx != sub->net_idx) {
- continue;
- }
-
- if (NID(data) == cred->cred[0].nid &&
- !net_decrypt(sub, cred->cred[0].enc, cred->cred[0].privacy,
- data, data_len, rx, buf)) {
- return 0;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
-
- if (NID(data) == cred->cred[1].nid &&
- !net_decrypt(sub, cred->cred[1].enc, cred->cred[1].privacy,
- data, data_len, rx, buf)) {
- rx->new_key = 1;
- return 0;
- }
+ if (bt_mesh_elem_find(rx->ctx.addr)) {
+ BT_DBG("Dropping locally originated packet");
+ return false;
}
- return -ENOENT;
-}
-
-static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
- struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_subnet *sub;
- unsigned int i;
-
- BT_DBG("");
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- sub = &bt_mesh.sub[i];
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if ((IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
- IS_ENABLED(CONFIG_BT_MESH_FRIEND)) &&
- !friend_decrypt(sub, data, data_len, rx, buf)) {
- rx->friend_cred = 1U;
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
-
- if (NID(data) == sub->keys[0].nid &&
- !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy,
- data, data_len, rx, buf)) {
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
-
- if (NID(data) == sub->keys[1].nid &&
- !net_decrypt(sub, sub->keys[1].enc, sub->keys[1].privacy,
- data, data_len, rx, buf)) {
- rx->new_key = 1;
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
+ if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(out)) {
+ BT_DBG("Duplicate found in Network Message Cache");
+ return false;
}
- return false;
+ BT_DBG("src 0x%04x", rx->ctx.addr);
+ return bt_mesh_net_decrypt(cred->enc, out, BT_MESH_NET_IVI_RX(rx),
+ proxy) == 0;
}
/* Relaying from advertising to the advertising bearer should only happen
@@ -1110,8 +590,6 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
static bool relay_to_adv(enum bt_mesh_net_if net_if)
{
switch (net_if) {
- case BT_MESH_NET_IF_LOCAL:
- return true;
case BT_MESH_NET_IF_ADV:
return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
case BT_MESH_NET_IF_PROXY:
@@ -1124,27 +602,16 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if)
static void bt_mesh_net_relay(struct os_mbuf *sbuf,
struct bt_mesh_net_rx *rx)
{
- const u8_t *enc, *priv;
+ const struct bt_mesh_net_cred *cred;
struct os_mbuf *buf;
- u8_t nid, transmit;
-
- if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
- /* Locally originated PDUs with TTL=1 will only be delivered
- * to local elements as per Mesh Profile 1.0 section 3.4.5.2:
- * "The output filter of the interface connected to
- * advertising or GATT bearers shall drop all messages with
- * TTL value set to 1."
- */
- if (rx->ctx.recv_ttl == 1) {
- return;
- }
- } else {
- if (rx->ctx.recv_ttl <= 1) {
- return;
- }
+ uint8_t transmit;
+
+ if (rx->ctx.recv_ttl <= 1U) {
+ return;
}
if (rx->net_if == BT_MESH_NET_IF_ADV &&
+ !rx->friend_cred &&
bt_mesh_relay_get() != BT_MESH_RELAY_ENABLED &&
bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_ENABLED) {
return;
@@ -1157,7 +624,7 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf,
* Anything else (like GATT to adv, or locally originated packets)
* use the Network Transmit state.
*/
- if (rx->net_if == BT_MESH_NET_IF_ADV) {
+ if (rx->net_if == BT_MESH_NET_IF_ADV && !rx->friend_cred) {
transmit = bt_mesh_relay_retransmit_get();
} else {
transmit = bt_mesh_net_transmit_get();
@@ -1169,57 +636,45 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf,
return;
}
- /* Only decrement TTL for non-locally originated packets */
- if (rx->net_if != BT_MESH_NET_IF_LOCAL) {
- /* Leave CTL bit intact */
- sbuf->om_data[1] &= 0x80;
- sbuf->om_data[1] |= rx->ctx.recv_ttl - 1;
- }
+ /* Leave CTL bit intact */
+ sbuf->om_data[1] &= 0x80;
+ sbuf->om_data[1] |= rx->ctx.recv_ttl - 1U;
net_buf_add_mem(buf, sbuf->om_data, sbuf->om_len);
- enc = rx->sub->keys[rx->sub->kr_flag].enc;
- priv = rx->sub->keys[rx->sub->kr_flag].privacy;
- nid = rx->sub->keys[rx->sub->kr_flag].nid;
+ cred = &rx->sub->keys[SUBNET_KEY_TX_IDX(rx->sub)].msg;
BT_DBG("Relaying packet. TTL is now %u", TTL(buf->om_data));
/* Update NID if RX or RX was with friend credentials */
if (rx->friend_cred) {
buf->om_data[0] &= 0x80; /* Clear everything except IVI */
- buf->om_data[0] |= nid;
+ buf->om_data[0] |= cred->nid;
}
/* We re-encrypt and obfuscate using the received IVI rather than
* the normal TX IVI (which may be different) since the transport
* layer nonce includes the IVI.
*/
- if (bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false)) {
+ if (net_encrypt(buf, cred, BT_MESH_NET_IVI_RX(rx), false)) {
BT_ERR("Re-encrypting failed");
goto done;
}
- if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) {
- BT_ERR("Re-obfuscating failed");
- goto done;
- }
-
BT_DBG("encoded %u bytes: %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- /* Sending to the GATT bearer should only happen if GATT Proxy
- * is enabled or the message originates from the local node.
+ /* When the Friend node relays message for lpn, the message will be
+ * retransmitted using the managed master security credentials and
+ * the Network PDU shall be retransmitted to all network interfaces.
*/
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED ||
- rx->net_if == BT_MESH_NET_IF_LOCAL)) {
- if (bt_mesh_proxy_relay(buf, rx->ctx.recv_dst) &&
- BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
- goto done;
- }
+ (rx->friend_cred ||
+ bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED)) {
+ bt_mesh_proxy_relay(buf, rx->ctx.recv_dst);
}
- if (relay_to_adv(rx->net_if)) {
+ if (relay_to_adv(rx->net_if) || rx->friend_cred) {
bt_mesh_adv_send(buf, NULL, NULL);
}
@@ -1238,26 +693,26 @@ void bt_mesh_net_header_parse(struct os_mbuf *buf,
rx->ctx.recv_dst = DST(buf->om_data);
}
-int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
- struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
+int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if,
+ struct bt_mesh_net_rx *rx, struct os_mbuf *out)
{
- if (data->om_len < BT_MESH_NET_MIN_PDU_LEN) {
- BT_WARN("Dropping too short mesh packet (len %u)", data->om_len);
- BT_WARN("%s", bt_hex(data->om_data, data->om_len));
+ if (in->om_len < BT_MESH_NET_MIN_PDU_LEN) {
+ BT_WARN("Dropping too short mesh packet (len %u)", in->om_len);
+ BT_WARN("%s", bt_hex(in->om_data, in->om_len));
return -EINVAL;
}
- if (net_if == BT_MESH_NET_IF_ADV && check_dup(data)) {
- BT_DBG("duplicate packet; dropping %u bytes: %s", data->om_len,
- bt_hex(data->om_data, data->om_len));
+ if (net_if == BT_MESH_NET_IF_ADV && check_dup(in)) {
+ BT_DBG("duplicate packet; dropping %u bytes: %s", in->om_len,
+ bt_hex(in->om_data, in->om_len));
return -EINVAL;
}
- BT_DBG("%u bytes: %s", data->om_len, bt_hex(data->om_data, data->om_len));
+ BT_DBG("%u bytes: %s", in->om_len, bt_hex(in->om_data, in->om_len));
rx->net_if = net_if;
- if (!net_find_and_decrypt(data->om_data, data->om_len, rx, buf)) {
+ if (!bt_mesh_net_cred_find(rx, in, out, net_decrypt)) {
BT_DBG("Unable to find matching net for packet");
return -ENOENT;
}
@@ -1265,7 +720,7 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
/* Initialize AppIdx to a sane value */
rx->ctx.app_idx = BT_MESH_KEY_UNUSED;
- rx->ctx.recv_ttl = TTL(buf->om_data);
+ rx->ctx.recv_ttl = TTL(out->om_data);
/* Default to responding with TTL 0 for non-routed messages */
if (rx->ctx.recv_ttl == 0) {
@@ -1274,12 +729,12 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
rx->ctx.send_ttl = BT_MESH_TTL_DEFAULT;
}
- rx->ctl = CTL(buf->om_data);
- rx->seq = SEQ(buf->om_data);
- rx->ctx.recv_dst = DST(buf->om_data);
+ rx->ctl = CTL(out->om_data);
+ rx->seq = SEQ(out->om_data);
+ rx->ctx.recv_dst = DST(out->om_data);
- BT_DBG("Decryption successful. Payload len %u: %s", buf->om_len,
- bt_hex(buf->om_data, buf->om_len));
+ BT_DBG("Decryption successful. Payload len %u: %s", out->om_len,
+ bt_hex(out->om_data, out->om_len));
if (net_if != BT_MESH_NET_IF_PROXY_CFG &&
rx->ctx.recv_dst == BT_MESH_ADDR_UNASSIGNED) {
@@ -1287,24 +742,16 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
return -EBADMSG;
}
- if (BT_MESH_ADDR_IS_RFU(rx->ctx.recv_dst)) {
- BT_ERR("Destination address is RFU; dropping packet");
- return -EBADMSG;
- }
-
- if (net_if != BT_MESH_NET_IF_LOCAL && bt_mesh_elem_find(rx->ctx.addr)) {
- BT_DBG("Dropping locally originated packet");
- return -EBADMSG;
- }
-
BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->ctx.recv_dst,
rx->ctx.recv_ttl);
- BT_DBG("PDU: %s", bt_hex(buf->om_data, buf->om_len));
+ BT_DBG("PDU: %s", bt_hex(out->om_data, out->om_len));
+
+ msg_cache_add(rx);
return 0;
}
-void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
+void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi,
enum bt_mesh_net_if net_if)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(29);
@@ -1348,7 +795,7 @@ void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
*/
if (bt_mesh_trans_recv(buf, &rx) == -EAGAIN) {
BT_WARN("Removing rejected message from Network Message Cache");
- msg_cache[rx.msg_cache_idx] = 0ULL;
+ msg_cache[rx.msg_cache_idx].src = BT_MESH_ADDR_UNASSIGNED;
/* Rewind the next index now that we're not using this entry */
msg_cache_next = rx.msg_cache_idx;
}
@@ -1368,7 +815,8 @@ done:
static void ivu_refresh(struct ble_npl_event *work)
{
- bt_mesh.ivu_duration += BT_MESH_IVU_HOURS;
+ bt_mesh.ivu_duration = MIN(UINT8_MAX,
+ bt_mesh.ivu_duration + BT_MESH_IVU_HOURS);
BT_DBG("%s for %u hour%s",
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ?
@@ -1392,42 +840,22 @@ static void ivu_refresh(struct ble_npl_event *work)
}
}
-void bt_mesh_net_start(void)
-{
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
- bt_mesh_beacon_enable();
- } else {
- bt_mesh_beacon_disable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
- bt_mesh_proxy_gatt_enable();
- bt_mesh_adv_update();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
- bt_mesh_lpn_init();
- } else {
- bt_mesh_scan_enable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_init();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
- u16_t net_idx = bt_mesh.sub[0].net_idx;
- u16_t addr = bt_mesh_primary_addr();
-
- bt_mesh_prov_complete(net_idx, addr);
- }
-}
-
void bt_mesh_net_init(void)
{
+ int rc;
+
k_delayed_work_init(&bt_mesh.ivu_timer, ivu_refresh);
k_work_init(&bt_mesh.local_work, bt_mesh_net_local);
net_buf_slist_init(&bt_mesh.local_queue);
+
+ rc = os_mempool_init(&loopback_buf_mempool, MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS),
+ LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE,
+ &loopback_mbuf_membuf[0], "loopback_buf_pool");
+ assert(rc == 0);
+
+ rc = os_mbuf_pool_init(&loopback_os_mbuf_pool, &loopback_buf_mempool,
+ LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE,
+ MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS));
+ assert(rc == 0);
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h
index 976da005..f4b1192b 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h
@@ -9,13 +9,7 @@
#ifndef __NET_H__
#define __NET_H__
-#define BT_MESH_NET_FLAG_KR BIT(0)
-#define BT_MESH_NET_FLAG_IVU BIT(1)
-
-#define BT_MESH_KR_NORMAL 0x00
-#define BT_MESH_KR_PHASE_1 0x01
-#define BT_MESH_KR_PHASE_2 0x02
-#define BT_MESH_KR_PHASE_3 0x03
+#include "subnet.h"
#define BT_MESH_IV_UPDATE(flags) ((flags >> 1) & 0x01)
#define BT_MESH_KEY_REFRESH(flags) (flags & 0x01)
@@ -31,64 +25,13 @@
CONFIG_BT_MESH_IVU_DIVIDER)
#define BT_MESH_IVU_TIMEOUT K_HOURS(BT_MESH_IVU_HOURS)
-struct bt_mesh_app_key {
- u16_t net_idx;
- u16_t app_idx;
- bool updated;
- struct bt_mesh_app_keys {
- u8_t id;
- u8_t val[16];
- } keys[2];
-};
+struct bt_mesh_net_cred;
struct bt_mesh_node {
- u16_t addr;
- u16_t net_idx;
- u8_t dev_key[16];
- u8_t num_elem;
-};
-
-struct bt_mesh_subnet {
- u32_t beacon_sent; /* Timestamp of last sent beacon */
- u8_t beacons_last; /* Number of beacons during last
- * observation window
- */
- u8_t beacons_cur; /* Number of beaconds observed during
- * currently ongoing window.
- */
-
- u8_t beacon_cache[21]; /* Cached last authenticated beacon */
-
- u16_t net_idx; /* NetKeyIndex */
-
- bool kr_flag; /* Key Refresh Flag */
- u8_t kr_phase; /* Key Refresh Phase */
-
- u8_t node_id; /* Node Identity State */
- u32_t node_id_start; /* Node Identity started timestamp */
-
- u8_t auth[8]; /* Beacon Authentication Value */
-
- struct bt_mesh_subnet_keys {
- u8_t net[16]; /* NetKey */
- u8_t nid; /* NID */
- u8_t enc[16]; /* EncKey */
- u8_t net_id[8]; /* Network ID */
-#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
- u8_t identity[16]; /* IdentityKey */
-#endif
- u8_t privacy[16]; /* PrivacyKey */
- u8_t beacon[16]; /* BeaconKey */
- } keys[2];
-};
-
-struct bt_mesh_rpl {
- u16_t src;
- bool old_iv;
-#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
- bool store;
-#endif
- u32_t seq;
+ uint16_t addr;
+ uint16_t net_idx;
+ uint8_t dev_key[16];
+ uint8_t num_elem;
};
#if MYNEWT_VAL(BLE_MESH_FRIEND)
@@ -100,23 +43,23 @@ struct bt_mesh_rpl {
#endif
struct bt_mesh_friend {
- u16_t lpn;
- u8_t recv_delay;
- u8_t fsn:1,
+ uint16_t lpn;
+ uint8_t recv_delay;
+ uint8_t fsn:1,
send_last:1,
pending_req:1,
- sec_update:1,
pending_buf:1,
- valid:1,
established:1;
- s32_t poll_to;
- u8_t num_elem;
- u16_t lpn_counter;
- u16_t counter;
+ int32_t poll_to;
+ uint8_t num_elem;
+ uint16_t lpn_counter;
+ uint16_t counter;
- u16_t net_idx;
+ struct bt_mesh_subnet *subnet;
- u16_t sub_list[FRIEND_SUB_LIST_SIZE];
+ struct bt_mesh_net_cred cred[2];
+
+ uint16_t sub_list[FRIEND_SUB_LIST_SIZE];
struct k_delayed_work timer;
@@ -127,19 +70,19 @@ struct bt_mesh_friend {
* the current number of segments, in the queue. This is
* used for Friend Queue free space calculations.
*/
- u8_t seg_count;
+ uint8_t seg_count;
} seg[FRIEND_SEG_RX];
struct os_mbuf *last;
struct net_buf_slist_t queue;
- u32_t queue_size;
+ uint32_t queue_size;
/* Friend Clear Procedure */
struct {
- u32_t start; /* Clear Procedure start */
- u16_t frnd; /* Previous Friend's address */
- u16_t repeat_sec; /* Repeat timeout in seconds */
+ uint32_t start; /* Clear Procedure start */
+ uint16_t frnd; /* Previous Friend's address */
+ uint16_t repeat_sec; /* Repeat timeout in seconds */
struct k_delayed_work timer; /* Repeat timer */
} clear;
};
@@ -165,23 +108,23 @@ struct bt_mesh_lpn {
} state;
/* Transaction Number (used for subscription list) */
- u8_t xact_next;
- u8_t xact_pending;
- u8_t sent_req;
+ uint8_t xact_next;
+ uint8_t xact_pending;
+ uint8_t sent_req;
/* Address of our Friend when we're a LPN. Unassigned if we don't
* have a friend yet.
*/
- u16_t frnd;
+ uint16_t frnd;
/* Value from the friend offer */
- u8_t recv_win;
+ uint8_t recv_win;
- u8_t req_attempts; /* Number of Request attempts */
+ uint8_t req_attempts; /* Number of Request attempts */
- s32_t poll_timeout;
+ int32_t poll_timeout;
- u8_t groups_changed:1, /* Friend Subscription List needs updating */
+ uint8_t groups_changed:1, /* Friend Subscription List needs updating */
pending_poll:1, /* Poll to be sent after subscription */
disable:1, /* Disable LPN after clearing */
fsn:1, /* Friend Sequence Number */
@@ -189,22 +132,29 @@ struct bt_mesh_lpn {
clear_success:1; /* Friend Clear Confirm received */
/* Friend Queue Size */
- u8_t queue_size;
+ uint8_t queue_size;
+
+ /* FriendCounter */
+ uint16_t frnd_counter;
/* LPNCounter */
- u16_t counter;
+ uint16_t lpn_counter;
/* Previous Friend of this LPN */
- u16_t old_friend;
+ uint16_t old_friend;
/* Duration reported for last advertising packet */
- u16_t adv_duration;
+ uint16_t adv_duration;
/* Next LPN related action timer */
struct k_delayed_work timer;
/* Subscribed groups */
- u16_t groups[LPN_GROUPS];
+ uint16_t groups[LPN_GROUPS];
+
+ struct bt_mesh_subnet *sub;
+
+ struct bt_mesh_net_cred cred[2];
/* Bit fields for tracking which groups the Friend knows about */
ATOMIC_DEFINE(added, LPN_GROUPS);
@@ -231,15 +181,20 @@ enum {
BT_MESH_CFG_PENDING,
BT_MESH_MOD_PENDING,
BT_MESH_VA_PENDING,
- BT_MESH_NODES_PENDING,
+
+ /* Feature flags */
+ BT_MESH_RELAY,
+ BT_MESH_BEACON,
+ BT_MESH_GATT_PROXY,
+ BT_MESH_FRIEND,
/* Don't touch - intentionally last */
BT_MESH_FLAG_COUNT,
};
struct bt_mesh_net {
- u32_t iv_index; /* Current IV Index */
- u32_t seq; /* Next outgoing sequence number (24 bits) */
+ uint32_t iv_index; /* Current IV Index */
+ uint32_t seq; /* Next outgoing sequence number (24 bits) */
ATOMIC_DEFINE(flags, BT_MESH_FLAG_COUNT);
@@ -257,22 +212,16 @@ struct bt_mesh_net {
#endif
/* Number of hours in current IV Update state */
- u8_t ivu_duration;
+ uint8_t ivu_duration;
+
+ uint8_t net_xmit;
+ uint8_t relay_xmit;
+ uint8_t default_ttl;
/* Timer to track duration in current IV Update state */
struct k_delayed_work ivu_timer;
- u8_t dev_key[16];
-
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- struct bt_mesh_node nodes[MYNEWT_VAL(BLE_MESH_NODE_COUNT)];
-#endif
-
- struct bt_mesh_app_key app_keys[MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)];
-
- struct bt_mesh_subnet sub[MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)];
-
- struct bt_mesh_rpl rpl[MYNEWT_VAL(BLE_MESH_CRPL)];
+ uint8_t dev_key[16];
};
/* Network interface */
@@ -287,24 +236,24 @@ enum bt_mesh_net_if {
struct bt_mesh_net_rx {
struct bt_mesh_subnet *sub;
struct bt_mesh_msg_ctx ctx;
- u32_t seq; /* Sequence Number */
- u8_t old_iv:1, /* iv_index - 1 was used */
+ uint32_t seq; /* Sequence Number */
+ uint8_t old_iv:1, /* iv_index - 1 was used */
new_key:1, /* Data was encrypted with updated key */
friend_cred:1, /* Data was encrypted with friend cred */
ctl:1, /* Network Control */
net_if:2, /* Network interface */
local_match:1, /* Matched a local element */
friend_match:1; /* Matched an LPN we're friends for */
- u16_t msg_cache_idx; /* Index of entry in message cache */
+ uint16_t msg_cache_idx; /* Index of entry in message cache */
};
/* Encoding context for Network/Transport data */
struct bt_mesh_net_tx {
struct bt_mesh_subnet *sub;
struct bt_mesh_msg_ctx *ctx;
- u16_t src;
- u8_t xmit;
- u8_t friend_cred:1,
+ uint16_t src;
+ uint8_t xmit;
+ uint8_t friend_cred:1,
aszmic:1,
aid:6;
};
@@ -318,80 +267,36 @@ extern struct bt_mesh_net bt_mesh;
#define BT_MESH_NET_HDR_LEN 9
-int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
- const u8_t key[16]);
-
-int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
- u32_t iv_index);
-
-u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
-
-bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key);
-
-void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub);
-
-int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub);
-
-void bt_mesh_rpl_reset(void);
-
-bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update);
-
-void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);
+static inline void *net_buf_user_data(const struct os_mbuf *buf)
+{
+ return (void *)buf->om_data;
+}
-struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx);
+int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
+ uint32_t iv_index);
-struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8],
- bool *new_key);
+bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update);
int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
bool proxy);
+int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if,
+ struct bt_mesh_net_rx *rx, struct os_mbuf *out);
+
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data);
-int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
- bool new_key, const struct bt_mesh_send_cb *cb,
- void *cb_data);
-
-int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
- struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
-
-void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
+void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi,
enum bt_mesh_net_if net_if);
-u32_t bt_mesh_next_seq(void);
+void bt_mesh_net_loopback_clear(uint16_t net_idx);
-void bt_mesh_net_start(void);
+uint32_t bt_mesh_next_seq(void);
void bt_mesh_net_init(void);
void bt_mesh_net_header_parse(struct os_mbuf *buf,
struct bt_mesh_net_rx *rx);
-/* Friendship Credential Management */
-struct friend_cred {
- u16_t net_idx;
- u16_t addr;
-
- u16_t lpn_counter;
- u16_t frnd_counter;
-
- struct {
- u8_t nid; /* NID */
- u8_t enc[16]; /* EncKey */
- u8_t privacy[16]; /* PrivacyKey */
- } cred[2];
-};
-
-int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
- const u8_t **enc, const u8_t **priv);
-int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]);
-void friend_cred_refresh(u16_t net_idx);
-int friend_cred_update(struct bt_mesh_subnet *sub);
-struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
- u16_t lpn_counter, u16_t frnd_counter);
-void friend_cred_clear(struct friend_cred *cred);
-int friend_cred_del(u16_t net_idx, u16_t addr);
static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb,
void *cb_data)
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c
new file mode 100644
index 00000000..28391b18
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c
@@ -0,0 +1,888 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "syscfg/syscfg.h"
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include <stdint.h>
+#include <string.h>
+#include "mesh/mesh.h"
+#include <os/os_mbuf.h>
+#include "testing.h"
+#include "net.h"
+#include "prov.h"
+#include "adv.h"
+#include "crypto.h"
+#include "beacon.h"
+#include "prov.h"
+#include "mesh/glue.h"
+
+#define GPCF(gpc) (gpc & 0x03)
+#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
+#define GPC_ACK 0x01
+#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02)
+#define GPC_CTL(op) (((op) << 2) | 0x03)
+
+#define START_PAYLOAD_MAX 20
+#define CONT_PAYLOAD_MAX 23
+
+#define START_LAST_SEG(gpc) (gpc >> 2)
+#define CONT_SEG_INDEX(gpc) (gpc >> 2)
+
+#define BEARER_CTL(gpc) (gpc >> 2)
+#define LINK_OPEN 0x00
+#define LINK_ACK 0x01
+#define LINK_CLOSE 0x02
+
+#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)])
+#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
+
+#define XACT_ID_MAX 0x7f
+#define XACT_ID_NVAL 0xff
+#define SEG_NVAL 0xff
+
+#define RETRANSMIT_TIMEOUT K_MSEC(MYNEWT_VAL(BLE_MESH_PB_ADV_RETRANS_TIMEOUT))
+#define BUF_TIMEOUT K_MSEC(400)
+#define CLOSING_TIMEOUT K_SECONDS(3)
+#define TRANSACTION_TIMEOUT K_SECONDS(30)
+
+/* Acked messages, will do retransmissions manually, taking acks into account:
+ */
+#define RETRANSMITS_RELIABLE 0
+/* Unacked messages: */
+#define RETRANSMITS_UNRELIABLE 2
+/* PDU acks: */
+#define RETRANSMITS_ACK 2
+
+enum {
+ ADV_LINK_ACTIVE, /* Link has been opened */
+ ADV_LINK_ACK_RECVD, /* Ack for link has been received */
+ ADV_LINK_CLOSING, /* Link is closing down */
+ ADV_LINK_INVALID, /* Error occurred during provisioning */
+ ADV_ACK_PENDING, /* An acknowledgment is being sent */
+ ADV_PROVISIONER, /* The link was opened as provisioner */
+
+ ADV_NUM_FLAGS,
+};
+
+struct pb_adv {
+ uint32_t id; /* Link ID */
+
+ ATOMIC_DEFINE(flags, ADV_NUM_FLAGS);
+
+ const struct prov_bearer_cb *cb;
+ void *cb_data;
+
+ struct {
+ uint8_t id; /* Most recent transaction ID */
+ uint8_t seg; /* Bit-field of unreceived segments */
+ uint8_t last_seg; /* Last segment (to check length) */
+ uint8_t fcs; /* Expected FCS value */
+ struct os_mbuf *buf;
+ } rx;
+
+ struct {
+ /* Start timestamp of the transaction */
+ int64_t start;
+
+ /* Transaction id */
+ uint8_t id;
+
+ /* Current ack id */
+ uint8_t pending_ack;
+
+ /* Pending outgoing buffer(s) */
+ struct os_mbuf *buf[3];
+
+ prov_bearer_send_complete_t cb;
+
+ void *cb_data;
+
+ /* Retransmit timer */
+ struct k_delayed_work retransmit;
+ } tx;
+
+ /* Protocol timeout */
+ struct k_delayed_work prot_timer;
+};
+
+struct prov_rx {
+ uint32_t link_id;
+ uint8_t xact_id;
+ uint8_t gpc;
+};
+
+static struct os_mbuf *rx_buf;
+static struct pb_adv link;
+
+static void gen_prov_ack_send(uint8_t xact_id);
+static void link_open(struct prov_rx *rx, struct os_mbuf *buf);
+static void link_ack(struct prov_rx *rx, struct os_mbuf *buf);
+static void link_close(struct prov_rx *rx, struct os_mbuf *buf);
+
+static void buf_sent(int err, void *user_data)
+{
+ BT_DBG("buf_send");
+
+ if (!link.tx.buf[0]) {
+ return;
+ }
+
+ BT_DBG("submit retransmit");
+ k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
+}
+
+static struct bt_mesh_send_cb buf_sent_cb = {
+ .end = buf_sent,
+};
+
+static uint8_t last_seg(uint8_t len)
+{
+ if (len <= START_PAYLOAD_MAX) {
+ return 0;
+ }
+
+ len -= START_PAYLOAD_MAX;
+
+ return 1 + (len / CONT_PAYLOAD_MAX);
+}
+
+static void free_segments(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+ struct os_mbuf *buf = link.tx.buf[i];
+
+ if (!buf) {
+ break;
+ }
+
+ link.tx.buf[i] = NULL;
+ /* Mark as canceled */
+ BT_MESH_ADV(buf)->busy = 0U;
+ net_buf_unref(buf);
+ }
+}
+
+static uint8_t next_transaction_id(uint8_t id)
+{
+ return (((id + 1) & XACT_ID_MAX) | (id & (XACT_ID_MAX+1)));
+}
+
+static void prov_clear_tx(void)
+{
+ BT_DBG("");
+
+ k_delayed_work_cancel(&link.tx.retransmit);
+
+ free_segments();
+}
+
+static void reset_adv_link(void)
+{
+ BT_DBG("");
+ prov_clear_tx();
+
+ k_delayed_work_cancel(&link.prot_timer);
+
+ if (atomic_test_bit(link.flags, ADV_PROVISIONER)) {
+ /* Clear everything except the retransmit and protocol timer
+ * delayed work objects.
+ */
+ (void)memset(&link, 0, offsetof(struct pb_adv, tx.retransmit));
+ link.rx.id = XACT_ID_NVAL;
+ } else {
+ /* Accept another provisioning attempt */
+ link.id = 0;
+ atomic_clear(link.flags);
+ link.rx.id = XACT_ID_MAX;
+ link.tx.id = XACT_ID_NVAL;
+ }
+ link.tx.pending_ack = XACT_ID_NVAL;
+ if (!rx_buf) {
+ rx_buf = NET_BUF_SIMPLE(65);
+ }
+ link.rx.buf = rx_buf;
+ net_buf_simple_reset(link.rx.buf);
+}
+
+static void close_link(enum prov_bearer_link_status reason)
+{
+ const struct prov_bearer_cb *cb = link.cb;
+ void *cb_data = link.cb_data;
+
+ reset_adv_link();
+ cb->link_closed(&pb_adv, cb_data, reason);
+}
+
+static struct os_mbuf *adv_buf_create(uint8_t retransmits)
+{
+ struct os_mbuf *buf;
+
+ buf = bt_mesh_adv_create(BT_MESH_ADV_PROV,
+ BT_MESH_TRANSMIT(retransmits, 20),
+ BUF_TIMEOUT);
+ if (!buf) {
+ BT_ERR("Out of provisioning buffers");
+ return NULL;
+ }
+
+ return buf;
+}
+
+static void ack_complete(uint16_t duration, int err, void *user_data)
+{
+ BT_DBG("xact 0x%x complete", (uint8_t)link.tx.pending_ack);
+ atomic_clear_bit(link.flags, ADV_ACK_PENDING);
+}
+
+static bool ack_pending(void)
+{
+ return atomic_test_bit(link.flags, ADV_ACK_PENDING);
+}
+
+static void prov_failed(uint8_t err)
+{
+ BT_DBG("%u", err);
+ link.cb->error(&pb_adv, link.cb_data, err);
+ atomic_set_bit(link.flags, ADV_LINK_INVALID);
+}
+
+static void prov_msg_recv(void)
+{
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
+ BT_ERR("Incorrect FCS");
+ return;
+ }
+
+ gen_prov_ack_send(link.rx.id);
+
+ if (atomic_test_bit(link.flags, ADV_LINK_INVALID)) {
+ BT_WARN("Unexpected msg 0x%02x on invalidated link",
+ link.rx.buf->om_data[0]);
+ prov_failed(PROV_ERR_UNEXP_PDU);
+ return;
+ }
+
+ link.cb->recv(&pb_adv, link.cb_data, link.rx.buf);
+}
+
+static void protocol_timeout(struct ble_npl_event *work)
+{
+ BT_DBG("");
+
+ link.rx.seg = 0U;
+ close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
+}
+/*******************************************************************************
+ * Generic provisioning
+ ******************************************************************************/
+
+static void gen_prov_ack_send(uint8_t xact_id)
+{
+ static const struct bt_mesh_send_cb cb = {
+ .start = ack_complete,
+ };
+ const struct bt_mesh_send_cb *complete;
+ struct os_mbuf *buf;
+ bool pending = atomic_test_and_set_bit(link.flags, ADV_ACK_PENDING);
+
+ BT_DBG("xact_id 0x%x", xact_id);
+
+ if (pending && link.tx.pending_ack == xact_id) {
+ BT_DBG("Not sending duplicate ack");
+ return;
+ }
+
+ buf = adv_buf_create(RETRANSMITS_ACK);
+ if (!buf) {
+ atomic_clear_bit(link.flags, ADV_ACK_PENDING);
+ return;
+ }
+
+ if (pending) {
+ complete = NULL;
+ } else {
+ link.tx.pending_ack = xact_id;
+ complete = &cb;
+ }
+
+ net_buf_add_be32(buf, link.id);
+ net_buf_add_u8(buf, xact_id);
+ net_buf_add_u8(buf, GPC_ACK);
+
+ bt_mesh_adv_send(buf, complete, NULL);
+ net_buf_unref(buf);
+}
+
+static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t seg = CONT_SEG_INDEX(rx->gpc);
+
+ BT_DBG("len %u, seg_index %u", buf->om_len, seg);
+
+ if (!link.rx.seg && link.rx.id == rx->xact_id) {
+ if (!ack_pending()) {
+ BT_DBG("Resending ack");
+ gen_prov_ack_send(rx->xact_id);
+ }
+
+ return;
+ }
+
+ if (!link.rx.seg &&
+ next_transaction_id(link.rx.id) == rx->xact_id) {
+ BT_DBG("Start segment lost");
+
+ link.rx.id = rx->xact_id;
+
+ net_buf_simple_reset(link.rx.buf);
+ link.rx.seg = SEG_NVAL;
+ link.rx.last_seg = SEG_NVAL;
+
+ prov_clear_tx();
+ } else if (rx->xact_id != link.rx.id) {
+ BT_WARN("Data for unknown transaction (0x%x != 0x%x)",
+ rx->xact_id, link.rx.id);
+ return;
+ }
+
+ if (seg > link.rx.last_seg) {
+ BT_ERR("Invalid segment index %u", seg);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (!(link.rx.seg & BIT(seg))) {
+ BT_DBG("Ignoring already received segment");
+ return;
+ }
+
+ memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len);
+ XACT_SEG_RECV(seg);
+
+ if (seg == link.rx.last_seg && !(link.rx.seg & BIT(0))) {
+ uint8_t expect_len;
+
+ expect_len = (link.rx.buf->om_len - 20U -
+ ((link.rx.last_seg - 1) * 23U));
+ if (expect_len != buf->om_len) {
+ BT_ERR("Incorrect last seg len: %u != %u", expect_len,
+ buf->om_len);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+ }
+
+ if (!link.rx.seg) {
+ prov_msg_recv();
+ }
+}
+
+static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (!link.tx.buf[0]) {
+ return;
+ }
+
+ if (rx->xact_id == link.tx.id) {
+ /* Don't clear resending of link_close messages */
+ if (!atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
+ prov_clear_tx();
+ }
+
+ if (link.tx.cb) {
+ link.tx.cb(0, link.tx.cb_data);
+ }
+ }
+}
+
+static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t seg = SEG_NVAL;
+
+ if (rx->xact_id == link.rx.id) {
+ if (!link.rx.seg) {
+ if (!ack_pending()) {
+ BT_DBG("Resending ack");
+ gen_prov_ack_send(rx->xact_id);
+ }
+
+ return;
+ }
+
+ if (!(link.rx.seg & BIT(0))) {
+ BT_DBG("Ignoring duplicate segment");
+ return;
+ }
+ } else if (rx->xact_id != next_transaction_id(link.rx.id)) {
+ BT_WARN("Unexpected xact 0x%x, expected 0x%x", rx->xact_id,
+ next_transaction_id(link.rx.id));
+ return;
+ }
+
+ net_buf_simple_reset(link.rx.buf);
+ link.rx.buf->om_len = net_buf_simple_pull_be16(buf);
+ link.rx.id = rx->xact_id;
+ link.rx.fcs = net_buf_simple_pull_u8(buf);
+
+ BT_DBG("%p len %u last_seg %u total_len %u fcs 0x%02x", link.rx.buf, buf->om_len,
+ START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs);
+
+ if (link.rx.buf->om_len < 1) {
+ BT_ERR("Ignoring zero-length provisioning PDU");
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20U) {
+ BT_ERR("Too small total length for multi-segment PDU");
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ prov_clear_tx();
+
+ link.rx.last_seg = START_LAST_SEG(rx->gpc);
+ if ((link.rx.seg & BIT(0)) &&
+ (find_msb_set((~link.rx.seg) & SEG_NVAL) - 1 > link.rx.last_seg)) {
+ BT_ERR("Invalid segment index %u", seg);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (link.rx.seg) {
+ seg = link.rx.seg;
+ }
+
+ link.rx.seg = seg & ((1 << (START_LAST_SEG(rx->gpc) + 1)) - 1);
+ memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len);
+ XACT_SEG_RECV(0);
+
+ if (!link.rx.seg) {
+ prov_msg_recv();
+ }
+}
+
+static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len);
+
+ switch (BEARER_CTL(rx->gpc)) {
+ case LINK_OPEN:
+ link_open(rx, buf);
+ break;
+ case LINK_ACK:
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return;
+ }
+
+ link_ack(rx, buf);
+ break;
+ case LINK_CLOSE:
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return;
+ }
+
+ link_close(rx, buf);
+ break;
+ default:
+ BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
+
+ if (IS_ENABLED(CONFIG_BT_TESTING)) {
+ bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc));
+ }
+
+ return;
+ }
+}
+
+static const struct {
+ void (*func)(struct prov_rx *rx, struct os_mbuf *buf);
+ bool require_link;
+ uint8_t min_len;
+} gen_prov[] = {
+ { gen_prov_start, true, 3 },
+ { gen_prov_ack, true, 0 },
+ { gen_prov_cont, true, 0 },
+ { gen_prov_ctl, false, 0 },
+};
+
+static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) {
+ BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
+ return;
+ }
+
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE) &&
+ gen_prov[GPCF(rx->gpc)].require_link) {
+ BT_DBG("Ignoring message that requires active link");
+ return;
+ }
+
+ gen_prov[GPCF(rx->gpc)].func(rx, buf);
+}
+
+/*******************************************************************************
+ * TX
+ ******************************************************************************/
+
+static void send_reliable(void)
+{
+ int i;
+
+ link.tx.start = k_uptime_get();
+
+ for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+ struct os_mbuf *buf = link.tx.buf[i];
+
+ if (!buf) {
+ break;
+ }
+
+ if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
+ bt_mesh_adv_send(buf, NULL, NULL);
+ } else {
+ bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+ }
+ }
+}
+
+static void prov_retransmit(struct ble_npl_event *work)
+{
+ int32_t timeout_ms;
+ int i;
+
+ BT_DBG("");
+
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ BT_WARN("Link not active");
+ return;
+ }
+
+ /*
+ * According to mesh profile spec (5.3.1.4.3), the close message should
+ * be restransmitted at least three times. Retransmit the link_close
+ * message until CLOSING_TIMEOUT has elapsed.
+ */
+ if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
+ timeout_ms = CLOSING_TIMEOUT;
+ } else {
+ timeout_ms = TRANSACTION_TIMEOUT;
+ }
+
+ if (k_uptime_get() - link.tx.start > timeout_ms) {
+ if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
+ close_link(PROV_BEARER_LINK_STATUS_SUCCESS);
+ } else {
+ BT_WARN("Giving up transaction");
+ close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
+ }
+
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+ struct os_mbuf *buf = link.tx.buf[i];
+
+ if (!buf) {
+ break;
+ }
+
+ if (BT_MESH_ADV(buf)->busy) {
+ continue;
+ }
+
+ BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
+
+ if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
+ bt_mesh_adv_send(buf, NULL, NULL);
+ } else {
+ bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+ }
+ }
+}
+
+static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len,
+ bool reliable)
+{
+ struct os_mbuf *buf;
+
+ BT_DBG("op 0x%02x data_len %u", op, data_len);
+
+ prov_clear_tx();
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ buf = adv_buf_create(reliable ? RETRANSMITS_RELIABLE :
+ RETRANSMITS_UNRELIABLE);
+ if (!buf) {
+ return -ENOBUFS;
+ }
+
+ net_buf_add_be32(buf, link.id);
+ /* Transaction ID, always 0 for Bearer messages */
+ net_buf_add_u8(buf, 0x00);
+ net_buf_add_u8(buf, GPC_CTL(op));
+ net_buf_add_mem(buf, data, data_len);
+
+ if (reliable) {
+ link.tx.buf[0] = buf;
+ send_reliable();
+ } else {
+ bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+ net_buf_unref(buf);
+ }
+
+ return 0;
+}
+
+static int prov_send_adv(struct os_mbuf *msg,
+ prov_bearer_send_complete_t cb, void *cb_data)
+{
+ struct os_mbuf *start, *buf;
+ uint8_t seg_len, seg_id;
+
+ prov_clear_tx();
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ start = adv_buf_create(RETRANSMITS_RELIABLE);
+ if (!start) {
+ return -ENOBUFS;
+ }
+
+ link.tx.id = next_transaction_id(link.tx.id);
+ net_buf_add_be32(start, link.id);
+ net_buf_add_u8(start, link.tx.id);
+
+ net_buf_add_u8(start, GPC_START(last_seg(msg->om_len)));
+ net_buf_add_be16(start, msg->om_len);
+ net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len));
+
+ link.tx.buf[0] = start;
+ link.tx.cb = cb;
+ link.tx.cb_data = cb_data;
+
+ BT_DBG("xact_id: 0x%x len: %u", link.tx.id, msg->om_len);
+
+ seg_len = MIN(msg->om_len, START_PAYLOAD_MAX);
+ BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len));
+ net_buf_add_mem(start, msg->om_data, seg_len);
+ net_buf_simple_pull_mem(msg, seg_len);
+
+ buf = start;
+ for (seg_id = 1U; msg->om_len > 0; seg_id++) {
+ if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
+ BT_ERR("Too big message");
+ free_segments();
+ return -E2BIG;
+ }
+
+ buf = adv_buf_create(RETRANSMITS_RELIABLE);
+ if (!buf) {
+ free_segments();
+ return -ENOBUFS;
+ }
+
+ link.tx.buf[seg_id] = buf;
+
+ seg_len = MIN(msg->om_len, CONT_PAYLOAD_MAX);
+
+ BT_DBG("seg %u len %u: %s", seg_id, seg_len,
+ bt_hex(msg->om_data, seg_len));
+
+ net_buf_add_be32(buf, link.id);
+ net_buf_add_u8(buf, link.tx.id);
+ net_buf_add_u8(buf, GPC_CONT(seg_id));
+ net_buf_add_mem(buf, msg->om_data, seg_len);
+ net_buf_simple_pull_mem(msg, seg_len);
+ }
+
+ send_reliable();
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Link management rx
+ ******************************************************************************/
+
+static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (buf->om_len < 16) {
+ BT_ERR("Too short bearer open message (len %u)", buf->om_len);
+ return;
+ }
+
+ if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ /* Send another link ack if the provisioner missed the last */
+ if (link.id == rx->link_id) {
+ BT_DBG("Resending link ack");
+ bearer_ctl_send(LINK_ACK, NULL, 0, false);
+ } else {
+ BT_DBG("Ignoring bearer open: link already active");
+ }
+
+ return;
+ }
+
+ if (memcmp(buf->om_data, bt_mesh_prov_get()->uuid, 16)) {
+ BT_DBG("Bearer open message not for us");
+ return;
+ }
+
+ link.id = rx->link_id;
+ atomic_set_bit(link.flags, ADV_LINK_ACTIVE);
+ net_buf_simple_reset(link.rx.buf);
+
+ bearer_ctl_send(LINK_ACK, NULL, 0, false);
+
+ link.cb->link_opened(&pb_adv, link.cb_data);
+}
+
+static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (atomic_test_bit(link.flags, ADV_PROVISIONER)) {
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACK_RECVD)) {
+ return;
+ }
+
+ prov_clear_tx();
+
+ link.cb->link_opened(&pb_adv, link.cb_data);
+ }
+}
+
+static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (buf->om_len != 1) {
+ return;
+ }
+
+ close_link(net_buf_simple_pull_u8(buf));
+}
+
+/*******************************************************************************
+ * Higher level functionality
+ ******************************************************************************/
+
+void bt_mesh_pb_adv_recv(struct os_mbuf *buf)
+{
+ struct prov_rx rx;
+
+ if (!link.cb) {
+ return;
+ }
+
+ if (buf->om_len < 6) {
+ BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
+ return;
+ }
+
+ rx.link_id = net_buf_simple_pull_be32(buf);
+ rx.xact_id = net_buf_simple_pull_u8(buf);
+ rx.gpc = net_buf_simple_pull_u8(buf);
+
+ if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE) && link.id != rx.link_id) {
+ return;
+ }
+
+ BT_DBG("link_id 0x%08x xact_id 0x%x", rx.link_id, rx.xact_id);
+
+ gen_prov_recv(&rx, buf);
+}
+
+static int prov_link_open(const uint8_t uuid[16], int32_t timeout,
+ const struct prov_bearer_cb *cb, void *cb_data)
+{
+ BT_DBG("uuid %s", bt_hex(uuid, 16));
+
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ atomic_set_bit(link.flags, ADV_PROVISIONER);
+
+ bt_rand(&link.id, sizeof(link.id));
+ link.tx.id = XACT_ID_MAX;
+ link.rx.id = XACT_ID_NVAL;
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ net_buf_simple_reset(link.rx.buf);
+
+ bearer_ctl_send(LINK_OPEN, uuid, 16, true);
+
+ return 0;
+}
+
+static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data)
+{
+ if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ link.rx.id = XACT_ID_MAX;
+ link.tx.id = XACT_ID_NVAL;
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ /* Make sure we're scanning for provisioning inviations */
+ bt_mesh_scan_enable();
+ /* Enable unprovisioned beacon sending */
+ bt_mesh_beacon_enable();
+
+ return 0;
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_CLOSING)) {
+ return;
+ }
+
+ bearer_ctl_send(LINK_CLOSE, &status, 1, true);
+}
+
+void pb_adv_init(void)
+{
+ k_delayed_work_init(&link.prot_timer, protocol_timeout);
+ k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
+
+ if (!rx_buf) {
+ rx_buf = NET_BUF_SIMPLE(65);
+ }
+ link.rx.buf = rx_buf;
+ net_buf_simple_reset(link.rx.buf);
+}
+
+void pb_adv_reset(void)
+{
+ reset_adv_link();
+}
+
+const struct prov_bearer pb_adv = {
+ .type = BT_MESH_PROV_ADV,
+ .link_open = prov_link_open,
+ .link_accept = prov_link_accept,
+ .link_close = prov_link_close,
+ .send = prov_send_adv,
+ .clear_tx = prov_clear_tx,
+};
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c
new file mode 100644
index 00000000..a8f73787
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c
@@ -0,0 +1,158 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include "mesh/mesh.h"
+#include "prov.h"
+#include "net.h"
+#include "proxy.h"
+#include "adv.h"
+#include "prov.h"
+
+struct prov_link {
+ uint16_t conn_handle;
+ const struct prov_bearer_cb *cb;
+ void *cb_data;
+ struct {
+ uint8_t id; /* Transaction ID */
+ uint8_t prev_id; /* Previous Transaction ID */
+ uint8_t seg; /* Bit-field of unreceived segments */
+ uint8_t last_seg; /* Last segment (to check length) */
+ uint8_t fcs; /* Expected FCS value */
+ struct os_mbuf *buf;
+ } rx;
+ struct k_delayed_work prot_timer;
+};
+
+static struct prov_link link;
+
+static void reset_state(void)
+{
+ link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
+
+ k_delayed_work_cancel(&link.prot_timer);
+
+ link.rx.buf = bt_mesh_proxy_get_buf();
+}
+
+static void link_closed(enum prov_bearer_link_status status)
+{
+ const struct prov_bearer_cb *cb = link.cb;
+
+ void *cb_data = link.cb_data;
+
+ reset_state();
+
+ cb->link_closed(&pb_gatt, cb_data, status);
+}
+
+static void protocol_timeout(struct ble_npl_event *work)
+{
+ BT_DBG("Protocol timeout");
+
+ link_closed(PROV_BEARER_LINK_STATUS_TIMEOUT);
+}
+
+int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf)
+{
+ BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
+
+ if (link.conn_handle != conn_handle || !link.cb) {
+ BT_WARN("Data for unexpected connection");
+ return -ENOTCONN;
+ }
+
+ if (buf->om_len < 1) {
+ BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
+ return -EINVAL;
+ }
+
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ link.cb->recv(&pb_gatt, link.cb_data, buf);
+
+ return 0;
+}
+
+int bt_mesh_pb_gatt_open(uint16_t conn_handle)
+{
+ BT_DBG("conn %p", conn_handle);
+
+ if (link.conn_handle) {
+ return -EBUSY;
+ }
+
+ link.conn_handle = conn_handle;
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ link.cb->link_opened(&pb_gatt, link.cb_data);
+
+ return 0;
+}
+
+int bt_mesh_pb_gatt_close(uint16_t conn_handle)
+{
+ BT_DBG("conn %p", conn_handle);
+
+ if (link.conn_handle != conn_handle) {
+ BT_DBG("Not connected");
+ return -ENOTCONN;
+ }
+
+ link.cb->link_closed(&pb_gatt, link.cb_data,
+ PROV_BEARER_LINK_STATUS_SUCCESS);
+
+ reset_state();
+
+ return 0;
+}
+
+static int link_accept(const struct prov_bearer_cb *cb, void *cb_data)
+{
+ bt_mesh_proxy_prov_enable();
+ bt_mesh_adv_update();
+
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ return 0;
+}
+
+static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb,
+ void *cb_data)
+{
+ if (!link.conn_handle) {
+ return -ENOTCONN;
+ }
+
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, buf);
+}
+
+static void clear_tx(void)
+{
+ /* No action */
+}
+
+void pb_gatt_init(void)
+{
+ k_delayed_work_init(&link.prot_timer, protocol_timeout);
+}
+
+void pb_gatt_reset(void)
+{
+ reset_state();
+}
+const struct prov_bearer pb_gatt = {
+ .type = BT_MESH_PROV_GATT,
+ .link_accept = link_accept,
+ .send = buf_send,
+ .clear_tx = clear_tx,
+}; \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c
index fe92c0e3..ba514dde 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c
@@ -9,8 +9,6 @@
#include "syscfg/syscfg.h"
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
-#if MYNEWT_VAL(BLE_MESH_PROV)
-
#include <errno.h>
#include "mesh/mesh.h"
@@ -18,700 +16,52 @@
#include "crypto.h"
#include "atomic.h"
-#include "adv.h"
#include "net.h"
#include "access.h"
#include "foundation.h"
-#include "proxy.h"
#include "prov.h"
#include "testing.h"
-#include "settings.h"
-#include "nodes.h"
-
-/* 3 transmissions, 20ms interval */
-#define PROV_XMIT BT_MESH_TRANSMIT(2, 20)
-
-#define AUTH_METHOD_NO_OOB 0x00
-#define AUTH_METHOD_STATIC 0x01
-#define AUTH_METHOD_OUTPUT 0x02
-#define AUTH_METHOD_INPUT 0x03
-
-#define OUTPUT_OOB_BLINK 0x00
-#define OUTPUT_OOB_BEEP 0x01
-#define OUTPUT_OOB_VIBRATE 0x02
-#define OUTPUT_OOB_NUMBER 0x03
-#define OUTPUT_OOB_STRING 0x04
-
-#define INPUT_OOB_PUSH 0x00
-#define INPUT_OOB_TWIST 0x01
-#define INPUT_OOB_NUMBER 0x02
-#define INPUT_OOB_STRING 0x03
-
-#define PUB_KEY_NO_OOB 0x00
-#define PUB_KEY_OOB 0x01
-
-#define PROV_ERR_NONE 0x00
-#define PROV_ERR_NVAL_PDU 0x01
-#define PROV_ERR_NVAL_FMT 0x02
-#define PROV_ERR_UNEXP_PDU 0x03
-#define PROV_ERR_CFM_FAILED 0x04
-#define PROV_ERR_RESOURCES 0x05
-#define PROV_ERR_DECRYPT 0x06
-#define PROV_ERR_UNEXP_ERR 0x07
-#define PROV_ERR_ADDR 0x08
-
-#define PROV_INVITE 0x00
-#define PROV_CAPABILITIES 0x01
-#define PROV_START 0x02
-#define PROV_PUB_KEY 0x03
-#define PROV_INPUT_COMPLETE 0x04
-#define PROV_CONFIRM 0x05
-#define PROV_RANDOM 0x06
-#define PROV_DATA 0x07
-#define PROV_COMPLETE 0x08
-#define PROV_FAILED 0x09
-
-#define PROV_NO_PDU 0xff
-
-#define PROV_ALG_P256 0x00
-
-#define GPCF(gpc) (gpc & 0x03)
-#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
-#define GPC_ACK 0x01
-#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02)
-#define GPC_CTL(op) (((op) << 2) | 0x03)
-
-#define START_PAYLOAD_MAX 20
-#define CONT_PAYLOAD_MAX 23
-
-#define START_LAST_SEG(gpc) (gpc >> 2)
-#define CONT_SEG_INDEX(gpc) (gpc >> 2)
-
-#define BEARER_CTL(gpc) (gpc >> 2)
-#define LINK_OPEN 0x00
-#define LINK_ACK 0x01
-#define LINK_CLOSE 0x02
-
-#define CLOSE_REASON_SUCCESS 0x00
-#define CLOSE_REASON_TIMEOUT 0x01
-#define CLOSE_REASON_FAILED 0x02
-
-#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)])
-#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
-
-#define XACT_NVAL 0xff
-
-enum {
- WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
- LINK_ACTIVE, /* Link has been opened */
- LINK_ACK_RECVD, /* Ack for link has been received */
- LINK_CLOSING, /* Link is closing down */
- SEND_PUB_KEY, /* Waiting to send PubKey */
- WAIT_NUMBER, /* Waiting for number input from user */
- WAIT_STRING, /* Waiting for string input from user */
- NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */
- LINK_INVALID, /* Error occurred during provisioning */
- PROVISIONER, /* The link was opened as provisioner */
-
- NUM_FLAGS,
-};
-
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-#define PROVISIONER_LINK 1
-#else
-#define PROVISIONER_LINK 0
-#endif
-
-struct provisioner_link {
- struct bt_mesh_node *node;
- u16_t addr;
- u16_t net_idx;
- u8_t attention_duration;
-};
-
-struct prov_link {
- ATOMIC_DEFINE(flags, NUM_FLAGS);
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- uint16_t conn_handle; /* GATT connection */
-#endif
- struct provisioner_link provisioner[PROVISIONER_LINK];
-
- u8_t dhkey[32]; /* Calculated DHKey */
- u8_t expect; /* Next expected PDU */
-
- u8_t oob_method;
- u8_t oob_action;
- u8_t oob_size;
-
- u8_t conf[16]; /* Remote Confirmation */
- u8_t rand[16]; /* Local Random */
- u8_t auth[16]; /* Authentication Value */
-
- u8_t conf_salt[16]; /* ConfirmationSalt */
- u8_t conf_key[16]; /* ConfirmationKey */
- u8_t conf_inputs[145]; /* ConfirmationInputs */
- u8_t prov_salt[16]; /* Provisioning Salt */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- u32_t id; /* Link ID */
-
- struct {
- u8_t id; /* Transaction ID */
- u8_t prev_id; /* Previous Transaction ID */
- u8_t seg; /* Bit-field of unreceived segments */
- u8_t last_seg; /* Last segment (to check length) */
- u8_t fcs; /* Expected FCS value */
- struct os_mbuf *buf;
- } rx;
-
- struct {
- /* Start timestamp of the transaction */
- s64_t start;
-
- /* Transaction id*/
- u8_t id;
-
- /* Pending outgoing buffer(s) */
- struct os_mbuf *buf[3];
-
- /* Retransmit timer */
- struct k_delayed_work retransmit;
- } tx;
-#endif
-
- struct k_delayed_work prot_timer;
-};
-
-struct prov_rx {
- u32_t link_id;
- u8_t xact_id;
- u8_t gpc;
-};
-
-#define RETRANSMIT_TIMEOUT K_MSEC(500)
-#define BUF_TIMEOUT K_MSEC(400)
-#define CLOSING_TIMEOUT K_SECONDS(3)
-#define TRANSACTION_TIMEOUT K_SECONDS(30)
-#define PROTOCOL_TIMEOUT K_SECONDS(60)
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-#define PROV_BUF_HEADROOM 5
-#else
-#define PROV_BUF_HEADROOM 0
-static struct os_mbuf *rx_buf;
-#endif
-
-#define PROV_BUF(len) NET_BUF_SIMPLE(PROV_BUF_HEADROOM + len)
-static struct prov_link link;
+struct bt_mesh_prov_link bt_mesh_prov_link;
+const struct bt_mesh_prov *bt_mesh_prov;
-static const struct bt_mesh_prov *prov;
-
-static void pub_key_ready(const u8_t *pkey);
+static void pub_key_ready(const uint8_t *pkey)
+{
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+ BT_DBG("Local public key ready");
+}
-static int reset_state(void)
+int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64]))
{
- static struct bt_pub_key_cb pub_key_cb = {
- .func = pub_key_ready,
- };
+ BT_DBG("bt_mesh_prov_reset_state");
+
int err;
+ static struct bt_pub_key_cb pub_key_cb;
+ const size_t offset = offsetof(struct bt_mesh_prov_link, dhkey);
- k_delayed_work_cancel(&link.prot_timer);
+ pub_key_cb.func = func ? func : pub_key_ready;
/* Disable Attention Timer if it was set */
- if (link.conf_inputs[0]) {
+ if (bt_mesh_prov_link.conf_inputs[0]) {
bt_mesh_attention(NULL, 0);
}
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- link.provisioner->node != NULL) {
- bt_mesh_node_del(link.provisioner->node, false);
- }
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- /* Clear everything except the retransmit and protocol timer
- * delayed work objects.
- */
- (void)memset(&link, 0, offsetof(struct prov_link, tx.retransmit));
- link.rx.prev_id = XACT_NVAL;
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.rx.buf = bt_mesh_proxy_get_buf();
-#else
- if (!rx_buf) {
- rx_buf = NET_BUF_SIMPLE(65);
- }
- net_buf_simple_init(rx_buf, 0);
- link.rx.buf = rx_buf;
-#endif /* PB_GATT */
-
-#else /* !PB_ADV */
- /* Clear everything except the protocol timer (k_delayed_work) */
- (void)memset(&link, 0, offsetof(struct prov_link, prot_timer));
-#endif /* PB_ADV */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
-#endif
+ atomic_clear(bt_mesh_prov_link.flags);
+ (void)memset((uint8_t *)&bt_mesh_prov_link + offset, 0,
+ sizeof(bt_mesh_prov_link) - offset);
err = bt_pub_key_gen(&pub_key_cb);
if (err) {
BT_ERR("Failed to generate public key (%d)", err);
return err;
}
-
return 0;
}
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-static void buf_sent(int err, void *user_data)
-{
- BT_DBG("buf_sent");
-
- if (!link.tx.buf[0]) {
- return;
- }
-
- k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
-}
-
-static struct bt_mesh_send_cb buf_sent_cb = {
- .end = buf_sent,
-};
-
-static void free_segments(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
- struct os_mbuf *buf = link.tx.buf[i];
-
- if (!buf) {
- break;
- }
-
- link.tx.buf[i] = NULL;
- /* Mark as canceled */
- BT_MESH_ADV(buf)->busy = 0;
- net_buf_unref(buf);
- }
-}
-
-static void prov_clear_tx(void)
-{
- BT_DBG("");
-
- k_delayed_work_cancel(&link.tx.retransmit);
-
- free_segments();
-}
-
-static void reset_adv_link(void)
-{
- prov_clear_tx();
-
- if (prov->link_close) {
- prov->link_close(BT_MESH_PROV_ADV);
- }
-
- reset_state();
-}
-
-static struct os_mbuf *adv_buf_create(void)
-{
- struct os_mbuf *buf;
-
- buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, PROV_XMIT, BUF_TIMEOUT);
- if (!buf) {
- BT_ERR("Out of provisioning buffers");
- assert(0);
- return NULL;
- }
-
- return buf;
-}
-
-static u8_t pending_ack = XACT_NVAL;
-
-static void ack_complete(u16_t duration, int err, void *user_data)
-{
- BT_DBG("xact %u complete", (u8_t)pending_ack);
- pending_ack = XACT_NVAL;
-}
-
-static void gen_prov_ack_send(u8_t xact_id)
-{
- static const struct bt_mesh_send_cb cb = {
- .start = ack_complete,
- };
- const struct bt_mesh_send_cb *complete;
- struct os_mbuf *buf;
-
- BT_DBG("xact_id %u", xact_id);
-
- if (pending_ack == xact_id) {
- BT_DBG("Not sending duplicate ack");
- return;
- }
-
- buf = adv_buf_create();
- if (!buf) {
- return;
- }
-
- if (pending_ack == XACT_NVAL) {
- pending_ack = xact_id;
- complete = &cb;
- } else {
- complete = NULL;
- }
-
- net_buf_add_be32(buf, link.id);
- net_buf_add_u8(buf, xact_id);
- net_buf_add_u8(buf, GPC_ACK);
-
- bt_mesh_adv_send(buf, complete, NULL);
- net_buf_unref(buf);
-}
-
-static void send_reliable(void)
-{
- int i;
-
- link.tx.start = k_uptime_get();
-
- for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
- struct os_mbuf *buf = link.tx.buf[i];
-
- if (!buf) {
- break;
- }
-
- if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
- bt_mesh_adv_send(buf, NULL, NULL);
- } else {
- bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
- }
- }
-}
-
-static int bearer_ctl_send(u8_t op, const void *data, u8_t data_len)
-{
- struct os_mbuf *buf;
-
- BT_DBG("op 0x%02x data_len %u", op, data_len);
-
- prov_clear_tx();
-
- buf = adv_buf_create();
- if (!buf) {
- return -ENOBUFS;
- }
-
- net_buf_add_be32(buf, link.id);
- /* Transaction ID, always 0 for Bearer messages */
- net_buf_add_u8(buf, 0x00);
- net_buf_add_u8(buf, GPC_CTL(op));
- net_buf_add_mem(buf, data, data_len);
-
- link.tx.buf[0] = buf;
- send_reliable();
-
- return 0;
-}
-
-static u8_t last_seg(u8_t len)
-{
- if (len <= START_PAYLOAD_MAX) {
- return 0;
- }
-
- len -= START_PAYLOAD_MAX;
-
- return 1 + (len / CONT_PAYLOAD_MAX);
-}
-
-static inline u8_t next_transaction_id(void)
-{
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- if (link.tx.id != 0x7F) {
- link.tx.id++;
- } else {
- link.tx.id = 0;
- }
- } else {
- if (link.tx.id != 0U && link.tx.id != 0xFF) {
- link.tx.id++;
- } else {
- link.tx.id = 0x80;
- }
- }
-
- return link.tx.id;
-}
-
-static int prov_send_adv(struct os_mbuf *msg)
-{
- struct os_mbuf *start, *buf;
- u8_t seg_len, seg_id;
- u8_t xact_id;
-
- BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len));
-
- prov_clear_tx();
-
- start = adv_buf_create();
- if (!start) {
- return -ENOBUFS;
- }
-
- xact_id = next_transaction_id();
- net_buf_add_be32(start, link.id);
- net_buf_add_u8(start, xact_id);
-
- net_buf_add_u8(start, GPC_START(last_seg(msg->om_len)));
- net_buf_add_be16(start, msg->om_len);
- net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len));
-
- link.tx.buf[0] = start;
-
- seg_len = min(msg->om_len, START_PAYLOAD_MAX);
- BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len));
- net_buf_add_mem(start, msg->om_data, seg_len);
- net_buf_simple_pull(msg, seg_len);
-
- buf = start;
- for (seg_id = 1; msg->om_len > 0; seg_id++) {
- if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
- BT_ERR("Too big message");
- free_segments();
- return -E2BIG;
- }
-
- buf = adv_buf_create();
- if (!buf) {
- free_segments();
- return -ENOBUFS;
- }
-
- link.tx.buf[seg_id] = buf;
-
- seg_len = min(msg->om_len, CONT_PAYLOAD_MAX);
-
- BT_DBG("seg_id %u len %u: %s", seg_id, seg_len,
- bt_hex(msg->om_data, seg_len));
-
- net_buf_add_be32(buf, link.id);
- net_buf_add_u8(buf, xact_id);
- net_buf_add_u8(buf, GPC_CONT(seg_id));
- net_buf_add_mem(buf, msg->om_data, seg_len);
- net_buf_simple_pull(msg, seg_len);
- }
-
- send_reliable();
-
- return 0;
-}
-
-#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-static int prov_send_gatt(struct os_mbuf *msg)
-{
- if (link.conn_handle == BLE_HS_CONN_HANDLE_NONE) {
- BT_ERR("No connection handle!?");
- return -ENOTCONN;
- }
-
- return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, msg);
-}
-#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
-
-static inline int prov_send(struct os_mbuf *buf)
-{
- k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- return prov_send_gatt(buf);
- }
-#endif
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- return prov_send_adv(buf);
-#else
- return 0;
-#endif
-}
-
-static void prov_buf_init(struct os_mbuf *buf, u8_t type)
-{
- net_buf_simple_init(buf, PROV_BUF_HEADROOM);
- net_buf_simple_add_u8(buf, type);
-}
-
-static void prov_send_fail_msg(u8_t err)
-{
- struct os_mbuf *buf = PROV_BUF(2);
-
- prov_buf_init(buf, PROV_FAILED);
- net_buf_simple_add_u8(buf, err);
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send Provisioning Failed message");
- }
-
- atomic_set_bit(link.flags, LINK_INVALID);
-
- os_mbuf_free_chain(buf);
-}
-
-static void prov_invite(const u8_t *data)
-{
- struct os_mbuf *buf = PROV_BUF(12);
-
- BT_DBG("Attention Duration: %u seconds", data[0]);
-
- if (data[0]) {
- bt_mesh_attention(NULL, data[0]);
- }
-
- link.conf_inputs[0] = data[0];
-
- prov_buf_init(buf, PROV_CAPABILITIES);
-
- /* Number of Elements supported */
- net_buf_simple_add_u8(buf, bt_mesh_elem_count());
-
- /* Supported algorithms - FIPS P-256 Eliptic Curve */
- net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256));
-
- /* Public Key Type, Only "No OOB" Public Key is supported*/
- net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB);
-
- /* Static OOB Type */
- net_buf_simple_add_u8(buf, prov->static_val ? BIT(0) : 0x00);
-
- /* Output OOB Size */
- net_buf_simple_add_u8(buf, prov->output_size);
-
- /* Output OOB Action */
- net_buf_simple_add_be16(buf, prov->output_actions);
-
- /* Input OOB Size */
- net_buf_simple_add_u8(buf, prov->input_size);
-
- /* Input OOB Action */
- net_buf_simple_add_be16(buf, prov->input_actions);
-
- memcpy(&link.conf_inputs[1], &buf->om_data[1], 11);
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send capabilities");
- goto done;
- }
-
- link.expect = PROV_START;
-
-done:
- os_mbuf_free_chain(buf);
-}
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
-static void send_invite(void)
-{
- struct os_mbuf *inv = PROV_BUF(2);
-
- BT_DBG("");
-
- prov_buf_init(inv, PROV_INVITE);
- net_buf_simple_add_u8(inv, link.provisioner->attention_duration);
-
- link.conf_inputs[0] = link.provisioner->attention_duration;
-
- if (prov_send(inv)) {
- BT_ERR("Failed to send invite");
- goto done;
- }
-
- link.expect = PROV_CAPABILITIES;
-
-done:
- os_mbuf_free_chain(inv);
-}
-#endif
-
-static void send_start(void)
-{
- struct os_mbuf *start = PROV_BUF(6);
-
- BT_DBG("");
-
- prov_buf_init(start, PROV_START);
-
- net_buf_simple_add_u8(start, PROV_ALG_P256);
- net_buf_simple_add_u8(start, PUB_KEY_NO_OOB);
- net_buf_simple_add_u8(start, AUTH_METHOD_NO_OOB);
- memset(link.auth, 0, sizeof(link.auth));
-
- net_buf_simple_add_u8(start, 0); /* Auth Action */
- net_buf_simple_add_u8(start, 0); /* Auth Size */
-
- memcpy(&link.conf_inputs[12], &start->om_data[1], 5);
-
- if (prov_send(start)) {
- BT_ERR("Failed to send start");
- }
-
- os_mbuf_free_chain(start);
-}
-
-static void prov_capabilities(const u8_t *data)
-{
- u16_t algorithms, output_action, input_action;
-
- if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- return;
- }
-
- BT_DBG("Elements: %u", data[0]);
-
- algorithms = sys_get_be16(&data[1]);
- BT_DBG("Algorithms: %u", algorithms);
-
- BT_DBG("Public Key Type: 0x%02x", data[3]);
- BT_DBG("Static OOB Type: 0x%02x", data[4]);
- BT_DBG("Output OOB Size: %u", data[5]);
-
- output_action = sys_get_be16(&data[6]);
- BT_DBG("Output OOB Action: 0x%04x", output_action);
-
- BT_DBG("Input OOB Size: %u", data[8]);
-
- input_action = sys_get_be16(&data[9]);
- BT_DBG("Input OOB Action: 0x%04x", input_action);
-
- if (data[0] == 0) {
- BT_ERR("Invalid number of elements");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- link.provisioner->node = bt_mesh_node_alloc(link.provisioner->addr,
- data[0],
- link.provisioner->net_idx);
- if (link.provisioner->node == NULL) {
- prov_send_fail_msg(PROV_ERR_RESOURCES);
- return;
- }
-
- memcpy(&link.conf_inputs[1], data, 11);
-
- atomic_set_bit(link.flags, SEND_PUB_KEY);
-
- send_start();
-}
-
-static bt_mesh_output_action_t output_action(u8_t action)
+static bt_mesh_output_action_t output_action(uint8_t action)
{
switch (action) {
case OUTPUT_OOB_BLINK:
@@ -729,7 +79,7 @@ static bt_mesh_output_action_t output_action(u8_t action)
}
}
-static bt_mesh_input_action_t input_action(u8_t action)
+static bt_mesh_input_action_t input_action(uint8_t action)
{
switch (action) {
case INPUT_OOB_PUSH:
@@ -745,7 +95,7 @@ static bt_mesh_input_action_t input_action(u8_t action)
}
}
-static int prov_auth(u8_t method, u8_t action, u8_t size)
+int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size)
{
bt_mesh_output_action_t output;
bt_mesh_input_action_t input;
@@ -756,16 +106,15 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- memset(link.auth, 0, sizeof(link.auth));
+ (void)memset(bt_mesh_prov_link.auth, 0, sizeof(bt_mesh_prov_link.auth));
return 0;
case AUTH_METHOD_STATIC:
if (action || size) {
return -EINVAL;
}
- memcpy(link.auth + 16 - prov->static_val_len,
- prov->static_val, prov->static_val_len);
- memset(link.auth, 0, sizeof(link.auth) - prov->static_val_len);
+ atomic_set_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY);
+
return 0;
case AUTH_METHOD_OUTPUT:
@@ -774,19 +123,19 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- if (!(prov->output_actions & output)) {
+ if (!(bt_mesh_prov->output_actions & output)) {
return -EINVAL;
}
- if (size > prov->output_size) {
+ if (size > bt_mesh_prov->output_size) {
return -EINVAL;
}
- atomic_set_bit(link.flags, NOTIFY_INPUT_COMPLETE);
+ atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE);
if (output == BT_MESH_DISPLAY_STRING) {
unsigned char str[9];
- u8_t i;
+ uint8_t i;
bt_rand(str, size);
@@ -801,22 +150,23 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
}
str[size] = '\0';
- memcpy(link.auth, str, size);
- memset(link.auth + size, 0, sizeof(link.auth) - size);
+ memcpy(bt_mesh_prov_link.auth, str, size);
+ memset(bt_mesh_prov_link.auth + size, 0,
+ sizeof(bt_mesh_prov_link.auth) - size);
- return prov->output_string((char *)str);
+ return bt_mesh_prov->output_string((char *)str);
} else {
- u32_t div[8] = { 10, 100, 1000, 10000, 100000,
+ uint32_t div[8] = { 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000 };
- u32_t num;
+ uint32_t num;
bt_rand(&num, sizeof(num));
num %= div[size - 1];
- sys_put_be32(num, &link.auth[12]);
- memset(link.auth, 0, 12);
+ sys_put_be32(num, &bt_mesh_prov_link.auth[12]);
+ memset(bt_mesh_prov_link.auth, 0, 12);
- return prov->output_number(output, num);
+ return bt_mesh_prov->output_number(output, num);
}
case AUTH_METHOD_INPUT:
@@ -825,140 +175,38 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- if (!(prov->input_actions & input)) {
+ if (!(bt_mesh_prov->input_actions & input)) {
return -EINVAL;
}
- if (size > prov->input_size) {
+ if (size > bt_mesh_prov->input_size) {
return -EINVAL;
}
if (input == BT_MESH_ENTER_STRING) {
- atomic_set_bit(link.flags, WAIT_STRING);
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING);
} else {
- atomic_set_bit(link.flags, WAIT_NUMBER);
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER);
}
- return prov->input(input, size);
+ return bt_mesh_prov->input(input, size);
default:
return -EINVAL;
}
}
-static void prov_start(const u8_t *data)
-{
- BT_DBG("Algorithm: 0x%02x", data[0]);
- BT_DBG("Public Key: 0x%02x", data[1]);
- BT_DBG("Auth Method: 0x%02x", data[2]);
- BT_DBG("Auth Action: 0x%02x", data[3]);
- BT_DBG("Auth Size: 0x%02x", data[4]);
-
- if (data[0] != PROV_ALG_P256) {
- BT_ERR("Unknown algorithm 0x%02x", data[0]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- if (data[1] != PUB_KEY_NO_OOB) {
- BT_ERR("Invalid public key type: 0x%02x", data[1]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- memcpy(&link.conf_inputs[12], data, 5);
-
- /* TODO: reset link when auth fails? */
- link.expect = PROV_PUB_KEY;
-
- if (prov_auth(data[2], data[3], data[4]) < 0) {
- BT_ERR("Invalid authentication method: 0x%02x; "
- "action: 0x%02x; size: 0x%02x", data[2], data[3],
- data[4]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- }
-}
-
-static void send_confirm(void)
-{
- struct os_mbuf *cfm = PROV_BUF(17);
-
- BT_DBG("ConfInputs[0] %s", bt_hex(link.conf_inputs, 64));
- BT_DBG("ConfInputs[64] %s", bt_hex(&link.conf_inputs[64], 64));
- BT_DBG("ConfInputs[128] %s", bt_hex(&link.conf_inputs[128], 17));
-
- if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) {
- BT_ERR("Unable to generate confirmation salt");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("ConfirmationSalt: %s", bt_hex(link.conf_salt, 16));
-
- if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) {
- BT_ERR("Unable to generate confirmation key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("ConfirmationKey: %s", bt_hex(link.conf_key, 16));
-
- if (bt_rand(link.rand, 16)) {
- BT_ERR("Unable to generate random number");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("LocalRandom: %s", bt_hex(link.rand, 16));
-
- prov_buf_init(cfm, PROV_CONFIRM);
-
- if (bt_mesh_prov_conf(link.conf_key, link.rand, link.auth,
- net_buf_simple_add(cfm, 16))) {
- BT_ERR("Unable to generate confirmation value");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- if (prov_send(cfm)) {
- BT_ERR("Failed to send Provisioning Confirm");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_CONFIRM;
- } else {
- link.expect = PROV_RANDOM;
- }
-
-done:
- os_mbuf_free_chain(cfm);
-}
-
-static void send_input_complete(void)
-{
- struct os_mbuf *buf = PROV_BUF(1);
-
- prov_buf_init(buf, PROV_INPUT_COMPLETE);
- if (prov_send(buf)) {
- BT_ERR("Failed to send Provisioning Input Complete");
- }
- link.expect = PROV_CONFIRM;
-
- os_mbuf_free_chain(buf);
-}
-
-int bt_mesh_input_number(u32_t num)
+int bt_mesh_input_number(uint32_t num)
{
BT_DBG("%u", (unsigned) num);
- if (!atomic_test_and_clear_bit(link.flags, WAIT_NUMBER)) {
+ if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_NUMBER)) {
return -EINVAL;
}
- sys_put_be32(num, &link.auth[12]);
+ sys_put_be32(num, &bt_mesh_prov_link.auth[12]);
- send_input_complete();
+ bt_mesh_prov_link.role->input_complete();
return 0;
}
@@ -967,991 +215,145 @@ int bt_mesh_input_string(const char *str)
{
BT_DBG("%s", str);
- if (!atomic_test_and_clear_bit(link.flags, WAIT_STRING)) {
+ if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_STRING)) {
return -EINVAL;
}
- strncpy((char *)link.auth, str, prov->input_size);
+ strncpy((char *)bt_mesh_prov_link.auth, str, bt_mesh_prov->input_size);
- send_input_complete();
+ bt_mesh_prov_link.role->input_complete();
return 0;
}
-static void send_pub_key(void)
-{
- struct os_mbuf *buf = PROV_BUF(65);
- const u8_t *key;
-
- key = bt_pub_key_get();
- if (!key) {
- BT_ERR("No public key available");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Local Public Key: %s", bt_hex(key, 64));
-
- prov_buf_init(buf, PROV_PUB_KEY);
-
- /* Swap X and Y halves independently to big-endian */
- sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
- sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- /* PublicKeyProvisioner */
- memcpy(&link.conf_inputs[17], &buf->om_data[1], 64);
- } else {
- /* PublicKeyRemote */
- memcpy(&link.conf_inputs[81], &buf->om_data[1], 64);
- }
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send Public Key");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_PUB_KEY;
- } else {
- if (atomic_test_bit(link.flags, WAIT_NUMBER) ||
- atomic_test_bit(link.flags, WAIT_STRING)) {
- link.expect = PROV_NO_PDU; /* Wait for input */
- } else {
- link.expect = PROV_CONFIRM;
- }
- }
-
-done:
- os_mbuf_free_chain(buf);
-}
-
-static void prov_dh_key_cb(const u8_t dhkey[32])
-{
- BT_DBG("%p", dhkey);
-
- if (!dhkey) {
- BT_ERR("DHKey generation failed");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- sys_memcpy_swap(link.dhkey, dhkey, 32);
-
- BT_DBG("DHkey: %s", bt_hex(link.dhkey, 32));
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_confirm();
- } else {
- send_pub_key();
- }
-}
-
-static void prov_dh_key_gen(void)
-{
- u8_t remote_pk_le[64], *remote_pk;
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- remote_pk = &link.conf_inputs[81];
- } else {
- remote_pk = &link.conf_inputs[17];
- }
-
- /* Copy remote key in little-endian for bt_dh_key_gen().
- * X and Y halves are swapped independently. The bt_dh_key_gen()
- * will also take care of validating the remote public key.
- */
- sys_memcpy_swap(remote_pk_le, remote_pk, 32);
- sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
-
- if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
- BT_ERR("Failed to generate DHKey");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- }
-}
-
-static void prov_pub_key(const u8_t *data)
-{
- BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- /* PublicKeyDevice */
- memcpy(&link.conf_inputs[81], data, 64);
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- prov_clear_tx();
-#endif
- } else {
- /* PublicKeyProvisioner */
- memcpy(&link.conf_inputs[17], data, 64);
-
- if (!bt_pub_key_get()) {
- /* Clear retransmit timer */
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- prov_clear_tx();
-#endif
-
- atomic_set_bit(link.flags, WAIT_PUB_KEY);
- BT_WARN("Waiting for local public key");
- return;
- }
- }
-
- prov_dh_key_gen();
-}
-
-static void pub_key_ready(const u8_t *pkey)
-{
- if (!pkey) {
- BT_WARN("Public key not available");
- return;
- }
-
- BT_DBG("Local public key ready");
-
- if (atomic_test_and_clear_bit(link.flags, WAIT_PUB_KEY)) {
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_pub_key();
- } else {
- prov_dh_key_gen();
- }
- }
-}
-
-static void notify_input_complete(void)
-{
- if (atomic_test_and_clear_bit(link.flags, NOTIFY_INPUT_COMPLETE) &&
- prov->input_complete) {
- prov->input_complete();
- }
-}
-
-static void prov_input_complete(const u8_t *data)
-{
- BT_DBG("");
- notify_input_complete();
-}
-
-static void send_prov_data(void)
-{
- struct os_mbuf *pdu = PROV_BUF(34);
- struct bt_mesh_subnet *sub;
- u8_t session_key[16];
- u8_t nonce[13];
- int err;
-
- err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
- if (err) {
- BT_ERR("Unable to generate session key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
-
- err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
- if (err) {
- BT_ERR("Unable to generate session nonce");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Nonce: %s", bt_hex(nonce, 13));
-
- err = bt_mesh_dev_key(link.dhkey, link.prov_salt,
- link.provisioner->node->dev_key);
- if (err) {
- BT_ERR("Unable to generate device key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("DevKey: %s", bt_hex(link.provisioner->node->dev_key, 16));
-
- sub = bt_mesh_subnet_get(link.provisioner->node->net_idx);
- if (sub == NULL) {
- BT_ERR("No subnet with net_idx %u",
- link.provisioner->node->net_idx);
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- prov_buf_init(pdu, PROV_DATA);
- net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net, 16);
- net_buf_simple_add_be16(pdu, link.provisioner->node->net_idx);
- net_buf_simple_add_u8(pdu, bt_mesh_net_flags(sub));
- net_buf_simple_add_be32(pdu, bt_mesh.iv_index);
- net_buf_simple_add_be16(pdu, link.provisioner->node->addr);
- net_buf_simple_add(pdu, 8); /* For MIC */
-
- BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
- link.provisioner->node->net_idx, bt_mesh.iv_index,
- link.provisioner->node->addr);
-
- err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1],
- &pdu->om_data[1]);
- if (err) {
- BT_ERR("Unable to encrypt provisioning data");
- prov_send_fail_msg(PROV_ERR_DECRYPT);
- goto done;
- }
-
- if (prov_send(pdu)) {
- BT_ERR("Failed to send Provisioning Data");
- goto done;
- }
-
- link.expect = PROV_COMPLETE;
-
-done:
- os_mbuf_free_chain(pdu);
-}
-
-static void prov_complete(const u8_t *data)
-{
- if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- return;
- }
-
- struct bt_mesh_node *node = link.provisioner->node;
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- u8_t reason = CLOSE_REASON_SUCCESS;
-#endif
-
- BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
- bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
- node->addr);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_node(node);
- }
-
- link.provisioner->node = NULL;
- link.expect = PROV_NO_PDU;
- atomic_set_bit(link.flags, LINK_CLOSING);
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
-#endif
-
- bt_mesh_prov_node_added(node->net_idx, node->addr, node->num_elem);
-
- /*
- * According to mesh profile spec (5.3.1.4.3), the close message should
- * be restransmitted at least three times. Retransmit the LINK_CLOSE
- * message until CLOSING_TIMEOUT has elapsed instead of resetting the
- * link here.
- */
-}
-
-static void send_random(void)
-{
- struct os_mbuf *rnd = PROV_BUF(17);
-
- prov_buf_init(rnd, PROV_RANDOM);
- net_buf_simple_add_mem(rnd, link.rand, 16);
-
- if (prov_send(rnd)) {
- BT_ERR("Failed to send Provisioning Random");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_RANDOM;
- } else {
- link.expect = PROV_DATA;
- }
-
-done:
- os_mbuf_free_chain(rnd);
-}
-
-static void prov_random(const u8_t *data)
-{
- u8_t conf_verify[16];
- const u8_t *prov_rand, *dev_rand;
-
- BT_DBG("Remote Random: %s", bt_hex(data, 16));
-
- if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
- BT_ERR("Unable to calculate confirmation verification");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- if (memcmp(conf_verify, link.conf, 16)) {
- BT_ERR("Invalid confirmation value");
- BT_DBG("Received: %s", bt_hex(link.conf, 16));
- BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
- prov_send_fail_msg(PROV_ERR_CFM_FAILED);
- return;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- prov_rand = link.rand;
- dev_rand = data;
- } else {
- prov_rand = data;
- dev_rand = link.rand;
- }
-
- if (bt_mesh_prov_salt(link.conf_salt, prov_rand, dev_rand,
- link.prov_salt)) {
- BT_ERR("Failed to generate provisioning salt");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- BT_DBG("ProvisioningSalt: %s", bt_hex(link.prov_salt, 16));
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_bit(link.flags, PROVISIONER)) {
- send_prov_data();
- } else {
- send_random();
- }
-}
-
-static void prov_confirm(const u8_t *data)
-{
- BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
-
- memcpy(link.conf, data, 16);
-
- notify_input_complete();
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_random();
- } else {
- send_confirm();
- }
-}
-
-static inline bool is_pb_gatt(void)
-{
-#if MYNEWT_VAL(BLE_MESH_PB_GATT)
- return (link.conn_handle != BLE_HS_CONN_HANDLE_NONE);
-#else
- return false;
-#endif
-}
-
-static void prov_data(const u8_t *data)
-{
- struct os_mbuf *msg = PROV_BUF(1);
- u8_t session_key[16];
- u8_t nonce[13];
- u8_t dev_key[16];
- u8_t pdu[25];
- u8_t flags;
- u32_t iv_index;
- u16_t addr;
- u16_t net_idx;
- int err;
- bool identity_enable;
-
- BT_DBG("");
-
- err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
- if (err) {
- BT_ERR("Unable to generate session key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
-
- err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
- if (err) {
- BT_ERR("Unable to generate session nonce");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Nonce: %s", bt_hex(nonce, 13));
-
- err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
- if (err) {
- BT_ERR("Unable to decrypt provisioning data");
- prov_send_fail_msg(PROV_ERR_DECRYPT);
- goto done;
- }
-
- err = bt_mesh_dev_key(link.dhkey, link.prov_salt, dev_key);
- if (err) {
- BT_ERR("Unable to generate device key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("DevKey: %s", bt_hex(dev_key, 16));
-
- net_idx = sys_get_be16(&pdu[16]);
- flags = pdu[18];
- iv_index = sys_get_be32(&pdu[19]);
- addr = sys_get_be16(&pdu[23]);
-
- BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
- net_idx, (unsigned) iv_index, addr);
-
- prov_buf_init(msg, PROV_COMPLETE);
- if (prov_send(msg)) {
- BT_ERR("Failed to send Provisioning Complete");
- goto done;
- }
-
- /* Ignore any further PDUs on this link */
- link.expect = PROV_NO_PDU;
-
- /* Store info, since bt_mesh_provision() will end up clearing it */
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
- identity_enable = is_pb_gatt();
- } else {
- identity_enable = false;
- }
-
- err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
- if (err) {
- BT_ERR("Failed to provision (err %d)", err);
- goto done;
- }
-
- /* After PB-GATT provisioning we should start advertising
- * using Node Identity.
- */
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) {
- bt_mesh_proxy_identity_enable();
- }
-
-done:
- os_mbuf_free_chain(msg);
-}
-
-static void prov_failed(const u8_t *data)
-{
- BT_WARN("Error: 0x%02x", data[0]);
-}
-
-static const struct {
- void (*func)(const u8_t *data);
- u16_t len;
-} prov_handlers[] = {
- { prov_invite, 1 },
- { prov_capabilities, 11 },
- { prov_start, 5, },
- { prov_pub_key, 64 },
- { prov_input_complete, 0 },
- { prov_confirm, 16 },
- { prov_random, 16 },
- { prov_data, 33 },
- { prov_complete, 0 },
- { prov_failed, 1 },
-};
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-static void prov_retransmit(struct ble_npl_event *work)
-{
- int i, timeout;
-
- BT_DBG("");
-
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- BT_WARN("Link not active");
- return;
- }
-
- if (atomic_test_bit(link.flags, LINK_CLOSING)) {
- timeout = CLOSING_TIMEOUT;
- } else {
- timeout = TRANSACTION_TIMEOUT;
- }
-
- if (k_uptime_get() - link.tx.start > timeout) {
- BT_WARN("Giving up transaction");
- reset_adv_link();
- return;
- }
-
- for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
- struct os_mbuf *buf = link.tx.buf[i];
-
- if (!buf) {
- break;
- }
-
- if (BT_MESH_ADV(buf)->busy) {
- continue;
- }
-
- BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
-
- if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) {
- bt_mesh_adv_send(buf, NULL, NULL);
- } else {
- bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
- }
-
- }
-}
-
-static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("link open: len %u", buf->om_len);
-
- if (buf->om_len < 16) {
- BT_ERR("Too short bearer open message (len %u)", buf->om_len);
- return;
- }
-
- if (atomic_test_bit(link.flags, LINK_ACTIVE)) {
- /* Send another link ack if the provisioner missed the last */
- if (link.id == rx->link_id && link.expect == PROV_INVITE) {
- BT_DBG("Resending link ack");
- bearer_ctl_send(LINK_ACK, NULL, 0);
- } else {
- BT_WARN("Ignoring bearer open: link already active");
- }
-
- return;
- }
-
- if (memcmp(buf->om_data, prov->uuid, 16)) {
- BT_DBG("Bearer open message not for us");
- return;
- }
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_ADV);
- }
-
- link.id = rx->link_id;
- atomic_set_bit(link.flags, LINK_ACTIVE);
- net_buf_simple_init(link.rx.buf, 0);
-
- bearer_ctl_send(LINK_ACK, NULL, 0);
-
- link.expect = PROV_INVITE;
-}
-
-static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("Link ack: len %u", buf->om_len);
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_bit(link.flags, PROVISIONER)) {
- if (atomic_test_and_set_bit(link.flags, LINK_ACK_RECVD)) {
- return;
- }
-
- prov_clear_tx();
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_ADV);
- }
-
- send_invite();
- }
-}
-
-static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
+const struct bt_mesh_prov *bt_mesh_prov_get(void)
{
- BT_DBG("Link close: len %u", buf->om_len);
-
- reset_adv_link();
+ return bt_mesh_prov;
}
-static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
+bool bt_mesh_prov_active(void)
{
- BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len);
-
- switch (BEARER_CTL(rx->gpc)) {
- case LINK_OPEN:
- link_open(rx, buf);
- break;
- case LINK_ACK:
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- return;
- }
-
- link_ack(rx, buf);
- break;
- case LINK_CLOSE:
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- return;
- }
-
- link_close(rx, buf);
- break;
- default:
- BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
-
- if (IS_ENABLED(CONFIG_BT_TESTING)) {
- bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc));
- }
-
- return;
- }
+ return atomic_test_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
}
-static void prov_msg_recv(void)
+static void prov_recv(const struct prov_bearer *bearer, void *cb_data,
+ struct os_mbuf *buf)
{
- u8_t type = link.rx.buf->om_data[0];
-
- BT_DBG("type 0x%02x len %u", type, link.rx.buf->om_len);
-
- k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
-
- if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
- BT_ERR("Incorrect FCS");
- return;
- }
-
- gen_prov_ack_send(link.rx.id);
- link.rx.prev_id = link.rx.id;
- link.rx.id = 0;
-
- if (atomic_test_bit(link.flags, LINK_INVALID)) {
- BT_WARN("Unexpected msg 0x%02x on invalidated link", type);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return;
- }
+ static const uint8_t op_len[10] = {
+ [PROV_INVITE] = 1,
+ [PROV_CAPABILITIES] = 11,
+ [PROV_START] = 5,
+ [PROV_PUB_KEY] = 64,
+ [PROV_INPUT_COMPLETE] = 0,
+ [PROV_CONFIRM] = 16,
+ [PROV_RANDOM] = 16,
+ [PROV_DATA] = 33,
+ [PROV_COMPLETE] = 0,
+ [PROV_FAILED] = 1,
+ };
- if (type != PROV_FAILED && type != link.expect) {
- BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return;
- }
+ uint8_t type = buf->om_data[0];
+ BT_DBG("type 0x%02x len %u", type, buf->om_len);
- if (type >= ARRAY_SIZE(prov_handlers)) {
+ if (type >= ARRAY_SIZE(bt_mesh_prov_link.role->op)) {
BT_ERR("Unknown provisioning PDU type 0x%02x", type);
- prov_send_fail_msg(PROV_ERR_NVAL_PDU);
+ bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT);
return;
}
- if (1 + prov_handlers[type].len != link.rx.buf->om_len) {
- BT_ERR("Invalid length %u for type 0x%02x",
- link.rx.buf->om_len, type);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
+ if ((type != PROV_FAILED && type != bt_mesh_prov_link.expect) ||
+ !bt_mesh_prov_link.role->op[type]) {
+ BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, bt_mesh_prov_link.expect);
+ bt_mesh_prov_link.role->error(PROV_ERR_UNEXP_PDU);
return;
}
- prov_handlers[type].func(&link.rx.buf->om_data[1]);
-}
-
-static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf)
-{
- u8_t seg = CONT_SEG_INDEX(rx->gpc);
-
- BT_DBG("len %u, seg_index %u", buf->om_len, seg);
-
- if (!link.rx.seg && link.rx.prev_id == rx->xact_id) {
- BT_WARN("Resending ack");
- gen_prov_ack_send(rx->xact_id);
- return;
- }
-
- if (rx->xact_id != link.rx.id) {
- BT_WARN("Data for unknown transaction (%u != %u)",
- rx->xact_id, link.rx.id);
- return;
- }
-
- if (seg > link.rx.last_seg) {
- BT_ERR("Invalid segment index %u", seg);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- } else if (seg == link.rx.last_seg) {
- u8_t expect_len;
-
- expect_len = (link.rx.buf->om_len - 20 -
- ((link.rx.last_seg - 1) * 23));
- if (expect_len != buf->om_len) {
- BT_ERR("Incorrect last seg len: %u != %u",
- expect_len, buf->om_len);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
- }
-
- if (!(link.rx.seg & BIT(seg))) {
- BT_WARN("Ignoring already received segment");
- return;
- }
-
- memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len);
- XACT_SEG_RECV(seg);
-
- if (!link.rx.seg) {
- prov_msg_recv();
- }
-}
-
-static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("len %u", buf->om_len);
-
- if (!link.tx.buf[0]) {
+ if (1 + op_len[type] != buf->om_len) {
+ BT_ERR("Invalid length %u for type 0x%02x", buf->om_len, type);
+ bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT);
return;
}
- if (rx->xact_id == link.tx.id) {
- /* Don't clear resending of LINK_CLOSE messages */
- if (!atomic_test_bit(link.flags, LINK_CLOSING)) {
- prov_clear_tx();
- }
-
- /* Send the PubKey when the the Start message is ACK'ed */
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_and_clear_bit(link.flags, SEND_PUB_KEY)) {
- if (!bt_pub_key_get()) {
- atomic_set_bit(link.flags, WAIT_PUB_KEY);
- BT_WARN("Waiting for local public key");
- } else {
- send_pub_key();
- }
- }
- }
+ bt_mesh_prov_link.role->op[type](&buf->om_data[1]);
}
-static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
+static void prov_link_opened(const struct prov_bearer *bearer, void *cb_data)
{
- u16_t trailing_space = 0;
+ atomic_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
- if (link.rx.seg) {
- BT_WARN("Got Start while there are unreceived segments");
- return;
- }
-
- if (link.rx.prev_id == rx->xact_id) {
- BT_WARN("Resending ack");
- gen_prov_ack_send(rx->xact_id);
- return;
- }
-
- trailing_space = OS_MBUF_TRAILINGSPACE(link.rx.buf);
-
- link.rx.buf->om_len = net_buf_simple_pull_be16(buf);
- link.rx.id = rx->xact_id;
- link.rx.fcs = net_buf_simple_pull_u8(buf);
-
- BT_DBG("len %u last_seg %u total_len %u fcs 0x%02x", buf->om_len,
- START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs);
-
- if (link.rx.buf->om_len < 1) {
- BT_ERR("Ignoring zero-length provisioning PDU");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
+ BT_ERR("bt_mesh_prov->link_open");
+ if (bt_mesh_prov->link_open) {
+ bt_mesh_prov->link_open(bearer->type);
}
- if (link.rx.buf->om_len > trailing_space) {
- BT_ERR("Too large provisioning PDU (%u bytes)",
- link.rx.buf->om_len);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20) {
- BT_ERR("Too small total length for multi-segment PDU");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- link.rx.seg = (1 << (START_LAST_SEG(rx->gpc) + 1)) - 1;
- link.rx.last_seg = START_LAST_SEG(rx->gpc);
- memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len);
- XACT_SEG_RECV(0);
-
- if (!link.rx.seg) {
- prov_msg_recv();
- }
-}
-
-static const struct {
- void (*func)(struct prov_rx *rx, struct os_mbuf *buf);
- bool require_link;
- u8_t min_len;
-} gen_prov[] = {
- { gen_prov_start, true, 3 },
- { gen_prov_ack, true, 0 },
- { gen_prov_cont, true, 0 },
- { gen_prov_ctl, false, 0 },
-};
-
-static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf)
-{
- if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) {
- BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
- return;
- }
+ BT_ERR("bt_mesh_prov_link.bearer");
+ bt_mesh_prov_link.bearer = bearer;
- if (!atomic_test_bit(link.flags, LINK_ACTIVE) &&
- gen_prov[GPCF(rx->gpc)].require_link) {
- BT_DBG("Ignoring message that requires active link");
- return;
+ BT_ERR("bt_mesh_prov_link.role->link_opened");
+ BT_ERR("%p", bt_mesh_prov_link.role);
+ BT_ERR("%p", bt_mesh_prov_link.role->link_opened);
+ if (bt_mesh_prov_link.role->link_opened) {
+ bt_mesh_prov_link.role->link_opened();
}
-
- BT_DBG("prov_action: %d", GPCF(rx->gpc));
- gen_prov[GPCF(rx->gpc)].func(rx, buf);
+ BT_ERR("done");
}
-void bt_mesh_pb_adv_recv(struct os_mbuf *buf)
+static void prov_link_closed(const struct prov_bearer *bearer, void *cb_data,
+ enum prov_bearer_link_status reason)
{
- struct prov_rx rx;
-
- if (!bt_prov_active() && bt_mesh_is_provisioned()) {
- BT_DBG("Ignoring provisioning PDU - already provisioned");
- return;
+ if (bt_mesh_prov_link.role->link_closed) {
+ bt_mesh_prov_link.role->link_closed();
}
- if (buf->om_len < 6) {
- BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
- return;
+ if (bt_mesh_prov->link_close) {
+ bt_mesh_prov->link_close(bearer->type);
}
-
- rx.link_id = net_buf_simple_pull_be32(buf);
- rx.xact_id = net_buf_simple_pull_u8(buf);
- rx.gpc = net_buf_simple_pull_u8(buf);
-
- BT_DBG("link_id 0x%08x xact_id %u", (unsigned) rx.link_id, rx.xact_id);
-
- if (atomic_test_bit(link.flags, LINK_ACTIVE) && link.id != rx.link_id) {
- BT_DBG("Ignoring mesh beacon for unknown link");
- return;
- }
-
- gen_prov_recv(&rx, buf);
}
-int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration)
+static void prov_bearer_error(const struct prov_bearer *bearer, void *cb_data,
+ uint8_t err)
{
- BT_DBG("uuid %s", bt_hex(uuid, 16));
-
- if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
- return -EBUSY;
+ if (bt_mesh_prov_link.role->error) {
+ bt_mesh_prov_link.role->error(err);
}
-
- atomic_set_bit(link.flags, PROVISIONER);
-
- bt_rand(&link.id, sizeof(link.id));
- link.tx.id = 0x7F;
- link.provisioner->addr = addr;
- link.provisioner->net_idx = net_idx;
- link.provisioner->attention_duration = attention_duration;
-
- net_buf_simple_init(link.rx.buf, 0);
-
- bearer_ctl_send(LINK_OPEN, uuid, 16);
-
- return 0;
}
-#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
+static const struct prov_bearer_cb prov_bearer_cb = {
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_bearer_error,
+ .recv = prov_recv,
+};
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf)
+const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void)
{
- u8_t type;
-
- BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
-
- if (link.conn_handle != conn_handle) {
- BT_WARN("Data for unexpected connection");
- return -ENOTCONN;
- }
-
- if (buf->om_len < 1) {
- BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
- return -EINVAL;
- }
-
- type = net_buf_simple_pull_u8(buf);
- if (type != PROV_FAILED && type != link.expect) {
- BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return -EINVAL;
- }
-
- if (type >= ARRAY_SIZE(prov_handlers)) {
- BT_ERR("Unknown provisioning PDU type 0x%02x", type);
- return -EINVAL;
- }
-
- if (prov_handlers[type].len != buf->om_len) {
- BT_ERR("Invalid length %u for type 0x%02x", buf->om_len, type);
- return -EINVAL;
- }
-
- prov_handlers[type].func(buf->om_data);
-
- return 0;
+ return &prov_bearer_cb;
}
-int bt_mesh_pb_gatt_open(uint16_t conn_handle)
+void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr)
{
- BT_DBG("conn_handle %d", conn_handle);
-
- if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
- BT_ERR("Link already opened?");
- return -EBUSY;
- }
-
- link.conn_handle = conn_handle;
- link.expect = PROV_INVITE;
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_GATT);
+ if (bt_mesh_prov->complete) {
+ bt_mesh_prov->complete(net_idx, addr);
}
-
- return 0;
}
-int bt_mesh_pb_gatt_close(uint16_t conn_handle)
+void bt_mesh_prov_reset(void)
{
- BT_DBG("conn_handle %d", conn_handle);
+ BT_DBG("bt_mesh_prov_reset");
- if (link.conn_handle != conn_handle) {
- BT_ERR("Not connected");
- return -ENOTCONN;
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+ pb_adv_reset();
}
- if (prov->link_close) {
- prov->link_close(BT_MESH_PROV_GATT);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+ pb_gatt_reset();
}
- return reset_state();
-}
-#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
-
-const struct bt_mesh_prov *bt_mesh_prov_get(void)
-{
- return prov;
-}
-
-bool bt_prov_active(void)
-{
- return atomic_test_bit(link.flags, LINK_ACTIVE);
-}
-
-static void protocol_timeout(struct ble_npl_event *work)
-{
- BT_DBG("Protocol timeout");
+ bt_mesh_prov_reset_state(NULL);
-#if MYNEWT_VAL(BLE_MESH_PB_GATT)
- if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- bt_mesh_pb_gatt_close(link.conn_handle);
- return;
+ if (bt_mesh_prov->reset) {
+ bt_mesh_prov->reset();
}
-#endif
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- u8_t reason = CLOSE_REASON_TIMEOUT;
-
- link.rx.seg = 0U;
- bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
-
- reset_state();
-#endif
}
int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
@@ -1961,48 +363,14 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
return -EINVAL;
}
- k_delayed_work_init(&link.prot_timer, protocol_timeout);
-
- prov = prov_info;
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
-#endif
-
- return reset_state();
-}
-
-void bt_mesh_prov_reset_link(void)
-{
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.rx.buf = bt_mesh_proxy_get_buf();
-#else
- net_buf_simple_init(rx_buf, 0);
- link.rx.buf = rx_buf;
-#endif
-#endif
-}
+ bt_mesh_prov = prov_info;
-void bt_mesh_prov_complete(u16_t net_idx, u16_t addr)
-{
- if (prov->complete) {
- prov->complete(net_idx, addr);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+ pb_adv_init();
}
-}
-
-void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
-{
- if (prov->node_added) {
- prov->node_added(net_idx, addr, num_elem);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+ pb_gatt_init();
}
-}
-void bt_mesh_prov_reset(void)
-{
- if (prov->reset) {
- prov->reset();
- }
+ return bt_mesh_prov_reset_state(NULL);
}
-
-#endif /* MYNEWT_VAL(BLE_MESH_PROV) */
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h
index 96e5a447..89f02725 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h
@@ -9,16 +9,131 @@
#ifndef __PROV_H__
#define __PROV_H__
+#include "prov_bearer.h"
#include "os/os_mbuf.h"
#include "mesh/mesh.h"
#include "../src/ble_hs_conn_priv.h"
-int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration);
+#define PROV_ERR_NONE 0x00
+#define PROV_ERR_NVAL_PDU 0x01
+#define PROV_ERR_NVAL_FMT 0x02
+#define PROV_ERR_UNEXP_PDU 0x03
+#define PROV_ERR_CFM_FAILED 0x04
+#define PROV_ERR_RESOURCES 0x05
+#define PROV_ERR_DECRYPT 0x06
+#define PROV_ERR_UNEXP_ERR 0x07
+#define PROV_ERR_ADDR 0x08
-void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
+#define AUTH_METHOD_NO_OOB 0x00
+#define AUTH_METHOD_STATIC 0x01
+#define AUTH_METHOD_OUTPUT 0x02
+#define AUTH_METHOD_INPUT 0x03
+
+#define OUTPUT_OOB_BLINK 0x00
+#define OUTPUT_OOB_BEEP 0x01
+#define OUTPUT_OOB_VIBRATE 0x02
+#define OUTPUT_OOB_NUMBER 0x03
+#define OUTPUT_OOB_STRING 0x04
+
+#define INPUT_OOB_PUSH 0x00
+#define INPUT_OOB_TWIST 0x01
+#define INPUT_OOB_NUMBER 0x02
+#define INPUT_OOB_STRING 0x03
+
+#define PUB_KEY_NO_OOB 0x00
+#define PUB_KEY_OOB 0x01
+
+#define PROV_INVITE 0x00
+#define PROV_CAPABILITIES 0x01
+#define PROV_START 0x02
+#define PROV_PUB_KEY 0x03
+#define PROV_INPUT_COMPLETE 0x04
+#define PROV_CONFIRM 0x05
+#define PROV_RANDOM 0x06
+#define PROV_DATA 0x07
+#define PROV_COMPLETE 0x08
+#define PROV_FAILED 0x09
+
+#define PROV_NO_PDU 0xff
+
+#define PROV_ALG_P256 0x00
+
+#define PROV_BUF(len) \
+ NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + len)
+
+enum {
+ WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
+ LINK_ACTIVE, /* Link has been opened */
+ WAIT_NUMBER, /* Waiting for number input from user */
+ WAIT_STRING, /* Waiting for string input from user */
+ NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */
+ PROVISIONER, /* The link was opened as provisioner */
+ OOB_PUB_KEY, /* OOB Public key used */
+ PUB_KEY_SENT, /* Public key has been sent */
+ REMOTE_PUB_KEY, /* Remote key has been received */
+ INPUT_COMPLETE, /* Device input completed */
+ WAIT_CONFIRM, /* Wait for send confirm */
+ WAIT_AUTH, /* Wait for auth response */
+ OOB_STATIC_KEY, /* OOB Static Authentication */
+
+ NUM_FLAGS,
+};
+
+/** Provisioning role */
+struct bt_mesh_prov_role {
+ void (*link_opened)(void);
+
+ void (*link_closed)(void);
+
+ void (*error)(uint8_t reason);
+
+ void (*input_complete)(void);
+
+ void (*op[10])(const uint8_t *data);
+};
+
+struct bt_mesh_prov_link {
+ ATOMIC_DEFINE(flags, NUM_FLAGS);
-bool bt_prov_active(void);
+ const struct prov_bearer *bearer;
+ const struct bt_mesh_prov_role *role;
+
+ uint8_t oob_method; /* Authen method */
+ uint8_t oob_action; /* Authen action */
+ uint8_t oob_size; /* Authen size */
+ uint8_t auth[16]; /* Authen value */
+
+ uint8_t dhkey[32]; /* Calculated DHKey */
+ uint8_t expect; /* Next expected PDU */
+ uint8_t conf[16]; /* Remote Confirmation */
+ uint8_t rand[16]; /* Local Random */
+
+ uint8_t conf_salt[16]; /* ConfirmationSalt */
+ uint8_t conf_key[16]; /* ConfirmationKey */
+ uint8_t conf_inputs[145]; /* ConfirmationInputs */
+ uint8_t prov_salt[16]; /* Provisioning Salt */
+};
+
+extern struct bt_mesh_prov_link bt_mesh_prov_link;
+extern const struct bt_mesh_prov *bt_mesh_prov;
+
+static inline int bt_mesh_prov_send(struct os_mbuf *buf,
+ prov_bearer_send_complete_t cb)
+{
+ return bt_mesh_prov_link.bearer->send(buf, cb, NULL);
+}
+
+static inline void bt_mesh_prov_buf_init(struct os_mbuf *buf, uint8_t type)
+{
+ net_buf_reserve(buf, PROV_BEARER_BUF_HEADROOM);
+ net_buf_simple_add_u8(buf, type);
+}
+
+int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64]));
+
+bool bt_mesh_prov_active(void);
+
+int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size);
int bt_mesh_pb_gatt_open(uint16_t conn_handle);
int bt_mesh_pb_gatt_close(uint16_t conn_handle);
@@ -26,12 +141,14 @@ int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf);
const struct bt_mesh_prov *bt_mesh_prov_get(void);
-int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
-
void bt_mesh_prov_reset_link(void);
-void bt_mesh_prov_complete(u16_t net_idx, u16_t addr);
-void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem);
+void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr);
void bt_mesh_prov_reset(void);
+const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void);
+
+void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
+
+int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h
new file mode 100644
index 00000000..3e526831
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h
@@ -0,0 +1,116 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define PROTOCOL_TIMEOUT K_SECONDS(60)
+
+/** @def PROV_BEARER_BUF_HEADROOM
+ *
+ * @brief Required headroom for the bearer packet buffers.
+ */
+#if MYNEWT_VAL(BLE_MESH_PB_GATT)
+#define PROV_BEARER_BUF_HEADROOM 5
+#else
+#define PROV_BEARER_BUF_HEADROOM 0
+#endif
+
+enum prov_bearer_link_status {
+ PROV_BEARER_LINK_STATUS_SUCCESS,
+ PROV_BEARER_LINK_STATUS_TIMEOUT,
+ PROV_BEARER_LINK_STATUS_FAIL,
+};
+
+struct prov_bearer;
+
+/** Callbacks from bearer to host */
+struct prov_bearer_cb {
+
+ void (*link_opened)(const struct prov_bearer *bearer, void *cb_data);
+
+ void (*link_closed)(const struct prov_bearer *bearer, void *cb_data,
+ enum prov_bearer_link_status reason);
+
+ void (*error)(const struct prov_bearer *bearer, void *cb_data,
+ uint8_t err);
+
+ void (*recv)(const struct prov_bearer *bearer, void *cb_data,
+ struct os_mbuf *buf);
+};
+
+typedef void (*prov_bearer_send_complete_t)(int err, void *cb_data);
+
+/** Provisioning bearer API */
+struct prov_bearer {
+ /** Provisioning bearer type. */
+ bt_mesh_prov_bearer_t type;
+
+ /** @brief Enable link establishment as a provisionee.
+ *
+ * Prompts the bearer to make itself visible to provisioners, and
+ * start accepting link open messages.
+ *
+ * @param cb Bearer event callbacks used for the duration of the link.
+ * @param cb_data Context parameter to pass to the bearer callbacks.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*link_accept)(const struct prov_bearer_cb *cb, void *cb_data);
+
+ /** @brief Send a packet on an established link.
+ *
+ * @param buf Payload buffer. Requires @ref
+ * PROV_BEARER_BUF_HEADROOM bytes of headroom.
+ * @param cb Callback to call when sending is complete.
+ * @param cb_data Callback data.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*send)(struct os_mbuf *buf, prov_bearer_send_complete_t cb,
+ void *cb_data);
+
+ /** @brief Clear any ongoing transmissions, if possible.
+ *
+ * Bearers that don't support tx clearing must implement this callback
+ * and leave it empty.
+ */
+ void (*clear_tx)(void);
+
+ /* Only available in provisioners: */
+
+ /** @brief Open a new link as a provisioner.
+ *
+ * Only available in provisioners. Bearers that don't support the
+ * provisioner role should leave this as NULL.
+ *
+ * @param uuid UUID of the node to establish a link to.
+ * @param timeout Protocol timeout.
+ * @param cb Bearer event callbacks used for the duration of the link.
+ * @param cb_data Context parameter to pass to the bearer callbacks.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*link_open)(const uint8_t uuid[16], int32_t timeout,
+ const struct prov_bearer_cb *cb, void *cb_data);
+
+ /** @brief Close the current link.
+ *
+ * Only available in provisioners. Bearers that don't support the
+ * provisioner role should leave this as NULL.
+ *
+ * @param status Link status for the link close message.
+ */
+ void (*link_close)(enum prov_bearer_link_status status);
+};
+
+extern const struct prov_bearer pb_adv;
+extern const struct prov_bearer pb_gatt;
+
+void pb_adv_init(void);
+void pb_gatt_init(void);
+
+void pb_adv_reset(void);
+void pb_gatt_reset(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c
new file mode 100644
index 00000000..38a96e7a
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c
@@ -0,0 +1,569 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include "testing.h"
+#include "crypto.h"
+#include "adv.h"
+#include "mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "prov.h"
+#include "settings.h"
+
+static void send_pub_key(void);
+static void pub_key_ready(const uint8_t *pkey);
+
+static int reset_state(void)
+{
+ return bt_mesh_prov_reset_state(pub_key_ready);
+}
+
+static void prov_send_fail_msg(uint8_t err)
+{
+ struct os_mbuf *buf = PROV_BUF(2);
+
+ BT_DBG("%u", err);
+
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ bt_mesh_prov_buf_init(buf, PROV_FAILED);
+ net_buf_simple_add_u8(buf, err);
+
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send Provisioning Failed message");
+ }
+}
+
+static void prov_fail(uint8_t reason)
+{
+ /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
+ * provisioner just closes the link when something fails, while the
+ * provisionee sends the fail message, and waits for the provisioner to
+ * close the link.
+ */
+ prov_send_fail_msg(reason);
+}
+
+static void prov_invite(const uint8_t *data)
+{
+ struct os_mbuf *buf = PROV_BUF(12);
+
+ BT_DBG("Attention Duration: %u seconds", data[0]);
+
+ if (data[0]) {
+ bt_mesh_attention(NULL, data[0]);
+ }
+
+ bt_mesh_prov_link.conf_inputs[0] = data[0];
+
+ bt_mesh_prov_buf_init(buf, PROV_CAPABILITIES);
+
+ /* Number of Elements supported */
+ net_buf_simple_add_u8(buf, bt_mesh_elem_count());
+
+ /* Supported algorithms - FIPS P-256 Eliptic Curve */
+ net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256));
+
+ /* Public Key Type, Only "No OOB" Public Key is supported */
+ net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB);
+
+ /* Static OOB Type */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->static_val ? BIT(0) : 0x00);
+
+ /* Output OOB Size */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->output_size);
+
+ /* Output OOB Action */
+ net_buf_simple_add_be16(buf, bt_mesh_prov->output_actions);
+
+ /* Input OOB Size */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->input_size);
+
+ /* Input OOB Action */
+ net_buf_simple_add_be16(buf, bt_mesh_prov->input_actions);
+
+ memcpy(&bt_mesh_prov_link.conf_inputs[1], &buf->om_data[1], 11);
+
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send capabilities");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_START;
+}
+
+static void prov_start(const uint8_t *data)
+{
+ BT_DBG("Algorithm: 0x%02x", data[0]);
+ BT_DBG("Public Key: 0x%02x", data[1]);
+ BT_DBG("Auth Method: 0x%02x", data[2]);
+ BT_DBG("Auth Action: 0x%02x", data[3]);
+ BT_DBG("Auth Size: 0x%02x", data[4]);
+
+ if (data[0] != PROV_ALG_P256) {
+ BT_ERR("Unknown algorithm 0x%02x", data[0]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (data[1] != PUB_KEY_NO_OOB) {
+ BT_ERR("Invalid public key type: 0x%02x", data[1]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ memcpy(&bt_mesh_prov_link.conf_inputs[12], data, 5);
+
+ bt_mesh_prov_link.expect = PROV_PUB_KEY;
+
+ if (bt_mesh_prov_auth(data[2], data[3], data[4]) < 0) {
+ BT_ERR("Invalid authentication method: 0x%02x; "
+ "action: 0x%02x; size: 0x%02x", data[2], data[3],
+ data[4]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ }
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY)) {
+ memcpy(bt_mesh_prov_link.auth + 16 - bt_mesh_prov->static_val_len,
+ bt_mesh_prov->static_val, bt_mesh_prov->static_val_len);
+ (void)memset(bt_mesh_prov_link.auth, 0,
+ sizeof(bt_mesh_prov_link.auth) - bt_mesh_prov->static_val_len);
+ }
+}
+
+static void send_confirm(void)
+{
+ struct os_mbuf *cfm = PROV_BUF(17);
+
+ BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64));
+ BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64));
+ BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17));
+
+ if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs,
+ bt_mesh_prov_link.conf_salt)) {
+ BT_ERR("Unable to generate confirmation salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16));
+
+ if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey, bt_mesh_prov_link.conf_salt,
+ bt_mesh_prov_link.conf_key)) {
+ BT_ERR("Unable to generate confirmation key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16));
+
+ if (bt_rand(bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Unable to generate random number");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16));
+
+ bt_mesh_prov_buf_init(cfm, PROV_CONFIRM);
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, bt_mesh_prov_link.rand,
+ bt_mesh_prov_link.auth, net_buf_simple_add(cfm, 16))) {
+ BT_ERR("Unable to generate confirmation value");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (bt_mesh_prov_send(cfm, NULL)) {
+ BT_ERR("Failed to send Provisioning Confirm");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_RANDOM;
+
+}
+
+static void send_input_complete(void)
+{
+ struct os_mbuf *buf = PROV_BUF(1);
+
+ bt_mesh_prov_buf_init(buf, PROV_INPUT_COMPLETE);
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send Provisioning Input Complete");
+ }
+ bt_mesh_prov_link.expect = PROV_CONFIRM;
+}
+
+static void public_key_sent(int err, void *cb_data)
+{
+ atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT);
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE)) {
+ send_input_complete();
+ return;
+ }
+}
+
+static void send_pub_key(void)
+{
+ struct os_mbuf *buf = PROV_BUF(65);
+ const uint8_t *key;
+
+ key = bt_pub_key_get();
+ if (!key) {
+ BT_ERR("No public key available");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Local Public Key: %s", bt_hex(key, 64));
+
+ bt_mesh_prov_buf_init(buf, PROV_PUB_KEY);
+
+ /* Swap X and Y halves independently to big-endian */
+ sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
+ sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
+
+ /* PublicKeyRemote */
+ memcpy(&bt_mesh_prov_link.conf_inputs[81], &buf->om_data[1], 64);
+
+ if (bt_mesh_prov_send(buf, public_key_sent)) {
+ BT_ERR("Failed to send Public Key");
+ return;
+ }
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) ||
+ atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING)) {
+ bt_mesh_prov_link.expect = PROV_NO_PDU; /* Wait for input */
+ } else {
+ bt_mesh_prov_link.expect = PROV_CONFIRM;
+ }
+}
+
+static void prov_dh_key_cb(const uint8_t dhkey[32])
+{
+ BT_DBG("%p", dhkey);
+
+ if (!dhkey) {
+ BT_ERR("DHKey generation failed");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32);
+
+ BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32));
+
+ send_pub_key();
+}
+
+static void prov_dh_key_gen(void)
+{
+ uint8_t remote_pk_le[64], *remote_pk;
+
+ remote_pk = &bt_mesh_prov_link.conf_inputs[17];
+
+ /* Copy remote key in little-endian for bt_dh_key_gen().
+ * X and Y halves are swapped independently. The bt_dh_key_gen()
+ * will also take care of validating the remote public key.
+ */
+ sys_memcpy_swap(remote_pk_le, remote_pk, 32);
+ sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
+
+ if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
+ BT_ERR("Failed to generate DHKey");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ }
+}
+
+static void prov_pub_key(const uint8_t *data)
+{
+ BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
+
+ /* PublicKeyProvisioner */
+ memcpy(&bt_mesh_prov_link.conf_inputs[17], data, 64);
+
+ if (!bt_pub_key_get()) {
+ /* Clear retransmit timer */
+ bt_mesh_prov_link.bearer->clear_tx();
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
+ BT_WARN("Waiting for local public key");
+ return;
+ }
+
+ prov_dh_key_gen();
+}
+
+static void pub_key_ready(const uint8_t *pkey)
+{
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+
+ BT_DBG("Local public key ready");
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
+ prov_dh_key_gen();
+ }
+}
+
+static void notify_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
+ NOTIFY_INPUT_COMPLETE) &&
+ bt_mesh_prov->input_complete) {
+ bt_mesh_prov->input_complete();
+ }
+}
+
+static void send_random(void)
+{
+ struct os_mbuf *rnd = PROV_BUF(17);
+
+ bt_mesh_prov_buf_init(rnd, PROV_RANDOM);
+ net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16);
+
+ if (bt_mesh_prov_send(rnd, NULL)) {
+ BT_ERR("Failed to send Provisioning Random");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_DATA;
+}
+
+static void prov_random(const uint8_t *data)
+{
+ uint8_t conf_verify[16];
+
+ BT_DBG("Remote Random: %s", bt_hex(data, 16));
+ if (!memcmp(data, bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Random value is identical to ours, rejecting.");
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, data,
+ bt_mesh_prov_link.auth, conf_verify)) {
+ BT_ERR("Unable to calculate confirmation verification");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) {
+ BT_ERR("Invalid confirmation value");
+ BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16));
+ BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt, data,
+ bt_mesh_prov_link.rand, bt_mesh_prov_link.prov_salt)) {
+ BT_ERR("Failed to generate provisioning salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16));
+
+ send_random();
+}
+
+static void prov_confirm(const uint8_t *data)
+{
+ BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
+
+ memcpy(bt_mesh_prov_link.conf, data, 16);
+
+ notify_input_complete();
+
+ send_confirm();
+}
+
+static inline bool is_pb_gatt(void)
+{
+ return bt_mesh_prov_link.bearer &&
+ bt_mesh_prov_link.bearer->type == BT_MESH_PROV_GATT;
+}
+
+static void prov_data(const uint8_t *data)
+{
+ struct os_mbuf *msg = PROV_BUF(1);
+ uint8_t session_key[16];
+ uint8_t nonce[13];
+ uint8_t dev_key[16];
+ uint8_t pdu[25];
+ uint8_t flags;
+ uint32_t iv_index;
+ uint16_t addr;
+ uint16_t net_idx;
+ int err;
+ bool identity_enable;
+
+ BT_DBG("");
+
+ err = bt_mesh_session_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, session_key);
+ if (err) {
+ BT_ERR("Unable to generate session key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
+
+ err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, nonce);
+ if (err) {
+ BT_ERR("Unable to generate session nonce");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Nonce: %s", bt_hex(nonce, 13));
+
+ err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
+ if (err) {
+ BT_ERR("Unable to decrypt provisioning data");
+ prov_fail(PROV_ERR_DECRYPT);
+ return;
+ }
+
+ err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, dev_key);
+ if (err) {
+ BT_ERR("Unable to generate device key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("DevKey: %s", bt_hex(dev_key, 16));
+
+ net_idx = sys_get_be16(&pdu[16]);
+ flags = pdu[18];
+ iv_index = sys_get_be32(&pdu[19]);
+ addr = sys_get_be16(&pdu[23]);
+
+ BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
+ net_idx, iv_index, addr);
+
+ bt_mesh_prov_buf_init(msg, PROV_COMPLETE);
+ if (bt_mesh_prov_send(msg, NULL)) {
+ BT_ERR("Failed to send Provisioning Complete");
+ return;
+ }
+
+ /* Ignore any further PDUs on this link */
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ /* Store info, since bt_mesh_provision() will end up clearing it */
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ identity_enable = is_pb_gatt();
+ } else {
+ identity_enable = false;
+ }
+
+ err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
+ if (err) {
+ BT_ERR("Failed to provision (err %d)", err);
+ return;
+ }
+
+ /* After PB-GATT provisioning we should start advertising
+ * using Node Identity.
+ */
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) {
+ bt_mesh_proxy_identity_enable();
+ }
+}
+
+static void local_input_complete(void)
+{
+ if (atomic_test_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT)) {
+ send_input_complete();
+ } else {
+ atomic_set_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE);
+ }
+}
+
+static void prov_link_closed(void)
+{
+ reset_state();
+}
+
+static void prov_link_opened(void)
+{
+ bt_mesh_prov_link.expect = PROV_INVITE;
+}
+
+static const struct bt_mesh_prov_role role_device = {
+ .input_complete = local_input_complete,
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_fail,
+ .op = {
+ [PROV_INVITE] = prov_invite,
+ [PROV_START] = prov_start,
+ [PROV_PUB_KEY] = prov_pub_key,
+ [PROV_CONFIRM] = prov_confirm,
+ [PROV_RANDOM] = prov_random,
+ [PROV_DATA] = prov_data,
+ },
+};
+
+int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
+{
+ BT_DBG("bt_mesh_prov_enable");
+
+ if (bt_mesh_is_provisioned()) {
+ return -EALREADY;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
+ (bearers & BT_MESH_PROV_ADV)) {
+ pb_adv.link_accept(bt_mesh_prov_bearer_cb_get(), NULL);
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+ (bearers & BT_MESH_PROV_GATT)) {
+ pb_gatt.link_accept(bt_mesh_prov_bearer_cb_get(), NULL);
+ }
+
+ BT_DBG("bt_mesh_prov_link.role = &role_device");
+ bt_mesh_prov_link.role = &role_device;
+
+ return 0;
+}
+
+int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
+{
+ if (bt_mesh_is_provisioned()) {
+ return -EALREADY;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
+ (bearers & BT_MESH_PROV_ADV)) {
+ bt_mesh_beacon_disable();
+ bt_mesh_scan_disable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+ (bearers & BT_MESH_PROV_GATT)) {
+ bt_mesh_proxy_prov_disable(true);
+ }
+
+ return 0;
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c
new file mode 100644
index 00000000..371c1f6c
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c
@@ -0,0 +1,746 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include "testing.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "prov.h"
+#include "settings.h"
+
+static struct {
+ struct bt_mesh_cdb_node *node;
+ uint16_t addr;
+ uint16_t net_idx;
+ uint8_t attention_duration;
+ uint8_t uuid[16];
+} prov_device;
+
+static void send_pub_key(void);
+static void prov_dh_key_gen(void);
+static void pub_key_ready(const uint8_t *pkey);
+
+static int reset_state(void)
+{
+#if BLE_MESH_CDB
+ if (prov_device.node != NULL) {
+ bt_mesh_cdb_node_del(prov_device.node, false);
+ }
+#endif
+ return bt_mesh_prov_reset_state(pub_key_ready);
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+ BT_DBG("%u", status);
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ bt_mesh_prov_link.bearer->link_close(status);
+}
+
+static void prov_fail(uint8_t reason)
+{
+ /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
+ * provisioner just closes the link when something fails, while the
+ * provisionee sends the fail message, and waits for the provisioner to
+ * close the link.
+ */
+ prov_link_close(PROV_BEARER_LINK_STATUS_FAIL);
+}
+
+static void send_invite(void)
+{
+ struct os_mbuf *inv = PROV_BUF(2);
+
+ BT_DBG("");
+
+ bt_mesh_prov_buf_init(inv, PROV_INVITE);
+ net_buf_simple_add_u8(inv, prov_device.attention_duration);
+
+ bt_mesh_prov_link.conf_inputs[0] = prov_device.attention_duration;
+
+ if (bt_mesh_prov_send(inv, NULL)) {
+ BT_ERR("Failed to send invite");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_CAPABILITIES;
+}
+
+static void start_sent(int err, void *cb_data)
+{
+ if (!bt_pub_key_get()) {
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
+ BT_WARN("Waiting for local public key");
+ } else {
+ send_pub_key();
+ }
+}
+
+static void send_start(void)
+{
+ BT_DBG("");
+ uint8_t method, action;
+ struct os_mbuf *start = PROV_BUF(6);
+
+ const uint8_t *data = &bt_mesh_prov_link.conf_inputs[1 + 3];
+
+ bt_mesh_prov_buf_init(start, PROV_START);
+ net_buf_simple_add_u8(start, PROV_ALG_P256);
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY) &&
+ *data == PUB_KEY_OOB) {
+ net_buf_simple_add_u8(start, PUB_KEY_OOB);
+ atomic_set_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY);
+ } else {
+ net_buf_simple_add_u8(start, PUB_KEY_NO_OOB);
+ }
+
+ if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) {
+ method = AUTH_METHOD_OUTPUT;
+ if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) {
+ action = OUTPUT_OOB_STRING;
+ } else {
+ action = OUTPUT_OOB_NUMBER;
+ }
+
+ } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) {
+ method = AUTH_METHOD_INPUT;
+ if (bt_mesh_prov_link.oob_action == OUTPUT_OOB_STRING) {
+ action = INPUT_OOB_STRING;
+ } else {
+ action = INPUT_OOB_NUMBER;
+ }
+ } else {
+ method = bt_mesh_prov_link.oob_method;
+ action = 0x00;
+ }
+
+ net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_method);
+
+ net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_action);
+
+ net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_size);
+
+ memcpy(&bt_mesh_prov_link.conf_inputs[12], &start->om_data[1], 5);
+
+ if (bt_mesh_prov_auth(method, action, bt_mesh_prov_link.oob_size) < 0) {
+ BT_ERR("Invalid authentication method: 0x%02x; "
+ "action: 0x%02x; size: 0x%02x", method,
+ action, bt_mesh_prov_link.oob_size);
+ return;
+ }
+
+ if (bt_mesh_prov_send(start, start_sent)) {
+ BT_ERR("Failed to send Provisioning Start");
+ return;
+ }
+}
+
+static bool prov_check_method(struct bt_mesh_dev_capabilities *caps)
+{
+ if (bt_mesh_prov_link.oob_method == AUTH_METHOD_STATIC) {
+ if (!caps->static_oob) {
+ BT_WARN("Device not support OOB static authentication provisioning");
+ return false;
+ }
+ } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) {
+ if (bt_mesh_prov_link.oob_size > caps->input_size) {
+ BT_WARN("The required input length (0x%02x) "
+ "exceeds the device capacity (0x%02x)",
+ bt_mesh_prov_link.oob_size, caps->input_size);
+ return false;
+ }
+
+ if (!(BIT(bt_mesh_prov_link.oob_action) & caps->input_actions)) {
+ BT_WARN("The required input action (0x%02x) "
+ "not supported by the device (0x%02x)",
+ bt_mesh_prov_link.oob_action, caps->input_actions);
+ return false;
+ }
+
+ if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) {
+ if (!bt_mesh_prov->output_string) {
+ BT_WARN("Not support output string");
+ return false;
+ }
+ } else {
+ if (!bt_mesh_prov->output_number) {
+ BT_WARN("Not support output number");
+ return false;
+ }
+ }
+ } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) {
+ if (bt_mesh_prov_link.oob_size > caps->output_size) {
+ BT_WARN("The required output length (0x%02x) "
+ "exceeds the device capacity (0x%02x)",
+ bt_mesh_prov_link.oob_size, caps->output_size);
+ return false;
+ }
+
+ if (!(BIT(bt_mesh_prov_link.oob_action) & caps->output_actions)) {
+ BT_WARN("The required output action (0x%02x) "
+ "not supported by the device (0x%02x)",
+ bt_mesh_prov_link.oob_action, caps->output_actions);
+ return false;
+ }
+
+ if (!bt_mesh_prov->input) {
+ BT_WARN("Not support input");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void prov_capabilities(const uint8_t *data)
+{
+ struct bt_mesh_dev_capabilities caps;
+
+ caps.elem_count = data[0];
+ BT_DBG("Elements: %u", caps.elem_count);
+
+ caps.algorithms = sys_get_be16(&data[1]);
+ BT_DBG("Algorithms: %u", caps.algorithms);
+
+ caps.pub_key_type = data[3];
+ caps.static_oob = data[4];
+ caps.output_size = data[5];
+ BT_DBG("Public Key Type: 0x%02x", caps.pub_key_type);
+ BT_DBG("Static OOB Type: 0x%02x", caps.static_oob);
+ BT_DBG("Output OOB Size: %u", caps.output_size);
+
+ caps.output_actions = (bt_mesh_output_action_t)data[6];
+ caps.input_size = data[8];
+ caps.input_actions = (bt_mesh_input_action_t)data[9];
+ BT_DBG("Output OOB Action: 0x%04x", caps.output_actions);
+ BT_DBG("Input OOB Size: %u", caps.input_size);
+ BT_DBG("Input OOB Action: 0x%04x", caps.input_actions);
+
+ if (data[0] == 0) {
+ BT_ERR("Invalid number of elements");
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+#if BLE_MESH_CDB
+ prov_device.node =
+ bt_mesh_cdb_node_alloc(prov_device.uuid,
+ prov_device.addr, data[0],
+ prov_device.net_idx);
+ if (prov_device.node == NULL) {
+ BT_ERR("Failed allocating node 0x%04x", prov_device.addr);
+ prov_fail(PROV_ERR_RESOURCES);
+ return;
+ }
+#endif
+ memcpy(&bt_mesh_prov_link.conf_inputs[1], data, 11);
+
+ if (bt_mesh_prov->capabilities) {
+ bt_mesh_prov->capabilities(&caps);
+ }
+
+ if (!prov_check_method(&caps)) {
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ send_start();
+}
+
+static void send_confirm(void)
+{
+ struct os_mbuf *cfm = PROV_BUF(17);
+
+ BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64));
+ BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64));
+ BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17));
+
+ if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs,
+ bt_mesh_prov_link.conf_salt)) {
+ BT_ERR("Unable to generate confirmation salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16));
+
+ if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.conf_salt, bt_mesh_prov_link.conf_key)) {
+ BT_ERR("Unable to generate confirmation key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16));
+
+ if (bt_rand(bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Unable to generate random number");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16));
+
+ bt_mesh_prov_buf_init(cfm, PROV_CONFIRM);
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key,
+ bt_mesh_prov_link.rand, bt_mesh_prov_link.auth,
+ net_buf_simple_add(cfm, 16))) {
+ BT_ERR("Unable to generate confirmation value");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (bt_mesh_prov_send(cfm, NULL)) {
+ BT_ERR("Failed to send Provisioning Confirm");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_CONFIRM;
+}
+
+static void public_key_sent(int err, void *cb_data)
+{
+ atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT);
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY) &&
+ atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) {
+ prov_dh_key_gen();
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_PUB_KEY;
+}
+
+static void send_pub_key(void)
+{
+ struct os_mbuf *buf = PROV_BUF(65);
+ const uint8_t *key;
+
+ key = bt_pub_key_get();
+ if (!key) {
+ BT_ERR("No public key available");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Local Public Key: %s", bt_hex(key, 64));
+
+ bt_mesh_prov_buf_init(buf, PROV_PUB_KEY);
+
+ /* Swap X and Y halves independently to big-endian */
+ sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32);
+ sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32);
+
+ /* PublicKeyProvisioner */
+ memcpy(&bt_mesh_prov_link.conf_inputs[17], &buf->om_databuf[1], 64);
+
+ if (bt_mesh_prov_send(buf, public_key_sent)) {
+ BT_ERR("Failed to send Public Key");
+ return;
+ }
+}
+
+static void prov_dh_key_cb(const uint8_t dhkey[32])
+{
+ BT_DBG("%p", dhkey);
+
+ if (!dhkey) {
+ BT_ERR("DHKey generation failed");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32);
+
+ BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32));
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING) ||
+ atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) ||
+ atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM);
+ return;
+ }
+
+ send_confirm();
+}
+
+static void prov_dh_key_gen(void)
+{
+ uint8_t remote_pk_le[64], *remote_pk;
+
+ remote_pk = &bt_mesh_prov_link.conf_inputs[81];
+
+ /* Copy remote key in little-endian for bt_dh_key_gen().
+ * X and Y halves are swapped independently. The bt_dh_key_gen()
+ * will also take care of validating the remote public key.
+ */
+ sys_memcpy_swap(remote_pk_le, remote_pk, 32);
+ sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32);
+
+ if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
+ BT_ERR("Failed to generate DHKey");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ }
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
+ bt_mesh_prov_link.expect = PROV_INPUT_COMPLETE;
+ }
+}
+
+static void prov_pub_key(const uint8_t *data)
+{
+ BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
+
+ atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY);
+
+ /* PublicKeyDevice */
+ memcpy(&bt_mesh_prov_link.conf_inputs[81], data, 64);
+ bt_mesh_prov_link.bearer->clear_tx();
+
+ prov_dh_key_gen();
+}
+
+static void pub_key_ready(const uint8_t *pkey)
+{
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+
+ BT_DBG("Local public key ready");
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
+ send_pub_key();
+ }
+}
+
+static void notify_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
+ NOTIFY_INPUT_COMPLETE) &&
+ bt_mesh_prov->input_complete) {
+ bt_mesh_prov->input_complete();
+ }
+}
+
+static void prov_input_complete(const uint8_t *data)
+{
+ BT_DBG("");
+
+ notify_input_complete();
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) {
+ send_confirm();
+ }
+}
+
+static void send_prov_data(void)
+{
+ struct os_mbuf *pdu = PROV_BUF(34);
+#if BLE_MESH_CDB
+ struct bt_mesh_cdb_subnet *sub;
+#endif
+ uint8_t session_key[16];
+ uint8_t nonce[13];
+ int err;
+
+ err = bt_mesh_session_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, session_key);
+ if (err) {
+ BT_ERR("Unable to generate session key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
+
+ err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, nonce);
+ if (err) {
+ BT_ERR("Unable to generate session nonce");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Nonce: %s", bt_hex(nonce, 13));
+
+ err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, prov_device.node->dev_key);
+ if (err) {
+ BT_ERR("Unable to generate device key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("DevKey: %s", bt_hex(prov_device.node->dev_key, 16));
+#if BLE_MESH_CDB
+ sub = bt_mesh_cdb_subnet_get(prov_device.node->net_idx);
+ if (sub == NULL) {
+ BT_ERR("No subnet with net_idx %u",
+ prov_device.node->net_idx);
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+#endif
+ bt_mesh_prov_buf_init(pdu, PROV_DATA);
+#if BLE_MESH_CDB
+ net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net_key, 16);
+ net_buf_simple_add_be16(pdu, prov_device.node->net_idx);
+ net_buf_simple_add_u8(pdu, bt_mesh_cdb_subnet_flags(sub));
+ net_buf_simple_add_be32(pdu, bt_mesh_cdb.iv_index);
+#endif
+ net_buf_simple_add_be16(pdu, prov_device.node->addr);
+ net_buf_simple_add(pdu, 8); /* For MIC */
+
+ BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
+ prov_device.node->net_idx, bt_mesh.iv_index,
+ prov_device.node->addr);
+
+ err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1],
+ &pdu->om_data[1]);
+ if (err) {
+ BT_ERR("Unable to encrypt provisioning data");
+ prov_fail(PROV_ERR_DECRYPT);
+ return;
+ }
+
+ if (bt_mesh_prov_send(pdu, NULL)) {
+ BT_ERR("Failed to send Provisioning Data");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_COMPLETE;
+}
+
+static void prov_complete(const uint8_t *data)
+{
+ struct bt_mesh_cdb_node *node = prov_device.node;
+
+ BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
+ bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
+ node->addr);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+
+ prov_device.node = NULL;
+ prov_link_close(PROV_BEARER_LINK_STATUS_SUCCESS);
+
+ if (bt_mesh_prov->node_added) {
+ bt_mesh_prov->node_added(node->net_idx, node->uuid, node->addr,
+ node->num_elem);
+ }
+}
+
+static void send_random(void)
+{
+ struct os_mbuf *rnd = PROV_BUF(17);
+
+ bt_mesh_prov_buf_init(rnd, PROV_RANDOM);
+ net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16);
+
+ if (bt_mesh_prov_send(rnd, NULL)) {
+ BT_ERR("Failed to send Provisioning Random");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_RANDOM;
+}
+
+static void prov_random(const uint8_t *data)
+{
+ uint8_t conf_verify[16];
+
+ BT_DBG("Remote Random: %s", bt_hex(data, 16));
+ if (!memcmp(data, bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Random value is identical to ours, rejecting.");
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key,
+ data, bt_mesh_prov_link.auth, conf_verify)) {
+ BT_ERR("Unable to calculate confirmation verification");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) {
+ BT_ERR("Invalid confirmation value");
+ BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16));
+ BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt,
+ bt_mesh_prov_link.rand, data, bt_mesh_prov_link.prov_salt)) {
+ BT_ERR("Failed to generate provisioning salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16));
+
+ send_prov_data();
+}
+
+static void prov_confirm(const uint8_t *data)
+{
+ BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
+
+ memcpy(bt_mesh_prov_link.conf, data, 16);
+
+ send_random();
+}
+
+static void prov_failed(const uint8_t *data)
+{
+ BT_WARN("Error: 0x%02x", data[0]);
+ reset_state();
+}
+
+static void local_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) {
+ send_confirm();
+ }
+}
+
+static void prov_link_closed(void)
+{
+ reset_state();
+}
+
+static void prov_link_opened(void)
+{
+ send_invite();
+}
+
+static const struct bt_mesh_prov_role role_provisioner = {
+ .input_complete = local_input_complete,
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_fail,
+ .op = {
+ [PROV_CAPABILITIES] = prov_capabilities,
+ [PROV_PUB_KEY] = prov_pub_key,
+ [PROV_INPUT_COMPLETE] = prov_input_complete,
+ [PROV_CONFIRM] = prov_confirm,
+ [PROV_RANDOM] = prov_random,
+ [PROV_COMPLETE] = prov_complete,
+ [PROV_FAILED] = prov_failed,
+ },
+};
+
+static void prov_set_method(uint8_t method, uint8_t action, uint8_t size)
+{
+ bt_mesh_prov_link.oob_method = method;
+ bt_mesh_prov_link.oob_action = action;
+ bt_mesh_prov_link.oob_size = size;
+}
+
+int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size)
+{
+ if (!action || !size || size > 8) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_INPUT, find_msb_set(action) - 1, size);
+ return 0;
+}
+
+int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size)
+{
+ if (!action || !size || size > 8) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_OUTPUT, find_msb_set(action) - 1, size);
+ return 0;
+}
+
+int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size)
+{
+ if (!size || !static_val || size > 16) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_STATIC, 0, 0);
+
+ memcpy(bt_mesh_prov_link.auth + 16 - size, static_val, size);
+ if (size < 16) {
+ (void)memset(bt_mesh_prov_link.auth, 0,
+ sizeof(bt_mesh_prov_link.auth) - size);
+ }
+ return 0;
+}
+
+int bt_mesh_auth_method_set_none(void)
+{
+ prov_set_method(AUTH_METHOD_NO_OOB, 0, 0);
+ return 0;
+}
+
+int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64])
+{
+ if (public_key == NULL) {
+ return -EINVAL;
+ }
+
+ if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) {
+ return -EALREADY;
+ }
+
+ /* Swap X and Y halves independently to big-endian */
+ memcpy(&bt_mesh_prov_link.conf_inputs[81], public_key, 32);
+ memcpy(&bt_mesh_prov_link.conf_inputs[81 + 32], &public_key[32], 32);
+
+ return 0;
+}
+
+#if defined(CONFIG_BT_MESH_PB_ADV)
+int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
+{
+ int err;
+
+ if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ atomic_set_bit(bt_mesh_prov_link.flags, PROVISIONER);
+ memcpy(prov_device.uuid, uuid, 16);
+ prov_device.addr = addr;
+ prov_device.net_idx = net_idx;
+ prov_device.attention_duration = attention_duration;
+ bt_mesh_prov_link.bearer = &pb_adv;
+ bt_mesh_prov_link.role = &role_provisioner;
+
+ err = bt_mesh_prov_link.bearer->link_open(prov_device.uuid, PROTOCOL_TIMEOUT,
+ bt_mesh_prov_bearer_cb_get(), NULL);
+ if (err) {
+ atomic_clear_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
+ }
+
+ return err;
+}
+#endif \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h
new file mode 100644
index 00000000..ccda47ef
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h
@@ -0,0 +1,10 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration); \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c
index 134a36dd..6d631b72 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c
@@ -19,6 +19,7 @@
#include "mesh_priv.h"
#include "adv.h"
#include "net.h"
+#include "rpl.h"
#include "prov.h"
#include "beacon.h"
#include "foundation.h"
@@ -28,6 +29,9 @@
#define PDU_TYPE(data) (data[0] & BIT_MASK(6))
#define PDU_SAR(data) (data[0] >> 6)
+#define BT_UUID_16_ENCODE(w16) \
+ (((w16) >> 0) & 0xFF), \
+ (((w16) >> 8) & 0xFF)
/* Mesh Profile 1.0 Section 6.6:
* "The timeout for the SAR transfer is 20 seconds. When the timeout
* expires, the Proxy Server shall disconnect."
@@ -110,14 +114,14 @@ static bool prov_fast_adv;
static struct bt_mesh_proxy_client {
uint16_t conn_handle;
- u16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
+ uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
enum __packed {
NONE,
WHITELIST,
BLACKLIST,
PROV,
} filter_type;
- u8_t msg_type;
+ uint8_t msg_type;
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
struct ble_npl_callout send_beacons;
#endif
@@ -127,6 +131,9 @@ static struct bt_mesh_proxy_client {
[0 ... (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1)] = { 0 },
};
+static sys_slist_t idle_waiters;
+static atomic_t pending_notifications;
+
/* Track which service is enabled */
static enum {
MESH_GATT_NONE,
@@ -195,15 +202,15 @@ static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle)
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
/* Next subnet in queue to be advertised */
-static int next_idx;
+static struct bt_mesh_subnet *beacon_sub;
-static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
+static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg);
static int filter_set(struct bt_mesh_proxy_client *client,
struct os_mbuf *buf)
{
- u8_t type;
+ uint8_t type;
if (buf->om_len < 1) {
BT_WARN("Too short Filter Set message");
@@ -230,7 +237,7 @@ static int filter_set(struct bt_mesh_proxy_client *client,
return 0;
}
-static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
+static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr)
{
int i;
@@ -254,7 +261,7 @@ static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
}
}
-static void filter_remove(struct bt_mesh_proxy_client *client, u16_t addr)
+static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr)
{
int i;
@@ -281,7 +288,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client,
.ctx = &rx->ctx,
.src = bt_mesh_primary_addr(),
};
- u16_t filter_size;
+ uint16_t filter_size;
int i, err;
/* Configuration messages always have dst unassigned */
@@ -323,7 +330,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(29);
struct bt_mesh_net_rx rx;
- u8_t opcode;
+ uint8_t opcode;
int err;
err = bt_mesh_net_decode(client->buf, BT_MESH_NET_IF_PROXY_CFG,
@@ -333,8 +340,16 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
goto done;
}
+ rx.local_match = 1U;
+
+ if (bt_mesh_rpl_check(&rx, NULL)) {
+ BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
+ rx.ctx.addr, rx.ctx.recv_dst, rx.seq);
+ goto done;
+ }
+
/* Remove network headers */
- net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN);
+ net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN);
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
@@ -351,7 +366,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
break;
case CFG_FILTER_ADD:
while (buf->om_len >= 2) {
- u16_t addr;
+ uint16_t addr;
addr = net_buf_simple_pull_be16(buf);
filter_add(client, addr);
@@ -360,7 +375,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
break;
case CFG_FILTER_REMOVE:
while (buf->om_len >= 2) {
- u16_t addr;
+ uint16_t addr;
addr = net_buf_simple_pull_be16(buf);
filter_remove(client, addr);
@@ -389,21 +404,20 @@ static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub)
return rc;
}
+static int send_beacon_cb(struct bt_mesh_subnet *sub, void *cb_data)
+{
+ struct bt_mesh_proxy_client *client = cb_data;
+
+ return beacon_send(client->conn_handle, sub);
+}
+
static void proxy_send_beacons(struct ble_npl_event *work)
{
struct bt_mesh_proxy_client *client;
- int i;
-
client = ble_npl_event_get_arg(work);
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx != BT_MESH_KEY_UNUSED) {
- beacon_send(client->conn_handle, sub);
- }
- }
+ (void)bt_mesh_subnet_find(send_beacon_cb, client);
}
static void proxy_sar_timeout(struct ble_npl_event *work)
@@ -429,12 +443,7 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
if (!sub) {
/* NULL means we send on all subnets */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_proxy_beacon_send(&bt_mesh.sub[i]);
- }
- }
-
+ bt_mesh_subnet_foreach(bt_mesh_proxy_beacon_send);
return;
}
@@ -445,13 +454,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
}
}
-void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
+static void node_id_start(struct bt_mesh_subnet *sub)
{
sub->node_id = BT_MESH_NODE_IDENTITY_RUNNING;
sub->node_id_start = k_uptime_get_32();
+}
+void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
+{
+ node_id_start(sub);
/* Prioritize the recently enabled subnet */
- next_idx = sub - bt_mesh.sub;
+ beacon_sub = sub;
}
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
@@ -462,30 +475,13 @@ void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
int bt_mesh_proxy_identity_enable(void)
{
- int i, count = 0;
-
BT_DBG("");
if (!bt_mesh_is_provisioned()) {
return -EAGAIN;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (sub->node_id == BT_MESH_NODE_IDENTITY_NOT_SUPPORTED) {
- continue;
- }
-
- bt_mesh_proxy_identity_start(sub);
- count++;
- }
-
- if (count) {
+ if (bt_mesh_subnet_foreach(node_id_start)) {
bt_mesh_adv_update();
}
@@ -528,9 +524,9 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_client *client)
static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg)
{
- struct bt_mesh_proxy_client *client;
- const u8_t *data = ctxt->om->om_data;
- u16_t len = ctxt->om->om_len;
+ struct bt_mesh_proxy_client *client = find_client(conn_handle);
+ const uint8_t *data = ctxt->om->om_data;
+ uint16_t len = ctxt->om->om_len;
client = find_client(conn_handle);
@@ -652,7 +648,9 @@ static void proxy_connected(uint16_t conn_handle)
static void proxy_disconnected(uint16_t conn_handle, int reason)
{
int i;
- bool disconnected = false;
+
+ BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason);
+ conn_count--;
for (i = 0; i < ARRAY_SIZE(clients); i++) {
struct bt_mesh_proxy_client *client = &clients[i];
@@ -665,16 +663,11 @@ static void proxy_disconnected(uint16_t conn_handle, int reason)
k_delayed_work_cancel(&client->sar_timer);
client->conn_handle = BLE_HS_CONN_HANDLE_NONE;
- conn_count--;
- disconnected = true;
break;
}
}
- if (disconnected) {
- BT_INFO("conn_handle %d reason %d", conn_handle, reason);
- bt_mesh_adv_update();
- }
+ bt_mesh_adv_update();
}
struct os_mbuf *bt_mesh_proxy_get_buf(void)
@@ -887,7 +880,7 @@ int bt_mesh_proxy_gatt_disable(void)
return 0;
}
-void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
+void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr)
{
struct bt_mesh_proxy_client *client = NULL;
int i;
@@ -911,7 +904,7 @@ void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
}
static bool client_filter_match(struct bt_mesh_proxy_client *client,
- u16_t addr)
+ uint16_t addr)
{
int i;
@@ -942,7 +935,7 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client,
return false;
}
-bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
+bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst)
{
bool relayed = false;
int i;
@@ -978,9 +971,25 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
#endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */
-static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
+static void notify_complete(void)
+{
+ sys_snode_t *n;
+
+ if (atomic_dec(&pending_notifications) > 1) {
+ return;
+ }
+
+ BT_DBG("");
+
+ while ((n = sys_slist_get(&idle_waiters))) {
+ CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb();
+ }
+}
+
+static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len)
{
struct os_mbuf *om;
+ int err = 0;
BT_DBG("%u bytes: %s", len, bt_hex(data, len));
@@ -988,7 +997,8 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
if (gatt_svc == MESH_GATT_PROXY) {
om = ble_hs_mbuf_from_flat(data, len);
assert(om);
- ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
+ err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
+ notify_complete();
}
#endif
@@ -996,17 +1006,22 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
if (gatt_svc == MESH_GATT_PROV) {
om = ble_hs_mbuf_from_flat(data, len);
assert(om);
- ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
+ err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
+ notify_complete();
}
#endif
- return 0;
+ if (!err) {
+ atomic_inc(&pending_notifications);
+ }
+
+ return err;
}
-static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
+static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg)
{
- u16_t mtu;
+ uint16_t mtu;
BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len,
bt_hex(msg->om_data, msg->om_len));
@@ -1020,7 +1035,7 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
proxy_send(conn_handle, msg->om_data, mtu);
- net_buf_simple_pull(msg, mtu);
+ net_buf_simple_pull_mem(msg, mtu);
while (msg->om_len) {
if (msg->om_len + 1 < mtu) {
@@ -1031,13 +1046,13 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
proxy_send(conn_handle, msg->om_data, mtu);
- net_buf_simple_pull(msg, mtu);
+ net_buf_simple_pull_mem(msg, mtu);
}
return 0;
}
-int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
+int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg)
{
struct bt_mesh_proxy_client *client = find_client(conn_handle);
@@ -1056,11 +1071,14 @@ int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
}
#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-static u8_t prov_svc_data[20] = { 0x27, 0x18, };
+static uint8_t prov_svc_data[20] = {
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL),
+};
static const struct bt_data prov_ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x27, 0x18),
+ BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)),
BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)),
};
#endif /* PB_GATT */
@@ -1075,23 +1093,27 @@ static const struct bt_data prov_ad[] = {
#define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BT_MESH_NODE_ID_TIMEOUT)
-static u8_t proxy_svc_data[NODE_ID_LEN] = { 0x28, 0x18, };
+static uint8_t proxy_svc_data[NODE_ID_LEN] = {
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL),
+};
static const struct bt_data node_id_ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18),
+ BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN),
};
static const struct bt_data net_id_ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18),
+ BT_DATA_BYTES(BT_DATA_UUID16_ALL,
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)),
BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN),
};
static int node_id_adv(struct bt_mesh_subnet *sub)
{
- u8_t tmp[16];
+ uint8_t tmp[16];
int err;
BT_DBG("");
@@ -1107,7 +1129,8 @@ static int node_id_adv(struct bt_mesh_subnet *sub)
memcpy(tmp + 6, proxy_svc_data + 11, 8);
sys_put_be16(bt_mesh_primary_addr(), tmp + 14);
- err = bt_encrypt_be(sub->keys[sub->kr_flag].identity, tmp, tmp);
+ err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp,
+ tmp);
if (err) {
return err;
}
@@ -1135,9 +1158,9 @@ static int net_id_adv(struct bt_mesh_subnet *sub)
proxy_svc_data[2] = ID_TYPE_NET;
BT_DBG("Advertising with NetId %s",
- bt_hex(sub->keys[sub->kr_flag].net_id, 8));
+ bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8));
- memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8);
+ memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8);
err = bt_le_adv_start(&slow_adv_param, net_id_ad,
ARRAY_SIZE(net_id_ad), NULL, 0);
@@ -1158,60 +1181,75 @@ static bool advertise_subnet(struct bt_mesh_subnet *sub)
}
return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING ||
- bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED);
+ bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
}
static struct bt_mesh_subnet *next_sub(void)
{
- int i;
+ struct bt_mesh_subnet *sub = NULL;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub;
+ if (!beacon_sub) {
+ beacon_sub = bt_mesh_subnet_next(NULL);
+ if (!beacon_sub) {
+ /* No valid subnets */
+ return NULL;
+ }
+ }
- sub = &bt_mesh.sub[(i + next_idx) % ARRAY_SIZE(bt_mesh.sub)];
+ sub = beacon_sub;
+ do {
if (advertise_subnet(sub)) {
- next_idx = (next_idx + 1) % ARRAY_SIZE(bt_mesh.sub);
+ beacon_sub = sub;
return sub;
}
- }
+
+ sub = bt_mesh_subnet_next(sub);
+ } while (sub != beacon_sub);
+
+ /* No subnets to advertise on */
return NULL;
}
-static int sub_count(void)
+static int sub_count_cb(struct bt_mesh_subnet *sub, void *cb_data)
{
- int i, count = 0;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+ int *count = cb_data;
- if (advertise_subnet(sub)) {
- count++;
- }
+ if (advertise_subnet(sub)) {
+ (*count)++;
}
+ return 0;
+}
+
+static int sub_count(void)
+{
+ int count = 0;
+
+ (void)bt_mesh_subnet_find(sub_count_cb, &count);
return count;
}
-static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
+static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
{
- s32_t remaining = K_FOREVER;
+ int32_t remaining = K_FOREVER;
int subnet_count;
BT_DBG("");
if (conn_count == CONFIG_BT_MAX_CONN) {
- BT_DBG("Connectable advertising deferred (max connections)");
- return remaining;
+ BT_DBG("Connectable advertising deferred (max connections %d)", conn_count);
+ return -ENOMEM;
}
+ sub = beacon_sub ? beacon_sub : bt_mesh_subnet_next(beacon_sub);
if (!sub) {
BT_WARN("No subnets to advertise on");
- return remaining;
+ return -ENOENT;
}
if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) {
- u32_t active = k_uptime_get_32() - sub->node_id_start;
+ uint32_t active = k_uptime_get_32() - sub->node_id_start;
if (active < NODE_ID_TIMEOUT) {
remaining = NODE_ID_TIMEOUT - active;
@@ -1231,7 +1269,7 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
subnet_count = sub_count();
BT_DBG("sub_count %u", subnet_count);
if (subnet_count > 1) {
- s32_t max_timeout;
+ int32_t max_timeout;
/* We use NODE_ID_TIMEOUT as a starting point since it may
* be less than 60 seconds. Divide this period into at least
@@ -1249,6 +1287,8 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
BT_DBG("Advertising %d ms for net_idx 0x%04x",
(int) remaining, sub->net_idx);
+ beacon_sub = bt_mesh_subnet_next(beacon_sub);
+
return remaining;
}
#endif /* GATT_PROXY */
@@ -1299,7 +1339,7 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[2])
}
#endif /* PB_GATT */
-s32_t bt_mesh_proxy_adv_start(void)
+int32_t bt_mesh_proxy_adv_start(void)
{
BT_DBG("");
@@ -1361,6 +1401,19 @@ void bt_mesh_proxy_adv_stop(void)
}
}
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ if (evt == BT_MESH_KEY_DELETED) {
+ if (sub == beacon_sub) {
+ beacon_sub = NULL;
+ }
+ } else {
+ bt_mesh_proxy_beacon_send(sub);
+ }
+}
+#endif
+
static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg)
{
#if MYNEWT_VAL(BLE_EXT_ADV)
@@ -1477,6 +1530,12 @@ int bt_mesh_proxy_init(void)
{
int i;
+#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
+ if (!bt_mesh_subnet_cb_list[4]) {
+ bt_mesh_subnet_cb_list[4] = subnet_evt;
+ }
+#endif
+
for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) {
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
k_work_init(&clients[i].send_beacons, proxy_send_beacons);
@@ -1496,4 +1555,14 @@ int bt_mesh_proxy_init(void)
return 0;
}
+void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb)
+{
+ if (!atomic_get(&pending_notifications)) {
+ cb->cb();
+ return;
+ }
+
+ sys_slist_append(&idle_waiters, &cb->n);
+}
+
#endif /* MYNEWT_VAL(BLE_MESH_PROXY) */
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h
index 64338a0a..ebade45a 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h
@@ -15,8 +15,14 @@
#define BT_MESH_PROXY_PROV 0x03
#include "mesh/mesh.h"
+#include "mesh/slist.h"
-int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, struct os_mbuf *msg);
+struct bt_mesh_proxy_idle_cb {
+ sys_snode_t n;
+ void (*cb)(void);
+};
+
+int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg);
int bt_mesh_proxy_prov_enable(void);
int bt_mesh_proxy_prov_disable(bool disconnect);
@@ -29,16 +35,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub);
struct os_mbuf *bt_mesh_proxy_get_buf(void);
-s32_t bt_mesh_proxy_adv_start(void);
+int32_t bt_mesh_proxy_adv_start(void);
void bt_mesh_proxy_adv_stop(void);
void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub);
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub);
-bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst);
-void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr);
+bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst);
+void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr);
int bt_mesh_proxy_init(void);
+void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb);
int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c
new file mode 100644
index 00000000..93c2e1a8
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c
@@ -0,0 +1,162 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_RPL_LOG
+
+#include "log/log.h"
+
+#include "mesh_priv.h"
+#include "adv.h"
+#include "net.h"
+#include "rpl.h"
+#include "settings.h"
+
+static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)];
+
+void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
+ struct bt_mesh_net_rx *rx)
+{
+ rpl->src = rx->ctx.addr;
+ rpl->seq = rx->seq;
+ rpl->old_iv = rx->old_iv;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_rpl(rpl);
+ }
+}
+
+/* Check the Replay Protection List for a replay attempt. If non-NULL match
+ * parameter is given the RPL slot is returned but it is not immediately
+ * updated (needed for segmented messages), whereas if a NULL match is given
+ * the RPL is immediately updated (used for unsegmented messages).
+ */
+bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
+ struct bt_mesh_rpl **match)
+{
+ int i;
+
+ /* Don't bother checking messages from ourselves */
+ if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+ return false;
+ }
+
+ /* The RPL is used only for the local node */
+ if (!rx->local_match) {
+ return false;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ struct bt_mesh_rpl *rpl = &replay_list[i];
+
+ /* Empty slot */
+ if (!rpl->src) {
+ if (match) {
+ *match = rpl;
+ } else {
+ bt_mesh_rpl_update(rpl, rx);
+ }
+
+ return false;
+ }
+
+ /* Existing slot for given address */
+ if (rpl->src == rx->ctx.addr) {
+ if (rx->old_iv && !rpl->old_iv) {
+ return true;
+ }
+
+ if ((!rx->old_iv && rpl->old_iv) ||
+ rpl->seq < rx->seq) {
+ if (match) {
+ *match = rpl;
+ } else {
+ bt_mesh_rpl_update(rpl, rx);
+ }
+
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ BT_ERR("RPL is full!");
+ return true;
+}
+
+void bt_mesh_rpl_clear(void)
+{
+ BT_DBG("");
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_clear_rpl();
+ } else {
+ (void)memset(replay_list, 0, sizeof(replay_list));
+ }
+}
+
+struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ if (replay_list[i].src == src) {
+ return &replay_list[i];
+ }
+ }
+
+ return NULL;
+}
+
+struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ if (!replay_list[i].src) {
+ replay_list[i].src = src;
+ return &replay_list[i];
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ func(&replay_list[i], user_data);
+ }
+}
+
+void bt_mesh_rpl_reset(void)
+{
+ int i;
+
+ /* Discard "old old" IV Index entries from RPL and flag
+ * any other ones (which are valid) as old.
+ */
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ struct bt_mesh_rpl *rpl = &replay_list[i];
+
+ if (rpl->src) {
+ if (rpl->old_iv) {
+ (void)memset(rpl, 0, sizeof(*rpl));
+ } else {
+ rpl->old_iv = true;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_rpl(rpl);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h
new file mode 100644
index 00000000..0592712f
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h
@@ -0,0 +1,30 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct bt_mesh_rpl {
+ uint16_t src;
+ bool old_iv;
+#if defined(CONFIG_BT_SETTINGS)
+ bool store;
+#endif
+ uint32_t seq;
+};
+
+typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl,
+ void *user_data);
+
+void bt_mesh_rpl_reset(void);
+bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
+ struct bt_mesh_rpl **match);
+void bt_mesh_rpl_clear(void);
+struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src);
+struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src);
+void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data);
+void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
+ struct bt_mesh_net_rx *rx); \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c
index 88d9b302..537bd785 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c
@@ -9,16 +9,23 @@
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
+#include "mesh_priv.h"
#include "mesh/mesh.h"
#include "mesh/glue.h"
+#include "subnet.h"
+#include "app_keys.h"
#include "net.h"
+#include "rpl.h"
#include "crypto.h"
#include "transport.h"
+#include "heartbeat.h"
#include "access.h"
#include "foundation.h"
#include "proxy.h"
#include "settings.h"
-#include "nodes.h"
+#include "lpn.h"
+#include "cfg.h"
+
#include "config/config.h"
@@ -27,116 +34,155 @@
* bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key
* gets deleted its struct becomes invalid and may be reused for other keys.
*/
-static struct key_update {
- u16_t key_idx:12, /* AppKey or NetKey Index */
+struct key_update {
+ uint16_t key_idx:12, /* AppKey or NetKey Index */
valid:1, /* 1 if this entry is valid, 0 if not */
app_key:1, /* 1 if this is an AppKey, 0 if a NetKey */
clear:1; /* 1 if key needs clearing, 0 if storing */
-} key_updates[CONFIG_BT_MESH_APP_KEY_COUNT + CONFIG_BT_MESH_SUBNET_COUNT];
+};
+
+static struct key_update key_updates[CONFIG_BT_MESH_APP_KEY_COUNT +
+ CONFIG_BT_MESH_SUBNET_COUNT];
static struct k_delayed_work pending_store;
/* Mesh network storage information */
struct net_val {
- u16_t primary_addr;
- u8_t dev_key[16];
+ uint16_t primary_addr;
+ uint8_t dev_key[16];
} __packed;
/* Sequence number storage */
struct seq_val {
- u8_t val[3];
+ uint8_t val[3];
} __packed;
/* Heartbeat Publication storage */
struct hb_pub_val {
- u16_t dst;
- u8_t period;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx:12,
+ uint16_t dst;
+ uint8_t period;
+ uint8_t ttl;
+ uint16_t feat;
+ uint16_t net_idx:12,
indefinite:1;
};
/* Miscelaneous configuration server model states */
struct cfg_val {
- u8_t net_transmit;
- u8_t relay;
- u8_t relay_retransmit;
- u8_t beacon;
- u8_t gatt_proxy;
- u8_t frnd;
- u8_t default_ttl;
+ uint8_t net_transmit;
+ uint8_t relay;
+ uint8_t relay_retransmit;
+ uint8_t beacon;
+ uint8_t gatt_proxy;
+ uint8_t frnd;
+ uint8_t default_ttl;
};
/* IV Index & IV Update storage */
struct iv_val {
- u32_t iv_index;
- u8_t iv_update:1,
+ uint32_t iv_index;
+ uint8_t iv_update:1,
iv_duration:7;
} __packed;
/* Replay Protection List storage */
struct rpl_val {
- u32_t seq:24,
+ uint32_t seq:24,
old_iv:1;
};
/* NetKey storage information */
struct net_key_val {
- u8_t kr_flag:1,
+ uint8_t kr_flag:1,
kr_phase:7;
- u8_t val[2][16];
+ uint8_t val[2][16];
} __packed;
/* AppKey storage information */
struct app_key_val {
- u16_t net_idx;
+ uint16_t net_idx;
bool updated;
- u8_t val[2][16];
+ uint8_t val[2][16];
} __packed;
struct mod_pub_val {
- u16_t addr;
- u16_t key;
- u8_t ttl;
- u8_t retransmit;
- u8_t period;
- u8_t period_div:4,
+ uint16_t addr;
+ uint16_t key;
+ uint8_t ttl;
+ uint8_t retransmit;
+ uint8_t period;
+ uint8_t period_div:4,
cred:1;
};
/* Virtual Address information */
struct va_val {
- u16_t ref;
- u16_t addr;
- u8_t uuid[16];
+ uint16_t ref;
+ uint16_t addr;
+ uint8_t uuid[16];
+} __packed;
+
+struct cdb_net_val {
+ uint32_t iv_index;
+ bool iv_update;
} __packed;
/* Node storage information */
struct node_val {
- u16_t net_idx;
- u8_t dev_key[16];
- u8_t num_elem;
+ uint16_t net_idx;
+ uint8_t num_elem;
+ uint8_t flags;
+#define F_NODE_CONFIGURED 0x01
+ uint8_t uuid[16];
+ uint8_t dev_key[16];
} __packed;
struct node_update {
- u16_t addr;
+ uint16_t addr;
bool clear;
};
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-static struct node_update node_updates[CONFIG_BT_MESH_NODE_COUNT];
+#if MYNEWT_VAL(BLE_MESH_CDB)
+static struct node_update cdb_node_updates[MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)];
+static struct key_update cdb_key_updates[
+ MYNEWT_VAL(BLE_MESH_CDB_SUBNET_COUNT) +
+ MYNEWT_VAL(BLE_MESH_CDB_APP_KEY_COUNT)];
#else
-static struct node_update node_updates[0];
+static struct node_update cdb_node_updates[0];
+static struct key_update cdb_key_updates[0];
#endif
-/* We need this so we don't overwrite app-hardcoded values in case FCB
- * contains a history of changes but then has a NULL at the end.
- */
-static struct {
- bool valid;
- struct cfg_val cfg;
-} stored_cfg;
+int settings_name_next(char *name, char **next)
+{
+ int rc = 0;
+
+ if (next) {
+ *next = NULL;
+ }
+
+ if (!name) {
+ return 0;
+ }
+
+ /* name might come from flash directly, in flash the name would end
+ * with '=' or '\0' depending how storage is done. Flash reading is
+ * limited to what can be read
+ */
+ while ((*name != '\0') && (*name != '=') &&
+ (*name != '/')) {
+ rc++;
+ name++;
+ }
+
+ if (*name == '/') {
+ if (next) {
+ *next = name + 1;
+ }
+ return rc;
+ }
+
+ return rc;
+}
static int net_set(int argc, char **argv, char *val)
{
@@ -231,8 +277,7 @@ static int seq_set(int argc, char **argv, char *val)
return -EINVAL;
}
- bt_mesh.seq = ((u32_t)seq.val[0] | ((u32_t)seq.val[1] << 8) |
- ((u32_t)seq.val[2] << 16));
+ bt_mesh.seq = sys_get_le24(seq.val);
if (CONFIG_BT_MESH_SEQ_STORE_RATE > 0) {
/* Make sure we have a large enough sequence number. We
@@ -249,39 +294,12 @@ static int seq_set(int argc, char **argv, char *val)
return 0;
}
-static struct bt_mesh_rpl *rpl_find(u16_t src)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- if (bt_mesh.rpl[i].src == src) {
- return &bt_mesh.rpl[i];
- }
- }
-
- return NULL;
-}
-
-static struct bt_mesh_rpl *rpl_alloc(u16_t src)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- if (!bt_mesh.rpl[i].src) {
- bt_mesh.rpl[i].src = src;
- return &bt_mesh.rpl[i];
- }
- }
-
- return NULL;
-}
-
static int rpl_set(int argc, char **argv, char *val)
{
struct bt_mesh_rpl *entry;
struct rpl_val rpl;
int len, err;
- u16_t src;
+ uint16_t src;
if (argc < 1) {
BT_ERR("Invalid argc (%d)", argc);
@@ -291,7 +309,7 @@ static int rpl_set(int argc, char **argv, char *val)
BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
src = strtol(argv[0], NULL, 16);
- entry = rpl_find(src);
+ entry = bt_mesh_rpl_find(src);
if (!val) {
if (entry) {
@@ -304,7 +322,7 @@ static int rpl_set(int argc, char **argv, char *val)
}
if (!entry) {
- entry = rpl_alloc(src);
+ entry = bt_mesh_rpl_alloc(src);
if (!entry) {
BT_ERR("Unable to allocate RPL entry for 0x%04x", src);
return -ENOMEM;
@@ -334,26 +352,13 @@ static int rpl_set(int argc, char **argv, char *val)
static int net_key_set(int argc, char **argv, char *val)
{
- struct bt_mesh_subnet *sub;
struct net_key_val key;
- int len, i, err;
- u16_t net_idx;
+ int len, err;
+ uint16_t net_idx;
BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
net_idx = strtol(argv[0], NULL, 16);
- sub = bt_mesh_subnet_get(net_idx);
-
- if (!val) {
- if (!sub) {
- BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
- return -ENOENT;
- }
-
- BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
- bt_mesh_subnet_del(sub, false);
- return 0;
- }
len = sizeof(key);
err = settings_bytes_from_str(val, &key, &len);
@@ -367,93 +372,41 @@ static int net_key_set(int argc, char **argv, char *val)
return -EINVAL;
}
- if (sub) {
- BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
-
- sub->kr_flag = key.kr_flag;
- sub->kr_phase = key.kr_phase;
- memcpy(sub->keys[0].net, &key.val[0], 16);
- memcpy(sub->keys[1].net, &key.val[1], 16);
-
- return 0;
- }
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
- sub = &bt_mesh.sub[i];
- break;
- }
- }
-
- if (!sub) {
- BT_ERR("No space to allocate a new subnet");
- return -ENOMEM;
- }
-
- sub->net_idx = net_idx;
- sub->kr_flag = key.kr_flag;
- sub->kr_phase = key.kr_phase;
- memcpy(sub->keys[0].net, &key.val[0], 16);
- memcpy(sub->keys[1].net, &key.val[1], 16);
-
BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
- return 0;
+ return bt_mesh_subnet_set(
+ net_idx, key.kr_phase, key.val[0],
+ (key.kr_phase != BT_MESH_KR_NORMAL) ? key.val[1] : NULL);
}
static int app_key_set(int argc, char **argv, char *val)
{
- struct bt_mesh_app_key *app;
struct app_key_val key;
- u16_t app_idx;
- int len, err;
+ uint16_t app_idx;
+ int len_rd, err;
BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
app_idx = strtol(argv[0], NULL, 16);
+ len_rd = strtol(argv[1], NULL, 16);
- if (!val) {
- BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
-
- app = bt_mesh_app_key_find(app_idx);
- if (app) {
- bt_mesh_app_key_del(app, false);
- }
-
+ if (!len_rd) {
return 0;
}
- len = sizeof(key);
- err = settings_bytes_from_str(val, &key, &len);
+ err = settings_bytes_from_str(val, &key, &len_rd);
if (err) {
BT_ERR("Failed to decode value %s (err %d)", val, err);
return err;
}
- if (len != sizeof(key)) {
- BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(key));
- return -EINVAL;
- }
-
- app = bt_mesh_app_key_find(app_idx);
- if (!app) {
- app = bt_mesh_app_key_alloc(app_idx);
- }
-
- if (!app) {
- BT_ERR("No space for a new app key");
- return -ENOMEM;
+ err = bt_mesh_app_key_set(app_idx, key.net_idx, key.val[0],
+ key.updated ? key.val[1] : NULL);
+ if (err) {
+ BT_ERR("Failed to set \'app-key\'");
+ return err;
}
- app->net_idx = key.net_idx;
- app->app_idx = app_idx;
- app->updated = key.updated;
- memcpy(app->keys[0].val, key.val[0], 16);
- memcpy(app->keys[1].val, key.val[1], 16);
-
- bt_mesh_app_id(app->keys[0].val, &app->keys[0].id);
- bt_mesh_app_id(app->keys[1].val, &app->keys[1].id);
-
BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
return 0;
@@ -461,27 +414,12 @@ static int app_key_set(int argc, char **argv, char *val)
static int hb_pub_set(int argc, char **argv, char *val)
{
- struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
+ struct bt_mesh_hb_pub pub;
struct hb_pub_val hb_val;
int len, err;
BT_DBG("val %s", val ? val : "(null)");
- if (!pub) {
- return -ENOENT;
- }
-
- if (!val) {
- pub->dst = BT_MESH_ADDR_UNASSIGNED;
- pub->count = 0;
- pub->ttl = 0;
- pub->period = 0;
- pub->feat = 0;
-
- BT_DBG("Cleared heartbeat publication");
- return 0;
- }
-
len = sizeof(hb_val);
err = settings_bytes_from_str(val, &hb_val, &len);
if (err) {
@@ -495,18 +433,20 @@ static int hb_pub_set(int argc, char **argv, char *val)
return -EINVAL;
}
- pub->dst = hb_val.dst;
- pub->period = hb_val.period;
- pub->ttl = hb_val.ttl;
- pub->feat = hb_val.feat;
- pub->net_idx = hb_val.net_idx;
+ pub.dst = hb_val.dst;
+ pub.period = bt_mesh_hb_pwr2(hb_val.period);
+ pub.ttl = hb_val.ttl;
+ pub.feat = hb_val.feat;
+ pub.net_idx = hb_val.net_idx;
if (hb_val.indefinite) {
- pub->count = 0xffff;
+ pub.count = 0xffff;
} else {
- pub->count = 0;
+ pub.count = 0;
}
+ (void)bt_mesh_hb_pub_set(&pub);
+
BT_DBG("Restored heartbeat publication");
return 0;
@@ -514,35 +454,36 @@ static int hb_pub_set(int argc, char **argv, char *val)
static int cfg_set(int argc, char **argv, char *val)
{
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
+ struct cfg_val cfg;
int len, err;
BT_DBG("val %s", val ? val : "(null)");
- if (!cfg) {
- return -ENOENT;
- }
-
if (!val) {
- stored_cfg.valid = false;
BT_DBG("Cleared configuration state");
return 0;
}
- len = sizeof(stored_cfg.cfg);
- err = settings_bytes_from_str(val, &stored_cfg.cfg, &len);
+ len = sizeof(cfg);
+ err = settings_bytes_from_str(val, &cfg, &len);
if (err) {
BT_ERR("Failed to decode value %s (err %d)", val, err);
return err;
}
- if (len != sizeof(stored_cfg.cfg)) {
+ if (len != sizeof(cfg)) {
BT_ERR("Unexpected value length (%d != %zu)", len,
- sizeof(stored_cfg.cfg));
+ sizeof(cfg));
return -EINVAL;
}
- stored_cfg.valid = true;
+ bt_mesh_net_transmit_set(cfg.net_transmit);
+ bt_mesh_relay_set(cfg.relay, cfg.relay_retransmit);
+ bt_mesh_beacon_set(cfg.beacon);
+ bt_mesh_gatt_proxy_set(cfg.gatt_proxy);
+ bt_mesh_friend_set(cfg.frnd);
+ bt_mesh_default_ttl_set(cfg.default_ttl);
+
BT_DBG("Restored configuration state");
return 0;
@@ -646,11 +587,25 @@ static int mod_set_pub(struct bt_mesh_model *mod, char *val)
return 0;
}
+static int mod_data_set(struct bt_mesh_model *mod,
+ char *name, char *len_rd)
+{
+ char *next;
+
+ settings_name_next(name, &next);
+
+ if (mod->cb && mod->cb->settings_set) {
+ return mod->cb->settings_set(mod, next, len_rd);
+ }
+
+ return 0;
+}
+
static int mod_set(bool vnd, int argc, char **argv, char *val)
{
struct bt_mesh_model *mod;
- u8_t elem_idx, mod_idx;
- u16_t mod_key;
+ uint8_t elem_idx, mod_idx;
+ uint16_t mod_key;
if (argc < 2) {
BT_ERR("Too small argc (%d)", argc);
@@ -684,11 +639,7 @@ static int mod_set(bool vnd, int argc, char **argv, char *val)
}
if (!strcmp(argv[1], "data")) {
- mod->flags |= BT_MESH_MOD_DATA_PRESENT;
-
- if (mod->cb && mod->cb->settings_set) {
- return mod->cb->settings_set(mod, val);
- }
+ return mod_data_set(mod, argv[1], val);
}
BT_WARN("Unknown module key %s", argv[1]);
@@ -709,8 +660,8 @@ static int vnd_mod_set(int argc, char **argv, char *val)
static int va_set(int argc, char **argv, char *val)
{
struct va_val va;
- struct label *lab;
- u16_t index;
+ struct bt_mesh_va *lab;
+ uint16_t index;
int len, err;
if (argc < 1) {
@@ -741,7 +692,7 @@ static int va_set(int argc, char **argv, char *val)
return 0;
}
- lab = get_label(index);
+ lab = bt_mesh_va_get(index);
if (lab == NULL) {
BT_WARN("Out of labels buffers");
return -ENOBUFS;
@@ -758,12 +709,35 @@ static int va_set(int argc, char **argv, char *val)
}
#endif
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-static int node_set(int argc, char **argv, char *str)
+#if MYNEWT_VAL(BLE_MESH_CDB)
+static int cdb_net_set(int argc, char *val)
+{
+ struct cdb_net_val net;
+ int len, err;
+
+ len = sizeof(net);
+ err = settings_bytes_from_str(val, &net, &len);
+ if (err) {
+ BT_ERR("Failed to set \'cdb_net\'");
+ return err;
+ }
+
+ bt_mesh_cdb.iv_index = net.iv_index;
+
+ if (net.iv_update) {
+ atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS);
+ }
+
+ atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
+
+ return 0;
+}
+
+static int cdb_node_set(int argc, char *str)
{
- struct bt_mesh_node *node;
+ struct bt_mesh_cdb_node *node;
struct node_val val;
- u16_t addr;
+ uint16_t addr;
int len, err;
if (argc < 1) {
@@ -771,15 +745,16 @@ static int node_set(int argc, char **argv, char *str)
return -ENOENT;
}
- addr = strtol(argv[0], NULL, 16);
+ addr = strtol(str, NULL, 16);
+ len = sizeof(str);
- if (str == NULL) {
+ if (argc < 1) {
BT_DBG("val (null)");
BT_DBG("Deleting node 0x%04x", addr);
- node = bt_mesh_node_find(addr);
+ node = bt_mesh_cdb_node_get(addr);
if (node) {
- bt_mesh_node_del(node, false);
+ bt_mesh_cdb_node_del(node, false);
}
return 0;
@@ -796,9 +771,10 @@ static int node_set(int argc, char **argv, char *str)
return -EINVAL;
}
- node = bt_mesh_node_find(addr);
+ node = bt_mesh_cdb_node_get(addr);
if (!node) {
- node = bt_mesh_node_alloc(addr, val.num_elem, val.net_idx);
+ node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem,
+ val.net_idx);
}
if (!node) {
@@ -806,12 +782,163 @@ static int node_set(int argc, char **argv, char *str)
return -ENOMEM;
}
- memcpy(node->dev_key, &val.dev_key, 16);
+ if (val.flags & F_NODE_CONFIGURED) {
+ atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED);
+ }
+
+ memcpy(node->uuid, val.uuid, 16);
+ memcpy(node->dev_key, val.dev_key, 16);
BT_DBG("Node 0x%04x recovered from storage", addr);
return 0;
}
+
+static int cdb_subnet_set(int argc, char *name)
+{
+ struct bt_mesh_cdb_subnet *sub;
+ struct net_key_val key;
+ uint16_t net_idx;
+ int len, len_rd, err;
+
+ if (!name) {
+ BT_ERR("Insufficient number of arguments");
+ return -ENOENT;
+ }
+
+ len_rd = sizeof(sub);
+ net_idx = strtol(name, NULL, 16);
+ sub = bt_mesh_cdb_subnet_get(net_idx);
+
+ if (len_rd == 0) {
+ BT_DBG("val (null)");
+ if (!sub) {
+ BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
+ return -ENOENT;
+ }
+
+ BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
+ bt_mesh_cdb_subnet_del(sub, false);
+ return 0;
+ }
+
+ len = sizeof(key);
+ err = settings_bytes_from_str(name, &key, &len);
+ if (err) {
+ BT_ERR("Failed to set \'net-key\'");
+ return err;
+ }
+
+ if (sub) {
+ BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx);
+
+ sub->kr_flag = key.kr_flag;
+ sub->kr_phase = key.kr_phase;
+ memcpy(sub->keys[0].net_key, &key.val[0], 16);
+ memcpy(sub->keys[1].net_key, &key.val[1], 16);
+
+ return 0;
+ }
+
+ sub = bt_mesh_cdb_subnet_alloc(net_idx);
+ if (!sub) {
+ BT_ERR("No space to allocate a new subnet");
+ return -ENOMEM;
+ }
+
+ sub->kr_flag = key.kr_flag;
+ sub->kr_phase = key.kr_phase;
+ memcpy(sub->keys[0].net_key, &key.val[0], 16);
+ memcpy(sub->keys[1].net_key, &key.val[1], 16);
+
+ BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
+
+ return 0;
+}
+
+static int cdb_app_key_set(int argc, char *name)
+{
+ struct bt_mesh_cdb_app_key *app;
+ struct app_key_val key;
+ uint16_t app_idx;
+ int len_rd, err;
+
+ app_idx = strtol(name, NULL, 16);
+ len_rd = sizeof(key);
+
+ if (len_rd == 0) {
+ BT_DBG("val (null)");
+ BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
+
+ app = bt_mesh_cdb_app_key_get(app_idx);
+ if (app) {
+ bt_mesh_cdb_app_key_del(app, false);
+ }
+
+ return 0;
+ }
+
+ err = settings_bytes_from_str(name, &key, &len_rd);
+ if (err) {
+ BT_ERR("Failed to set \'app-key\'");
+ return err;
+ }
+
+ app = bt_mesh_cdb_app_key_get(app_idx);
+ if (!app) {
+ app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx);
+ }
+
+ if (!app) {
+ BT_ERR("No space for a new app key");
+ return -ENOMEM;
+ }
+
+ memcpy(app->keys[0].app_key, key.val[0], 16);
+ memcpy(app->keys[1].app_key, key.val[1], 16);
+
+ BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
+
+ return 0;
+}
+
+static int cdb_set(int argc, char **argv, char *name)
+{
+ int len;
+ char *next;
+
+ if (argc < 1) {
+ BT_ERR("Insufficient number of arguments");
+ return -ENOENT;
+ }
+
+ if (!strcmp(name, "Net")) {
+ return cdb_net_set(1, name);
+ }
+
+
+ len = settings_name_next(name, &next);
+
+ if (!next) {
+ BT_ERR("Insufficient number of arguments");
+ return -ENOENT;
+ }
+
+ if (!strncmp(name, "Node", len)) {
+ return cdb_node_set(1, next);
+ }
+
+ if (!strncmp(name, "Subnet", len)) {
+ return cdb_subnet_set(1, next);
+ }
+
+ if (!strncmp(name, "AppKey", len)) {
+ return cdb_app_key_set(1, next);
+ }
+
+ BT_WARN("Unknown module key %s", name);
+ return -ENOENT;
+}
#endif
const struct mesh_setting {
@@ -831,8 +958,8 @@ const struct mesh_setting {
#if CONFIG_BT_MESH_LABEL_COUNT > 0
{ "Va", va_set },
#endif
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- { "Node", node_set },
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ { "cdb", cdb_set },
#endif
};
@@ -861,43 +988,12 @@ static int mesh_set(int argc, char **argv, char *val)
return -ENOENT;
}
-static int subnet_init(struct bt_mesh_subnet *sub)
-{
- int err;
-
- err = bt_mesh_net_keys_create(&sub->keys[0], sub->keys[0].net);
- if (err) {
- BT_ERR("Unable to generate keys for subnet");
- return -EIO;
- }
-
- if (sub->kr_phase != BT_MESH_KR_NORMAL) {
- err = bt_mesh_net_keys_create(&sub->keys[1], sub->keys[1].net);
- if (err) {
- BT_ERR("Unable to generate keys for subnet");
- memset(&sub->keys[0], 0, sizeof(sub->keys[0]));
- return -EIO;
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
-
- return 0;
-}
-
static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
if (mod->pub && mod->pub->update &&
mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
- s32_t ms = bt_mesh_model_pub_period_get(mod);
+ int32_t ms = bt_mesh_model_pub_period_get(mod);
if (ms) {
BT_DBG("Starting publish timer (period %u ms)",
(unsigned) ms);
@@ -905,20 +1001,20 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
}
}
- if (mod->cb && mod->cb->settings_commit) {
- mod->cb->settings_commit(mod);
+ if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+ return;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(mod->groups); i++) {
+ if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
+ bt_mesh_lpn_group_add(mod->groups[i]);
+ }
}
}
static int mesh_commit(void)
{
- struct bt_mesh_hb_pub *hb_pub;
- struct bt_mesh_cfg_srv *cfg;
- int i;
-
- BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx);
-
- if (bt_mesh.sub[0].net_idx == BT_MESH_KEY_UNUSED) {
+ if (!bt_mesh_subnet_next(NULL)) {
/* Nothing to do since we're not yet provisioned */
return 0;
}
@@ -927,47 +1023,15 @@ static int mesh_commit(void)
bt_mesh_proxy_prov_disable(true);
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
- int err;
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- err = subnet_init(sub);
- if (err) {
- BT_ERR("Failed to init subnet 0x%03x", sub->net_idx);
- }
- }
-
if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) {
k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
}
bt_mesh_model_foreach(commit_mod, NULL);
- hb_pub = bt_mesh_hb_pub_get();
- if (hb_pub && hb_pub->dst != BT_MESH_ADDR_UNASSIGNED &&
- hb_pub->count && hb_pub->period) {
- BT_DBG("Starting heartbeat publication");
- k_work_submit(&hb_pub->timer.work);
- }
-
- cfg = bt_mesh_cfg_get();
- if (cfg && stored_cfg.valid) {
- cfg->net_transmit = stored_cfg.cfg.net_transmit;
- cfg->relay = stored_cfg.cfg.relay;
- cfg->relay_retransmit = stored_cfg.cfg.relay_retransmit;
- cfg->beacon = stored_cfg.cfg.beacon;
- cfg->gatt_proxy = stored_cfg.cfg.gatt_proxy;
- cfg->frnd = stored_cfg.cfg.frnd;
- cfg->default_ttl = stored_cfg.cfg.default_ttl;
- }
-
atomic_set_bit(bt_mesh.flags, BT_MESH_VALID);
- bt_mesh_net_start();
+ bt_mesh_start();
return 0;
}
@@ -981,12 +1045,11 @@ static int mesh_commit(void)
#define GENERIC_PENDING_BITS (BIT(BT_MESH_KEYS_PENDING) | \
BIT(BT_MESH_HB_PUB_PENDING) | \
BIT(BT_MESH_CFG_PENDING) | \
- BIT(BT_MESH_MOD_PENDING) | \
- BIT(BT_MESH_NODES_PENDING))
+ BIT(BT_MESH_MOD_PENDING))
static void schedule_store(int flag)
{
- s32_t timeout, remaining;
+ int32_t timeout, remaining;
atomic_set_bit(bt_mesh.flags, flag);
@@ -1112,9 +1175,7 @@ static void store_pending_seq(void)
char *str;
int err;
- seq.val[0] = bt_mesh.seq;
- seq.val[1] = bt_mesh.seq >> 8;
- seq.val[2] = bt_mesh.seq >> 16;
+ sys_put_le24(bt_mesh.seq, seq.val);
str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf));
if (!str) {
@@ -1172,69 +1233,54 @@ static void store_rpl(struct bt_mesh_rpl *entry)
}
}
-static void clear_rpl(void)
+static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{
- int i, err;
-
- BT_DBG("");
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
- char path[18];
-
- if (!rpl->src) {
- continue;
- }
+ int err;
+ char path[18];
- snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src);
- err = settings_save_one(path, NULL);
- if (err) {
- BT_ERR("Failed to clear RPL");
- } else {
- BT_DBG("Cleared RPL");
- }
+ if (!rpl->src) {
+ return;
+ }
- memset(rpl, 0, sizeof(*rpl));
+ snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src);
+ err = settings_save_one(path, NULL);
+ if (err) {
+ BT_ERR("Failed to clear RPL");
+ } else {
+ BT_DBG("Cleared RPL");
}
+
+ (void)memset(rpl, 0, sizeof(*rpl));
}
-static void store_pending_rpl(void)
+static void store_pending_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{
- int i;
-
BT_DBG("");
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
- if (rpl->store) {
- rpl->store = false;
- store_rpl(rpl);
- }
+ if (rpl->store) {
+ rpl->store = false;
+ store_rpl(rpl);
}
}
static void store_pending_hb_pub(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct hb_pub_val))];
- struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
+ struct bt_mesh_hb_pub pub;
struct hb_pub_val val;
char *str;
int err;
- if (!pub) {
- return;
- }
-
- if (pub->dst == BT_MESH_ADDR_UNASSIGNED) {
+ bt_mesh_hb_pub_get(&pub);
+ if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
str = NULL;
} else {
- val.indefinite = (pub->count == 0xffff);
- val.dst = pub->dst;
- val.period = pub->period;
- val.ttl = pub->ttl;
- val.feat = pub->feat;
- val.net_idx = pub->net_idx;
+ val.indefinite = (pub.count == 0xffff);
+ val.dst = pub.dst;
+ val.period = bt_mesh_hb_log(pub.period);
+ val.ttl = pub.ttl;
+ val.feat = pub.feat;
+ val.net_idx = pub.net_idx;
str = settings_str_from_bytes(&val, sizeof(val),
buf, sizeof(buf));
@@ -1257,22 +1303,17 @@ static void store_pending_hb_pub(void)
static void store_pending_cfg(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct cfg_val))];
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
struct cfg_val val;
char *str;
int err;
- if (!cfg) {
- return;
- }
-
- val.net_transmit = cfg->net_transmit;
- val.relay = cfg->relay;
- val.relay_retransmit = cfg->relay_retransmit;
- val.beacon = cfg->beacon;
- val.gatt_proxy = cfg->gatt_proxy;
- val.frnd = cfg->frnd;
- val.default_ttl = cfg->default_ttl;
+ val.net_transmit = bt_mesh_net_transmit_get();
+ val.relay = bt_mesh_relay_get();
+ val.relay_retransmit = bt_mesh_relay_retransmit_get();
+ val.beacon = bt_mesh_beacon_enabled();
+ val.gatt_proxy = bt_mesh_gatt_proxy_get();
+ val.frnd = bt_mesh_friend_get();
+ val.default_ttl = bt_mesh_default_ttl_get();
str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf));
if (!str) {
@@ -1301,7 +1342,7 @@ static void clear_cfg(void)
}
}
-static void clear_app_key(u16_t app_idx)
+static void clear_app_key(uint16_t app_idx)
{
char path[20];
int err;
@@ -1317,7 +1358,7 @@ static void clear_app_key(u16_t app_idx)
}
}
-static void clear_net_key(u16_t net_idx)
+static void clear_net_key(uint16_t net_idx)
{
char path[20];
int err;
@@ -1333,31 +1374,36 @@ static void clear_net_key(u16_t net_idx)
}
}
-static void store_net_key(struct bt_mesh_subnet *sub)
+static void store_subnet(uint16_t net_idx)
{
- char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))];
+ const struct bt_mesh_subnet *sub;
struct net_key_val key;
+ char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))];
char path[20];
char *str;
int err;
- BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
- bt_hex(sub->keys[0].net, 16));
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ BT_WARN("NetKeyIndex 0x%03x not found", net_idx);
+ return;
+ }
+
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
+
+ snprintk(path, sizeof(path), "bt/mesh/NetKey/%x", net_idx);
memcpy(&key.val[0], sub->keys[0].net, 16);
memcpy(&key.val[1], sub->keys[1].net, 16);
- key.kr_flag = sub->kr_flag;
+ key.kr_flag = 0U; /* Deprecated */
key.kr_phase = sub->kr_phase;
str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf));
if (!str) {
- BT_ERR("Unable to encode NetKey as value");
+ BT_ERR("Unable to encode AppKey as value");
return;
}
- snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", sub->net_idx);
-
- BT_DBG("Saving NetKey %s as value %s", path, str);
err = settings_save_one(path, str);
if (err) {
BT_ERR("Failed to store NetKey");
@@ -1366,16 +1412,26 @@ static void store_net_key(struct bt_mesh_subnet *sub)
}
}
-static void store_app_key(struct bt_mesh_app_key *app)
+static void store_app(uint16_t app_idx)
{
+ const struct bt_mesh_app_key *app;
char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))];
struct app_key_val key;
char path[20];
char *str;
int err;
- key.net_idx = app->net_idx;
- key.updated = app->updated;
+ snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app_idx);
+
+ app = bt_mesh_app_key_get(app_idx);
+ if (!app) {
+ BT_WARN("ApKeyIndex 0x%03x not found", app_idx);
+ return;
+ }
+
+ key.net_idx = app->net_idx,
+ key.updated = app->updated,
+
memcpy(key.val[0], app->keys[0].val, 16);
memcpy(key.val[1], app->keys[1].val, 16);
@@ -1414,47 +1470,71 @@ static void store_pending_keys(void)
clear_net_key(update->key_idx);
}
} else {
- if (update->app_key) {
- struct bt_mesh_app_key *key;
+ store_subnet(update->key_idx);
+ }
- key = bt_mesh_app_key_find(update->key_idx);
- if (key) {
- store_app_key(key);
- } else {
- BT_WARN("AppKeyIndex 0x%03x not found",
- update->key_idx);
- }
+ update->valid = 0;
+ }
+}
- } else {
- struct bt_mesh_subnet *sub;
+static void clear_cdb(void)
+{
+ int err;
- sub = bt_mesh_subnet_get(update->key_idx);
- if (sub) {
- store_net_key(sub);
- } else {
- BT_WARN("NetKeyIndex 0x%03x not found",
- update->key_idx);
- }
- }
- }
+ err = settings_save_one("bt/mesh/cdb/Net", NULL);
+ if (err) {
+ BT_ERR("Failed to clear Network");
+ } else {
+ BT_DBG("Cleared Network");
+ }
+}
- update->valid = 0;
+static void store_pending_cdb(void)
+{
+ char buf[BT_SETTINGS_SIZE(sizeof(struct cdb_net_val))];
+ struct cdb_net_val net;
+ int err;
+ char *str;
+
+ BT_DBG("");
+
+ net.iv_index = bt_mesh_cdb.iv_index;
+ net.iv_update = atomic_test_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_IVU_IN_PROGRESS);
+
+ str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf));
+ if (!str) {
+ BT_ERR("Unable to encode Network as value");
+ return;
+ }
+ err = settings_save_one("bt/mesh/cdb/Net", str);
+ if (err) {
+ BT_ERR("Failed to store Network value");
+ } else {
+ BT_DBG("Stored Network value");
}
}
-static void store_node(struct bt_mesh_node *node)
+static void store_cdb_node(const struct bt_mesh_cdb_node *node)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct node_val))];
struct node_val val;
- char path[20];
+ char path[30];
char *str;
int err;
val.net_idx = node->net_idx;
val.num_elem = node->num_elem;
+ val.flags = 0;
+
+ if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) {
+ val.flags |= F_NODE_CONFIGURED;
+ }
+
+ memcpy(val.uuid, node->uuid, 16);
memcpy(val.dev_key, node->dev_key, 16);
- snprintk(path, sizeof(path), "bt_mesh/Node/%x", node->addr);
+ snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", node->addr);
str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf));
if (!str) {
@@ -1471,14 +1551,14 @@ static void store_node(struct bt_mesh_node *node)
}
}
-static void clear_node(u16_t addr)
+static void clear_cdb_node(uint16_t addr)
{
- char path[20];
+ char path[30];
int err;
BT_DBG("Node 0x%04x", addr);
- snprintk(path, sizeof(path), "bt_mesh/Node/%x", addr);
+ snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", addr);
err = settings_save_one(path, NULL);
if (err) {
BT_ERR("Failed to clear Node 0x%04x", addr);
@@ -1487,25 +1567,27 @@ static void clear_node(u16_t addr)
}
}
-static void store_pending_nodes(void)
+static void store_pending_cdb_nodes(void)
{
int i;
- for (i = 0; i < ARRAY_SIZE(node_updates); ++i) {
- struct node_update *update = &node_updates[i];
+ for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) {
+ struct node_update *update = &cdb_node_updates[i];
if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
continue;
}
+ BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear);
+
if (update->clear) {
- clear_node(update->addr);
+ clear_cdb_node(update->addr);
} else {
- struct bt_mesh_node *node;
+ struct bt_mesh_cdb_node *node;
- node = bt_mesh_node_find(update->addr);
+ node = bt_mesh_cdb_node_get(update->addr);
if (node) {
- store_node(node);
+ store_cdb_node(node);
} else {
BT_WARN("Node 0x%04x not found", update->addr);
}
@@ -1515,8 +1597,139 @@ static void store_pending_nodes(void)
}
}
-static struct node_update *node_update_find(u16_t addr,
- struct node_update **free_slot)
+static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
+{
+ char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))];
+ struct net_key_val key;
+ char path[30];
+ int err;
+ char *str;
+
+ BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
+ bt_hex(sub->keys[0].net_key, 16));
+
+ memcpy(&key.val[0], sub->keys[0].net_key, 16);
+ memcpy(&key.val[1], sub->keys[1].net_key, 16);
+ key.kr_flag = sub->kr_flag;
+ key.kr_phase = sub->kr_phase;
+
+ snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx);
+
+
+ str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf));
+ if (!str) {
+ BT_ERR("Unable to encode Subnet as value");
+ return;
+ }
+ err = settings_save_one(path, str);
+ if (err) {
+ BT_ERR("Failed to store Subnet value");
+ } else {
+ BT_DBG("Stored Subnet value");
+ }
+}
+
+static void clear_cdb_subnet(uint16_t net_idx)
+{
+ char path[30];
+ int err;
+
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
+
+ snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", net_idx);
+ err = settings_save_one(path, NULL);
+ if (err) {
+ BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx);
+ } else {
+ BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx);
+ }
+}
+
+static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app)
+{
+ char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))];
+ struct app_key_val key;
+ char path[30];
+ int err;
+ char *str;
+
+ key.net_idx = app->net_idx;
+ key.updated = false;
+ memcpy(key.val[0], app->keys[0].app_key, 16);
+ memcpy(key.val[1], app->keys[1].app_key, 16);
+
+ snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app->app_idx);
+
+ str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf));
+ err = settings_save_one(path, str);
+ if (err) {
+ BT_ERR("Failed to store AppKey");
+ } else {
+ BT_DBG("Stored AppKey");
+ }
+}
+
+static void clear_cdb_app_key(uint16_t app_idx)
+{
+ char path[30];
+ int err;
+
+ snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app_idx);
+ err = settings_save_one(path, NULL);
+ if (err) {
+ BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx);
+ } else {
+ BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx);
+ }
+}
+
+static void store_pending_cdb_keys(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
+ struct key_update *update = &cdb_key_updates[i];
+
+ if (!update->valid) {
+ continue;
+ }
+
+ if (update->clear) {
+ if (update->app_key) {
+ clear_cdb_app_key(update->key_idx);
+ } else {
+ clear_cdb_subnet(update->key_idx);
+ }
+ } else {
+ if (update->app_key) {
+ struct bt_mesh_cdb_app_key *key;
+
+ key = bt_mesh_cdb_app_key_get(update->key_idx);
+ if (key) {
+ store_cdb_app_key(key);
+ } else {
+ BT_WARN("AppKeyIndex 0x%03x not found",
+ update->key_idx);
+ }
+ } else {
+ struct bt_mesh_cdb_subnet *sub;
+
+ sub = bt_mesh_cdb_subnet_get(update->key_idx);
+ if (sub) {
+ store_cdb_subnet(sub);
+ } else {
+ BT_WARN("NetKeyIndex 0x%03x not found",
+ update->key_idx);
+ }
+ }
+ }
+
+ update->valid = 0U;
+ }
+}
+
+static struct node_update *cdb_node_update_find(uint16_t addr,
+ struct node_update **free_slot)
{
struct node_update *match;
int i;
@@ -1524,8 +1737,8 @@ static struct node_update *node_update_find(u16_t addr,
match = NULL;
*free_slot = NULL;
- for (i = 0; i < ARRAY_SIZE(node_updates); i++) {
- struct node_update *update = &node_updates[i];
+ for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) {
+ struct node_update *update = &cdb_node_updates[i];
if (update->addr == BT_MESH_ADDR_UNASSIGNED) {
*free_slot = update;
@@ -1543,7 +1756,7 @@ static struct node_update *node_update_find(u16_t addr,
static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
const char *key, char *path, size_t path_len)
{
- u16_t mod_key = (((u16_t)mod->elem_idx << 8) | mod->mod_idx);
+ uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx);
if (vnd) {
snprintk(path, path_len, "bt_mesh/v/%x/%s", mod_key, key);
@@ -1554,7 +1767,7 @@ static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
{
- u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
+ uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
char buf[BT_SETTINGS_SIZE(sizeof(keys))];
char path[20];
int i, count, err;
@@ -1590,7 +1803,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
{
- u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
+ uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
char buf[BT_SETTINGS_SIZE(sizeof(groups))];
char path[20];
int i, count, err;
@@ -1690,19 +1903,20 @@ static void store_pending_mod(struct bt_mesh_model *mod,
static void store_pending_va(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct va_val))];
- struct label *lab;
+ struct bt_mesh_va *lab;
struct va_val va;
char path[18];
char *val;
- u16_t i;
+ uint16_t i;
int err = 0;
- for (i = 0; (lab = get_label(i)) != NULL; i++) {
- if (!atomic_test_and_clear_bit(lab->flags,
- BT_MESH_VA_CHANGED)) {
+ for (i = 0; (lab = bt_mesh_va_get(i)) != NULL; i++) {
+ if (!lab->changed) {
continue;
}
+ lab->changed = 0U;
+
snprintk(path, sizeof(path), "bt_mesh/Va/%x", i);
if (IS_VA_DEL(lab)) {
@@ -1738,9 +1952,9 @@ static void store_pending(struct ble_npl_event *work)
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) {
if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
- store_pending_rpl();
+ bt_mesh_rpl_foreach(store_pending_rpl, NULL);
} else {
- clear_rpl();
+ bt_mesh_rpl_foreach(clear_rpl, NULL);
}
}
@@ -1788,9 +2002,26 @@ static void store_pending(struct ble_npl_event *work)
store_pending_va();
}
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NODES_PENDING)) {
- store_pending_nodes();
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_SUBNET_PENDING)) {
+ if (atomic_test_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_VALID)) {
+ store_pending_cdb();
+ } else {
+ clear_cdb();
+ }
+ }
+
+ if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_NODES_PENDING)) {
+ store_pending_cdb_nodes();
+ }
+
+ if (atomic_test_and_clear_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_KEYS_PENDING)) {
+ store_pending_cdb_keys();
+ }
}
}
@@ -1800,7 +2031,7 @@ void bt_mesh_store_rpl(struct bt_mesh_rpl *entry)
schedule_store(BT_MESH_RPL_PENDING);
}
-static struct key_update *key_update_find(bool app_key, u16_t key_idx,
+static struct key_update *key_update_find(bool app_key, uint16_t key_idx,
struct key_update **free_slot)
{
struct key_update *match;
@@ -1829,13 +2060,13 @@ static struct key_update *key_update_find(bool app_key, u16_t key_idx,
return match;
}
-void bt_mesh_store_subnet(struct bt_mesh_subnet *sub)
+void bt_mesh_store_subnet(uint16_t net_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
- update = key_update_find(false, sub->net_idx, &free_slot);
+ update = key_update_find(false, net_idx, &free_slot);
if (update) {
update->clear = 0;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1843,25 +2074,25 @@ void bt_mesh_store_subnet(struct bt_mesh_subnet *sub)
}
if (!free_slot) {
- store_net_key(sub);
+ store_subnet(net_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = sub->net_idx;
+ free_slot->key_idx = net_idx;
free_slot->app_key = 0;
free_slot->clear = 0;
schedule_store(BT_MESH_KEYS_PENDING);
}
-void bt_mesh_store_app_key(struct bt_mesh_app_key *key)
+void bt_mesh_store_app_key(uint16_t app_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+ BT_DBG("AppKeyIndex 0x%03x", app_idx);
- update = key_update_find(true, key->app_idx, &free_slot);
+ update = key_update_find(true, app_idx, &free_slot);
if (update) {
update->clear = 0;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1869,12 +2100,12 @@ void bt_mesh_store_app_key(struct bt_mesh_app_key *key)
}
if (!free_slot) {
- store_app_key(key);
+ store_app(app_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = key->app_idx;
+ free_slot->key_idx = app_idx;
free_slot->app_key = 1;
free_slot->clear = 0;
@@ -1898,13 +2129,13 @@ void bt_mesh_clear_net(void)
schedule_store(BT_MESH_CFG_PENDING);
}
-void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub)
+void bt_mesh_clear_subnet(uint16_t net_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
- update = key_update_find(false, sub->net_idx, &free_slot);
+ update = key_update_find(false, net_idx, &free_slot);
if (update) {
update->clear = 1;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1912,25 +2143,25 @@ void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub)
}
if (!free_slot) {
- clear_net_key(sub->net_idx);
+ clear_net_key(net_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = sub->net_idx;
+ free_slot->key_idx = net_idx;
free_slot->app_key = 0;
free_slot->clear = 1;
schedule_store(BT_MESH_KEYS_PENDING);
}
-void bt_mesh_clear_app_key(struct bt_mesh_app_key *key)
+void bt_mesh_clear_app_key(uint16_t app_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+ BT_DBG("AppKeyIndex 0x%03x", app_idx);
- update = key_update_find(true, key->app_idx, &free_slot);
+ update = key_update_find(true, app_idx, &free_slot);
if (update) {
update->clear = 1;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1938,12 +2169,12 @@ void bt_mesh_clear_app_key(struct bt_mesh_app_key *key)
}
if (!free_slot) {
- clear_app_key(key->app_idx);
+ clear_app_key(app_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = key->app_idx;
+ free_slot->key_idx = app_idx;
free_slot->app_key = 1;
free_slot->clear = 1;
@@ -1979,64 +2210,215 @@ void bt_mesh_store_label(void)
schedule_store(BT_MESH_VA_PENDING);
}
-void bt_mesh_store_node(struct bt_mesh_node *node)
+static void schedule_cdb_store(int flag)
+{
+ atomic_set_bit(bt_mesh_cdb.flags, flag);
+ k_delayed_work_submit(&pending_store, K_NO_WAIT);
+}
+
+void bt_mesh_store_cdb(void)
+{
+ schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING);
+}
+
+void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node)
{
struct node_update *update, *free_slot;
BT_DBG("Node 0x%04x", node->addr);
- update = node_update_find(node->addr, &free_slot);
+ update = cdb_node_update_find(node->addr, &free_slot);
if (update) {
update->clear = false;
- schedule_store(BT_MESH_NODES_PENDING);
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
return;
}
if (!free_slot) {
- store_node(node);
+ store_cdb_node(node);
return;
}
free_slot->addr = node->addr;
+ free_slot->clear = false;
- schedule_store(BT_MESH_NODES_PENDING);
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
}
-void bt_mesh_clear_node(struct bt_mesh_node *node)
+void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node)
{
struct node_update *update, *free_slot;
BT_DBG("Node 0x%04x", node->addr);
- update = node_update_find(node->addr, &free_slot);
+ update = cdb_node_update_find(node->addr, &free_slot);
if (update) {
update->clear = true;
- schedule_store(BT_MESH_NODES_PENDING);
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
return;
}
if (!free_slot) {
- clear_node(node->addr);
+ clear_cdb_node(node->addr);
return;
}
free_slot->addr = node->addr;
+ free_slot->clear = true;
+
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
+}
+
+/* TODO: Could be shared with key_update_find? */
+static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx,
+ struct key_update **free_slot)
+{
+ struct key_update *match;
+ int i;
+
+ match = NULL;
+ *free_slot = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) {
+ struct key_update *update = &cdb_key_updates[i];
+
+ if (!update->valid) {
+ *free_slot = update;
+ continue;
+ }
+
+ if (update->app_key != app_key) {
+ continue;
+ }
+
+ if (update->key_idx == key_idx) {
+ match = update;
+ }
+ }
- schedule_store(BT_MESH_NODES_PENDING);
+ return match;
+}
+
+void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub)
+{
+ struct key_update *update, *free_slot;
+
+ BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+
+ update = cdb_key_update_find(false, sub->net_idx, &free_slot);
+ if (update) {
+ update->clear = 0U;
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ store_cdb_subnet(sub);
+ return;
+ }
+
+ free_slot->valid = 1U;
+ free_slot->key_idx = sub->net_idx;
+ free_slot->app_key = 0U;
+ free_slot->clear = 0U;
+
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub)
+{
+ struct key_update *update, *free_slot;
+
+ BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+
+ update = cdb_key_update_find(false, sub->net_idx, &free_slot);
+ if (update) {
+ update->clear = 1U;
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ clear_cdb_subnet(sub->net_idx);
+ return;
+ }
+
+ free_slot->valid = 1U;
+ free_slot->key_idx = sub->net_idx;
+ free_slot->app_key = 0U;
+ free_slot->clear = 1U;
+
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *key)
+{
+ struct key_update *update, *free_slot;
+
+ BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+
+ update = cdb_key_update_find(true, key->app_idx, &free_slot);
+ if (update) {
+ update->clear = 0U;
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ store_cdb_app_key(key);
+ return;
+ }
+
+ free_slot->valid = 1U;
+ free_slot->key_idx = key->app_idx;
+ free_slot->app_key = 1U;
+ free_slot->clear = 0U;
+
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+}
+
+void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *key)
+{
+ struct key_update *update, *free_slot;
+
+ BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+
+ update = cdb_key_update_find(true, key->app_idx, &free_slot);
+ if (update) {
+ update->clear = 1U;
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
+ return;
+ }
+
+ if (!free_slot) {
+ clear_cdb_app_key(key->app_idx);
+ return;
+ }
+
+ free_slot->valid = 1U;
+ free_slot->key_idx = key->app_idx;
+ free_slot->app_key = 1U;
+ free_slot->clear = 1U;
+
+ schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING);
}
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
- const void *data, size_t data_len)
+ const char *name, const void *data,
+ size_t data_len)
{
- char path[20];
+ char path[30];
char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))];
char *val;
int err;
encode_mod_path(mod, vnd, "data", path, sizeof(path));
+ if (name) {
+ strcat(path, "/");
+ strncat(path, name, 8);
+ }
if (data_len) {
- mod->flags |= BT_MESH_MOD_DATA_PRESENT;
val = settings_str_from_bytes(data, data_len,
buf, sizeof(buf));
if (!val) {
@@ -2044,12 +2426,8 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
return -EINVAL;
}
err = settings_save_one(path, val);
- } else if (mod->flags & BT_MESH_MOD_DATA_PRESENT) {
- mod->flags &= ~BT_MESH_MOD_DATA_PRESENT;
- err = settings_save_one(path, NULL);
} else {
- /* Nothing to delete */
- err = 0;
+ err = settings_save_one(path, NULL);
}
if (err) {
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h
index c630814e..9060a14a 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h
@@ -8,20 +8,25 @@ void bt_mesh_store_net(void);
void bt_mesh_store_iv(bool only_duration);
void bt_mesh_store_seq(void);
void bt_mesh_store_rpl(struct bt_mesh_rpl *rpl);
-void bt_mesh_store_subnet(struct bt_mesh_subnet *sub);
-void bt_mesh_store_app_key(struct bt_mesh_app_key *key);
+void bt_mesh_store_subnet(uint16_t net_idx);
+void bt_mesh_store_app_key(uint16_t app_idx);
void bt_mesh_store_hb_pub(void);
void bt_mesh_store_cfg(void);
void bt_mesh_store_mod_bind(struct bt_mesh_model *mod);
void bt_mesh_store_mod_sub(struct bt_mesh_model *mod);
void bt_mesh_store_mod_pub(struct bt_mesh_model *mod);
void bt_mesh_store_label(void);
-void bt_mesh_store_node(struct bt_mesh_node *node);
+void bt_mesh_store_cdb(void);
+void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node);
+void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub);
+void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *app);
void bt_mesh_clear_net(void);
-void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);
-void bt_mesh_clear_app_key(struct bt_mesh_app_key *key);
+void bt_mesh_clear_subnet(uint16_t net_idx);
+void bt_mesh_clear_app_key(uint16_t app_idx);
void bt_mesh_clear_rpl(void);
-void bt_mesh_clear_node(struct bt_mesh_node *node);
+void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node);
+void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub);
+void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *app);
void bt_mesh_settings_init(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c
index 91fbd978..d597ed6d 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c
@@ -25,6 +25,7 @@
/* Private includes for raw Network & Transport layer access */
#include "net.h"
+#include "rpl.h"
#include "access.h"
#include "mesh_priv.h"
#include "lpn.h"
@@ -55,50 +56,29 @@ static struct os_eventq mesh_shell_queue;
#define VND_MODEL_ID_1 0x1234
/* Default net, app & dev key values, unless otherwise specified */
-static const u8_t default_key[16] = {
+static const uint8_t default_key[16] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
};
static struct {
- u16_t local;
- u16_t dst;
- u16_t net_idx;
- u16_t app_idx;
+ uint16_t local;
+ uint16_t dst;
+ uint16_t net_idx;
+ uint16_t app_idx;
} net = {
.local = BT_MESH_ADDR_UNASSIGNED,
.dst = BT_MESH_ADDR_UNASSIGNED,
};
-static struct bt_mesh_cfg_srv cfg_srv = {
- .relay = BT_MESH_RELAY_DISABLED,
- .beacon = BT_MESH_BEACON_ENABLED,
-#if MYNEWT_VAL(BLE_MESH_FRIEND)
- .frnd = BT_MESH_FRIEND_DISABLED,
-#else
- .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
-#endif
-#if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
- .gatt_proxy = BT_MESH_GATT_PROXY_DISABLED,
-#else
- .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
-#endif
-
- .default_ttl = 7,
-
- /* 3 transmissions with 20ms interval */
- .net_transmit = BT_MESH_TRANSMIT(2, 20),
- .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
-};
-
#define CUR_FAULTS_MAX 4
-static u8_t cur_faults[CUR_FAULTS_MAX];
-static u8_t reg_faults[CUR_FAULTS_MAX * 2];
+static uint8_t cur_faults[CUR_FAULTS_MAX];
+static uint8_t reg_faults[CUR_FAULTS_MAX * 2];
-static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
+static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
{
- u8_t i, limit = *count;
+ uint8_t i, limit = *count;
for (i = 0, *count = 0; i < faults_size && *count < limit; i++) {
if (faults[i]) {
@@ -108,8 +88,8 @@ static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
}
}
-static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
- u16_t *company_id, u8_t *faults, u8_t *fault_count)
+static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id,
+ uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
{
printk("Sending current faults\n");
@@ -121,8 +101,8 @@ static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
return 0;
}
-static int fault_get_reg(struct bt_mesh_model *model, u16_t cid,
- u8_t *test_id, u8_t *faults, u8_t *fault_count)
+static int fault_get_reg(struct bt_mesh_model *model, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
{
if (cid != CID_VENDOR) {
printk("Faults requested for unknown Company ID 0x%04x\n", cid);
@@ -189,7 +169,7 @@ static struct bt_mesh_cfg_cli cfg_cli = {
#endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
#if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
-void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
+void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count)
{
size_t i;
@@ -207,8 +187,8 @@ void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
}
}
-static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr,
- u8_t test_id, u16_t cid, u8_t *faults,
+static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
+ uint8_t test_id, uint16_t cid, uint8_t *faults,
size_t fault_count)
{
printk("Health Current Status from 0x%04x\n", addr);
@@ -242,22 +222,22 @@ static struct bt_mesh_light_lightness_srv light_lightness_srv = {
.set = light_model_light_lightness_set,
};
-void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
- int (*set)(struct bt_mesh_model *model, u8_t state))
+void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state),
+ int (*set)(struct bt_mesh_model *model, uint8_t state))
{
gen_onoff_srv.get = get;
gen_onoff_srv.set = set;
}
-void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
- int (*set)(struct bt_mesh_model *model, s16_t level))
+void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level))
{
gen_level_srv.get = get;
gen_level_srv.set = set;
}
-void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
- int (*set)(struct bt_mesh_model *model, s16_t level))
+void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level))
{
light_lightness_srv.get = get;
light_lightness_srv.set = set;
@@ -265,7 +245,7 @@ void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model,
#endif
static struct bt_mesh_model root_models[] = {
- BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
#if MYNEWT_VAL(BLE_MESH_CFG_CLI)
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
@@ -297,7 +277,7 @@ static const struct bt_mesh_comp comp = {
.elem_count = ARRAY_SIZE(elements),
};
-static u8_t hex2val(char c)
+static uint8_t hex2val(char c)
{
if (c >= '0' && c <= '9') {
return c - '0';
@@ -310,7 +290,54 @@ static u8_t hex2val(char c)
}
}
-static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
+int char2hex(char c, uint8_t *x)
+{
+ if (c >= '0' && c <= '9') {
+ *x = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ *x = c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ *x = c - 'A' + 10;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int hex2char(uint8_t x, char *c)
+{
+ if (x <= 9) {
+ *c = x + '0';
+ } else if (x <= 15) {
+ *c = x - 10 + 'a';
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)
+{
+ if ((hexlen + 1) < buflen * 2) {
+ return 0;
+ }
+
+ for (size_t i = 0; i < buflen; i++) {
+ if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) {
+ return 0;
+ }
+ if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) {
+ return 0;
+ }
+ }
+
+ hex[2 * buflen] = '\0';
+ return 2 * buflen;
+}
+
+static size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len)
{
size_t len = 0;
@@ -328,7 +355,7 @@ static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
return len;
}
-static void prov_complete(u16_t net_idx, u16_t addr)
+static void prov_complete(uint16_t net_idx, uint16_t addr)
{
printk("Local node provisioned, net_idx 0x%04x address 0x%04x\n",
net_idx, addr);
@@ -337,7 +364,8 @@ static void prov_complete(u16_t net_idx, u16_t addr)
net.dst = addr;
}
-static void prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
+static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem)
{
printk("Node provisioned, net_idx 0x%04x address "
"0x%04x elements %d", net_idx, addr, num_elem);
@@ -369,7 +397,7 @@ static int output_string(const char *str)
}
static bt_mesh_input_action_t input_act;
-static u8_t input_size;
+static uint8_t input_size;
static int cmd_input_num(int argc, char *argv[])
{
@@ -437,7 +465,7 @@ struct shell_cmd_help cmd_input_str_help = {
NULL, "<string>", NULL
};
-static int input(bt_mesh_input_action_t act, u8_t size)
+static int input(bt_mesh_input_action_t act, uint8_t size)
{
switch (act) {
case BT_MESH_ENTER_NUMBER:
@@ -481,9 +509,9 @@ static void link_close(bt_mesh_prov_bearer_t bearer)
printk("Provisioning link closed on %s\n", bearer2str(bearer));
}
-static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
+static uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
-static u8_t static_val[16];
+static uint8_t static_val[16];
static struct bt_mesh_prov prov = {
.uuid = dev_uuid,
@@ -534,7 +562,7 @@ struct shell_cmd_help cmd_static_oob_help = {
static int cmd_uuid(int argc, char *argv[])
{
- u8_t uuid[16];
+ uint8_t uuid[16];
size_t len;
if (argc < 2) {
@@ -560,12 +588,38 @@ struct shell_cmd_help cmd_uuid_help = {
static int cmd_reset(int argc, char *argv[])
{
- bt_mesh_reset();
- printk("Local node reset complete\n");
+ uint16_t addr;
+ if (argc < 2) {
+ return -EINVAL;
+ }
+
+ addr = strtoul(argv[1], NULL, 0);
+
+ if (addr == net.local) {
+ bt_mesh_reset();
+ printk("Local node reset complete");
+ } else {
+ int err;
+ bool reset = false;
+
+ err = bt_mesh_cfg_node_reset(net.net_idx, net.dst, &reset);
+ if (err) {
+ printk("Unable to send "
+ "Remote Node Reset (err %d)", err);
+ return 0;
+ }
+
+ printk("Remote node reset complete");
+ }
+
return 0;
}
-static u8_t str2u8(const char *str)
+struct shell_cmd_help cmd_reset_help = {
+ NULL, "<addr>", NULL
+};
+
+static uint8_t str2u8(const char *str)
{
if (isdigit(str[0])) {
return strtoul(str, NULL, 0);
@@ -631,7 +685,7 @@ static int cmd_poll(int argc, char *argv[])
return 0;
}
-static void lpn_cb(u16_t friend_addr, bool established)
+static void lpn_cb(uint16_t friend_addr, bool established)
{
if (established) {
printk("Friendship (as LPN) established to Friend 0x%04x\n",
@@ -784,8 +838,6 @@ static int cmd_net_send(int argc, char *argv[])
struct bt_mesh_net_tx tx = {
.ctx = &ctx,
.src = net.local,
- .xmit = bt_mesh_net_transmit_get(),
- .sub = bt_mesh_subnet_get(net.net_idx),
};
size_t len;
int err = 0;
@@ -795,12 +847,6 @@ static int cmd_net_send(int argc, char *argv[])
goto done;
}
- if (!tx.sub) {
- printk("No matching subnet for NetKey Index 0x%04x\n",
- net.net_idx);
- goto done;
- }
-
net_buf_simple_init(msg, 0);
len = hex2bin(argv[1], msg->om_data, net_buf_simple_tailroom(msg) - 4);
net_buf_simple_add(msg, len);
@@ -828,7 +874,7 @@ static int cmd_rpl_clear(int argc, char *argv[])
#if MYNEWT_VAL(BLE_MESH_LOW_POWER)
static int cmd_lpn_subscribe(int argc, char *argv[])
{
- u16_t address;
+ uint16_t address;
if (argc < 2) {
return -EINVAL;
@@ -849,7 +895,7 @@ struct shell_cmd_help cmd_lpn_subscribe_help = {
static int cmd_lpn_unsubscribe(int argc, char *argv[])
{
- u16_t address;
+ uint16_t address;
if (argc < 2) {
return -EINVAL;
@@ -912,7 +958,7 @@ struct shell_cmd_help cmd_iv_update_test_help = {
int cmd_timeout(int argc, char *argv[])
{
- s32_t timeout;
+ int32_t timeout;
if (argc < 2) {
timeout = bt_mesh_cfg_cli_timeout_get();
@@ -952,7 +998,7 @@ struct shell_cmd_help cmd_timeout_help = {
static int cmd_get_comp(int argc, char *argv[])
{
struct os_mbuf *comp = NET_BUF_SIMPLE(32);
- u8_t status, page = 0x00;
+ uint8_t status, page = 0x00;
int err = 0;
if (argc > 1) {
@@ -980,8 +1026,8 @@ static int cmd_get_comp(int argc, char *argv[])
printk("\tFeatures 0x%04x\n", net_buf_simple_pull_le16(comp));
while (comp->om_len > 4) {
- u8_t sig, vnd;
- u16_t loc;
+ uint8_t sig, vnd;
+ uint16_t loc;
int i;
loc = net_buf_simple_pull_le16(comp);
@@ -1002,7 +1048,7 @@ static int cmd_get_comp(int argc, char *argv[])
}
for (i = 0; i < sig; i++) {
- u16_t mod_id = net_buf_simple_pull_le16(comp);
+ uint16_t mod_id = net_buf_simple_pull_le16(comp);
printk("\t\t\t0x%04x\n", mod_id);
}
@@ -1014,8 +1060,8 @@ static int cmd_get_comp(int argc, char *argv[])
}
for (i = 0; i < vnd; i++) {
- u16_t cid = net_buf_simple_pull_le16(comp);
- u16_t mod_id = net_buf_simple_pull_le16(comp);
+ uint16_t cid = net_buf_simple_pull_le16(comp);
+ uint16_t mod_id = net_buf_simple_pull_le16(comp);
printk("\t\t\tCompany 0x%04x: 0x%04x\n", cid, mod_id);
}
@@ -1032,13 +1078,13 @@ struct shell_cmd_help cmd_get_comp_help = {
static int cmd_beacon(int argc, char *argv[])
{
- u8_t status;
+ uint8_t status;
int err;
if (argc < 2) {
err = bt_mesh_cfg_beacon_get(net.net_idx, net.dst, &status);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_beacon_set(net.net_idx, net.dst, val,
&status);
@@ -1054,19 +1100,49 @@ static int cmd_beacon(int argc, char *argv[])
return 0;
}
+static void print_unprovisioned_beacon(uint8_t uuid[16],
+ bt_mesh_prov_oob_info_t oob_info,
+ uint32_t *uri_hash)
+{
+ char uuid_hex_str[32 + 1];
+
+ bin2hex(uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
+
+ printk("UUID %s, OOB Info 0x%04x, URI Hash 0x%lx",
+ uuid_hex_str, oob_info,
+ (uri_hash == NULL ? 0 : *uri_hash));
+}
+
+static int cmd_beacon_listen(int argc, char *argv[])
+{
+ uint8_t val = str2u8(argv[1]);
+
+ if (val) {
+ prov.unprovisioned_beacon = print_unprovisioned_beacon;
+ } else {
+ prov.unprovisioned_beacon = NULL;
+ }
+
+ return 0;
+}
+
struct shell_cmd_help cmd_beacon_help = {
NULL, "[val: off, on]", NULL
};
+struct shell_cmd_help cmd_beacon_listen_help = {
+ NULL, "[val: off, on]", NULL
+};
+
static int cmd_ttl(int argc, char *argv[])
{
- u8_t ttl;
+ uint8_t ttl;
int err;
if (argc < 2) {
err = bt_mesh_cfg_ttl_get(net.net_idx, net.dst, &ttl);
} else {
- u8_t val = strtoul(argv[1], NULL, 0);
+ uint8_t val = strtoul(argv[1], NULL, 0);
err = bt_mesh_cfg_ttl_set(net.net_idx, net.dst, val, &ttl);
}
@@ -1087,13 +1163,13 @@ struct shell_cmd_help cmd_ttl_help = {
static int cmd_friend(int argc, char *argv[])
{
- u8_t frnd;
+ uint8_t frnd;
int err;
if (argc < 2) {
err = bt_mesh_cfg_friend_get(net.net_idx, net.dst, &frnd);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_friend_set(net.net_idx, net.dst, val, &frnd);
}
@@ -1114,13 +1190,13 @@ struct shell_cmd_help cmd_friend_help = {
static int cmd_gatt_proxy(int argc, char *argv[])
{
- u8_t proxy;
+ uint8_t proxy;
int err;
if (argc < 2) {
err = bt_mesh_cfg_gatt_proxy_get(net.net_idx, net.dst, &proxy);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_gatt_proxy_set(net.net_idx, net.dst, val,
&proxy);
@@ -1140,17 +1216,60 @@ struct shell_cmd_help cmd_gatt_proxy_help = {
NULL, "[val: off, on]", NULL
};
+static int cmd_net_transmit(int argc, char *argv[])
+{
+ uint8_t transmit;
+ int err;
+
+ if (argc < 2) {
+ err = bt_mesh_cfg_net_transmit_get(net.net_idx,
+ net.dst, &transmit);
+ } else {
+ if (argc != 3) {
+ printk("Wrong number of input arguments"
+ "(2 arguments are required)");
+ return -EINVAL;
+ }
+
+ uint8_t count, interval, new_transmit;
+
+ count = strtoul(argv[1], NULL, 0);
+ interval = strtoul(argv[2], NULL, 0);
+
+ new_transmit = BT_MESH_TRANSMIT(count, interval);
+
+ err = bt_mesh_cfg_net_transmit_set(net.net_idx, net.dst,
+ new_transmit, &transmit);
+ }
+
+ if (err) {
+ printk("Unable to send network transmit"
+ " Get/Set (err %d)", err);
+ return 0;
+ }
+
+ printk("Transmit 0x%02x (count %u interval %ums)",
+ transmit, BT_MESH_TRANSMIT_COUNT(transmit),
+ BT_MESH_TRANSMIT_INT(transmit));
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_transmit_help = {
+ NULL, "[<count: 0-7> <interval: 10-320>]", NULL
+};
+
static int cmd_relay(int argc, char *argv[])
{
- u8_t relay, transmit;
+ uint8_t relay, transmit;
int err;
if (argc < 2) {
err = bt_mesh_cfg_relay_get(net.net_idx, net.dst, &relay,
&transmit);
} else {
- u8_t val = str2u8(argv[1]);
- u8_t count, interval, new_transmit;
+ uint8_t val = str2u8(argv[1]);
+ uint8_t count, interval, new_transmit;
if (val) {
if (argc > 2) {
@@ -1192,9 +1311,10 @@ struct shell_cmd_help cmd_relay_help = {
static int cmd_net_key_add(int argc, char *argv[])
{
- u8_t key_val[16];
- u16_t key_net_idx;
- u8_t status;
+ bool has_key_val = (argc > 2);
+ uint8_t key_val[16];
+ uint16_t key_net_idx;
+ uint8_t status;
int err;
if (argc < 2) {
@@ -1203,7 +1323,7 @@ static int cmd_net_key_add(int argc, char *argv[])
key_net_idx = strtoul(argv[1], NULL, 0);
- if (argc > 2) {
+ if (has_key_val) {
size_t len;
len = hex2bin(argv[3], key_val, sizeof(key_val));
@@ -1212,6 +1332,29 @@ static int cmd_net_key_add(int argc, char *argv[])
memcpy(key_val, default_key, sizeof(key_val));
}
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ struct bt_mesh_cdb_subnet *subnet;
+
+ subnet = bt_mesh_cdb_subnet_get(key_net_idx);
+ if (subnet) {
+ if (has_key_val) {
+ printk("Subnet 0x%03x already has a value", key_net_idx);
+ return 0;
+ }
+
+ memcpy(key_val, subnet->keys[0].net_key, 16);
+ } else {
+ subnet = bt_mesh_cdb_subnet_alloc(key_net_idx);
+ if (!subnet) {
+ printk("No space for subnet in cdb");
+ return 0;
+ }
+
+ memcpy(subnet->keys[0].net_key, key_val, 16);
+ bt_mesh_cdb_subnet_store(subnet);
+ }
+ }
+
err = bt_mesh_cfg_net_key_add(net.net_idx, net.dst, key_net_idx,
key_val, &status);
if (err) {
@@ -1232,11 +1375,67 @@ struct shell_cmd_help cmd_net_key_add_help = {
NULL, "<NetKeyIndex> [val]", NULL
};
+static int cmd_net_key_get(int argc, char *argv[])
+{
+ uint16_t keys[16];
+ size_t cnt;
+ int err, i;
+
+ cnt = ARRAY_SIZE(keys);
+
+ err = bt_mesh_cfg_net_key_get(net.net_idx, net.dst, keys, &cnt);
+ if (err) {
+ printk("Unable to send NetKeyGet (err %d)", err);
+ return 0;
+ }
+
+ printk("NetKeys known by 0x%04x:", net.dst);
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%03x", keys[i]);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_key_get_help = {
+ NULL, NULL, NULL
+};
+
+static int cmd_net_key_del(int argc, char *argv[])
+{
+ uint16_t key_net_idx;
+ uint8_t status;
+ int err;
+
+ key_net_idx = strtoul(argv[1], NULL, 0);
+
+ err = bt_mesh_cfg_net_key_del(net.net_idx, net.dst, key_net_idx,
+ &status);
+ if (err) {
+ printk("Unable to send NetKeyDel (err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("NetKeyDel failed with status 0x%02x",
+ status);
+ } else {
+ printk("NetKey 0x%03x deleted", key_net_idx);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_key_del_help = {
+ NULL, "<NetKeyIndex>", NULL
+};
+
static int cmd_app_key_add(int argc, char *argv[])
{
- u8_t key_val[16];
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint8_t key_val[16];
+ uint16_t key_net_idx, key_app_idx;
+ bool has_key_val = (argc > 3);
+ uint8_t status;
int err;
if (argc < 3) {
@@ -1246,7 +1445,7 @@ static int cmd_app_key_add(int argc, char *argv[])
key_net_idx = strtoul(argv[1], NULL, 0);
key_app_idx = strtoul(argv[2], NULL, 0);
- if (argc > 3) {
+ if (has_key_val) {
size_t len;
len = hex2bin(argv[3], key_val, sizeof(key_val));
@@ -1255,6 +1454,30 @@ static int cmd_app_key_add(int argc, char *argv[])
memcpy(key_val, default_key, sizeof(key_val));
}
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ struct bt_mesh_cdb_app_key *app_key;
+
+ app_key = bt_mesh_cdb_app_key_get(key_app_idx);
+ if (app_key) {
+ if (has_key_val) {
+ printk("App key 0x%03x already has a value", key_app_idx);
+ return 0;
+ }
+
+ memcpy(key_val, app_key->keys[0].app_key, 16);
+ } else {
+ app_key = bt_mesh_cdb_app_key_alloc(key_net_idx,
+ key_app_idx);
+ if (!app_key) {
+ printk("No space for app key in cdb");
+ return 0;
+ }
+
+ memcpy(app_key->keys[0].app_key, key_val, 16);
+ bt_mesh_cdb_app_key_store(app_key);
+ }
+ }
+
err = bt_mesh_cfg_app_key_add(net.net_idx, net.dst, key_net_idx,
key_app_idx, key_val, &status);
if (err) {
@@ -1276,10 +1499,83 @@ struct shell_cmd_help cmd_app_key_add_help = {
NULL, "<NetKeyIndex> <AppKeyIndex> [val]", NULL
};
+static int cmd_app_key_get(int argc, char *argv[])
+{
+ uint16_t net_idx;
+ uint16_t keys[16];
+ size_t cnt;
+ uint8_t status;
+ int err, i;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+ cnt = ARRAY_SIZE(keys);
+
+ err = bt_mesh_cfg_app_key_get(net.net_idx, net.dst, net_idx, &status,
+ keys, &cnt);
+ if (err) {
+ printk("Unable to send AppKeyGet (err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("AppKeyGet failed with status 0x%02x",
+ status);
+ return 0;
+ }
+
+ printk(
+ "AppKeys for NetKey 0x%03x known by 0x%04x:", net_idx,
+ net.dst);
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%03x", keys[i]);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_app_key_get_help = {
+ NULL, "<NetKeyIndex>", NULL
+};
+
+static int cmd_app_key_del(int argc, char *argv[])
+{
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
+ int err;
+
+ if (argc < 3) {
+ return -EINVAL;
+ }
+
+ key_net_idx = strtoul(argv[1], NULL, 0);
+ key_app_idx = strtoul(argv[2], NULL, 0);
+
+ err = bt_mesh_cfg_app_key_del(net.net_idx, net.dst, key_net_idx,
+ key_app_idx, &status);
+ if (err) {
+ printk("Unable to send App Key del(err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("AppKeyDel failed with status 0x%02x",
+ status);
+ } else {
+ printk("AppKey deleted, NetKeyIndex 0x%04x "
+ "AppKeyIndex 0x%04x", key_net_idx, key_app_idx);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_app_key_del_help = {
+ NULL, "<NetKeyIndex> <AppKeyIndex>", NULL
+};
+
static int cmd_mod_app_bind(int argc, char *argv[])
{
- u16_t elem_addr, mod_app_idx, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1318,10 +1614,107 @@ struct shell_cmd_help cmd_mod_app_bind_help = {
NULL, "<addr> <AppIndex> <Model ID> [Company ID]", NULL
};
+static int cmd_mod_app_unbind(int argc, char *argv[])
+{
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint8_t status;
+ int err;
+
+ if (argc < 4) {
+ return -EINVAL;
+ }
+
+ elem_addr = strtoul(argv[1], NULL, 0);
+ mod_app_idx = strtoul(argv[2], NULL, 0);
+ mod_id = strtoul(argv[3], NULL, 0);
+
+ if (argc > 4) {
+ cid = strtoul(argv[4], NULL, 0);
+ err = bt_mesh_cfg_mod_app_unbind_vnd(net.net_idx, net.dst,
+ elem_addr, mod_app_idx,
+ mod_id, cid, &status);
+ } else {
+ err = bt_mesh_cfg_mod_app_unbind(net.net_idx, net.dst,
+ elem_addr, mod_app_idx, mod_id, &status);
+ }
+
+ if (err) {
+ printk("Unable to send Model App Unbind (err %d)",
+ err);
+ return 0;
+ }
+
+ if (status) {
+ printk("Model App Unbind failed with status 0x%02x",
+ status);
+ } else {
+ printk("AppKey successfully unbound");
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_mod_app_unbind_help = {
+ NULL, "<addr> <AppIndex> <Model ID> [Company ID]", NULL
+};
+
+static int cmd_mod_app_get(int argc,
+ char *argv[])
+{
+ uint16_t elem_addr, mod_id, cid;
+ uint16_t apps[16];
+ uint8_t status;
+ size_t cnt;
+ int err, i;
+
+ elem_addr = strtoul(argv[1], NULL, 0);
+ mod_id = strtoul(argv[2], NULL, 0);
+ cnt = ARRAY_SIZE(apps);
+
+ if (argc > 3) {
+ cid = strtoul(argv[3], NULL, 0);
+ err = bt_mesh_cfg_mod_app_get_vnd(net.net_idx, net.dst,
+ elem_addr, mod_id, cid,
+ &status, apps, &cnt);
+ } else {
+ err = bt_mesh_cfg_mod_app_get(net.net_idx, net.dst, elem_addr,
+ mod_id, &status, apps, &cnt);
+ }
+
+ if (err) {
+ printk("Unable to send Model App Get (err %d)",
+ err);
+ return 0;
+ }
+
+ if (status) {
+ printk("Model App Get failed with status 0x%02x",
+ status);
+ } else {
+ printk(
+ "Apps bound to Element 0x%04x, Model 0x%04x %s:",
+ elem_addr, mod_id, argc > 3 ? argv[3] : "(SIG)");
+
+ if (!cnt) {
+ printk("\tNone.");
+ }
+
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%04x", apps[i]);
+ }
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_mod_app_get_help = {
+ NULL, "<elem addr> <Model ID> [Company ID]", NULL
+};
+
static int cmd_mod_sub_add(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1363,8 +1756,8 @@ struct shell_cmd_help cmd_mod_sub_add_help = {
static int cmd_mod_sub_del(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1407,9 +1800,9 @@ struct shell_cmd_help cmd_mod_sub_del_help = {
static int cmd_mod_sub_add_va(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t label[16];
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t label[16];
+ uint8_t status;
size_t len;
int err;
@@ -1457,9 +1850,9 @@ struct shell_cmd_help cmd_mod_sub_add_va_help = {
static int cmd_mod_sub_del_va(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t label[16];
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t label[16];
+ uint8_t status;
size_t len;
int err;
@@ -1506,10 +1899,64 @@ struct shell_cmd_help cmd_mod_sub_del_va_help = {
NULL, "<elem addr> <Label UUID> <Model ID> [Company ID]", NULL
};
-static int mod_pub_get(u16_t addr, u16_t mod_id, u16_t cid)
+static int cmd_mod_sub_get(int argc,
+ char *argv[])
+{
+ uint16_t elem_addr, mod_id, cid;
+ uint16_t subs[16];
+ uint8_t status;
+ size_t cnt;
+ int err, i;
+
+ elem_addr = strtoul(argv[1], NULL, 0);
+ mod_id = strtoul(argv[2], NULL, 0);
+ cnt = ARRAY_SIZE(subs);
+
+ if (argc > 3) {
+ cid = strtoul(argv[3], NULL, 0);
+ err = bt_mesh_cfg_mod_sub_get_vnd(net.net_idx, net.dst,
+ elem_addr, mod_id, cid,
+ &status, subs, &cnt);
+ } else {
+ err = bt_mesh_cfg_mod_sub_get(net.net_idx, net.dst, elem_addr,
+ mod_id, &status, subs, &cnt);
+ }
+
+ if (err) {
+ printk("Unable to send Model Subscription Get "
+ "(err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("Model Subscription Get failed with "
+ "status 0x%02x", status);
+ } else {
+ printk(
+ "Model Subscriptions for Element 0x%04x, "
+ "Model 0x%04x %s:",
+ elem_addr, mod_id, argc > 3 ? argv[3] : "(SIG)");
+
+ if (!cnt) {
+ printk("\tNone.");
+ }
+
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%04x", subs[i]);
+ }
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_mod_sub_get_help = {
+ NULL, "<elem addr> <Model ID> [Company ID]", NULL
+};
+
+static int mod_pub_get(uint16_t addr, uint16_t mod_id, uint16_t cid)
{
struct bt_mesh_cfg_mod_pub pub;
- u8_t status;
+ uint8_t status;
int err;
if (cid == CID_NVAL) {
@@ -1546,11 +1993,11 @@ static int mod_pub_get(u16_t addr, u16_t mod_id, u16_t cid)
return 0;
}
-static int mod_pub_set(u16_t addr, u16_t mod_id, u16_t cid, char *argv[])
+static int mod_pub_set(uint16_t addr, uint16_t mod_id, uint16_t cid, char *argv[])
{
struct bt_mesh_cfg_mod_pub pub;
- u8_t status, count;
- u16_t interval;
+ uint8_t status, count;
+ uint16_t interval;
int err;
pub.addr = strtoul(argv[0], NULL, 0);
@@ -1598,7 +2045,7 @@ static int mod_pub_set(u16_t addr, u16_t mod_id, u16_t cid, char *argv[])
static int cmd_mod_pub(int argc, char *argv[])
{
- u16_t addr, mod_id, cid;
+ uint16_t addr, mod_id, cid;
if (argc < 3) {
return -EINVAL;
@@ -1650,7 +2097,7 @@ static void hb_sub_print(struct bt_mesh_cfg_hb_sub *sub)
static int hb_sub_get(int argc, char *argv[])
{
struct bt_mesh_cfg_hb_sub sub;
- u8_t status;
+ uint8_t status;
int err;
err = bt_mesh_cfg_hb_sub_get(net.net_idx, net.dst, &sub, &status);
@@ -1672,7 +2119,7 @@ static int hb_sub_get(int argc, char *argv[])
static int hb_sub_set(int argc, char *argv[])
{
struct bt_mesh_cfg_hb_sub sub;
- u8_t status;
+ uint8_t status;
int err;
sub.src = strtoul(argv[1], NULL, 0);
@@ -1715,7 +2162,7 @@ struct shell_cmd_help cmd_hb_sub_help = {
static int hb_pub_get(int argc, char *argv[])
{
struct bt_mesh_cfg_hb_pub pub;
- u8_t status;
+ uint8_t status;
int err;
err = bt_mesh_cfg_hb_pub_get(net.net_idx, net.dst, &pub, &status);
@@ -1742,7 +2189,7 @@ static int hb_pub_get(int argc, char *argv[])
static int hb_pub_set(int argc, char *argv[])
{
struct bt_mesh_cfg_hb_pub pub;
- u8_t status;
+ uint8_t status;
int err;
pub.dst = strtoul(argv[1], NULL, 0);
@@ -1787,7 +2234,7 @@ struct shell_cmd_help cmd_hb_pub_help = {
#endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
-#if MYNEWT_VAL(BLE_MESH_PROV)
+#if MYNEWT_VAL(BLE_MESH_PROV_DEVICE)
static int cmd_pb(bt_mesh_prov_bearer_t bearer, int argc, char *argv[])
{
int err;
@@ -1833,10 +2280,10 @@ static int cmd_pb_adv(int argc, char *argv[])
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
static int cmd_provision_adv(int argc, char *argv[])
{
- u8_t uuid[16];
- u8_t attention_duration;
- u16_t net_idx;
- u16_t addr;
+ uint8_t uuid[16];
+ uint8_t attention_duration;
+ uint16_t net_idx;
+ uint16_t addr;
size_t len;
int err;
@@ -1871,8 +2318,9 @@ static int cmd_pb_gatt(int argc, char *argv[])
static int cmd_provision(int argc, char *argv[])
{
- u16_t net_idx, addr;
- u32_t iv_index;
+ const uint8_t *net_key = default_key;
+ uint16_t net_idx, addr;
+ uint32_t iv_index;
int err;
if (argc < 3) {
@@ -1888,7 +2336,19 @@ static int cmd_provision(int argc, char *argv[])
iv_index = 0;
}
- err = bt_mesh_provision(default_key, net_idx, 0, iv_index, addr,
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ const struct bt_mesh_cdb_subnet *sub;
+
+ sub = bt_mesh_cdb_subnet_get(net_idx);
+ if (!sub) {
+ printk("No cdb entry for subnet 0x%03x", net_idx);
+ return 0;
+ }
+
+ net_key = sub->keys[sub->kr_flag].net_key;
+ }
+
+ err = bt_mesh_provision(net_key, net_idx, 0, iv_index, addr,
default_key);
if (err) {
printk("Provisioning failed (err %d)\n", err);
@@ -1905,10 +2365,10 @@ struct shell_cmd_help cmd_provision_help = {
static int cmd_fault_get(int argc, char *argv[])
{
- u8_t faults[32];
+ uint8_t faults[32];
size_t fault_count;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
int err;
if (argc < 2) {
@@ -1918,8 +2378,8 @@ static int cmd_fault_get(int argc, char *argv[])
cid = strtoul(argv[1], NULL, 0);
fault_count = sizeof(faults);
- err = bt_mesh_health_fault_get(net.net_idx, net.dst, net.app_idx, cid,
- &test_id, faults, &fault_count);
+ err = bt_mesh_health_fault_get(net.dst, net.app_idx, cid, &test_id,
+ faults, &fault_count);
if (err) {
printk("Failed to send Health Fault Get (err %d)\n", err);
} else {
@@ -1935,10 +2395,10 @@ struct shell_cmd_help cmd_fault_get_help = {
static int cmd_fault_clear(int argc, char *argv[])
{
- u8_t faults[32];
+ uint8_t faults[32];
size_t fault_count;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
int err;
if (argc < 2) {
@@ -1948,8 +2408,8 @@ static int cmd_fault_clear(int argc, char *argv[])
cid = strtoul(argv[1], NULL, 0);
fault_count = sizeof(faults);
- err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
- cid, &test_id, faults, &fault_count);
+ err = bt_mesh_health_fault_clear(net.dst, net.app_idx, cid,
+ &test_id, faults, &fault_count);
if (err) {
printk("Failed to send Health Fault Clear (err %d)\n", err);
} else {
@@ -1965,7 +2425,7 @@ struct shell_cmd_help cmd_fault_clear_help = {
static int cmd_fault_clear_unack(int argc, char *argv[])
{
- u16_t cid;
+ uint16_t cid;
int err;
if (argc < 2) {
@@ -1974,8 +2434,8 @@ static int cmd_fault_clear_unack(int argc, char *argv[])
cid = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
- cid, NULL, NULL, NULL);
+ err = bt_mesh_health_fault_clear(net.dst, net.app_idx, cid,
+ NULL, NULL, NULL);
if (err) {
printk("Health Fault Clear Unacknowledged failed (err %d)\n",
err);
@@ -1990,10 +2450,10 @@ struct shell_cmd_help cmd_fault_clear_unack_help = {
static int cmd_fault_test(int argc, char *argv[])
{
- u8_t faults[32];
+ uint8_t faults[32];
size_t fault_count;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
int err;
if (argc < 3) {
@@ -2004,8 +2464,8 @@ static int cmd_fault_test(int argc, char *argv[])
test_id = strtoul(argv[2], NULL, 0);
fault_count = sizeof(faults);
- err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
- cid, test_id, faults, &fault_count);
+ err = bt_mesh_health_fault_test(net.dst, net.app_idx, cid,
+ test_id, faults, &fault_count);
if (err) {
printk("Failed to send Health Fault Test (err %d)\n", err);
} else {
@@ -2021,8 +2481,8 @@ struct shell_cmd_help cmd_fault_test_help = {
static int cmd_fault_test_unack(int argc, char *argv[])
{
- u16_t cid;
- u8_t test_id;
+ uint16_t cid;
+ uint8_t test_id;
int err;
if (argc < 3) {
@@ -2032,8 +2492,8 @@ static int cmd_fault_test_unack(int argc, char *argv[])
cid = strtoul(argv[1], NULL, 0);
test_id = strtoul(argv[2], NULL, 0);
- err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
- cid, test_id, NULL, NULL);
+ err = bt_mesh_health_fault_test(net.dst, net.app_idx, cid,
+ test_id, NULL, NULL);
if (err) {
printk("Health Fault Test Unacknowledged failed (err %d)\n",
err);
@@ -2048,11 +2508,10 @@ struct shell_cmd_help cmd_fault_test_unack_help = {
static int cmd_period_get(int argc, char *argv[])
{
- u8_t divisor;
+ uint8_t divisor;
int err;
- err = bt_mesh_health_period_get(net.net_idx, net.dst, net.app_idx,
- &divisor);
+ err = bt_mesh_health_period_get(net.dst, net.app_idx, &divisor);
if (err) {
printk("Failed to send Health Period Get (err %d)\n", err);
} else {
@@ -2064,7 +2523,7 @@ static int cmd_period_get(int argc, char *argv[])
static int cmd_period_set(int argc, char *argv[])
{
- u8_t divisor, updated_divisor;
+ uint8_t divisor, updated_divisor;
int err;
if (argc < 2) {
@@ -2073,8 +2532,8 @@ static int cmd_period_set(int argc, char *argv[])
divisor = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
- divisor, &updated_divisor);
+ err = bt_mesh_health_period_set(net.dst, net.app_idx, divisor,
+ &updated_divisor);
if (err) {
printk("Failed to send Health Period Set (err %d)\n", err);
} else {
@@ -2090,7 +2549,7 @@ struct shell_cmd_help cmd_period_set_help = {
static int cmd_period_set_unack(int argc, char *argv[])
{
- u8_t divisor;
+ uint8_t divisor;
int err;
if (argc < 2) {
@@ -2099,8 +2558,7 @@ static int cmd_period_set_unack(int argc, char *argv[])
divisor = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
- divisor, NULL);
+ err = bt_mesh_health_period_set(net.dst, net.app_idx, divisor, NULL);
if (err) {
printk("Failed to send Health Period Set (err %d)\n", err);
}
@@ -2114,11 +2572,11 @@ struct shell_cmd_help cmd_period_set_unack_help = {
static int cmd_attention_get(int argc, char *argv[])
{
- u8_t attention;
+ uint8_t attention;
int err;
- err = bt_mesh_health_attention_get(net.net_idx, net.dst, net.app_idx,
- &attention);
+ err = bt_mesh_health_attention_get(net.dst, net.app_idx,
+ &attention);
if (err) {
printk("Failed to send Health Attention Get (err %d)\n", err);
} else {
@@ -2130,7 +2588,7 @@ static int cmd_attention_get(int argc, char *argv[])
static int cmd_attention_set(int argc, char *argv[])
{
- u8_t attention, updated_attention;
+ uint8_t attention, updated_attention;
int err;
if (argc < 2) {
@@ -2139,8 +2597,8 @@ static int cmd_attention_set(int argc, char *argv[])
attention = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
- attention, &updated_attention);
+ err = bt_mesh_health_attention_set(net.dst, net.app_idx, attention,
+ &updated_attention);
if (err) {
printk("Failed to send Health Attention Set (err %d)\n", err);
} else {
@@ -2156,7 +2614,7 @@ struct shell_cmd_help cmd_attention_set_help = {
static int cmd_attention_set_unack(int argc, char *argv[])
{
- u8_t attention;
+ uint8_t attention;
int err;
if (argc < 2) {
@@ -2165,8 +2623,8 @@ static int cmd_attention_set_unack(int argc, char *argv[])
attention = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
- attention, NULL);
+ err = bt_mesh_health_attention_set(net.dst, net.app_idx, attention,
+ NULL);
if (err) {
printk("Failed to send Health Attention Set (err %d)\n", err);
}
@@ -2182,8 +2640,8 @@ struct shell_cmd_help cmd_attention_set_unack_help = {
static int cmd_add_fault(int argc, char *argv[])
{
- u8_t fault_id;
- u8_t i;
+ uint8_t fault_id;
+ uint8_t i;
if (argc < 2) {
return -EINVAL;
@@ -2229,8 +2687,8 @@ struct shell_cmd_help cmd_add_fault_help = {
static int cmd_del_fault(int argc, char *argv[])
{
- u8_t fault_id;
- u8_t i;
+ uint8_t fault_id;
+ uint8_t i;
if (argc < 2) {
memset(cur_faults, 0, sizeof(cur_faults));
@@ -2261,10 +2719,337 @@ struct shell_cmd_help cmd_del_fault_help = {
NULL, "[Fault ID]", NULL
};
+#if BLE_MESH_CDB
+struct shell_cmd_help cmd_cdb_create_help = {
+ NULL, "[NetKey]", NULL
+};
+struct shell_cmd_help cmd_cdb_clear_help = {
+ NULL, NULL, NULL
+};
+struct shell_cmd_help cmd_cdb_show_help = {
+ NULL, NULL, NULL
+};
+struct shell_cmd_help cmd_cdb_node_add_help = {
+ NULL, "<UUID> <addr> <num-elem> "
+ "<NetKeyIdx> [DevKey]", NULL
+};
+struct shell_cmd_help cmd_cdb_node_del_help = {
+ NULL, "<addr>", NULL
+};
+struct shell_cmd_help cmd_cdb_subnet_add_help = {
+ NULL, "<NeyKeyIdx> [<NetKey>]", NULL
+};
+struct shell_cmd_help cmd_cdb_subnet_del_help = {
+ NULL, "<NetKeyIdx>", NULL
+};
+struct shell_cmd_help cmd_cdb_app_key_add_help = {
+ NULL, "<NetKeyIdx> <AppKeyIdx> [<AppKey>]", NULL
+};
+struct shell_cmd_help cmd_cdb_app_key_del_help = {
+ NULL, "<AppKeyIdx>", NULL
+};
+
+static int cmd_cdb_create(int argc, char *argv[])
+{
+ uint8_t net_key[16];
+ size_t len;
+ int err;
+
+ if (argc < 2) {
+ bt_rand(net_key, 16);
+ } else {
+ len = hex2bin(argv[1], net_key, sizeof(net_key));
+ memset(net_key + len, 0, sizeof(net_key) - len);
+ }
+
+ err = bt_mesh_cdb_create(net_key);
+ if (err < 0) {
+ printk("Failed to create CDB (err %d)", err);
+ }
+
+ return 0;
+}
+
+static int cmd_cdb_clear(int argc, char *argv[])
+{
+ bt_mesh_cdb_clear();
+
+ printk("Cleared CDB");
+
+ return 0;
+}
+
+static void cdb_print_nodes(void)
+{
+ char key_hex_str[32 + 1], uuid_hex_str[32 + 1];
+ struct bt_mesh_cdb_node *node;
+ int i, total = 0;
+ bool configured;
+
+ printk("Address Elements Flags %-32s DevKey", "UUID");
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+ node = &bt_mesh_cdb.nodes[i];
+ if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+ continue;
+ }
+
+ configured = atomic_test_bit(node->flags,
+ BT_MESH_CDB_NODE_CONFIGURED);
+
+ total++;
+ bin2hex(node->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
+ bin2hex(node->dev_key, 16, key_hex_str, sizeof(key_hex_str));
+ printk("0x%04x %-8d %-5s %s %s", node->addr,
+ node->num_elem, configured ? "C" : "-",
+ uuid_hex_str, key_hex_str);
+ }
+
+ printk("> Total nodes: %d", total);
+}
+
+static void cdb_print_subnets(void)
+{
+ struct bt_mesh_cdb_subnet *subnet;
+ char key_hex_str[32 + 1];
+ int i, total = 0;
+
+ printk("NetIdx NetKey");
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ subnet = &bt_mesh_cdb.subnets[i];
+ if (subnet->net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ total++;
+ bin2hex(subnet->keys[0].net_key, 16, key_hex_str,
+ sizeof(key_hex_str));
+ printk("0x%03x %s", subnet->net_idx,
+ key_hex_str);
+ }
+
+ printk("> Total subnets: %d", total);
+}
+
+static void cdb_print_app_keys(void)
+{
+ struct bt_mesh_cdb_app_key *app_key;
+ char key_hex_str[32 + 1];
+ int i, total = 0;
+
+ printk("NetIdx AppIdx AppKey");
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+ app_key = &bt_mesh_cdb.app_keys[i];
+ if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ total++;
+ bin2hex(app_key->keys[0].app_key, 16, key_hex_str,
+ sizeof(key_hex_str));
+ printk("0x%03x 0x%03x %s",
+ app_key->net_idx, app_key->app_idx, key_hex_str);
+ }
+
+ printk("> Total app-keys: %d", total);
+}
+
+static int cmd_cdb_show(int argc, char *argv[])
+{
+ if (!atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID)) {
+ printk("No valid networks");
+ return 0;
+ }
+
+ printk("Mesh Network Information");
+ printk("========================");
+
+ cdb_print_nodes();
+ printk("---");
+ cdb_print_subnets();
+ printk("---");
+ cdb_print_app_keys();
+
+ return 0;
+}
+
+static int cmd_cdb_node_add(int argc, char *argv[])
+{
+ struct bt_mesh_cdb_node *node;
+ uint8_t uuid[16], dev_key[16];
+ uint16_t addr, net_idx;
+ uint8_t num_elem;
+ size_t len;
+
+ len = hex2bin(argv[1], uuid, sizeof(uuid));
+ memset(uuid + len, 0, sizeof(uuid) - len);
+
+ addr = strtoul(argv[2], NULL, 0);
+ num_elem = strtoul(argv[3], NULL, 0);
+ net_idx = strtoul(argv[4], NULL, 0);
+
+ if (argc < 6) {
+ bt_rand(dev_key, 16);
+ } else {
+ len = hex2bin(argv[5], dev_key, sizeof(dev_key));
+ memset(dev_key + len, 0, sizeof(dev_key) - len);
+ }
+
+ node = bt_mesh_cdb_node_alloc(uuid, addr, num_elem, net_idx);
+ if (node == NULL) {
+ printk("Failed to allocate node");
+ return 0;
+ }
+
+ memcpy(node->dev_key, dev_key, 16);
+
+ if (IS_ENABLED(CONFIG_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+
+ printk("Added node 0x%04x", addr);
+
+ return 0;
+}
+
+static int cmd_cdb_node_del(int argc, char *argv[])
+{
+ struct bt_mesh_cdb_node *node;
+ uint16_t addr;
+
+ addr = strtoul(argv[1], NULL, 0);
+
+ node = bt_mesh_cdb_node_get(addr);
+ if (node == NULL) {
+ printk("No node with address 0x%04x", addr);
+ return 0;
+ }
+
+ bt_mesh_cdb_node_del(node, true);
+
+ printk("Deleted node 0x%04x", addr);
+
+ return 0;
+}
+
+static int cmd_cdb_subnet_add(int argc,
+ char *argv[])
+{
+ struct bt_mesh_cdb_subnet *sub;
+ uint8_t net_key[16];
+ uint16_t net_idx;
+ size_t len;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+
+ if (argc < 3) {
+ bt_rand(net_key, 16);
+ } else {
+ len = hex2bin(argv[2], net_key, sizeof(net_key));
+ memset(net_key + len, 0, sizeof(net_key) - len);
+ }
+
+ sub = bt_mesh_cdb_subnet_alloc(net_idx);
+ if (sub == NULL) {
+ printk("Could not add subnet");
+ return 0;
+ }
+
+ memcpy(sub->keys[0].net_key, net_key, 16);
+
+ if (IS_ENABLED(CONFIG_SETTINGS)) {
+ bt_mesh_store_cdb_subnet(sub);
+ }
+
+ printk("Added Subnet 0x%03x", net_idx);
+
+ return 0;
+}
+
+static int cmd_cdb_subnet_del(int argc,
+ char *argv[])
+{
+ struct bt_mesh_cdb_subnet *sub;
+ uint16_t net_idx;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+
+ sub = bt_mesh_cdb_subnet_get(net_idx);
+ if (sub == NULL) {
+ printk("No subnet with NetIdx 0x%03x", net_idx);
+ return 0;
+ }
+
+ bt_mesh_cdb_subnet_del(sub, true);
+
+ printk("Deleted subnet 0x%03x", net_idx);
+
+ return 0;
+}
+
+static int cmd_cdb_app_key_add(int argc,
+ char *argv[])
+{
+ struct bt_mesh_cdb_app_key *key;
+ uint16_t net_idx, app_idx;
+ uint8_t app_key[16];
+ size_t len;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+ app_idx = strtoul(argv[2], NULL, 0);
+
+ if (argc < 4) {
+ bt_rand(app_key, 16);
+ } else {
+ len = hex2bin(argv[3], app_key, sizeof(app_key));
+ memset(app_key + len, 0, sizeof(app_key) - len);
+ }
+
+ key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx);
+ if (key == NULL) {
+ printk("Could not add AppKey");
+ return 0;
+ }
+
+ memcpy(key->keys[0].app_key, app_key, 16);
+
+ if (IS_ENABLED(CONFIG_SETTINGS)) {
+ bt_mesh_store_cdb_app_key(key);
+ }
+
+ printk("Added AppKey 0x%03x", app_idx);
+
+ return 0;
+}
+
+static int cmd_cdb_app_key_del(int argc,
+ char *argv[])
+{
+ struct bt_mesh_cdb_app_key *key;
+ uint16_t app_idx;
+
+ app_idx = strtoul(argv[1], NULL, 0);
+
+ key = bt_mesh_cdb_app_key_get(app_idx);
+ if (key == NULL) {
+ printk("No AppKey 0x%03x", app_idx);
+ return 0;
+ }
+
+ bt_mesh_cdb_app_key_del(key, true);
+
+ printk("Deleted AppKey 0x%03x", app_idx);
+
+ return 0;
+}
+#endif
+
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
static int cmd_gen_onoff_get(int argc, char *argv[])
{
- u8_t state;
+ uint8_t state;
int err;
err = bt_mesh_gen_onoff_get(net.net_idx, net.dst, net.app_idx,
@@ -2280,8 +3065,8 @@ static int cmd_gen_onoff_get(int argc, char *argv[])
static int cmd_gen_onoff_set(int argc, char *argv[])
{
- u8_t state;
- u8_t val;
+ uint8_t state;
+ uint8_t val;
int err;
if (argc < 2) {
@@ -2307,7 +3092,7 @@ struct shell_cmd_help cmd_gen_onoff_set_help = {
static int cmd_gen_onoff_set_unack(int argc, char *argv[])
{
- u8_t val;
+ uint8_t val;
int err;
if (argc < 2) {
@@ -2331,7 +3116,7 @@ struct shell_cmd_help cmd_gen_onoff_set_unack_help = {
static int cmd_gen_level_get(int argc, char *argv[])
{
- s16_t state;
+ int16_t state;
int err;
err = bt_mesh_gen_level_get(net.net_idx, net.dst, net.app_idx,
@@ -2347,15 +3132,15 @@ static int cmd_gen_level_get(int argc, char *argv[])
static int cmd_gen_level_set(int argc, char *argv[])
{
- s16_t state;
- s16_t val;
+ int16_t state;
+ int16_t val;
int err;
if (argc < 2) {
return -EINVAL;
}
- val = (s16_t)strtoul(argv[1], NULL, 0);
+ val = (int16_t)strtoul(argv[1], NULL, 0);
err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
val, &state);
@@ -2374,14 +3159,14 @@ struct shell_cmd_help cmd_gen_level_set_help = {
static int cmd_gen_level_set_unack(int argc, char *argv[])
{
- s16_t val;
+ int16_t val;
int err;
if (argc < 2) {
return -EINVAL;
}
- val = (s16_t)strtoul(argv[1], NULL, 0);
+ val = (int16_t)strtoul(argv[1], NULL, 0);
err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
val, NULL);
@@ -2479,7 +3264,7 @@ static const struct shell_cmd mesh_commands[] = {
{
.sc_cmd = "reset",
.sc_cmd_func = cmd_reset,
- .help = NULL,
+ .help = &cmd_reset_help,
},
{
.sc_cmd = "uuid",
@@ -2606,6 +3391,11 @@ static const struct shell_cmd mesh_commands[] = {
.help = &cmd_beacon_help,
},
{
+ .sc_cmd = "beacon-listen",
+ .sc_cmd_func = cmd_beacon_listen,
+ .help = &cmd_beacon_listen_help,
+ },
+ {
.sc_cmd = "ttl",
.sc_cmd_func = cmd_ttl,
.help = &cmd_ttl_help,
@@ -2631,16 +3421,51 @@ static const struct shell_cmd mesh_commands[] = {
.help = &cmd_net_key_add_help,
},
{
+ .sc_cmd = "net-key-get",
+ .sc_cmd_func = cmd_net_key_get,
+ .help = &cmd_net_key_get_help,
+ },
+ {
+ .sc_cmd = "net-key-del",
+ .sc_cmd_func = cmd_net_key_del,
+ .help = &cmd_net_key_del_help,
+ },
+ {
.sc_cmd = "app-key-add",
.sc_cmd_func = cmd_app_key_add,
.help = &cmd_app_key_add_help,
},
{
+ .sc_cmd = "app-key-del",
+ .sc_cmd_func = cmd_app_key_del,
+ .help = &cmd_app_key_del_help,
+ },
+ {
+ .sc_cmd = "app-key-get",
+ .sc_cmd_func = cmd_app_key_get,
+ .help = &cmd_app_key_get_help,
+ },
+ {
+ .sc_cmd = "net-transmit-param",
+ .sc_cmd_func = cmd_net_transmit,
+ .help = &cmd_net_transmit_help,
+ },
+ {
.sc_cmd = "mod-app-bind",
.sc_cmd_func = cmd_mod_app_bind,
.help = &cmd_mod_app_bind_help,
},
{
+ .sc_cmd = "mod-app-get",
+ .sc_cmd_func = cmd_mod_app_get,
+ .help = &cmd_mod_app_get_help,
+ },
+ {
+ .sc_cmd = "mod-app-unbind",
+ .sc_cmd_func = cmd_mod_app_unbind,
+ .help = &cmd_mod_app_unbind_help,
+ },
+ {
.sc_cmd = "mod-pub",
.sc_cmd_func = cmd_mod_pub,
.help = &cmd_mod_pub_help,
@@ -2661,6 +3486,11 @@ static const struct shell_cmd mesh_commands[] = {
.help = &cmd_mod_sub_add_va_help,
},
{
+ .sc_cmd = "mod-sub-get",
+ .sc_cmd_func = cmd_mod_sub_get,
+ .help = &cmd_mod_sub_get_help,
+ },
+ {
.sc_cmd = "mod-sub-del-va",
.sc_cmd_func = cmd_mod_sub_del_va,
.help = &cmd_mod_sub_del_va_help,
@@ -2748,6 +3578,46 @@ static const struct shell_cmd mesh_commands[] = {
.help = &cmd_del_fault_help,
},
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ {
+ .sc_cmd = "cdb-create",
+ .sc_cmd_func = cmd_cdb_create,
+ .help = &cmd_cdb_create_help,
+ },{
+ .sc_cmd = "cdb-clear",
+ .sc_cmd_func = cmd_cdb_clear,
+ .help = &cmd_cdb_clear_help,
+ },{
+ .sc_cmd = "cdb-show",
+ .sc_cmd_func = cmd_cdb_show,
+ .help = &cmd_cdb_show_help,
+ },{
+ .sc_cmd = "cdb-node-add",
+ .sc_cmd_func = cmd_cdb_node_add,
+ .help = &cmd_cdb_node_add_help,
+ },{
+ .sc_cmd = "cdb-node-del",
+ .sc_cmd_func = cmd_cdb_node_del,
+ .help = &cmd_cdb_node_del_help,
+ },{
+ .sc_cmd = "cdb-subnet-add",
+ .sc_cmd_func = cmd_cdb_subnet_add,
+ .help = &cmd_cdb_subnet_add_help,
+ },{
+ .sc_cmd = "cdb-subnet-del",
+ .sc_cmd_func = cmd_cdb_subnet_del,
+ .help = &cmd_cdb_subnet_del_help,
+ },{
+ .sc_cmd = "cdb-app-key-add",
+ .sc_cmd_func = cmd_cdb_app_key_add,
+ .help = &cmd_cdb_app_key_add_help,
+ },{
+ .sc_cmd = "cdb-app-key-add",
+ .sc_cmd_func = cmd_cdb_app_key_del,
+ .help = &cmd_cdb_app_key_del_help,
+ },
+#endif
+
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
/* Generic Client Model Operations */
{
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.c
new file mode 100644
index 00000000..d6fcfbee
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "syscfg/syscfg.h"
+#define MESH_LOG_MODULE BLE_MESH_NET_KEYS_LOG
+
+#include "log/log.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "mesh/mesh.h"
+#include "net.h"
+#include "mesh_priv.h"
+#include "lpn.h"
+#include "friend.h"
+#include "proxy.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+#include "beacon.h"
+#include "rpl.h"
+#include "settings.h"
+#include "prov.h"
+
+#ifdef CONFIG_BT_MESH_GATT_PROXY
+void (*bt_mesh_subnet_cb_list[5]) (struct bt_mesh_subnet *sub,
+ enum bt_mesh_key_evt evt);
+#else
+void (*bt_mesh_subnet_cb_list[4]) (struct bt_mesh_subnet *sub,
+ enum bt_mesh_key_evt evt);
+#endif
+
+static struct bt_mesh_subnet subnets[CONFIG_BT_MESH_SUBNET_COUNT] = {
+ [0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = {
+ .net_idx = BT_MESH_KEY_UNUSED,
+ },
+};
+
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ int i;
+ for (i = 0; i < (sizeof(bt_mesh_subnet_cb_list)/sizeof(void *)); i++) {
+ BT_DBG("%d", i);
+ if (bt_mesh_subnet_cb_list[i]) {
+ bt_mesh_subnet_cb_list[i] (sub, evt);
+ }
+ }
+}
+
+uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
+{
+ uint8_t flags = 0x00;
+
+ if (sub && (sub->kr_phase == BT_MESH_KR_PHASE_2)) {
+ flags |= BT_MESH_NET_FLAG_KR;
+ }
+
+ if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
+ flags |= BT_MESH_NET_FLAG_IVU;
+ }
+
+ return flags;
+}
+
+static void key_refresh(struct bt_mesh_subnet *sub, uint8_t new_phase)
+{
+ BT_DBG("Phase 0x%02x -> 0x%02x", sub->kr_phase, new_phase);
+
+ switch (new_phase) {
+ /* Added second set of keys */
+ case BT_MESH_KR_PHASE_1:
+ sub->kr_phase = new_phase;
+ subnet_evt(sub, BT_MESH_KEY_UPDATED);
+ break;
+ /* Now using new keys for TX */
+ case BT_MESH_KR_PHASE_2:
+ sub->kr_phase = new_phase;
+ subnet_evt(sub, BT_MESH_KEY_SWAPPED);
+ break;
+ /* Revoking keys */
+ case BT_MESH_KR_PHASE_3:
+ if (sub->kr_phase == BT_MESH_KR_NORMAL) {
+ return;
+ }
+ /* __fallthrough; */
+ case BT_MESH_KR_NORMAL:
+ sub->kr_phase = BT_MESH_KR_NORMAL;
+ memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0]));
+ sub->keys[1].valid = 0U;
+ subnet_evt(sub, BT_MESH_KEY_REVOKED);
+ break;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing Updated NetKey persistently");
+ bt_mesh_store_subnet(sub->net_idx);
+ }
+}
+
+void bt_mesh_kr_update(struct bt_mesh_subnet *sub, bool kr_flag, bool new_key)
+{
+ if (!new_key) {
+ return;
+ }
+
+ if (sub->kr_phase == BT_MESH_KR_PHASE_1) {
+ /* Bluetooth Mesh Profile Specification Section 3.10.4.1:
+ * Can skip phase 2 if we get KR=0 on new key.
+ */
+ key_refresh(sub, (kr_flag ? BT_MESH_KR_PHASE_2 :
+ BT_MESH_KR_PHASE_3));
+ } else if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !kr_flag) {
+ key_refresh(sub, BT_MESH_KR_PHASE_3);
+ }
+}
+
+static struct bt_mesh_subnet *subnet_alloc(uint16_t net_idx)
+{
+ struct bt_mesh_subnet *sub = NULL;
+
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ /* Check for already existing subnet */
+ if (subnets[i].net_idx == net_idx) {
+ return &subnets[i];
+ }
+
+ if (!sub && subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+ sub = &subnets[i];
+ }
+ }
+
+ return sub;
+}
+
+static void subnet_del(struct bt_mesh_subnet *sub)
+{
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_clear_subnet(sub->net_idx);
+ }
+
+ bt_mesh_net_loopback_clear(sub->net_idx);
+
+ subnet_evt(sub, BT_MESH_KEY_DELETED);
+ (void)memset(sub, 0, sizeof(*sub));
+ sub->net_idx = BT_MESH_KEY_UNUSED;
+}
+
+static int msg_cred_create(struct bt_mesh_net_cred *cred, const uint8_t *p,
+ size_t p_len, const uint8_t key[16])
+{
+ return bt_mesh_k2(key, p, p_len, &cred->nid, cred->enc, cred->privacy);
+}
+
+static int net_keys_create(struct bt_mesh_subnet_keys *keys,
+ const uint8_t key[16])
+{
+ uint8_t p = 0;
+ int err;
+
+ err = msg_cred_create(&keys->msg, &p, 1, key);
+ if (err) {
+ BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
+ return err;
+ }
+
+ memcpy(keys->net, key, 16);
+
+ BT_DBG("NID 0x%02x EncKey %s", keys->msg.nid,
+ bt_hex(keys->msg.enc, 16));
+ BT_DBG("PrivacyKey %s", bt_hex(keys->msg.privacy, 16));
+
+ err = bt_mesh_k3(key, keys->net_id);
+ if (err) {
+ BT_ERR("Unable to generate Net ID");
+ return err;
+ }
+
+ BT_DBG("NetID %s", bt_hex(keys->net_id, 8));
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+ err = bt_mesh_identity_key(key, keys->identity);
+ if (err) {
+ BT_ERR("Unable to generate IdentityKey");
+ return err;
+ }
+
+ BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16));
+#endif /* GATT_PROXY */
+
+ err = bt_mesh_beacon_key(key, keys->beacon);
+ if (err) {
+ BT_ERR("Unable to generate beacon key");
+ return err;
+ }
+
+ BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16));
+
+ keys->valid = 1U;
+
+ return 0;
+}
+
+uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16])
+{
+ struct bt_mesh_subnet *sub = NULL;
+ int err;
+
+ BT_DBG("0x%03x", net_idx);
+
+ sub = subnet_alloc(net_idx);
+ if (!sub) {
+ return STATUS_INSUFF_RESOURCES;
+ }
+
+ if (sub->net_idx == net_idx) {
+ if (memcmp(key, sub->keys[0].net, 16)) {
+ return STATUS_IDX_ALREADY_STORED;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ err = net_keys_create(&sub->keys[0], key);
+ if (err) {
+ return STATUS_UNSPECIFIED;
+ }
+
+ sub->net_idx = net_idx;
+ sub->kr_phase = BT_MESH_KR_NORMAL;
+
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
+ } else {
+ sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
+ }
+
+ subnet_evt(sub, BT_MESH_KEY_ADDED);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing NetKey persistently");
+ bt_mesh_store_subnet(sub->net_idx);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+bool bt_mesh_subnet_exists(uint16_t net_idx)
+{
+ return !!bt_mesh_subnet_get(net_idx);
+}
+
+uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16])
+{
+ struct bt_mesh_subnet *sub;
+ int err;
+
+ BT_DBG("0x%03x", net_idx);
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ /* The node shall successfully process a NetKey Update message on a
+ * valid NetKeyIndex when the NetKey value is different and the Key
+ * Refresh procedure has not been started, or when the NetKey value is
+ * the same in Phase 1. The NetKey Update message shall generate an
+ * error when the node is in Phase 2, or Phase 3.
+ */
+ switch (sub->kr_phase) {
+ case BT_MESH_KR_NORMAL:
+ if (!memcmp(key, sub->keys[0].net, 16)) {
+ return STATUS_IDX_ALREADY_STORED;
+ }
+ break;
+ case BT_MESH_KR_PHASE_1:
+ if (!memcmp(key, sub->keys[1].net, 16)) {
+ return STATUS_SUCCESS;
+ }
+ /* __fallthrough; */
+ case BT_MESH_KR_PHASE_2:
+ case BT_MESH_KR_PHASE_3:
+ return STATUS_CANNOT_UPDATE;
+ }
+
+ err = net_keys_create(&sub->keys[1], key);
+ if (err) {
+ return STATUS_CANNOT_UPDATE;
+ }
+
+ key_refresh(sub, BT_MESH_KR_PHASE_1);
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_del(uint16_t net_idx)
+{
+ struct bt_mesh_subnet *sub;
+
+ BT_DBG("0x%03x", net_idx);
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ /* This could be a retry of a previous attempt that had its
+ * response lost, so pretend that it was a success.
+ */
+ return STATUS_INVALID_NETKEY;
+ }
+
+ subnet_del(sub);
+
+ return STATUS_SUCCESS;
+}
+
+int bt_mesh_friend_cred_create(struct bt_mesh_net_cred *cred, uint16_t lpn_addr,
+ uint16_t frnd_addr, uint16_t lpn_counter,
+ uint16_t frnd_counter, const uint8_t key[16])
+{
+ uint8_t p[9];
+
+ p[0] = 0x01;
+ sys_put_be16(lpn_addr, p + 1);
+ sys_put_be16(frnd_addr, p + 3);
+ sys_put_be16(lpn_counter, p + 5);
+ sys_put_be16(frnd_counter, p + 7);
+
+ return msg_cred_create(cred, p, sizeof(p), key);
+}
+
+uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase)
+{
+ /* Table in Bluetooth Mesh Profile Specification Section 4.2.14: */
+ const uint8_t valid_transitions[] = {
+ BIT(BT_MESH_KR_PHASE_3), /* Normal phase: KR is started by key update */
+ BIT(BT_MESH_KR_PHASE_2) | BIT(BT_MESH_KR_PHASE_3), /* Phase 1 */
+ BIT(BT_MESH_KR_PHASE_3), /* Phase 2 */
+ /* Subnet is never in Phase 3 */
+ };
+ struct bt_mesh_subnet *sub;
+
+ BT_DBG("0x%03x", net_idx);
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ *phase = 0x00;
+ return STATUS_INVALID_NETKEY;
+ }
+
+ if (*phase == sub->kr_phase) {
+ return STATUS_SUCCESS;
+ }
+
+ if (sub->kr_phase < ARRAY_SIZE(valid_transitions) &&
+ valid_transitions[sub->kr_phase] & BIT(*phase)) {
+ key_refresh(sub, *phase);
+
+ *phase = sub->kr_phase;
+
+ return STATUS_SUCCESS;
+ }
+
+ BT_WARN("Invalid KR transition: 0x%02x -> 0x%02x", sub->kr_phase,
+ *phase);
+
+ *phase = sub->kr_phase;
+
+ return STATUS_CANNOT_UPDATE;
+}
+
+uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase)
+{
+ struct bt_mesh_subnet *sub;
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ *phase = BT_MESH_KR_NORMAL;
+ return STATUS_INVALID_NETKEY;
+ }
+
+ *phase = sub->kr_phase;
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
+ enum bt_mesh_feat_state node_id)
+{
+ struct bt_mesh_subnet *sub;
+
+ if (node_id == BT_MESH_FEATURE_NOT_SUPPORTED) {
+ return STATUS_CANNOT_SET;
+ }
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ return STATUS_FEAT_NOT_SUPP;
+ }
+
+ if (node_id) {
+ bt_mesh_proxy_identity_start(sub);
+ } else {
+ bt_mesh_proxy_identity_stop(sub);
+ }
+
+ bt_mesh_adv_update();
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
+ enum bt_mesh_feat_state *node_id)
+{
+ struct bt_mesh_subnet *sub;
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ *node_id = 0x00;
+ return STATUS_INVALID_NETKEY;
+ }
+
+ *node_id = sub->node_id;
+
+ return STATUS_SUCCESS;
+}
+
+ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip)
+{
+ size_t count = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ struct bt_mesh_subnet *sub = &subnets[i];
+
+ if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (skip) {
+ skip--;
+ continue;
+ }
+
+ if (count >= max) {
+ return -ENOMEM;
+ }
+
+ net_idxs[count++] = sub->net_idx;
+ }
+
+ return count;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx)
+{
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ struct bt_mesh_subnet *sub = &subnets[i];
+
+ if (sub->net_idx == net_idx) {
+ return sub;
+ }
+ }
+
+ return NULL;
+}
+
+int bt_mesh_subnet_set(uint16_t net_idx, uint8_t kr_phase,
+ const uint8_t old_key[16], const uint8_t new_key[16])
+{
+ const uint8_t *keys[] = { old_key, new_key };
+ struct bt_mesh_subnet *sub;
+
+ sub = subnet_alloc(net_idx);
+ if (!sub) {
+ return -ENOMEM;
+ }
+
+ if (sub->net_idx == net_idx) {
+ return -EALREADY;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(keys); i++) {
+ if (!keys[i]) {
+ continue;
+ }
+
+ if (net_keys_create(&sub->keys[i], keys[i])) {
+ return -EIO;
+ }
+ }
+
+ sub->net_idx = net_idx;
+ sub->kr_phase = kr_phase;
+
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
+ } else {
+ sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
+ }
+
+ /* Make sure we have valid beacon data to be sent */
+ bt_mesh_beacon_update(sub);
+
+ return 0;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_find(int (*cb)(struct bt_mesh_subnet *sub,
+ void *cb_data),
+ void *cb_data)
+{
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ if (subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (!cb || cb(&subnets[i], cb_data)) {
+ return &subnets[i];
+ }
+ }
+
+ return NULL;
+}
+
+size_t bt_mesh_subnet_foreach(void (*cb)(struct bt_mesh_subnet *sub))
+{
+ size_t count = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ if (subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ cb(&subnets[i]);
+ count++;
+ }
+
+ return count;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_next(struct bt_mesh_subnet *sub)
+{
+ if (sub) {
+ sub++;
+ } else {
+ sub = &subnets[0];
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++, sub++) {
+ /* Roll over once we reach the end */
+ if (sub == &subnets[ARRAY_SIZE(subnets)]) {
+ sub = &subnets[0];
+ }
+
+ if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+ return sub;
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_net_keys_reset(void)
+{
+ int i;
+
+ /* Delete all net keys, which also takes care of all app keys which
+ * are associated with each net key.
+ */
+ for (i = 0; i < ARRAY_SIZE(subnets); i++) {
+ struct bt_mesh_subnet *sub = &subnets[i];
+
+ if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+ subnet_del(sub);
+ }
+ }
+}
+
+bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+ struct os_mbuf *out,
+ bool (*cb)(struct bt_mesh_net_rx *rx,
+ struct os_mbuf *in,
+ struct os_mbuf *out,
+ const struct bt_mesh_net_cred *cred))
+{
+ int i, j;
+
+ BT_DBG("");
+
+#if MYNEWT_VAL(BLE_MESH_LOW_POWER)
+ if (bt_mesh_lpn_waiting_update()) {
+ rx->sub = bt_mesh.lpn.sub;
+
+ for (j = 0; j < ARRAY_SIZE(bt_mesh.lpn.cred); j++) {
+ if (!rx->sub->keys[j].valid) {
+ continue;
+ }
+
+ if (cb(rx, in, out, &bt_mesh.lpn.cred[j])) {
+ rx->new_key = (j > 0);
+ rx->friend_cred = 1U;
+ rx->ctx.net_idx = rx->sub->net_idx;
+ return true;
+ }
+ }
+
+ /* LPN Should only receive on the friendship credentials when in
+ * a friendship.
+ */
+ return false;
+ }
+#endif
+
+#if MYNEWT_VAL(BLE_MESH_FRIEND)
+ /** Each friendship has unique friendship credentials */
+ for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+ struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+ if (!frnd->subnet) {
+ continue;
+ }
+
+ rx->sub = frnd->subnet;
+
+ for (j = 0; j < ARRAY_SIZE(frnd->cred); j++) {
+ if (!rx->sub->keys[j].valid) {
+ continue;
+ }
+
+ if (cb(rx, in, out, &frnd->cred[j])) {
+ rx->new_key = (j > 0);
+ rx->friend_cred = 1U;
+ rx->ctx.net_idx = rx->sub->net_idx;
+ return true;
+ }
+ }
+ }
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(subnets); i++) {
+ rx->sub = &subnets[i];
+ if (rx->sub->net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ for (j = 0; j < ARRAY_SIZE(rx->sub->keys); j++) {
+ if (!rx->sub->keys[j].valid) {
+ continue;
+ }
+
+ if (cb(rx, in, out, &rx->sub->keys[j].msg)) {
+ rx->new_key = (j > 0);
+ rx->friend_cred = 0U;
+ rx->ctx.net_idx = rx->sub->net_idx;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.h
new file mode 100644
index 00000000..154b5d4e
--- /dev/null
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/subnet.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _BLUETOOTH_MESH_SUBNET_H_
+#define _BLUETOOTH_MESH_SUBNET_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+#include "mesh/glue.h"
+#define BT_MESH_NET_FLAG_KR BIT(0)
+#define BT_MESH_NET_FLAG_IVU BIT(1)
+
+#define BT_MESH_KR_NORMAL 0x00
+#define BT_MESH_KR_PHASE_1 0x01
+#define BT_MESH_KR_PHASE_2 0x02
+#define BT_MESH_KR_PHASE_3 0x03
+
+/** Which of the two subnet.keys should be used for sending. */
+#define SUBNET_KEY_TX_IDX(sub) ((sub)->kr_phase == BT_MESH_KR_PHASE_2)
+
+struct bt_mesh_net_rx;
+enum bt_mesh_key_evt;
+
+/** Network message encryption credentials */
+struct bt_mesh_net_cred {
+ uint8_t nid; /* NID */
+ uint8_t enc[16]; /* EncKey */
+ uint8_t privacy[16]; /* PrivacyKey */
+};
+
+/** Subnet instance. */
+struct bt_mesh_subnet {
+ uint32_t beacon_sent; /* Timestamp of last sent beacon */
+ uint8_t beacons_last; /* Number of beacons during last
+ * observation window
+ */
+ uint8_t beacons_cur; /* Number of beaconds observed during
+ * currently ongoing window.
+ */
+
+ uint8_t beacon_cache[21]; /* Cached last authenticated beacon */
+
+ uint16_t net_idx; /* NetKeyIndex */
+
+ uint8_t kr_phase; /* Key Refresh Phase */
+
+ uint8_t node_id; /* Node Identity State */
+ uint32_t node_id_start; /* Node Identity started timestamp */
+
+ uint8_t auth[8]; /* Beacon Authentication Value */
+
+ struct bt_mesh_subnet_keys {
+ bool valid;
+ uint8_t net[16]; /* NetKey */
+ struct bt_mesh_net_cred msg;
+ uint8_t net_id[8]; /* Network ID */
+ #if defined(CONFIG_BT_MESH_GATT_PROXY)
+ uint8_t identity[16]; /* IdentityKey */
+ #endif
+ uint8_t beacon[16]; /* BeaconKey */
+ } keys[2];
+};
+
+#ifdef CONFIG_BT_MESH_GATT_PROXY
+extern void (*bt_mesh_subnet_cb_list[5]) (struct bt_mesh_subnet *sub,
+ enum bt_mesh_key_evt evt);
+#else
+extern void (*bt_mesh_subnet_cb_list[4]) (struct bt_mesh_subnet *sub,
+ enum bt_mesh_key_evt evt);
+#endif
+
+/** Subnet callback structure. Instantiate with @ref BT_MESH_SUBNET_CB */
+struct bt_mesh_subnet_cb {
+ void (*evt_handler)(struct bt_mesh_subnet *subnet,
+ enum bt_mesh_key_evt evt);
+};
+
+/** @brief Reset all Network keys. */
+void bt_mesh_net_keys_reset(void);
+
+/** @brief Call cb on every valid Subnet until it returns a non-zero value.
+ *
+ * @param cb Callback to call, or NULL to return first valid subnet.
+ * @param cb_data Callback data to pass to callback.
+ *
+ * @return Subnet that returned non-zero value.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_find(int (*cb)(struct bt_mesh_subnet *sub,
+ void *cb_data),
+ void *cb_data);
+
+/** @brief Iterate through all valid Subnets.
+ *
+ * @param cb Callback to call on every Subnet.
+ *
+ * @returns The number of valid subnets.
+ */
+size_t bt_mesh_subnet_foreach(void (*cb)(struct bt_mesh_subnet *sub));
+
+/** @brief Get the next valid Subnet.
+ *
+ * If there's only one valid Subnet, this will be returned on every call.
+ *
+ * @param sub Previous Subnet, or NULL to get the first valid.
+ *
+ * @returns Gets the next valid Subnet after @c sub, or NULL if there are no
+ * valid Subnets.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_next(struct bt_mesh_subnet *sub);
+
+/** @brief Get a pointer to the Subnet with the given index.
+ *
+ * @param net_idx Network index to look for.
+ *
+ * @returns Subnet with index @c net_idx, or NULL if no such Subnet is known.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx);
+
+/** @brief Initialize a new Subnet.
+ *
+ * @param net_idx Network index of the Subnet.
+ * @param kr_phase Key refresh phase the Subnet should be in.
+ * @param key The current network key for the Subnet.
+ * @param new_key New network key, if available.
+ *
+ * @returns 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_subnet_set(uint16_t net_idx, uint8_t kr_phase,
+ const uint8_t key[16], const uint8_t new_key[16]);
+
+/** @brief Create Friendship credentials.
+ *
+ * @param cred Credential object to create.
+ * @param lpn_addr Address of the LPN node in the friendship.
+ * @param frnd_addr Address of the Friend node in the friendship.
+ * @param lpn_counter The LPN's counter parameter.
+ * @param frnd_counter The Friend node's counter parameter.
+ * @param key Network key to create the Friendship credentials for.
+ *
+ * @returns 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_friend_cred_create(struct bt_mesh_net_cred *cred,
+ uint16_t lpn_addr, uint16_t frnd_addr,
+ uint16_t lpn_counter, uint16_t frnd_counter,
+ const uint8_t key[16]);
+
+/** @brief Iterate through all valid network credentials to decrypt a message.
+ *
+ * @param rx Network RX parameters, passed to the callback.
+ * @param in Input message buffer, passed to the callback.
+ * @param out Output message buffer, passed to the callback.
+ * @param cb Callback to call for each known network credential. Iteration
+ * stops when this callback returns @c true.
+ *
+ * @returns Whether any of the credentials got a @c true return from the
+ * callback.
+ */
+bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+ struct os_mbuf *out,
+ bool (*cb)(struct bt_mesh_net_rx *rx,
+ struct os_mbuf *in,
+ struct os_mbuf *out,
+ const struct bt_mesh_net_cred *cred));
+
+/** @brief Get the network flags of the given Subnet.
+ *
+ * @param sub Subnet to get the network flags of.
+ *
+ * @returns A bitmap of @ref BT_MESH_NET_FLAG_KR and @ref BT_MESH_NET_FLAG_IVU.
+ */
+uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
+
+/** @brief Process a Key Refresh event from a beacon.
+ *
+ * @param sub Subnet the Key Refresh was received on.
+ * @param kr_flag Key Refresh flag.
+ * @param new_key Whether the Key Refresh event was received on the new key
+ * set.
+ */
+void bt_mesh_kr_update(struct bt_mesh_subnet *sub, bool kr_flag, bool new_key);
+
+/** @brief Check whether the Subnet has the refreshed keys.
+ *
+ * @param sub Subnet.
+ *
+ * @returns Whether the Subnet's second key is valid.
+ */
+static inline bool
+bt_mesh_subnet_has_new_key(const struct bt_mesh_subnet *sub)
+{
+ return sub->kr_phase != BT_MESH_KR_NORMAL;
+}
+
+#endif /* _BLUETOOTH_MESH_SUBNET_H_ */ \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c
index d0a05376..bde8ff3b 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.c
@@ -13,6 +13,8 @@
#include "mesh/access.h"
#include "net.h"
+#include "app_keys.h"
+#include "rpl.h"
#include "testing.h"
#include "access.h"
#include "foundation.h"
@@ -31,7 +33,7 @@ void bt_test_cb_unregister(struct bt_test_cb *cb)
sys_slist_find_and_remove(&cb_slist, &cb->node);
}
-void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
+void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
const void *payload, size_t payload_len)
{
struct bt_test_cb *cb;
@@ -44,8 +46,8 @@ void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
}
}
-void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx)
+void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx)
{
struct bt_test_cb *cb;
@@ -56,8 +58,8 @@ void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model,
}
}
-void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx)
+void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx)
{
struct bt_test_cb *cb;
@@ -68,7 +70,7 @@ void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model,
}
}
-void bt_test_mesh_prov_invalid_bearer(u8_t opcode)
+void bt_test_mesh_prov_invalid_bearer(uint8_t opcode)
{
struct bt_test_cb *cb;
@@ -90,14 +92,14 @@ void bt_test_mesh_trans_incomp_timer_exp(void)
}
}
-int bt_test_mesh_lpn_group_add(u16_t group)
+int bt_test_mesh_lpn_group_add(uint16_t group)
{
bt_mesh_lpn_group_add(group);
return 0;
}
-int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count)
+int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count)
{
bt_mesh_lpn_group_del(groups, groups_count);
@@ -114,38 +116,38 @@ int bt_test_mesh_rpl_clear(void)
void bt_test_print_credentials(void)
{
int i;
- u8_t nid;
- const u8_t *enc;
- const u8_t *priv;
- struct bt_mesh_subnet *sub;
- struct bt_mesh_app_key *app_key;
+ struct bt_mesh_cdb_subnet *sub;
+ struct bt_mesh_cdb_app_key *app_key;
+ struct bt_mesh_subnet *subnet;
console_printf("IV Index: %08lx\n", (long) bt_mesh.iv_index);
console_printf("Dev key: %s\n", bt_hex(bt_mesh.dev_key, 16));
- for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i)
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i)
{
- if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) {
+ app_key = &bt_mesh_cdb.app_keys[i];
+ if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
continue;
}
- sub = &bt_mesh.sub[i];
+ sub = bt_mesh_cdb_subnet_get(i);
console_printf("Subnet: %d\n", i);
console_printf("\tNetKeyIdx: %04x\n",
sub->net_idx);
console_printf("\tNetKey: %s\n",
- bt_hex(sub->keys[sub->kr_flag].net, 16));
+ bt_hex(sub->keys[sub->kr_flag].net_key, 16));
}
- for (i = 0; i < MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT); ++i)
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i)
{
- if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) {
+ app_key = &bt_mesh_cdb.app_keys[i];
+ if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
continue;
}
- sub = &bt_mesh.sub[i];
- app_key = &bt_mesh.app_keys[i];
+ sub = bt_mesh_cdb_subnet_get(i);
+ app_key = &bt_mesh_cdb.app_keys[i];
console_printf("AppKey: %d\n", i);
console_printf("\tNetKeyIdx: %04x\n",
@@ -153,28 +155,27 @@ void bt_test_print_credentials(void)
console_printf("\tAppKeyIdx: %04x\n",
app_key->app_idx);
console_printf("\tAppKey: %s\n",
- bt_hex(app_key->keys[sub->kr_flag].val, 16));
+ bt_hex(app_key->keys[sub->kr_flag].app_key, 16));
}
- for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i)
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i)
{
- if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
+ sub = bt_mesh_cdb_subnet_get(i);
+ app_key = &bt_mesh_cdb.app_keys[i];
+ if (sub[i].net_idx == BT_MESH_KEY_UNUSED) {
continue;
}
- if (friend_cred_get(&bt_mesh.sub[i], BT_MESH_ADDR_UNASSIGNED,
- &nid, &enc, &priv)) {
- return;
- }
+ subnet = bt_mesh_subnet_get(app_key->net_idx);
console_printf("Friend cred: %d\n", i);
console_printf("\tNetKeyIdx: %04x\n",
- bt_mesh.sub[i].net_idx);
- console_printf("\tNID: %02x\n", nid);
+ sub[i].net_idx);
+ console_printf("\tNID: %02x\n", subnet->keys->msg.nid);
console_printf("\tEncKey: %s\n",
- bt_hex(enc, 16));
+ bt_hex(subnet->keys->msg.enc, 16));
console_printf("\tPrivKey: %s\n",
- bt_hex(priv, 16));
+ bt_hex(subnet->keys->msg.privacy, 16));
}
}
@@ -187,7 +188,7 @@ int bt_test_shell_init(void)
#endif
}
-int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, u16_t key_idx, u16_t id)
+int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, uint16_t key_idx, uint16_t id)
{
struct bt_mesh_model *found_model;
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h
index 166a9eea..68f7fd72 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/testing.h
@@ -12,12 +12,12 @@
#include "mesh/glue.h"
#include "mesh/access.h"
-void bt_test_mesh_model_bound(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx);
-void bt_test_mesh_model_unbound(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx);
-void bt_test_mesh_prov_invalid_bearer(u8_t opcode);
-void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
+void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx);
+void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx);
+void bt_test_mesh_prov_invalid_bearer(uint8_t opcode);
+void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
const void *payload, size_t payload_len);
void bt_test_mesh_trans_incomp_timer_exp(void);
void bt_test_print_credentials(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c
index caf1b4f1..00ccb088 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.c
@@ -13,42 +13,38 @@
#include <string.h>
#include "mesh/mesh.h"
+#include "mesh/glue.h"
#include "mesh_priv.h"
#include "crypto.h"
#include "adv.h"
#include "net.h"
+#include "app_keys.h"
+#include "rpl.h"
#include "lpn.h"
#include "friend.h"
#include "access.h"
#include "foundation.h"
#include "settings.h"
+#include "heartbeat.h"
#include "transport.h"
#include "testing.h"
-#include "nodes.h"
-/* The transport layer needs at least three buffers for itself to avoid
- * deadlocks. Ensure that there are a sufficient number of advertising
- * buffers available compared to the maximum supported outgoing segment
- * count.
- */
-BUILD_ASSERT(CONFIG_BT_MESH_ADV_BUF_COUNT >= (CONFIG_BT_MESH_TX_SEG_MAX + 3));
-
-#define AID_MASK ((u8_t)(BIT_MASK(6)))
+#define AID_MASK ((uint8_t)(BIT_MASK(6)))
#define SEG(data) ((data)[0] >> 7)
#define AKF(data) (((data)[0] >> 6) & 0x01)
#define AID(data) ((data)[0] & AID_MASK)
#define ASZMIC(data) (((data)[1] >> 7) & 1)
-#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
+#define APP_MIC_LEN(aszmic) ((aszmic) ? BT_MESH_MIC_LONG : BT_MESH_MIC_SHORT)
#define UNSEG_HDR(akf, aid) ((akf << 6) | (aid & AID_MASK))
#define SEG_HDR(akf, aid) (UNSEG_HDR(akf, aid) | 0x80)
-#define BLOCK_COMPLETE(seg_n) (u32_t)(((u64_t)1 << (seg_n + 1)) - 1)
+#define BLOCK_COMPLETE(seg_n) (uint32_t)(((uint64_t)1 << (seg_n + 1)) - 1)
-#define SEQ_AUTH(iv_index, seq) (((u64_t)iv_index) << 24 | (u64_t)seq)
+#define SEQ_AUTH(iv_index, seq) (((uint64_t)iv_index) << 24 | (uint64_t)seq)
/* Number of retransmit attempts (after the initial transmit) per segment */
#define SEG_RETRANSMIT_ATTEMPTS (MYNEWT_VAL(BLE_MESH_SEG_RETRANSMIT_ATTEMPTS))
@@ -57,59 +53,84 @@ BUILD_ASSERT(CONFIG_BT_MESH_ADV_BUF_COUNT >= (CONFIG_BT_MESH_TX_SEG_MAX + 3));
* We use 400 since 300 is a common send duration for standard HCI, and we
* need to have a timeout that's bigger than that.
*/
-#define SEG_RETRANSMIT_TIMEOUT(tx) (K_MSEC(400) + 50 * (tx)->ttl)
+#define SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) \
+ (MYNEWT_VAL(BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST) + 50 * (tx)->ttl)
+/* When sending to a group, the messages are not acknowledged, and there's no
+ * reason to delay the repetitions significantly. Delaying by more than 0 ms
+ * to avoid flooding the network.
+ */
+#define SEG_RETRANSMIT_TIMEOUT_GROUP \
+ MYNEWT_VAL(BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP)
+#define SEG_RETRANSMIT_TIMEOUT(tx) \
+ (BT_MESH_ADDR_IS_UNICAST(tx->dst) ? \
+ SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) : \
+ SEG_RETRANSMIT_TIMEOUT_GROUP)
/* How long to wait for available buffers before giving up */
#define BUF_TIMEOUT K_NO_WAIT
static struct seg_tx {
- struct bt_mesh_subnet *sub;
- struct os_mbuf *seg[CONFIG_BT_MESH_TX_SEG_MAX];
- u64_t seq_auth;
- u16_t dst;
- u8_t seg_n:5, /* Last segment index */
- new_key:1; /* New/old key */
- u8_t nack_count; /* Number of unacked segs */
- u8_t ttl;
+ struct bt_mesh_subnet *sub;
+ void *seg[CONFIG_BT_MESH_TX_SEG_MAX];
+ uint64_t seq_auth;
+ uint16_t src;
+ uint16_t dst;
+ uint16_t len;
+ uint8_t hdr;
+ uint8_t xmit;
+ uint8_t seg_n; /* Last segment index */
+ uint8_t seg_o; /* Segment being sent */
+ uint8_t nack_count; /* Number of unacked segs */
+ uint8_t attempts; /* Remaining tx attempts */
+ uint8_t ttl; /* Transmitted TTL value */
+ uint8_t seg_pending; /* Number of segments pending */
+ uint8_t blocked:1, /* Blocked by ongoing tx */
+ ctl:1, /* Control packet */
+ aszmic:1, /* MIC size */
+ started:1, /* Start cb called */
+ sending:1, /* Sending is in progress */
+ friend_cred:1; /* Using Friend credentials */
const struct bt_mesh_send_cb *cb;
- void *cb_data;
- struct k_delayed_work retransmit; /* Retransmit timer */
+ void *cb_data;
+ struct k_delayed_work retransmit; /* Retransmit timer */
} seg_tx[MYNEWT_VAL(BLE_MESH_TX_SEG_MSG_COUNT)];
static struct seg_rx {
struct bt_mesh_subnet *sub;
- u64_t seq_auth;
- u8_t seg_n:5,
- ctl:1,
- in_use:1,
- obo:1;
- u8_t hdr;
- u8_t ttl;
- u16_t src;
- u16_t dst;
- u32_t block;
- u32_t last;
+ void *seg[CONFIG_BT_MESH_RX_SEG_MAX];
+ uint64_t seq_auth;
+ uint16_t src;
+ uint16_t dst;
+ uint16_t len;
+ uint8_t hdr;
+ uint8_t seg_n:5,
+ ctl:1,
+ in_use:1,
+ obo:1;
+ uint8_t ttl;
+ uint32_t block;
+ uint32_t last;
struct k_delayed_work ack;
- struct os_mbuf *buf;
-} seg_rx[MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT)] = {
- [0 ... (MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT) - 1)] = { 0 },
-};
+} seg_rx[CONFIG_BT_MESH_RX_SEG_MSG_COUNT];
-static u16_t hb_sub_dst = BT_MESH_ADDR_UNASSIGNED;
+char _k_mem_slab_buffer_[(BT_MESH_APP_SEG_SDU_MAX*CONFIG_BT_MESH_SEG_BUFS)];
-void bt_mesh_set_hb_sub_dst(u16_t addr)
-{
- hb_sub_dst = addr;
-}
+struct k_mem_slab segs = {
+ .num_blocks = CONFIG_BT_MESH_SEG_BUFS,
+ .block_size = BT_MESH_APP_SEG_SDU_MAX,
+ .buffer = _k_mem_slab_buffer_,
+ .free_list = NULL,
+ .num_used = 0
+};
+
+static struct bt_mesh_va virtual_addrs[CONFIG_BT_MESH_LABEL_COUNT];
static int send_unseg(struct bt_mesh_net_tx *tx, struct os_mbuf *sdu,
- const struct bt_mesh_send_cb *cb, void *cb_data)
+ const struct bt_mesh_send_cb *cb, void *cb_data,
+ const uint8_t *ctl_op)
{
struct os_mbuf *buf;
- BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u",
- tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->om_len);
-
buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
if (!buf) {
BT_ERR("Out of network buffers");
@@ -118,7 +139,9 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct os_mbuf *sdu,
net_buf_reserve(buf, BT_MESH_NET_HDR_LEN);
- if (BT_MESH_IS_DEV_KEY(tx->ctx->app_idx)) {
+ if (ctl_op) {
+ net_buf_add_u8(buf, TRANS_CTL_HDR(*ctl_op, 0));
+ } else if (BT_MESH_IS_DEV_KEY(tx->ctx->app_idx)) {
net_buf_add_u8(buf, UNSEG_HDR(0, 0));
} else {
net_buf_add_u8(buf, UNSEG_HDR(1, tx->aid));
@@ -156,6 +179,15 @@ send:
return bt_mesh_net_send(tx, buf, cb, cb_data);
}
+static inline uint8_t seg_len(bool ctl)
+{
+ if (ctl) {
+ return BT_MESH_CTL_SEG_SDU_MAX;
+ } else {
+ return BT_MESH_APP_SEG_SDU_MAX;
+ }
+}
+
bool bt_mesh_tx_in_progress(void)
{
int i;
@@ -169,6 +201,41 @@ bool bt_mesh_tx_in_progress(void)
return false;
}
+static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx)
+{
+ k_mem_slab_free(&segs, (void **)&tx->seg[seg_idx]);
+ tx->seg[seg_idx] = NULL;
+ tx->nack_count--;
+}
+
+static bool seg_tx_blocks(struct seg_tx *tx, uint16_t src, uint16_t dst)
+{
+ return (tx->src == src) && (tx->dst == dst);
+}
+
+static void seg_tx_unblock_check(struct seg_tx *tx)
+{
+ struct seg_tx *blocked = NULL;
+ int i;
+
+ /* Unblock the first blocked tx with the same params. */
+ for (i = 0; i < ARRAY_SIZE(seg_tx); ++i) {
+ if (&seg_tx[i] != tx &&
+ seg_tx[i].blocked &&
+ seg_tx_blocks(tx, seg_tx[i].src, seg_tx[i].dst) &&
+ (!blocked || seg_tx[i].seq_auth < blocked->seq_auth)) {
+ blocked = &seg_tx[i];
+ }
+ }
+
+ if (blocked) {
+ BT_DBG("Unblocked 0x%04x",
+ (uint16_t)(blocked->seq_auth & TRANS_SEQ_ZERO_MASK));
+ blocked->blocked = false;
+ k_delayed_work_submit(&blocked->retransmit, 0);
+ }
+}
+
static void seg_tx_reset(struct seg_tx *tx)
{
int i;
@@ -179,22 +246,19 @@ static void seg_tx_reset(struct seg_tx *tx)
tx->cb_data = NULL;
tx->seq_auth = 0;
tx->sub = NULL;
+ tx->src = BT_MESH_ADDR_UNASSIGNED;
tx->dst = BT_MESH_ADDR_UNASSIGNED;
+ tx->blocked = false;
- if (!tx->nack_count) {
- return;
- }
-
- for (i = 0; i <= tx->seg_n; i++) {
+ for (i = 0; i <= tx->seg_n && tx->nack_count; i++) {
if (!tx->seg[i]) {
continue;
}
- net_buf_unref(tx->seg[i]);
- tx->seg[i] = NULL;
+ seg_tx_done(tx, i);
}
- tx->nack_count = 0U;
+ tx->nack_count = 0;
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_IVU_PENDING)) {
BT_DBG("Proceding with pending IV Update");
@@ -202,41 +266,60 @@ static void seg_tx_reset(struct seg_tx *tx)
/* bt_mesh_net_iv_update() will re-enable the flag if this
* wasn't the only transfer.
*/
- if (bt_mesh_net_iv_update(bt_mesh.iv_index, false)) {
- bt_mesh_net_sec_update(NULL);
- }
+ bt_mesh_net_iv_update(bt_mesh.iv_index, false);
}
}
static inline void seg_tx_complete(struct seg_tx *tx, int err)
{
- if (tx->cb && tx->cb->end) {
- tx->cb->end(err, tx->cb_data);
- }
+ const struct bt_mesh_send_cb *cb = tx->cb;
+ void *cb_data = tx->cb_data;
+
+ seg_tx_unblock_check(tx);
seg_tx_reset(tx);
+
+ if (cb && cb->end) {
+ cb->end(err, cb_data);
+ }
}
-static void seg_first_send_start(u16_t duration, int err, void *user_data)
+static void schedule_retransmit(struct seg_tx *tx)
{
- struct seg_tx *tx = user_data;
+ if (!tx->nack_count) {
+ return;
+ }
- if (tx->cb && tx->cb->start) {
- tx->cb->start(duration, err, tx->cb_data);
+ if (--tx->seg_pending || tx->sending) {
+ return;
}
+
+ BT_DBG("");
+
+ /* If we haven't gone through all the segments for this attempt yet,
+ * (likely because of a buffer allocation failure or because we
+ * called this from inside bt_mesh_net_send), we should continue the
+ * retransmit immediately, as we just freed up a tx buffer.
+ */
+ k_delayed_work_submit(&tx->retransmit,
+ tx->seg_o ? 0 : K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
}
-static void seg_send_start(u16_t duration, int err, void *user_data)
+static void seg_send_start(uint16_t duration, int err, void *user_data)
{
struct seg_tx *tx = user_data;
+ if (!tx->started && tx->cb && tx->cb->start) {
+ tx->cb->start(duration, err, tx->cb_data);
+ tx->started = 1U;
+ }
+
/* If there's an error in transmitting the 'sent' callback will never
* be called. Make sure that we kick the retransmit timer also in this
* case since otherwise we risk the transmission of becoming stale.
*/
if (err) {
- k_delayed_work_submit(&tx->retransmit,
- SEG_RETRANSMIT_TIMEOUT(tx));
+ schedule_retransmit(tx);
}
}
@@ -244,52 +327,107 @@ static void seg_sent(int err, void *user_data)
{
struct seg_tx *tx = user_data;
- k_delayed_work_submit(&tx->retransmit,
- SEG_RETRANSMIT_TIMEOUT(tx));
+ schedule_retransmit(tx);
}
-static const struct bt_mesh_send_cb first_sent_cb = {
- .start = seg_first_send_start,
- .end = seg_sent,
-};
-
static const struct bt_mesh_send_cb seg_sent_cb = {
.start = seg_send_start,
.end = seg_sent,
};
+static void seg_tx_buf_build(struct seg_tx *tx, uint8_t seg_o,
+ struct os_mbuf *buf)
+{
+ uint16_t seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK;
+ uint8_t len = MIN(seg_len(tx->ctl), tx->len - (seg_len(tx->ctl) * seg_o));
+
+ net_buf_simple_add_u8(buf, tx->hdr);
+ net_buf_simple_add_u8(buf, (tx->aszmic << 7) | seq_zero >> 6);
+ net_buf_simple_add_u8(buf, (((seq_zero & 0x3f) << 2) | (seg_o >> 3)));
+ net_buf_simple_add_u8(buf, ((seg_o & 0x07) << 5) | tx->seg_n);
+ net_buf_simple_add_mem(buf, tx->seg[seg_o], len);
+}
+
static void seg_tx_send_unacked(struct seg_tx *tx)
{
- int i, err;
+ if (!tx->nack_count) {
+ return;
+ }
- for (i = 0; i <= tx->seg_n; i++) {
- struct os_mbuf *seg = tx->seg[i];
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = tx->sub->net_idx,
+ /* App idx only used by network to detect control messages: */
+ .app_idx = (tx->ctl ? BT_MESH_KEY_UNUSED : 0),
+ .addr = tx->dst,
+ .send_rel = true,
+ .send_ttl = tx->ttl,
+ };
+ struct bt_mesh_net_tx net_tx = {
+ .sub = tx->sub,
+ .ctx = &ctx,
+ .src = tx->src,
+ .xmit = tx->xmit,
+ .friend_cred = tx->friend_cred,
+ .aid = tx->hdr & AID_MASK,
+ };
- if (!seg) {
- continue;
+ if (!tx->attempts) {
+ if (BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
+ BT_ERR("Ran out of retransmit attempts");
+ seg_tx_complete(tx, -ETIMEDOUT);
+ } else {
+ /* Segmented sending to groups doesn't have acks, so
+ * running out of attempts is the expected behavior.
+ */
+ seg_tx_complete(tx, 0);
}
- if (BT_MESH_ADV(seg)->busy) {
- BT_DBG("Skipping segment that's still advertising");
+ return;
+ }
+
+ BT_DBG("SeqZero: 0x%04x Attempts: %u",
+ (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->attempts);
+
+ tx->sending = 1U;
+
+ for (; tx->seg_o <= tx->seg_n; tx->seg_o++) {
+ struct os_mbuf *seg;
+ int err;
+
+ if (!tx->seg[tx->seg_o]) {
continue;
}
- if (!(BT_MESH_ADV(seg)->seg.attempts--)) {
- BT_ERR("Ran out of retransmit attempts");
- seg_tx_complete(tx, -ETIMEDOUT);
- return;
+ seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit,
+ BUF_TIMEOUT);
+ if (!seg) {
+ BT_DBG("Allocating segment failed");
+ goto end;
}
- BT_DBG("resending %u/%u", i, tx->seg_n);
+ net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
+ seg_tx_buf_build(tx, tx->seg_o, seg);
+
+ tx->seg_pending++;
+
+ BT_DBG("Sending %u/%u", tx->seg_o, tx->seg_n);
- err = bt_mesh_net_resend(tx->sub, seg, tx->new_key,
- &seg_sent_cb, tx);
+ err = bt_mesh_net_send(&net_tx, seg, &seg_sent_cb, tx);
if (err) {
- BT_ERR("Sending segment failed");
- seg_tx_complete(tx, -EIO);
- return;
+ BT_DBG("Sending segment failed");
+ tx->seg_pending--;
+ goto end;
}
}
+ tx->seg_o = 0U;
+ tx->attempts--;
+end:
+ if (!tx->seg_pending) {
+ k_delayed_work_submit(&tx->retransmit,
+ SEG_RETRANSMIT_TIMEOUT(tx));
+ }
+
+ tx->sending = 0U;
}
static void seg_retransmit(struct ble_npl_event *work)
@@ -299,31 +437,24 @@ static void seg_retransmit(struct ble_npl_event *work)
}
static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
- const struct bt_mesh_send_cb *cb, void *cb_data)
+ const struct bt_mesh_send_cb *cb, void *cb_data,
+ uint8_t *ctl_op)
{
- u8_t seg_hdr, seg_o;
- u16_t seq_zero;
+ bool blocked = false;
struct seg_tx *tx;
+ uint8_t seg_o;
int i;
BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u",
net_tx->src, net_tx->ctx->addr, net_tx->ctx->app_idx,
net_tx->aszmic, sdu->om_len);
- if (sdu->om_len < 1) {
- BT_ERR("Zero-length SDU not allowed");
- return -EINVAL;
- }
-
- if (sdu->om_len > BT_MESH_TX_SDU_MAX) {
- BT_ERR("Not enough segment buffers for length %u", sdu->om_len);
- return -EMSGSIZE;
- }
-
for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) {
- if (!seg_tx[i].nack_count) {
+ if (seg_tx[i].nack_count) {
+ blocked |= seg_tx_blocks(&seg_tx[i], net_tx->src,
+ net_tx->ctx->addr);
+ } else if (!tx) {
tx = &seg_tx[i];
- break;
}
}
@@ -332,31 +463,37 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
return -EBUSY;
}
- if (BT_MESH_IS_DEV_KEY(net_tx->ctx->app_idx)) {
- seg_hdr = SEG_HDR(0, 0);
+ if (ctl_op) {
+ tx->hdr = TRANS_CTL_HDR(*ctl_op, 1);
+ } else if (BT_MESH_IS_DEV_KEY(net_tx->ctx->app_idx)) {
+ tx->hdr = SEG_HDR(0, 0);
} else {
- seg_hdr = SEG_HDR(1, net_tx->aid);
+ tx->hdr = SEG_HDR(1, net_tx->aid);
}
- seg_o = 0;
+ tx->src = net_tx->src;
tx->dst = net_tx->ctx->addr;
- tx->seg_n = (sdu->om_len - 1) / 12;
+ tx->seg_n = (sdu->om_len - 1) / seg_len(!!ctl_op);
+ tx->seg_o = 0;
+ tx->len = sdu->om_len;
tx->nack_count = tx->seg_n + 1;
tx->seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_TX, bt_mesh.seq);
tx->sub = net_tx->sub;
- tx->new_key = net_tx->sub->kr_flag;
tx->cb = cb;
tx->cb_data = cb_data;
+ tx->attempts = SEG_RETRANSMIT_ATTEMPTS;
+ tx->seg_pending = 0;
+ tx->xmit = net_tx->xmit;
+ tx->aszmic = net_tx->aszmic;
+ tx->friend_cred = net_tx->friend_cred;
+ tx->blocked = blocked;
+ tx->started = 0;
+ tx->ctl = !!ctl_op;
- if (net_tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
- tx->ttl = bt_mesh_default_ttl_get();
- } else {
- tx->ttl = net_tx->ctx->send_ttl;
- }
+ tx->ttl = net_tx->ctx->send_ttl;
- seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK;
-
- BT_DBG("SeqZero 0x%04x", seq_zero);
+ BT_DBG("SeqZero 0x%04x (segs: %u)",
+ (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->nack_count);
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) &&
!bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src,
@@ -370,66 +507,48 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
}
for (seg_o = 0; sdu->om_len; seg_o++) {
- struct os_mbuf *seg;
- u16_t len;
+ void *buf;
+ uint16_t len;
int err;
- seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, net_tx->xmit,
- BUF_TIMEOUT);
- if (!seg) {
+ err = k_mem_slab_alloc(&segs, &buf);
+ if (err) {
BT_ERR("Out of segment buffers");
seg_tx_reset(tx);
return -ENOBUFS;
}
- BT_MESH_ADV(seg)->seg.attempts = SEG_RETRANSMIT_ATTEMPTS;
+ len = MIN(sdu->om_len, seg_len(!!ctl_op));
+ memcpy(buf, net_buf_simple_pull_mem(sdu, len), len);
+ BT_DBG("seg %u: %s", seg_o, bt_hex(buf, len));
- net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
-
- net_buf_add_u8(seg, seg_hdr);
- net_buf_add_u8(seg, (net_tx->aszmic << 7) | seq_zero >> 6);
- net_buf_add_u8(seg, (((seq_zero & 0x3f) << 2) |
- (seg_o >> 3)));
- net_buf_add_u8(seg, ((seg_o & 0x07) << 5) | tx->seg_n);
-
- len = min(sdu->om_len, 12);
- net_buf_add_mem(seg, sdu->om_data, len);
- net_buf_simple_pull(sdu, len);
+ tx->seg[seg_o] = buf;
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
enum bt_mesh_friend_pdu_type type;
+ struct os_mbuf *seg = NET_BUF_SIMPLE(16);
+ seg_tx_buf_build(tx, seg_o, seg);
+
if (seg_o == tx->seg_n) {
type = BT_MESH_FRIEND_PDU_COMPLETE;
} else {
type = BT_MESH_FRIEND_PDU_PARTIAL;
}
- if (bt_mesh_friend_enqueue_tx(net_tx, type,
- &tx->seq_auth,
- tx->seg_n + 1,
- seg) &&
+ if (bt_mesh_friend_enqueue_tx(
+ net_tx, type, ctl_op ? NULL : &tx->seq_auth,
+ tx->seg_n + 1, seg) &&
BT_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;
+ k_mem_slab_free(&segs, &buf);
+ tx->seg[seg_o] = NULL;
}
+ os_mbuf_free_chain(seg);
}
- tx->seg[seg_o] = net_buf_ref(seg);
-
- BT_DBG("Sending %u/%u", seg_o, tx->seg_n);
-
- err = bt_mesh_net_send(net_tx, seg,
- seg_o ? &seg_sent_cb : &first_sent_cb,
- tx);
- if (err) {
- BT_ERR("Sending segment failed");
- seg_tx_reset(tx);
- return err;
- }
}
/* This can happen if segments only went into the Friend Queue */
@@ -441,8 +560,21 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
* with the Friend Queue.
*/
send_cb_finalize(cb, cb_data);
+ return 0;
+ }
+
+ if (blocked) {
+ /* Move the sequence number, so we don't end up creating
+ * another segmented transmission with the same SeqZero while
+ * this one is blocked.
+ */
+ bt_mesh_next_seq();
+ BT_DBG("Blocked.");
+ return 0;
}
+ seg_tx_send_unacked(tx);
+
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
bt_mesh_lpn_established()) {
bt_mesh_lpn_poll();
@@ -451,50 +583,75 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
return 0;
}
-struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx)
+static int trans_encrypt(const struct bt_mesh_net_tx *tx, const uint8_t *key,
+ struct os_mbuf *msg)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+ struct bt_mesh_app_crypto_ctx crypto = {
+ .dev_key = BT_MESH_IS_DEV_KEY(tx->ctx->app_idx),
+ .aszmic = tx->aszmic,
+ .src = tx->src,
+ .dst = tx->ctx->addr,
+ .seq_num = bt_mesh.seq,
+ .iv_index = BT_MESH_NET_IVI_TX,
+ };
- if (key->net_idx != BT_MESH_KEY_UNUSED &&
- key->app_idx == app_idx) {
- return key;
- }
+ if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
+ crypto.ad = bt_mesh_va_label_get(tx->ctx->addr);
}
- return NULL;
+ return bt_mesh_app_encrypt(key, &crypto, msg);
}
int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
- const u8_t *key;
- u8_t *ad;
- u8_t aid;
+ const uint8_t *key;
+ uint8_t aid;
int err;
+ if (msg->om_len < 1) {
+ BT_ERR("Zero-length SDU not allowed");
+ return -EINVAL;
+ }
+
+ if (msg->om_len > BT_MESH_TX_SDU_MAX) {
+ BT_ERR("Not enough segment buffers for length %u", msg->om_len);
+ return -EMSGSIZE;
+ }
+
if (net_buf_simple_tailroom(msg) < 4) {
BT_ERR("Insufficient tailroom for Transport MIC");
return -EINVAL;
}
- if (msg->om_len > 11) {
- tx->ctx->send_rel = 1;
+ if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
+ tx->ctx->send_ttl = bt_mesh_default_ttl_get();
+ } else if (tx->ctx->send_ttl > BT_MESH_TTL_MAX) {
+ BT_ERR("TTL too large (max 127)");
+ return -EINVAL;
+ }
+
+ if (msg->om_len > BT_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_rel = true;
}
+ if (tx->ctx->addr == BT_MESH_ADDR_UNASSIGNED ||
+ (!BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) &&
+ BT_MESH_IS_DEV_KEY(tx->ctx->app_idx))) {
+ BT_ERR("Invalid destination address");
+ return -EINVAL;
+ }
+
BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx,
tx->ctx->app_idx, tx->ctx->addr);
BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len));
- err = bt_mesh_app_key_get(tx->sub, tx->ctx->app_idx,
- tx->ctx->addr, &key, &aid);
+ err = bt_mesh_keys_resolve(tx->ctx, &tx->sub, &key, &aid);
if (err) {
return err;
}
+ tx->xmit = bt_mesh_net_transmit_get();
tx->aid = aid;
if (!tx->ctx->send_rel || net_buf_simple_tailroom(msg) < 8) {
@@ -503,114 +660,79 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
tx->aszmic = 1;
}
- if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
- ad = bt_mesh_label_uuid_get(tx->ctx->addr);
- } else {
- ad = NULL;
- }
-
- err = bt_mesh_app_encrypt(key, BT_MESH_IS_DEV_KEY(tx->ctx->app_idx),
- tx->aszmic, msg, ad, tx->src, tx->ctx->addr,
- bt_mesh.seq, BT_MESH_NET_IVI_TX);
+ err = trans_encrypt(tx, key, msg);
if (err) {
return err;
}
if (tx->ctx->send_rel) {
- err = send_seg(tx, msg, cb, cb_data);
+ err = send_seg(tx, msg, cb, cb_data, NULL);
} else {
- err = send_unseg(tx, msg, cb, cb_data);
+ err = send_unseg(tx, msg, cb, cb_data, NULL);
}
return err;
}
-static void update_rpl(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx)
-{
- rpl->src = rx->ctx.addr;
- rpl->seq = rx->seq;
- rpl->old_iv = rx->old_iv;
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_rpl(rpl);
- }
-}
-
-/* Check the Replay Protection List for a replay attempt. If non-NULL match
- * parameter is given the RPL slot is returned but it is not immediately
- * updated (needed for segmented messages), whereas if a NULL match is given
- * the RPL is immediately updated (used for unsegmented messages).
- */
-static bool is_replay(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
+static void seg_rx_assemble(struct seg_rx *rx, struct os_mbuf *buf,
+ uint8_t aszmic)
{
int i;
- /* Don't bother checking messages from ourselves */
- if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
- return false;
- }
+ net_buf_simple_reset(buf);
- /* The RPL is used only for the local node */
- if (!rx->local_match) {
- return false;
+ for (i = 0; i <= rx->seg_n; i++) {
+ net_buf_simple_add_mem(buf, rx->seg[i],
+ MIN(seg_len(rx->ctl),
+ rx->len - (i * seg_len(rx->ctl))));
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
- /* Empty slot */
- if (!rpl->src) {
- if (match) {
- *match = rpl;
- } else {
- update_rpl(rpl, rx);
- }
-
- return false;
- }
+ /* Adjust the length to not contain the MIC at the end */
+ if (!rx->ctl) {
+ buf->om_len -= APP_MIC_LEN(aszmic);
+ }
+}
- /* Existing slot for given address */
- if (rpl->src == rx->ctx.addr) {
- if (rx->old_iv && !rpl->old_iv) {
- return true;
- }
+struct decrypt_ctx {
+ struct bt_mesh_app_crypto_ctx crypto;
+ struct os_mbuf *buf;
+ struct os_mbuf *sdu;
+ struct seg_rx *seg;
+};
- if ((!rx->old_iv && rpl->old_iv) ||
- rpl->seq < rx->seq) {
- if (match) {
- *match = rpl;
- } else {
- update_rpl(rpl, rx);
- }
+static int sdu_try_decrypt(struct bt_mesh_net_rx *rx, const uint8_t key[16],
+ void *cb_data)
+{
+ const struct decrypt_ctx *ctx = cb_data;
- return false;
- } else {
- return true;
- }
- }
+ if (ctx->seg) {
+ seg_rx_assemble(ctx->seg, ctx->buf, ctx->crypto.aszmic);
}
- BT_ERR("RPL is full!");
- return true;
+ net_buf_simple_reset(ctx->sdu);
+
+ return bt_mesh_app_decrypt(key, &ctx->crypto, ctx->buf, ctx->sdu);
}
-static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
- u8_t aszmic, struct os_mbuf *buf)
+static int sdu_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, uint8_t aszmic,
+ struct os_mbuf *buf, struct os_mbuf *sdu,
+ struct seg_rx *seg)
{
- struct os_mbuf *sdu =
- NET_BUF_SIMPLE(MYNEWT_VAL(BLE_MESH_RX_SDU_MAX) - 4);
- u8_t *ad;
- u16_t i;
- int err = 0;
+ struct decrypt_ctx ctx = {
+ .crypto = {
+ .dev_key = !AKF(&hdr),
+ .aszmic = aszmic,
+ .src = rx->ctx.addr,
+ .dst = rx->ctx.recv_dst,
+ .seq_num = seg ? (seg->seq_auth & 0xffffff) : rx->seq,
+ .iv_index = BT_MESH_NET_IVI_RX(rx),
+ },
+ .buf = buf,
+ .sdu = sdu,
+ .seg = seg,
+ };
- BT_DBG("ASZMIC %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr));
- BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
-
- if (buf->om_len < 1 + APP_MIC_LEN(aszmic)) {
- BT_ERR("Too short SDU + MIC");
- err = -EINVAL;
- goto done;
- }
+ BT_DBG("AKF %u AID 0x%02x", !ctx.crypto.dev_key, AID(&hdr));
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !rx->local_match) {
BT_DBG("Ignoring PDU for LPN 0x%04x of this Friend",
@@ -619,109 +741,26 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
}
if (BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
- ad = bt_mesh_label_uuid_get(rx->ctx.recv_dst);
- } else {
- ad = NULL;
- }
-
- /* Adjust the length to not contain the MIC at the end */
- buf->om_len -= APP_MIC_LEN(aszmic);
-
- if (!AKF(&hdr)) {
- net_buf_simple_init(sdu, 0);
- err = bt_mesh_app_decrypt(bt_mesh.dev_key, true, aszmic, buf,
- sdu, ad, rx->ctx.addr,
- rx->ctx.recv_dst, seq,
- BT_MESH_NET_IVI_RX(rx));
- if (err) {
- BT_WARN("Unable to decrypt with local DevKey");
- } else {
- rx->ctx.app_idx = BT_MESH_KEY_DEV_LOCAL;
- bt_mesh_model_recv(rx, sdu);
- goto done;
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- struct bt_mesh_node *node;
-
- /*
- * There is no way of knowing if we should use our
- * local DevKey or the remote DevKey to decrypt the
- * message so we must try both.
- */
-
- node = bt_mesh_node_find(rx->ctx.addr);
- if (node == NULL) {
- BT_ERR("No node found for addr 0x%04x",
- rx->ctx.addr);
- return -EINVAL;
- }
-
- net_buf_simple_init(sdu, 0);
- err = bt_mesh_app_decrypt(node->dev_key, true, aszmic,
- buf, sdu, ad, rx->ctx.addr,
- rx->ctx.recv_dst, seq,
- BT_MESH_NET_IVI_RX(rx));
- if (err) {
- BT_ERR("Unable to decrypt with node DevKey");
- return -EINVAL;
- }
-
- rx->ctx.app_idx = BT_MESH_KEY_DEV_REMOTE;
- bt_mesh_model_recv(rx, sdu);
- return 0;
- }
-
- return -EINVAL;
+ ctx.crypto.ad = bt_mesh_va_label_get(rx->ctx.recv_dst);
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
- struct bt_mesh_app_keys *keys;
-
- /* Check that this AppKey matches received net_idx */
- if (key->net_idx != rx->sub->net_idx) {
- continue;
- }
-
- if (rx->new_key && key->updated) {
- keys = &key->keys[1];
- } else {
- keys = &key->keys[0];
- }
-
- /* Check that the AppKey ID matches */
- if (AID(&hdr) != keys->id) {
- continue;
- }
-
- net_buf_simple_init(sdu, 0);
- err = bt_mesh_app_decrypt(keys->val, false, aszmic, buf,
- sdu, ad, rx->ctx.addr,
- rx->ctx.recv_dst, seq,
- BT_MESH_NET_IVI_RX(rx));
- if (err) {
- BT_WARN("Unable to decrypt with AppKey 0x%03x",
- key->app_idx);
- continue;
-
- }
-
- rx->ctx.app_idx = key->app_idx;
-
- bt_mesh_model_recv(rx, sdu);
+ rx->ctx.app_idx = bt_mesh_app_key_find(ctx.crypto.dev_key, AID(&hdr),
+ rx, sdu_try_decrypt, &ctx);
+ if (rx->ctx.app_idx == BT_MESH_KEY_UNUSED) {
+ BT_DBG("No matching AppKey");
goto done;
}
- BT_WARN("No matching AppKey");
+ BT_DBG("Decrypted (AppIdx: 0x%03x)", rx->ctx.app_idx);
+
+ bt_mesh_model_recv(rx, sdu);
- err = -EINVAL;
done:
os_mbuf_free_chain(sdu);
- return err;
+ return 0;
}
-static struct seg_tx *seg_tx_lookup(u16_t seq_zero, u8_t obo, u16_t addr)
+static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t addr)
{
struct seg_tx *tx;
int i;
@@ -751,14 +790,14 @@ static struct seg_tx *seg_tx_lookup(u16_t seq_zero, u8_t obo, u16_t addr)
return NULL;
}
-static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
- struct os_mbuf *buf, u64_t *seq_auth)
+static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
+ struct os_mbuf *buf, uint64_t *seq_auth)
{
struct seg_tx *tx;
unsigned int bit;
- u32_t ack;
- u16_t seq_zero;
- u8_t obo;
+ uint32_t ack;
+ uint16_t seq_zero;
+ uint8_t obo;
if (buf->om_len < 6) {
BT_ERR("Too short ack message");
@@ -787,6 +826,11 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
return -EINVAL;
}
+ if (!BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
+ BT_ERR("Received ack for group seg");
+ return -EINVAL;
+ }
+
*seq_auth = tx->seq_auth;
if (!ack) {
@@ -805,9 +849,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
while ((bit = find_lsb_set(ack))) {
if (tx->seg[bit - 1]) {
BT_DBG("seg %u/%u acked", bit - 1, tx->seg_n);
- net_buf_unref(tx->seg[bit - 1]);
- tx->seg[bit - 1] = NULL;
- tx->nack_count--;
+ seg_tx_done(tx, bit - 1);
}
ack &= ~BIT(bit - 1);
@@ -823,40 +865,10 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
return 0;
}
-static int trans_heartbeat(struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- u8_t init_ttl, hops;
- u16_t feat;
-
- if (buf->om_len < 3) {
- BT_ERR("Too short heartbeat message");
- return -EINVAL;
- }
-
- if (rx->ctx.recv_dst != hb_sub_dst) {
- BT_WARN("Ignoring heartbeat to non-subscribed destination");
- return 0;
- }
-
- init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
- feat = net_buf_simple_pull_be16(buf);
-
- hops = (init_ttl - rx->ctx.recv_ttl + 1);
-
- BT_DBG("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x",
- rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
- (hops == 1) ? "" : "s", feat);
-
- bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
-
- return 0;
-}
-
-static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
- struct os_mbuf *buf, u64_t *seq_auth)
+static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr,
+ struct os_mbuf *buf, uint64_t *seq_auth)
{
- u8_t ctl_op = TRANS_CTL_OP(&hdr);
+ uint8_t ctl_op = TRANS_CTL_OP(&hdr);
BT_DBG("OpCode 0x%02x len %u", ctl_op, buf->om_len);
@@ -864,7 +876,7 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
case TRANS_CTL_OP_ACK:
return trans_ack(rx, hdr, buf, seq_auth);
case TRANS_CTL_OP_HEARTBEAT:
- return trans_heartbeat(rx, buf);
+ return bt_mesh_hb_recv(rx, buf);
}
/* Only acks and heartbeats may need processing without local_match */
@@ -919,9 +931,10 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
}
static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
- u64_t *seq_auth)
+ uint64_t *seq_auth)
{
- u8_t hdr;
+ struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_SDU_UNSEG_MAX);
+ uint8_t hdr;
BT_DBG("AFK %u AID 0x%02x", AKF(buf->om_data), AID(buf->om_data));
@@ -930,7 +943,7 @@ static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
return -EINVAL;
}
- if (is_replay(rx, NULL)) {
+ if (bt_mesh_rpl_check(rx, NULL)) {
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
rx->ctx.addr, rx->ctx.recv_dst, (unsigned) rx->seq);
return -EINVAL;
@@ -940,20 +953,23 @@ static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
if (rx->ctl) {
return ctl_recv(rx, hdr, buf, seq_auth);
- } else {
- /* SDUs must match a local element or an LPN of this Friend. */
- if (!rx->local_match && !rx->friend_match) {
- return 0;
- }
+ }
- return sdu_recv(rx, rx->seq, hdr, 0, buf);
+ if (buf->om_len < 1 + APP_MIC_LEN(0)) {
+ BT_ERR("Too short SDU + MIC");
+ return -EINVAL;
}
+
+ /* Adjust the length to not contain the MIC at the end */
+ buf->om_len -= APP_MIC_LEN(0);
+
+ return sdu_recv(rx, hdr, 0, buf, sdu, NULL);
}
-static inline s32_t ack_timeout(struct seg_rx *rx)
+static inline int32_t ack_timeout(struct seg_rx *rx)
{
- s32_t to;
- u8_t ttl;
+ int32_t to;
+ uint8_t ttl;
if (rx->ttl == BT_MESH_TTL_DEFAULT) {
ttl = bt_mesh_default_ttl_get();
@@ -975,45 +991,46 @@ static inline s32_t ack_timeout(struct seg_rx *rx)
return max(to, K_MSEC(400));
}
-int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
- size_t data_len, u64_t *seq_auth,
- const struct bt_mesh_send_cb *cb, void *cb_data)
+int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
+ size_t data_len, const struct bt_mesh_send_cb *cb, void *cb_data)
{
- struct os_mbuf *buf;
+ struct os_mbuf *buf = NET_BUF_SIMPLE(data_len);
- BT_DBG("src 0x%04x dst 0x%04x ttl 0x%02x ctl 0x%02x", tx->src,
- tx->ctx->addr, tx->ctx->send_ttl, ctl_op);
- BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len));
+ net_buf_simple_init_with_data(buf, data, data_len);
- buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
- if (!buf) {
- BT_ERR("Out of transport buffers");
- return -ENOBUFS;
+ if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
+ tx->ctx->send_ttl = bt_mesh_default_ttl_get();
+ } else if (tx->ctx->send_ttl > BT_MESH_TTL_MAX) {
+ BT_ERR("TTL too large (max 127)");
+ return -EINVAL;
}
- net_buf_reserve(buf, BT_MESH_NET_HDR_LEN);
-
- net_buf_add_u8(buf, TRANS_CTL_HDR(ctl_op, 0));
+ if (data_len > BT_MESH_SDU_UNSEG_MAX) {
+ tx->ctx->send_rel = true;
+ }
- net_buf_add_mem(buf, data, data_len);
+ tx->ctx->app_idx = BT_MESH_KEY_UNUSED;
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- if (bt_mesh_friend_enqueue_tx(tx, BT_MESH_FRIEND_PDU_SINGLE,
- seq_auth, 1, buf) &&
- BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
- /* PDUs for a specific Friend should only go
- * out through the Friend Queue.
- */
- net_buf_unref(buf);
- return 0;
- }
+ if (tx->ctx->addr == BT_MESH_ADDR_UNASSIGNED ||
+ BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
+ BT_ERR("Invalid destination address");
+ return -EINVAL;
}
- return bt_mesh_net_send(tx, buf, cb, cb_data);
+ BT_DBG("src 0x%04x dst 0x%04x ttl 0x%02x ctl 0x%02x", tx->src,
+ tx->ctx->addr, tx->ctx->send_ttl, ctl_op);
+ BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len));
+
+ if (tx->ctx->send_rel) {
+ return send_seg(tx, buf, cb, cb_data, &ctl_op);
+ } else {
+ return send_unseg(tx, buf, cb, cb_data, &ctl_op);
+ }
+ os_mbuf_free_chain(buf);
}
-static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
- u8_t ttl, u64_t *seq_auth, u32_t block, u8_t obo)
+static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst,
+ uint8_t ttl, uint64_t *seq_auth, uint32_t block, uint8_t obo)
{
struct bt_mesh_msg_ctx ctx = {
.net_idx = sub->net_idx,
@@ -1027,8 +1044,8 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
.src = obo ? bt_mesh_primary_addr() : src,
.xmit = bt_mesh_net_transmit_get(),
};
- u16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK;
- u8_t buf[6];
+ uint16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK;
+ uint8_t buf[6];
BT_DBG("SeqZero 0x%04x Block 0x%08x OBO %u", seq_zero,
(unsigned) block, obo);
@@ -1042,7 +1059,7 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
* or virtual address.
*/
if (!BT_MESH_ADDR_IS_UNICAST(src)) {
- BT_WARN("Not sending ack for non-unicast address");
+ BT_DBG("Not sending ack for non-unicast address");
return 0;
}
@@ -1050,11 +1067,13 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
sys_put_be32(block, &buf[2]);
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_ACK, buf, sizeof(buf),
- NULL, NULL, NULL);
+ NULL, NULL);
}
static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
{
+ int i;
+
BT_DBG("rx %p", rx);
k_delayed_work_cancel(&rx->ack);
@@ -1066,6 +1085,15 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
&rx->seq_auth);
}
+ for (i = 0; i <= rx->seg_n; i++) {
+ if (!rx->seg[i]) {
+ continue;
+ }
+
+ k_mem_slab_free(&segs, &rx->seg[i]);
+ rx->seg[i] = NULL;
+ }
+
rx->in_use = 0;
/* We don't always reset these values since we need to be able to
@@ -1083,6 +1111,7 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
static void seg_ack(struct ble_npl_event *work)
{
struct seg_rx *rx = ble_npl_event_get_arg(work);
+ int32_t timeout;
BT_DBG("rx %p", rx);
@@ -1100,25 +1129,17 @@ static void seg_ack(struct ble_npl_event *work)
send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth,
rx->block, rx->obo);
- k_delayed_work_submit(&rx->ack, ack_timeout(rx));
+ timeout = ack_timeout(rx);
+ k_delayed_work_submit(&rx->ack, K_MSEC(timeout));
}
-static inline u8_t seg_len(bool ctl)
+static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
{
- if (ctl) {
- return 8;
- } else {
- return 12;
- }
-}
-
-static inline bool sdu_len_is_ok(bool ctl, u8_t seg_n)
-{
- return ((seg_n * seg_len(ctl) + 1) <= MYNEWT_VAL(BLE_MESH_RX_SDU_MAX));
+ return (seg_n < CONFIG_BT_MESH_RX_SEG_MAX);
}
static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
- const u64_t *seq_auth)
+ const uint64_t *seq_auth)
{
int i;
@@ -1155,7 +1176,7 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
}
static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
- const u8_t *hdr, u8_t seg_n)
+ const uint8_t *hdr, uint8_t seg_n)
{
if (rx->hdr != *hdr || rx->seg_n != seg_n) {
BT_ERR("Invalid segment for ongoing session");
@@ -1176,11 +1197,19 @@ static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
}
static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
- const u8_t *hdr, const u64_t *seq_auth,
- u8_t seg_n)
+ const uint8_t *hdr, const uint64_t *seq_auth,
+ uint8_t seg_n)
{
int i;
+ /* No race condition on this check, as this function only executes in
+ * the collaborative Bluetooth rx thread:
+ */
+ if (k_mem_slab_num_free_get(&segs) < 1) {
+ BT_WARN("Not enough segments for incoming message");
+ return NULL;
+ }
+
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i];
@@ -1189,7 +1218,6 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
}
rx->in_use = 1;
- net_buf_simple_init(rx->buf, 0);
rx->sub = net_rx->sub;
rx->ctl = net_rx->ctl;
rx->seq_auth = *seq_auth;
@@ -1210,15 +1238,15 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
}
static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
- enum bt_mesh_friend_pdu_type *pdu_type, u64_t *seq_auth,
- u8_t *seg_count)
+ enum bt_mesh_friend_pdu_type *pdu_type, uint64_t *seq_auth,
+ uint8_t *seg_count)
{
struct bt_mesh_rpl *rpl = NULL;
struct seg_rx *rx;
- u8_t *hdr = buf->om_data;
- u16_t seq_zero;
- u8_t seg_n;
- u8_t seg_o;
+ uint8_t *hdr = buf->om_data;
+ uint16_t seq_zero;
+ uint8_t seg_n;
+ uint8_t seg_o;
int err;
if (buf->om_len < 5) {
@@ -1226,7 +1254,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
return -EINVAL;
}
- if (is_replay(net_rx, &rpl)) {
+ if (bt_mesh_rpl_check(net_rx, &rpl)) {
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq);
return -EINVAL;
@@ -1290,14 +1318,14 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
}
if (rx->block == BLOCK_COMPLETE(rx->seg_n)) {
- BT_WARN("Got segment for already complete SDU");
+ BT_DBG("Got segment for already complete SDU");
send_ack(net_rx->sub, net_rx->ctx.recv_dst,
net_rx->ctx.addr, net_rx->ctx.send_ttl,
seq_auth, rx->block, rx->obo);
if (rpl) {
- update_rpl(rpl, net_rx);
+ bt_mesh_rpl_update(rpl, net_rx);
}
return -EALREADY;
@@ -1351,7 +1379,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
found_rx:
if (BIT(seg_o) & rx->block) {
- BT_WARN("Received already received fragment");
+ BT_DBG("Received already received fragment");
return -EALREADY;
}
@@ -1361,11 +1389,11 @@ found_rx:
*/
if (seg_o == seg_n) {
/* Set the expected final buffer length */
- rx->buf->om_len = seg_n * seg_len(rx->ctl) + buf->om_len;
+ rx->len = seg_n * seg_len(rx->ctl) + buf->om_len;
BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(rx->ctl),
- buf->om_len, rx->buf->om_len);
+ buf->om_len, rx->len);
- if (rx->buf->om_len > MYNEWT_VAL(BLE_MESH_RX_SDU_MAX)) {
+ if (rx->len > BT_MESH_RX_SDU_MAX) {
BT_ERR("Too large SDU len");
send_ack(net_rx->sub, net_rx->ctx.recv_dst,
net_rx->ctx.addr, net_rx->ctx.send_ttl,
@@ -1385,11 +1413,20 @@ found_rx:
if (!k_delayed_work_remaining_get(&rx->ack) &&
!bt_mesh_lpn_established()) {
- k_delayed_work_submit(&rx->ack, ack_timeout(rx));
+ int32_t timeout = ack_timeout(rx);
+
+ k_delayed_work_submit(&rx->ack, K_MSEC(timeout));
}
- /* Location in buffer can be calculated based on seg_o & rx->ctl */
- memcpy(rx->buf->om_data + (seg_o * seg_len(rx->ctl)), buf->om_data, buf->om_len);
+ /* Allocated segment here */
+ err = k_mem_slab_alloc(&segs, &rx->seg[seg_o]);
+ if (err) {
+ BT_WARN("Unable allocate buffer for Seg %u", seg_o);
+ return -ENOBUFS;
+ }
+
+ os_mbuf_copydata(buf, 0, buf->om_len, rx->seg[seg_o]);
+ BT_DBG("copied %s", bt_hex(rx->seg[seg_o], rx->len));
BT_DBG("Received %u/%u", seg_o, seg_n);
@@ -1404,7 +1441,7 @@ found_rx:
BT_DBG("Complete SDU");
if (rpl) {
- update_rpl(rpl, net_rx);
+ bt_mesh_rpl_update(rpl, net_rx);
}
*pdu_type = BT_MESH_FRIEND_PDU_COMPLETE;
@@ -1414,23 +1451,40 @@ found_rx:
net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
if (net_rx->ctl) {
- err = ctl_recv(net_rx, *hdr, rx->buf, seq_auth);
+ struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_RX_CTL_MAX);
+ seg_rx_assemble(rx, sdu, 0U);
+ err = ctl_recv(net_rx, *hdr, sdu, seq_auth);
+ } else if (rx->len < 1 + APP_MIC_LEN(ASZMIC(hdr))) {
+ BT_ERR("Too short SDU + MIC");
+ err = -EINVAL;
} else {
- err = sdu_recv(net_rx, (rx->seq_auth & 0xffffff), *hdr,
- ASZMIC(hdr), rx->buf);
+ struct os_mbuf *seg_buf = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX);
+ struct os_mbuf *sdu;
+
+ /* Decrypting in place to avoid creating two assembly buffers.
+ * We'll reassemble the buffer from the segments before each
+ * decryption attempt.
+ */
+ net_buf_simple_init(seg_buf, 0);
+
+ sdu = NET_BUF_SIMPLE(rx->len - APP_MIC_LEN(ASZMIC(hdr)));
+ net_buf_simple_init_with_data(
+ sdu, seg_buf->om_data, rx->len - APP_MIC_LEN(ASZMIC(hdr)));
+
+ err = sdu_recv(net_rx, *hdr, ASZMIC(hdr), seg_buf, sdu, rx);
+ os_mbuf_free_chain(seg_buf);
}
seg_rx_reset(rx, false);
-
return err;
}
int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx)
{
- u64_t seq_auth = TRANS_SEQ_AUTH_NVAL;
+ uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL;
enum bt_mesh_friend_pdu_type pdu_type = BT_MESH_FRIEND_PDU_SINGLE;
struct net_buf_simple_state state;
- u8_t seg_count = 0;
+ uint8_t seg_count = 0;
int err;
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
@@ -1525,28 +1579,43 @@ void bt_mesh_rx_reset(void)
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
seg_rx_reset(&seg_rx[i], true);
}
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_clear_rpl();
- } else {
- memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
- }
}
-void bt_mesh_tx_reset(void)
+void bt_mesh_trans_reset(void)
{
int i;
+ bt_mesh_rx_reset();
+
BT_DBG("");
for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
seg_tx_reset(&seg_tx[i]);
}
+
+ for (i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+ if (virtual_addrs[i].ref) {
+ virtual_addrs[i].ref = 0U;
+ virtual_addrs[i].changed = 1U;
+ }
+ }
+
+ bt_mesh_rpl_clear();
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_label();
+ }
}
void bt_mesh_trans_init(void)
{
- int i;
+ int i, rc;
+
+ /* We need to initialize memslab free list here */
+ rc = create_free_list(&segs);
+ if (rc) {
+ BT_ERR("Failed to create free memslab list")
+ }
for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
k_delayed_work_init(&seg_tx[i].retransmit, seg_retransmit);
@@ -1557,112 +1626,124 @@ void bt_mesh_trans_init(void)
* For now we increase MSYS_1_BLOCK_COUNT
*/
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
- seg_rx[i].buf = NET_BUF_SIMPLE(MYNEWT_VAL(BLE_MESH_RX_SDU_MAX));
k_delayed_work_init(&seg_rx[i].ack, seg_ack);
k_delayed_work_add_arg(&seg_rx[i].ack, &seg_rx[i]);
}
}
-void bt_mesh_rpl_clear(void)
+struct bt_mesh_va *bt_mesh_va_get(uint16_t index)
{
- BT_DBG("");
- memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
+ if (index >= ARRAY_SIZE(virtual_addrs)) {
+ return NULL;
+ }
+
+ return &virtual_addrs[index];
}
-void bt_mesh_heartbeat_send(void)
+static inline void va_store(struct bt_mesh_va *store)
{
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
- u16_t feat = 0U;
- struct __packed {
- u8_t init_ttl;
- u16_t feat;
- } hb;
- struct bt_mesh_msg_ctx ctx = {
- .net_idx = cfg->hb_pub.net_idx,
- .app_idx = BT_MESH_KEY_UNUSED,
- .addr = cfg->hb_pub.dst,
- .send_ttl = cfg->hb_pub.ttl,
- };
- struct bt_mesh_net_tx tx = {
- .sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx),
- .ctx = &ctx,
- .src = bt_mesh_model_elem(cfg->model)->addr,
- .xmit = bt_mesh_net_transmit_get(),
- };
-
- /* Do nothing if heartbeat publication is not enabled */
- if (cfg->hb_pub.dst == BT_MESH_ADDR_UNASSIGNED) {
- return;
+ store->changed = 1U;
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_label();
}
+}
- hb.init_ttl = cfg->hb_pub.ttl;
+uint8_t bt_mesh_va_add(uint8_t uuid[16], uint16_t *addr)
+{
+ struct bt_mesh_va *va = NULL;
+ int err;
- if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) {
- feat |= BT_MESH_FEAT_RELAY;
- }
+ for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+ if (!virtual_addrs[i].ref) {
+ if (!va) {
+ va = &virtual_addrs[i];
+ }
+
+ continue;
+ }
- if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
- feat |= BT_MESH_FEAT_PROXY;
+ if (!memcmp(uuid, virtual_addrs[i].uuid,
+ ARRAY_SIZE(virtual_addrs[i].uuid))) {
+ *addr = virtual_addrs[i].addr;
+ virtual_addrs[i].ref++;
+ va_store(&virtual_addrs[i]);
+ return STATUS_SUCCESS;
+ }
}
- if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) {
- feat |= BT_MESH_FEAT_FRIEND;
+ if (!va) {
+ return STATUS_INSUFF_RESOURCES;
}
- if (bt_mesh_lpn_established()) {
- feat |= BT_MESH_FEAT_LOW_POWER;
+ memcpy(va->uuid, uuid, ARRAY_SIZE(va->uuid));
+ err = bt_mesh_virtual_addr(uuid, &va->addr);
+ if (err) {
+ va->addr = BT_MESH_ADDR_UNASSIGNED;
+ return STATUS_UNSPECIFIED;
}
- hb.feat = sys_cpu_to_be16(feat);
+ va->ref = 1;
+ va_store(va);
- BT_DBG("InitTTL %u feat 0x%04x", cfg->hb_pub.ttl, feat);
+ *addr = va->addr;
- bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
- NULL, NULL, NULL);
+ return STATUS_SUCCESS;
}
-int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
- u16_t addr, const u8_t **key, u8_t *aid)
+uint8_t bt_mesh_va_del(uint8_t uuid[16], uint16_t *addr)
{
- struct bt_mesh_app_key *app_key;
-
- if (app_idx == BT_MESH_KEY_DEV_LOCAL ||
- (app_idx == BT_MESH_KEY_DEV_REMOTE &&
- bt_mesh_elem_find(addr) != NULL)) {
- *aid = 0;
- *key = bt_mesh.dev_key;
- return 0;
- } else if (app_idx == BT_MESH_KEY_DEV_REMOTE) {
- if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- return -EINVAL;
- }
+ struct bt_mesh_va *va = NULL;
- struct bt_mesh_node *node = bt_mesh_node_find(addr);
- if (!node) {
- return -EINVAL;
+ for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+ if (virtual_addrs[i].ref &&
+ !memcmp(uuid, virtual_addrs[i].uuid,
+ ARRAY_SIZE(virtual_addrs[i].uuid))) {
+ va = &virtual_addrs[i];
+ break;
}
+ }
- *key = node->dev_key;
- *aid = 0;
- return 0;
+ if (!va) {
+ return STATUS_CANNOT_REMOVE;
}
- if (!subnet) {
- return -EINVAL;
+ va->ref--;
+ if (addr) {
+ *addr = va->addr;
}
- app_key = bt_mesh_app_key_find(app_idx);
- if (!app_key) {
- return -ENOENT;
+ va_store(va);
+ return STATUS_SUCCESS;
+}
+
+struct bt_mesh_va *bt_mesh_va_find(uint8_t uuid[16])
+{
+ for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+ if (virtual_addrs[i].ref &&
+ !memcmp(uuid, virtual_addrs[i].uuid,
+ ARRAY_SIZE(virtual_addrs[i].uuid))) {
+ return &virtual_addrs[i];
+ }
}
- if (subnet->kr_phase == BT_MESH_KR_PHASE_2 && app_key->updated) {
- *key = app_key->keys[1].val;
- *aid = app_key->keys[1].id;
- } else {
- *key = app_key->keys[0].val;
- *aid = app_key->keys[0].id;
+ return NULL;
+}
+
+uint8_t *bt_mesh_va_label_get(uint16_t addr)
+{
+ int i;
+
+ BT_DBG("addr 0x%04x", addr);
+
+ for (i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+ if (virtual_addrs[i].ref && virtual_addrs[i].addr == addr) {
+ BT_DBG("Found Label UUID for 0x%04x: %s", addr,
+ bt_hex(virtual_addrs[i].uuid, 16));
+ return virtual_addrs[i].uuid;
+ }
}
- return 0;
+ BT_WARN("No matching Label UUID for 0x%04x", addr);
+
+ return NULL;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h
index eff768e9..23be7139 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/transport.h
@@ -11,10 +11,12 @@
#define TRANS_SEQ_AUTH_NVAL 0xffffffffffffffff
-#define BT_MESH_TX_SDU_MAX (CONFIG_BT_MESH_TX_SEG_MAX * 12)
+#define BT_MESH_SDU_UNSEG_MAX 11
+#define BT_MESH_CTL_SEG_SDU_MAX 8
+#define BT_MESH_RX_CTL_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_CTL_SEG_SDU_MAX)
-#define TRANS_SEQ_ZERO_MASK ((u16_t)BIT_MASK(13))
-#define TRANS_CTL_OP_MASK ((u8_t)BIT_MASK(7))
+#define TRANS_SEQ_ZERO_MASK ((uint16_t)BIT_MASK(13))
+#define TRANS_CTL_OP_MASK ((uint8_t)BIT_MASK(7))
#define TRANS_CTL_OP(data) ((data)[0] & TRANS_CTL_OP_MASK)
#define TRANS_CTL_HDR(op, seg) ((op & TRANS_CTL_OP_MASK) | (seg << 7))
@@ -31,64 +33,65 @@
#define TRANS_CTL_OP_HEARTBEAT 0x0a
struct bt_mesh_ctl_friend_poll {
- u8_t fsn;
+ uint8_t fsn;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_update {
- u8_t flags;
- u32_t iv_index;
- u8_t md;
+ uint8_t flags;
+ uint32_t iv_index;
+ uint8_t md;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_req {
- u8_t criteria;
- u8_t recv_delay;
- u8_t poll_to[3];
- u16_t prev_addr;
- u8_t num_elem;
- u16_t lpn_counter;
+ uint8_t criteria;
+ uint8_t recv_delay;
+ uint8_t poll_to[3];
+ uint16_t prev_addr;
+ uint8_t num_elem;
+ uint16_t lpn_counter;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_offer {
- u8_t recv_win;
- u8_t queue_size;
- u8_t sub_list_size;
- s8_t rssi;
- u16_t frnd_counter;
+ uint8_t recv_win;
+ uint8_t queue_size;
+ uint8_t sub_list_size;
+ int8_t rssi;
+ uint16_t frnd_counter;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_clear {
- u16_t lpn_addr;
- u16_t lpn_counter;
+ uint16_t lpn_addr;
+ uint16_t lpn_counter;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_clear_confirm {
- u16_t lpn_addr;
- u16_t lpn_counter;
+ uint16_t lpn_addr;
+ uint16_t lpn_counter;
}__attribute__((__packed__));
#define BT_MESH_FRIEND_SUB_MIN_LEN (1 + 2)
struct bt_mesh_ctl_friend_sub {
- u8_t xact;
- u16_t addr_list[5];
+ uint8_t xact;
+ uint16_t addr_list[5];
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_sub_confirm {
- u8_t xact;
+ uint8_t xact;
}__attribute__((__packed__));
-void bt_mesh_set_hb_sub_dst(u16_t addr);
-
-struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx);
+struct bt_mesh_va {
+ uint16_t ref:15,
+ changed:1;
+ uint16_t addr;
+ uint8_t uuid[16];
+};
bool bt_mesh_tx_in_progress(void);
void bt_mesh_rx_reset(void);
-void bt_mesh_tx_reset(void);
-int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
- size_t data_len, u64_t *seq_auth,
- const struct bt_mesh_send_cb *cb, void *cb_data);
+int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
+ size_t data_len, const struct bt_mesh_send_cb *cb, void *cb_data);
int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
const struct bt_mesh_send_cb *cb, void *cb_data);
@@ -97,9 +100,14 @@ int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx);
void bt_mesh_trans_init(void);
-void bt_mesh_rpl_clear(void);
+void bt_mesh_trans_reset(void);
+
+struct bt_mesh_va *bt_mesh_va_get(uint16_t index);
+
+struct bt_mesh_va *bt_mesh_va_find(uint8_t uuid[16]);
+
+uint8_t bt_mesh_va_add(uint8_t uuid[16], uint16_t *addr);
-void bt_mesh_heartbeat_send(void);
+uint8_t bt_mesh_va_del(uint8_t uuid[16], uint16_t *addr);
-int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
- u16_t addr, const u8_t **key, u8_t *aid);
+uint8_t *bt_mesh_va_label_get(uint16_t addr); \ No newline at end of file
diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml b/src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml
index 98632232..cf0c7f75 100644
--- a/src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml
+++ b/src/libs/mynewt-nimble/nimble/host/mesh/syscfg.yml
@@ -29,17 +29,57 @@ syscfg.defs:
the advertising bearer.
value: 1
+ BLE_MESH_UNPROV_BEACON_INT:
+ description: >
+ This option specifies the interval (in seconds) at which the
+ device sends unprovisioned beacon.
+ value: 5
+
+ BLE_MESH_PB_ADV_RETRANS_TIMEOUT:
+ description: >
+ Timeout value of retransmit provisioning PDUs.
+ value: 500
+
+ BLE_MESH_PROV_DEVICE:
+ description: >
+ Enable this option to allow the device to be provisioned into a mesh network.
+ value: 1
+ restrictions: BLE_MESH_PROV
+
BLE_MESH_PROVISIONER:
description: >
Enable this option to have support for provisioning remote devices.
- value: 0
+ value: 1
restrictions:
- - (BLE_MESH_PROV)
+ - BLE_MESH_PROV
+ - BLE_MESH_PB_ADV
+
+ BLE_MESH_CDB:
+ description: >
+ Mesh Configuration Database [EXPERIMENTAL]
+ value: 0
- BLE_MESH_NODE_COUNT:
+ BLE_MESH_CDB_NODE_COUNT:
description: >
This option specifies how many nodes each network can at most
- save in the provisioning database. Range 1-4096
+ save in the configuration database.
+ value: 1
+
+ BLE_MESH_CDB_SUBNET_COUNT:
+ description: >
+ This option specifies how many subnets that can at most be
+ saved in the configuration database.
+ value: 1
+
+ BLE_MESH_CDB_APP_KEY_COUNT:
+ description: >
+ This option specifies how many application keys that can at most
+ be saved in the configuration database.
+ value: 1
+
+ BLE_MESH_DEBUG_CDB:
+ description:
+ Use this option to enable configuration database debug logs.
value: 1
BLE_MESH_PROXY:
@@ -61,6 +101,19 @@ syscfg.defs:
and a Mesh network.
value: 1
+ BLE_MESH_GATT_PROXY_ENABLED:
+ description: >
+ Controls whether the GATT Proxy feature is enabled by default.
+ Can be changed through runtime configuration.
+ value: 1
+ restrictions: BLE_MESH_GATT_PROXY
+
+ BLE_MESH_DEFAULT_TTL:
+ description: >
+ Controls the default TTL value for outgoing messages. Can be changed
+ through runtime configuration.
+ value: 7
+
BLE_MESH_NODE_ID_TIMEOUT:
description: >
This option determines for how long the local node advertises
@@ -136,6 +189,13 @@ syscfg.defs:
supported outgoing segment count (BT_MESH_TX_SEG_MAX).
value: 6
+ BLE_MESH_ADV_STACK_SIZE:
+ description: >
+ Mesh advertiser thread stack size.
+ NOTE: This is an advanced setting and should not be changed unless
+ absolutely necessary
+ value: 768
+
BLE_MESH_IVU_DIVIDER:
description: >
When the IV Update state enters Normal operation or IV Update
@@ -164,7 +224,7 @@ syscfg.defs:
description: >
Maximum number of simultaneous outgoing multi-segment and/or
reliable messages.
- value: 4
+ value: 1
BLE_MESH_RX_SEG_MSG_COUNT:
description: >
@@ -172,38 +232,79 @@ syscfg.defs:
reliable messages.
value: 2
- BLE_MESH_RX_SDU_MAX:
+ BLE_MESH_SEG_BUFS:
description: >
- Maximum incoming Upper Transport Access PDU length. This
- determines also how many segments incoming segmented messages
- can have. Each segment can contain 12 bytes, so this value should
- be set to a multiple of 12 to avoid wasted memory. The minimum
- requirement is 2 segments (24 bytes) whereas the maximum supported
- by the Mesh specification is 32 segments (384 bytes).
- value: 72
+ The incoming and outgoing segmented messages allocate their
+ segments from the same pool. Each segment is a 12 byte block,
+ and may only be used by one message at the time.
- BLE_MESH_TX_SEG_MAX:
+ Outgoing messages will allocate their segments at the start of the
+ transmission, and release them one by one as soon as they have been
+ acknowledged by the receiver. Incoming messages allocate all their
+ segments at the start of the transaction, and won't release them until
+ the message is fully received.
+ value:
+ 64
+
+ BLE_MESH_RX_SEG_MAX:
description: >
- Maximum number of segments supported for outgoing messages.
+ Maximum number of segments supported for incoming messages.
This value should typically be fine-tuned based on what
models the local node supports, i.e. what's the largest
- message payload that the node needs to be able to send.
+ message payload that the node needs to be able to receive.
This value affects memory and call stack consumption, which
is why the default is lower than the maximum that the
specification would allow (32 segments).
+ The maximum incoming SDU size is 12 times this number (out of
+ which 4 or 8 bytes is used for the Transport Layer MIC). For
+ example, 5 segments means the maximum SDU size is 60 bytes,
+ which leaves 56 bytes for application layer data using a
+ 4-byte MIC and 52 bytes using an 8-byte MIC.
+ value:
+ 3
+
+
+
+ BLE_MESH_TX_SEG_MAX:
+ description: >
+ Maximum number of segments supported for outgoing messages.
+ This value should typically be fine-tuned based on what
+ models the local node supports, i.e. what's the largest
+ message payload that the node needs to be able to send.
+ This value affects memory consumption, which is why the
+ default is lower than the maximum that the specification
+ would allow (32 segments).
+
The maximum outgoing SDU size is 12 times this number (out of
which 4 or 8 bytes is used for the Transport Layer MIC). For
example, 5 segments means the maximum SDU size is 60 bytes,
which leaves 56 bytes for application layer data using a
4-byte MIC and 52 bytes using an 8-byte MIC.
+ value: 3
- Be sure to specify a sufficient number of advertising buffers
- when setting this option to a higher value. There must be at
- least three more advertising buffers (BT_MESH_ADV_BUF_COUNT)
- as there are outgoing segments.
+ BLE_MESH_LOOPBACK_BUFS:
+ description: >
+ The number of buffers allocated for the network loopback mechanism.
+ Loopback is used when the device sends messages to itself.
value: 3
+ BLE_MESH_TX_SEG_RETRANS_COUNT:
+ description: >
+ Maximum number of transport message segment retransmit attempts
+ for outgoing segment message.
+ value: 4
+
+ BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST:
+ description: >
+ Maximum time of retransmit segment message to unicast address.
+ value: 400
+
+ BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP:
+ description: >
+ Maximum time of retransmit segment message to group address.
+ value: 50
+
BLE_MESH_SEG_RETRANSMIT_ATTEMPTS:
description: >
Number of retransmit attempts (after the initial transmit) per segment
@@ -212,8 +313,56 @@ syscfg.defs:
BLE_MESH_RELAY:
description: >
+ Controls the initial number of retransmissions of original messages,
+ in addition to the first transmission. Can be changed through runtime
+ configuration.
+ value: 2
+
+ BLE_MESH_NETWORK_TRANSMIT_COUNT:
+ description: >
+ Controls the initial number of retransmissions of original messages,
+ in addition to the first transmission. Can be changed through runtime
+ configuration.
+ value: 2
+
+ BLE_MESH_NETWORK_TRANSMIT_INTERVAL:
+ description: >
+ Controls the initial interval between retransmissions of original
+ messages, in milliseconds. Can be changed through runtime
+ configuration.
+ value: 20
+
+ BT_MESH_RELAY:
+ description: >
Support for acting as a Mesh Relay Node.
- value: 0
+ value: 1
+
+ BLE_MESH_RELAY_ENABLED:
+ description: >
+ Controls whether the Mesh Relay feature is enabled by default. Can be
+ changed through runtime configuration.
+ value: 1
+
+ BLE_MESH_RELAY_RETRANSMIT_COUNT:
+ description: >
+ Controls the initial number of retransmissions of relayed messages, in
+ addition to the first transmission. Can be changed through runtime
+ configuration.
+
+ value: 2
+
+ BLE_MESH_RELAY_RETRANSMIT_INTERVAL:
+ description: >
+ Controls the initial interval between retransmissions of relayed
+ messages, in milliseconds. Can be changed through runtime
+ configuration.
+ value: 20
+
+ BLE_MESH_BEACON_ENABLED:
+ description: >
+ Controls whether the Secure network beacon feature is enabled by
+ default. Can be changed through runtime configuration.
+ value: 1
BLE_MESH_LOW_POWER:
description: >
@@ -287,6 +436,16 @@ syscfg.defs:
a value of 300 means 30 seconds.
value: 300
+ BLE_MESH_LPN_POLL_TIMEOUT:
+ description: >
+ PollTimeout timer is used to measure time between two
+ consecutive requests sent by the Low Power node. If no
+ requests are received by the Friend node before the
+ PollTimeout timer expires, then the friendship is considered
+ terminated. The value is in units of 100 milliseconds, so e.g.
+ a value of 300 means 30 seconds.
+ value: 300
+
BLE_MESH_LPN_INIT_POLL_TIMEOUT:
description: >
The initial value of the PollTimeout timer when Friendship
@@ -308,11 +467,23 @@ syscfg.defs:
Maximum number of groups that the LPN can subscribe to.
value: 10
+ BLE_MESH_LPN_SUB_ALL_NODES_ADDR:
+ description: >
+ Automatically subscribe all nodes address when friendship
+ established.
+ value: 1
+
BLE_MESH_FRIEND:
description: >
Enable this option to be able to act as a Friend Node.
value: 0
+ BLE_MESH_FRIEND_ENABLED:
+ description: >
+ Controls whether the Friend feature is enabled by default. Can be
+ changed through runtime configuration.
+ value: 1
+
BLE_MESH_FRIEND_RECV_WIN:
description: >
Receive Window in milliseconds supported by the Friend node.
@@ -336,6 +507,7 @@ syscfg.defs:
with simultaneously.
value: 2
+
BLE_MESH_FRIEND_SEG_RX:
description: >
Number of incomplete segment lists that we track for each LPN
@@ -344,6 +516,7 @@ syscfg.defs:
messages from when the messages are going into the Friend queue.
value: 1
+
BLE_MESH_CFG_CLI:
description: >
Enable support for the configuration client model.
@@ -592,6 +765,51 @@ syscfg.defs:
Minimum level for the BLE Mesh Transport Layer log.
value: 1
+ BLE_MESH_RPL_LOG_MOD:
+ description: >
+ Numeric module ID to use for BLE Mesh Replay protection list messages.
+ value: 22
+ BLE_MESH_RPL_LOG_LVL:
+ description: >
+ Minimum level for the BLE Mesh Replay protection list log.
+ value: 1
+
+ BLE_MESH_NET_KEYS_LOG_MOD:
+ description: >
+ Numeric module ID to use for BLE Mesh Replay protection list messages.
+ value: 23
+ BLE_MESH_NET_KEYS_LOG_LVL:
+ description: >
+ Minimum level for the BLE Mesh Replay protection list log.
+ value: 1
+
+ BLE_MESH_PROV_DEVICE_LOG_MOD:
+ description: >
+ Numeric module ID to use for BLE Mesh Replay protection list messages.
+ value: 24
+ BLE_MESH_PROV_DEVICE_LOG_LVL:
+ description: >
+ Minimum level for the BLE Mesh Replay protection list log.
+ value: 1
+
+ BLE_MESH_PROVISIONER_LOG_MOD:
+ description: >
+ Numeric module ID to use for BLE Mesh Replay protection list messages.
+ value: 25
+ BLE_MESH_PROVISIONER_LOG_LVL:
+ description: >
+ Minimum level for the BLE Mesh Replay protection list log.
+ value: 1
+
+ BLE_MESH_HEARTBEAT_LOG_MOD:
+ description: >
+ Numeric module ID to use for BLE Mesh Replay protection list messages.
+ value: 26
+ BLE_MESH_HEARTBEAT_LOG_LVL:
+ description: >
+ Minimum level for the BLE Mesh Replay protection list log.
+ value: 1
+
syscfg.logs:
BLE_MESH_LOG:
module: MYNEWT_VAL(BLE_MESH_LOG_MOD)
@@ -641,10 +859,30 @@ syscfg.logs:
module: MYNEWT_VAL(BLE_MESH_SETTINGS_LOG_MOD)
level: MYNEWT_VAL(BLE_MESH_SETTINGS_LOG_LVL)
+ BLE_MESH_RPL_LOG:
+ module: MYNEWT_VAL(BLE_MESH_RPL_LOG_MOD)
+ level: MYNEWT_VAL(BLE_MESH_RPL_LOG_LVL)
+
BLE_MESH_TRANS_LOG:
module: MYNEWT_VAL(BLE_MESH_TRANS_LOG_MOD)
level: MYNEWT_VAL(BLE_MESH_TRANS_LOG_LVL)
+ BLE_MESH_NET_KEYS_LOG:
+ module: MYNEWT_VAL(BLE_MESH_NET_KEYS_LOG_MOD)
+ level: MYNEWT_VAL(BLE_MESH_NET_KEYS_LOG_LVL)
+
+ BLE_MESH_PROV_DEVICE_LOG:
+ module: MYNEWT_VAL(BLE_MESH_PROV_DEVICE_LOG_MOD)
+ level: MYNEWT_VAL(BLE_MESH_PROV_DEVICE_LOG_LVL)
+
+ BLE_MESH_PROVISIONER_LOG:
+ module: MYNEWT_VAL(BLE_MESH_PROVISIONER_LOG_MOD)
+ level: MYNEWT_VAL(BLE_MESH_PROVISIONER_LOG_LVL)
+
+ BLE_MESH_HEARTBEAT_LOG:
+ module: MYNEWT_VAL(BLE_MESH_HEARTBEAT_LOG_MOD)
+ level: MYNEWT_VAL(BLE_MESH_HEARTBEAT_LOG_LVL)
+
syscfg.vals.BLE_MESH_SHELL:
BLE_MESH_CFG_CLI: 1
BLE_MESH_HEALTH_CLI: 1
diff --git a/src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h b/src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
index 2706b5d3..24b9a26c 100644
--- a/src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
+++ b/src/libs/mynewt-nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
@@ -28,4 +28,6 @@
int ble_svc_bas_battery_level_set(uint8_t level);
+void ble_svc_bas_init(void);
+
#endif
diff --git a/src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h b/src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
index d7b60df4..707a3bd0 100644
--- a/src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
+++ b/src/libs/mynewt-nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
@@ -34,6 +34,7 @@ extern "C" {
#define BLE_SVC_GAP_APPEARANCE_GEN_UNKNOWN 0
#define BLE_SVC_GAP_APPEARANCE_GEN_COMPUTER 128
+#define BLE_SVC_GAP_APPEARANCE_GEN_HID 960
#define BLE_SVC_GAP_APPEARANCE_CYC_SPEED_AND_CADENCE_SENSOR 1157
typedef void (ble_svc_gap_chr_changed_fn) (uint16_t uuid);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c b/src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c
index a123c857..81b070f9 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_att_cmd.c
@@ -66,11 +66,10 @@ ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom)
ble_hs_lock();
- ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn,
- &chan);
- if (chan == NULL) {
+ rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn,
+ &chan);
+ if (rc != 0) {
os_mbuf_free_chain(txom);
- rc = BLE_HS_ENOTCONN;
} else {
ble_att_truncate_to_mtu(chan, txom);
rc = ble_l2cap_tx(conn, chan, txom);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c b/src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c
index 46a71681..be61e4b8 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_att_svr.c
@@ -1360,7 +1360,7 @@ done:
*att_err = 0;
/* Fill the response base. */
- rsp->batp_length = htole16(sizeof(*data) + prev_attr_len);
+ rsp->batp_length = sizeof(*data) + prev_attr_len;
}
*out_txom = txom;
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c b/src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c
index 7d80d134..eccb3e98 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_eddystone.c
@@ -76,7 +76,7 @@ ble_eddystone_set_adv_data_gen(struct ble_hs_adv_fields *adv_fields,
if (adv_fields->num_uuids16 > BLE_EDDYSTONE_MAX_UUIDS16) {
return BLE_HS_EINVAL;
}
- if (svc_data_len > BLE_EDDYSTONE_MAX_SVC_DATA_LEN) {
+ if (svc_data_len > (BLE_EDDYSTONE_MAX_SVC_DATA_LEN - BLE_EDDYSTONE_SVC_DATA_BASE_SZ)) {
return BLE_HS_EINVAL;
}
if (adv_fields->num_uuids16 > 0 && !adv_fields->uuids16_is_complete) {
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c b/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c
index e32482e6..bbedc319 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c
@@ -310,14 +310,12 @@ ble_gap_log_conn(uint8_t own_addr_type, const ble_addr_t *peer_addr,
BLE_HS_LOG_ADDR(INFO, peer_addr->val);
}
- /* // NRF LOG support max 6 params in log
BLE_HS_LOG(INFO, " scan_itvl=%d scan_window=%d itvl_min=%d itvl_max=%d "
"latency=%d supervision_timeout=%d min_ce_len=%d "
"max_ce_len=%d own_addr_type=%d",
params->scan_itvl, params->scan_window, params->itvl_min,
params->itvl_max, params->latency, params->supervision_timeout,
params->min_ce_len, params->max_ce_len, own_addr_type);
- */
}
#endif
@@ -341,10 +339,10 @@ ble_gap_log_update(uint16_t conn_handle,
{
BLE_HS_LOG(INFO, "connection parameter update; "
"conn_handle=%d itvl_min=%d itvl_max=%d latency=%d "
- "supervision_timeout=%d min_ce_len=%d max_ce_len=???",
+ "supervision_timeout=%d min_ce_len=%d max_ce_len=%d",
conn_handle, params->itvl_min, params->itvl_max,
params->latency, params->supervision_timeout,
- params->min_ce_len);
+ params->min_ce_len, params->max_ce_len);
}
#endif
@@ -747,7 +745,7 @@ ble_gap_has_client(struct ble_gap_master_state *out_state)
return 0;
}
- return out_state->cb;
+ return out_state->cb != NULL;
}
static void
@@ -932,7 +930,7 @@ ble_gap_master_ticks_until_exp(void)
return 0;
}
-#if !MYNEWT_VAL(BLE_EXT_ADV)
+#if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
static uint32_t
ble_gap_slave_ticks_until_exp(void)
{
@@ -1000,7 +998,7 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now)
}
-#if MYNEWT_VAL(BLE_ROLE_CENTRAL)
+#if NIMBLE_BLE_SCAN
static void
ble_gap_master_set_timer(uint32_t ticks_from_now)
{
@@ -1022,7 +1020,7 @@ ble_gap_slave_set_timer(uint32_t ticks_from_now)
}
#endif
-#if NIMBLE_BLE_CONNECT
+#if (NIMBLE_BLE_CONNECT || NIMBLE_BLE_SCAN)
/**
* Called when an error is encountered while the master-connection-fsm is
* active.
@@ -1036,12 +1034,22 @@ ble_gap_master_failed(int status)
ble_gap_master_connect_failure(status);
break;
+#if NIMBLE_BLE_SCAN
+ case BLE_GAP_OP_M_DISC:
+ STATS_INC(ble_gap_stats, initiate_fail);
+ ble_gap_disc_complete();
+ ble_gap_master_reset_state();
+ break;
+#endif
+
default:
BLE_HS_DBG_ASSERT(0);
break;
}
}
+#endif
+#if NIMBLE_BLE_CONNECT
static void
ble_gap_update_failed(uint16_t conn_handle, int status)
{
@@ -1239,6 +1247,46 @@ ble_gap_adv_active_instance(uint8_t instance)
return ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV;
}
+/**
+ * Clears advertisement and discovery state. This function is necessary
+ * when the controller loses its active state (e.g. on stack reset).
+ */
+void
+ble_gap_reset_state(int reason)
+{
+ uint16_t conn_handle;
+
+ while (1) {
+ conn_handle = ble_hs_atomic_first_conn_handle();
+ if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
+ break;
+ }
+
+ ble_gap_conn_broken(conn_handle, reason);
+ }
+
+#if NIMBLE_BLE_ADVERTISE
+#if MYNEWT_VAL(BLE_EXT_ADV)
+ uint8_t i;
+ for (i = 0; i < BLE_ADV_INSTANCES; i++) {
+ if (ble_gap_adv_active_instance(i)) {
+ /* Indicate to application that advertising has stopped. */
+ ble_gap_adv_finished(i, reason, 0, 0);
+ }
+ }
+#else
+ if (ble_gap_adv_active_instance(0)) {
+ /* Indicate to application that advertising has stopped. */
+ ble_gap_adv_finished(0, reason, 0, 0);
+ }
+#endif
+#endif
+
+#if (NIMBLE_BLE_SCAN || NIMBLE_BLE_CONNECT)
+ ble_gap_master_failed(reason);
+#endif
+}
+
#if NIMBLE_BLE_CONNECT
static int
ble_gap_accept_master_conn(void)
@@ -1893,7 +1941,7 @@ ble_gap_master_timer(void)
return BLE_HS_FOREVER;
}
-#if !MYNEWT_VAL(BLE_EXT_ADV)
+#if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
static int32_t
ble_gap_slave_timer(void)
{
@@ -1945,7 +1993,6 @@ ble_gap_update_timer(void)
ble_hs_unlock();
if (entry != NULL) {
- ble_gap_update_notify(conn_handle, BLE_HS_ETIMEOUT);
ble_gap_update_entry_free(entry);
}
} while (entry != NULL);
@@ -1993,7 +2040,7 @@ ble_gap_timer(void)
min_ticks = min(master_ticks, update_ticks);
-#if !MYNEWT_VAL(BLE_EXT_ADV)
+#if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
min_ticks = min(min_ticks, ble_gap_slave_timer());
#endif
@@ -5547,7 +5594,7 @@ ble_gap_unpair_oldest_peer(void)
}
if (num_peers == 0) {
- return 0;
+ return BLE_HS_ENOENT;
}
rc = ble_gap_unpair(&oldest_peer_id_addr);
@@ -5558,6 +5605,36 @@ ble_gap_unpair_oldest_peer(void)
return 0;
}
+int
+ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr)
+{
+ ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
+ int num_peers;
+ int rc, i;
+
+ rc = ble_store_util_bonded_peers(
+ &peer_id_addrs[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS));
+ if (rc != 0) {
+ return rc;
+ }
+
+ if (num_peers == 0) {
+ return BLE_HS_ENOENT;
+ }
+
+ for (i = 0; i < num_peers; i++) {
+ if (ble_addr_cmp(peer_addr, &peer_id_addrs[i]) != 0) {
+ break;
+ }
+ }
+
+ if (i >= num_peers) {
+ return BLE_HS_ENOMEM;
+ }
+
+ return ble_gap_unpair(&peer_id_addrs[i]);
+}
+
void
ble_gap_passkey_event(uint16_t conn_handle,
struct ble_gap_passkey_params *passkey_params)
@@ -5577,7 +5654,8 @@ ble_gap_passkey_event(uint16_t conn_handle,
}
void
-ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
+ble_gap_enc_event(uint16_t conn_handle, int status,
+ int security_restored, int bonded)
{
#if NIMBLE_BLE_SM
struct ble_gap_event event;
@@ -5590,12 +5668,24 @@ ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
ble_gap_event_listener_call(&event);
ble_gap_call_conn_event_cb(&event, conn_handle);
- if (status == 0) {
- if (security_restored) {
- ble_gatts_bonding_restored(conn_handle);
- } else {
- ble_gatts_bonding_established(conn_handle);
- }
+ if (status != 0) {
+ return;
+ }
+
+ /* If encryption succeded and encryption has been restored for bonded device,
+ * notify gatt server so it has chance to send notification/indication if needed.
+ */
+ if (security_restored) {
+ ble_gatts_bonding_restored(conn_handle);
+ return;
+ }
+
+ /* If this is fresh pairing and bonding has been established,
+ * notify gatt server about that so previous subscriptions (before bonding)
+ * can be stored.
+ */
+ if (bonded) {
+ ble_gatts_bonding_established(conn_handle);
}
#endif
}
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h b/src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h
index ce443198..499823bc 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_gap_priv.h
@@ -116,7 +116,7 @@ int ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
struct ble_gap_upd_params *params);
void ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev);
void ble_gap_enc_event(uint16_t conn_handle, int status,
- int security_restored);
+ int security_restored, int bonded);
void ble_gap_passkey_event(uint16_t conn_handle,
struct ble_gap_passkey_params *passkey_params);
void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
@@ -136,6 +136,7 @@ void ble_gap_preempt(void);
void ble_gap_preempt_done(void);
int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason);
+void ble_gap_reset_state(int reason);
void ble_gap_conn_broken(uint16_t conn_handle, int reason);
int32_t ble_gap_timer(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs.c
index 23ac1d14..731e8155 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs.c
@@ -361,7 +361,6 @@ ble_hs_sync(void)
static int
ble_hs_reset(void)
{
- uint16_t conn_handle;
int rc;
STATS_INC(ble_hs_stats, reset);
@@ -376,14 +375,8 @@ ble_hs_reset(void)
ble_hs_clear_rx_queue();
- while (1) {
- conn_handle = ble_hs_atomic_first_conn_handle();
- if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
- break;
- }
-
- ble_gap_conn_broken(conn_handle, ble_hs_reset_reason);
- }
+ /* Clear adverising and scanning states. */
+ ble_gap_reset_state(ble_hs_reset_reason);
/* Clear configured addresses. */
ble_hs_id_reset();
@@ -680,7 +673,7 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg)
/* If flow control is enabled, mark this packet with its corresponding
* connection handle.
*/
- ble_hs_flow_fill_acl_usrhdr(om);
+ ble_hs_flow_track_data_mbuf(om);
rc = ble_mqueue_put(&ble_hs_rx_q, ble_hs_evq, om);
if (rc != 0) {
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c
index f7edb624..ea89460c 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_conn.c
@@ -327,6 +327,7 @@ ble_hs_conn_find_by_addr(const ble_addr_t *addr)
#endif
struct ble_hs_conn *conn;
+ struct ble_hs_conn_addrs addrs;
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
@@ -343,6 +344,14 @@ ble_hs_conn_find_by_addr(const ble_addr_t *addr)
if (ble_addr_cmp(&conn->bhc_peer_addr, addr) == 0) {
return conn;
}
+ if (conn->bhc_peer_addr.type < BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT) {
+ continue;
+ }
+ /*If type 0x02 or 0x03 is used, let's double check if address is good */
+ ble_hs_conn_addrs(conn, &addrs);
+ if (ble_addr_cmp(&addrs.peer_id_addr, addr) == 0) {
+ return conn;
+ }
}
}
@@ -472,29 +481,52 @@ ble_hs_conn_timer(void)
int32_t time_diff;
uint16_t conn_handle;
- conn_handle = BLE_HS_CONN_HANDLE_NONE;
- next_exp_in = BLE_HS_FOREVER;
- now = ble_npl_time_get();
+ for (;;) {
+ conn_handle = BLE_HS_CONN_HANDLE_NONE;
+ next_exp_in = BLE_HS_FOREVER;
+ now = ble_npl_time_get();
- ble_hs_lock();
+ ble_hs_lock();
- /* This loop performs one of two tasks:
- * 1. Determine if any connections need to be terminated due to timeout.
- * If so, break out of the loop and terminate the connection. This
- * function will need to be executed again.
- * 2. Otherwise, determine when the next timeout will occur.
- */
- SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) {
- if (!(conn->bhc_flags & BLE_HS_CONN_F_TERMINATING)) {
+ /* This loop performs one of two tasks:
+ * 1. Determine if any connections need to be terminated due to timeout.
+ * If so, break out of the loop and terminate the connection. This
+ * function will need to be executed again.
+ * 2. Otherwise, determine when the next timeout will occur.
+ */
+ SLIST_FOREACH(conn, &ble_hs_conns, bhc_next) {
+ if (!(conn->bhc_flags & BLE_HS_CONN_F_TERMINATING)) {
#if MYNEWT_VAL(BLE_L2CAP_RX_FRAG_TIMEOUT) != 0
- /* Check each connection's rx fragment timer. If too much time
- * passes after a partial packet is received, the connection is
- * terminated.
- */
- if (conn->bhc_rx_chan != NULL) {
- time_diff = conn->bhc_rx_timeout - now;
+ /* Check each connection's rx fragment timer. If too much time
+ * passes after a partial packet is received, the connection is
+ * terminated.
+ */
+ if (conn->bhc_rx_chan != NULL) {
+ time_diff = conn->bhc_rx_timeout - now;
+
+ if (time_diff <= 0) {
+ /* ACL reassembly has timed out. Remember the connection
+ * handle so it can be terminated after the mutex is
+ * unlocked.
+ */
+ conn_handle = conn->bhc_handle;
+ break;
+ }
+
+ /* Determine if this connection is the soonest to time out. */
+ if (time_diff < next_exp_in) {
+ next_exp_in = time_diff;
+ }
+ }
+#endif
+#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO
+ /* Check each connection's rx queued write timer. If too much
+ * time passes after a prep write is received, the queue is
+ * cleared.
+ */
+ time_diff = ble_att_svr_ticks_until_tmo(&conn->bhc_att_svr, now);
if (time_diff <= 0) {
/* ACL reassembly has timed out. Remember the connection
* handle so it can be terminated after the mutex is
@@ -508,45 +540,22 @@ ble_hs_conn_timer(void)
if (time_diff < next_exp_in) {
next_exp_in = time_diff;
}
- }
#endif
-
-#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO
- /* Check each connection's rx queued write timer. If too much
- * time passes after a prep write is received, the queue is
- * cleared.
- */
- time_diff = ble_att_svr_ticks_until_tmo(&conn->bhc_att_svr, now);
- if (time_diff <= 0) {
- /* ACL reassembly has timed out. Remember the connection
- * handle so it can be terminated after the mutex is
- * unlocked.
- */
- conn_handle = conn->bhc_handle;
- break;
}
-
- /* Determine if this connection is the soonest to time out. */
- if (time_diff < next_exp_in) {
- next_exp_in = time_diff;
- }
-#endif
}
- }
- ble_hs_unlock();
+ ble_hs_unlock();
- /* If a connection has timed out, terminate it. We need to recursively
- * call this function again to determine when the next timeout is. This
- * is a tail-recursive call, so it should be optimized to execute in the
- * same stack frame.
- */
- if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
- return ble_hs_conn_timer();
- }
+ /* If a connection has timed out, terminate it. We need to repeatedly
+ * call this function again to determine when the next timeout is.
+ */
+ if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
+ ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
+ continue;
+ }
- return next_exp_in;
+ return next_exp_in;
+ }
}
int
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c
index d224e6ee..2520c854 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c
@@ -40,6 +40,23 @@ static ble_npl_event_fn ble_hs_flow_event_cb;
static struct ble_npl_event ble_hs_flow_ev;
+/* Connection handle associated with each mbuf in ACL pool */
+static uint16_t ble_hs_flow_mbuf_conn_handle[ MYNEWT_VAL(BLE_ACL_BUF_COUNT) ];
+
+static inline int
+ble_hs_flow_mbuf_index(const struct os_mbuf *om)
+{
+ const struct os_mempool *mp = om->om_omp->omp_pool;
+ uintptr_t addr = (uintptr_t)om;
+ int idx;
+
+ idx = (addr - mp->mp_membuf_addr) / mp->mp_block_size;
+
+ BLE_HS_DBG_ASSERT(mp->mp_membuf_addr + idx * mp->mp_block_size == addr);
+
+ return idx;
+}
+
static int
ble_hs_flow_tx_num_comp_pkts(void)
{
@@ -143,18 +160,13 @@ ble_hs_flow_acl_free(struct os_mempool_ext *mpe, void *data, void *arg)
struct ble_hs_conn *conn;
const struct os_mbuf *om;
uint16_t conn_handle;
+ int idx;
int rc;
om = data;
- /* An ACL data packet must be a single mbuf, and it must contain the
- * corresponding connection handle in its user header.
- */
- assert(OS_MBUF_IS_PKTHDR(om));
- assert(OS_MBUF_USRHDR_LEN(om) >= sizeof conn_handle);
-
- /* Copy the connection handle out of the mbuf. */
- memcpy(&conn_handle, OS_MBUF_USRHDR(om), sizeof conn_handle);
+ idx = ble_hs_flow_mbuf_index(om);
+ conn_handle = ble_hs_flow_mbuf_conn_handle[idx];
/* Free the mbuf back to its pool. */
rc = os_memblock_put_from_cb(&mpe->mpe_mp, data);
@@ -190,23 +202,19 @@ ble_hs_flow_connection_broken(uint16_t conn_handle)
}
/**
- * Fills the user header of an incoming data packet. On function return, the
- * header contains the connection handle associated with the sender.
+ * Associates incoming data packet with a connection handle of the sender.
*
* If flow control is disabled, this function is a no-op.
*/
void
-ble_hs_flow_fill_acl_usrhdr(struct os_mbuf *om)
+ble_hs_flow_track_data_mbuf(struct os_mbuf *om)
{
#if MYNEWT_VAL(BLE_HS_FLOW_CTRL)
const struct hci_data_hdr *hdr;
- uint16_t *conn_handle;
-
- BLE_HS_DBG_ASSERT(OS_MBUF_USRHDR_LEN(om) >= sizeof *conn_handle);
- conn_handle = OS_MBUF_USRHDR(om);
+ int idx = ble_hs_flow_mbuf_index(om);
hdr = (void *)om->om_data;
- *conn_handle = BLE_HCI_DATA_HANDLE(hdr->hdh_handle_pb_bc);
+ ble_hs_flow_mbuf_conn_handle[idx] = BLE_HCI_DATA_HANDLE(hdr->hdh_handle_pb_bc);
#endif
}
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h
index b1aa8c2f..753eaf8f 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_flow_priv.h
@@ -26,7 +26,7 @@ extern "C" {
#endif
void ble_hs_flow_connection_broken(uint16_t conn_handle);
-void ble_hs_flow_fill_acl_usrhdr(struct os_mbuf *om);
+void ble_hs_flow_track_data_mbuf(struct os_mbuf *om);
int ble_hs_flow_startup(void);
#ifdef __cplusplus
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c
index a334a747..ac472a9e 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_hci.c
@@ -447,8 +447,8 @@ ble_hs_hci_acl_hdr_prepend(struct os_mbuf *om, uint16_t handle,
struct hci_data_hdr hci_hdr;
struct os_mbuf *om2;
- hci_hdr.hdh_handle_pb_bc =
- ble_hs_hci_util_handle_pb_bc_join(handle, pb_flag, 0);
+ put_le16(&hci_hdr.hdh_handle_pb_bc,
+ ble_hs_hci_util_handle_pb_bc_join(handle, pb_flag, 0));
put_le16(&hci_hdr.hdh_len, OS_MBUF_PKTHDR(om)->omp_len);
om2 = os_mbuf_prepend(om, sizeof hci_hdr);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c
index 6c6da467..dfb46b74 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_misc.c
@@ -56,7 +56,7 @@ ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
return rc;
}
-void
+int
ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
struct ble_hs_conn **out_conn,
struct ble_l2cap_chan **out_chan)
@@ -66,7 +66,9 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
int rc;
rc = ble_hs_misc_conn_chan_find(conn_handle, cid, &conn, &chan);
- BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+ if (rc != 0) {
+ return rc;
+ }
if (out_conn != NULL) {
*out_conn = conn;
@@ -74,6 +76,8 @@ ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
if (out_chan != NULL) {
*out_chan = chan;
}
+
+ return 0;
}
uint8_t
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h
index 2cad6ef1..538d07a9 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_hs_priv.h
@@ -114,9 +114,9 @@ int ble_hs_hci_evt_acl_process(struct os_mbuf *om);
int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
struct ble_hs_conn **out_conn,
struct ble_l2cap_chan **out_chan);
-void ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
- struct ble_hs_conn **out_conn,
- struct ble_l2cap_chan **out_chan);
+int ble_hs_misc_conn_chan_find_reqd(uint16_t conn_handle, uint16_t cid,
+ struct ble_hs_conn **out_conn,
+ struct ble_l2cap_chan **out_chan);
uint8_t ble_hs_misc_own_addr_type_to_id(uint8_t addr_type);
uint8_t ble_hs_misc_peer_addr_type_to_id(uint8_t addr_type);
int ble_hs_misc_restore_irks(void);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c
index 41a83156..8dc367ed 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_coc.c
@@ -73,7 +73,7 @@ ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu,
srv = ble_l2cap_coc_srv_alloc();
if (!srv) {
- return BLE_HS_ENOMEM;
+ return BLE_HS_ENOMEM;
}
srv->psm = psm;
@@ -392,6 +392,8 @@ ble_l2cap_event_coc_unstalled(struct ble_l2cap_chan *chan, int status)
chan->cb(&event, chan->cb_arg);
}
+/* WARNING: this function is called from different task contexts. We expect the
+ * host to be locked (ble_hs_lock()) before entering this function! */
static int
ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
{
@@ -406,6 +408,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
/* If there is no data to send, just return success */
tx = &chan->coc_tx;
if (!tx->sdu) {
+ ble_hs_unlock();
return 0;
}
@@ -440,6 +443,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
BLE_HS_LOG(DEBUG, "Sending SDU len=%d\n", OS_MBUF_PKTLEN(tx->sdu));
rc = os_mbuf_append(txom, &l, sizeof(uint16_t));
if (rc) {
+ rc = BLE_HS_ENOMEM;
BLE_HS_LOG(DEBUG, "Could not append data rc=%d", rc);
goto failed;
}
@@ -452,55 +456,63 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
rc = os_mbuf_appendfrom(txom, tx->sdu, tx->data_offset,
len - sdu_size_offset);
if (rc) {
+ rc = BLE_HS_ENOMEM;
BLE_HS_LOG(DEBUG, "Could not append data rc=%d", rc);
- goto failed;
+ goto failed;
}
- ble_hs_lock();
conn = ble_hs_conn_find_assert(chan->conn_handle);
rc = ble_l2cap_tx(conn, chan, txom);
- ble_hs_unlock();
if (rc) {
- /* txom is consumed by l2cap */
- txom = NULL;
- goto failed;
+ /* txom is consumed by l2cap */
+ txom = NULL;
+ goto failed;
} else {
- tx->credits --;
+ tx->credits--;
tx->data_offset += len - sdu_size_offset;
}
BLE_HS_LOG(DEBUG, "Sent %d bytes, credits=%d, to send %d bytes \n",
- len, tx->credits, OS_MBUF_PKTLEN(tx->sdu)- tx->data_offset );
+ len, tx->credits, OS_MBUF_PKTLEN(tx->sdu)- tx->data_offset);
if (tx->data_offset == OS_MBUF_PKTLEN(tx->sdu)) {
- BLE_HS_LOG(DEBUG, "Complete package sent\n");
- os_mbuf_free_chain(tx->sdu);
- tx->sdu = 0;
- tx->data_offset = 0;
- if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
- ble_l2cap_event_coc_unstalled(chan, 0);
- tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
- }
- break;
+ BLE_HS_LOG(DEBUG, "Complete package sent\n");
+ os_mbuf_free_chain(tx->sdu);
+ tx->sdu = NULL;
+ tx->data_offset = 0;
+ break;
}
}
if (tx->sdu) {
/* Not complete SDU sent, wait for credits */
tx->flags |= BLE_L2CAP_COC_FLAG_STALLED;
+ ble_hs_unlock();
return BLE_HS_ESTALLED;
}
+ if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
+ tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
+ ble_hs_unlock();
+ ble_l2cap_event_coc_unstalled(chan, 0);
+ } else {
+ ble_hs_unlock();
+ }
+
return 0;
failed:
os_mbuf_free_chain(tx->sdu);
tx->sdu = NULL;
+
os_mbuf_free_chain(txom);
if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
- ble_l2cap_event_coc_unstalled(chan, rc);
tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
+ ble_hs_unlock();
+ ble_l2cap_event_coc_unstalled(chan, rc);
+ } else {
+ ble_hs_unlock();
}
return rc;
@@ -535,7 +547,8 @@ ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid,
}
chan->coc_tx.credits += credits;
- ble_hs_unlock();
+
+ /* leave the host locked on purpose when ble_l2cap_coc_continue_tx() */
ble_l2cap_coc_continue_tx(chan);
}
@@ -584,18 +597,22 @@ ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx)
{
struct ble_l2cap_coc_endpoint *tx;
- tx = &chan->coc_tx;
- if (tx->sdu) {
- return BLE_HS_EBUSY;
- }
+ tx = &chan->coc_tx;
if (OS_MBUF_PKTLEN(sdu_tx) > tx->mtu) {
return BLE_HS_EBADDATA;
}
+ ble_hs_lock();
+ if (tx->sdu) {
+ ble_hs_unlock();
+ return BLE_HS_EBUSY;
+ }
tx->sdu = sdu_tx;
+
+ /* leave the host locked on purpose when ble_l2cap_coc_continue_tx() */
return ble_l2cap_coc_continue_tx(chan);
}
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c
index bb4d8a5a..ad81c64a 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig.c
@@ -508,8 +508,13 @@ ble_l2cap_sig_update(uint16_t conn_handle,
STATS_INC(ble_l2cap_stats, update_init);
ble_hs_lock();
- ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
- &conn, &chan);
+ rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
+ &conn, &chan);
+ if (rc != 0) {
+ ble_hs_unlock();
+ goto done;
+ }
+
master = conn->bhc_flags & BLE_HS_CONN_F_MASTER;
ble_hs_unlock();
@@ -656,8 +661,8 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
continue;
}
- if ((status == 0) && (chan->dcid != 0)) {
- ble_l2cap_event_coc_connected(chan, status);
+ if (chan->dcid != 0) {
+ ble_l2cap_event_coc_connected(chan, 0);
/* Let's forget about connected channel now.
* Not connected will be freed later on.
*/
@@ -859,6 +864,7 @@ ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data;
ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+ ble_l2cap_sig_proc_free(proc);
return 0;
}
@@ -1061,7 +1067,15 @@ ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle,
if (rsp->result) {
rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result));
- goto done;
+ /* Below results means that some of the channels has not been created
+ * and we have to look closer into the response.
+ * Any other results means that all the connections has been refused.
+ */
+ if ((rsp->result != BLE_L2CAP_COC_ERR_NO_RESOURCES) &&
+ (rsp->result != BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID) &&
+ (rsp->result != BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED)) {
+ goto done;
+ }
}
ble_hs_lock();
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c
index 366dde62..510420f0 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_l2cap_sig_cmd.c
@@ -28,9 +28,11 @@ ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom)
int rc;
ble_hs_lock();
- ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
- &conn, &chan);
- rc = ble_l2cap_tx(conn, chan, txom);
+ rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
+ &conn, &chan);
+ if (rc == 0) {
+ rc = ble_l2cap_tx(conn, chan, txom);
+ }
ble_hs_unlock();
return rc;
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c b/src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c
index 6057e7e2..55524f2d 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_monitor.c
@@ -29,7 +29,6 @@
#include <stdarg.h>
#include <stdio.h>
#include <inttypes.h>
-#include <libs/mynewt-nimble/porting/nimble/include/os/os_cputime.h>
#include "os/os.h"
#include "log/log.h"
#if MYNEWT_VAL(BLE_MONITOR_UART)
@@ -162,7 +161,7 @@ update_drop_counters(struct ble_monitor_hdr *failed_hdr)
if (*cnt < UINT8_MAX) {
(*cnt)++;
- ble_npl_callout_reset(&rtt_drops.tmo, OS_TICKS_PER_SEC);
+ ble_npl_callout_reset(&rtt_drops.tmo, portMAX_DELAY);
}
}
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_sm.c b/src/libs/mynewt-nimble/nimble/host/src/ble_sm.c
index cfd80fcb..91afb75c 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_sm.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_sm.c
@@ -938,7 +938,7 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res)
if (res->enc_cb) {
BLE_HS_DBG_ASSERT(proc == NULL || rm);
- ble_gap_enc_event(conn_handle, res->app_status, res->restore);
+ ble_gap_enc_event(conn_handle, res->app_status, res->restore, res->bonded);
}
if (res->app_status == 0 &&
@@ -1190,6 +1190,7 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
ble_hs_unlock();
+ res.bonded = bonded;
ble_sm_process_result(conn_handle, &res);
}
@@ -2425,7 +2426,7 @@ ble_sm_timer(void)
* procedures without reconnect.
*/
while ((proc = STAILQ_FIRST(&exp_list)) != NULL) {
- ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0);
+ ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0, 0);
STAILQ_REMOVE_HEAD(&exp_list, next);
ble_sm_proc_free(proc);
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c
index 50fd77ec..148995c8 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c
@@ -68,8 +68,6 @@ ble_sm_alg_encrypt(const uint8_t *key, const uint8_t *plaintext,
swap_buf(tmp, plaintext, 16);
-
-
if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) {
return BLE_HS_EUNKNOWN;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c
index 5eef798d..01651f1d 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c
@@ -52,12 +52,17 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
{
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
+ int rc;
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
STATS_INC(ble_l2cap_stats, sm_tx);
- ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
- &conn, &chan);
- return ble_l2cap_tx(conn, chan, txom);
+ rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SM,
+ &conn, &chan);
+ if (rc == 0) {
+ rc = ble_l2cap_tx(conn, chan, txom);
+ }
+
+ return rc;
}
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h
index 6d5601bf..27e75aa1 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_sm_priv.h
@@ -279,10 +279,10 @@ struct ble_sm_result {
uint8_t sm_err;
struct ble_gap_passkey_params passkey_params;
void *state_arg;
- unsigned execute:1;
- unsigned enc_cb:1;
- unsigned persist_keys:1;
- unsigned restore:1;
+ unsigned execute : 1;
+ unsigned enc_cb : 1;
+ unsigned bonded : 1;
+ unsigned restore : 1;
};
#if MYNEWT_VAL(BLE_HS_DEBUG)
diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c b/src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c
index 444cc55d..7de48272 100644
--- a/src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c
+++ b/src/libs/mynewt-nimble/nimble/host/src/ble_store_util.c
@@ -233,13 +233,15 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg)
switch (event->event_code) {
case BLE_STORE_EVENT_OVERFLOW:
switch (event->overflow.obj_type) {
- case BLE_STORE_OBJ_TYPE_OUR_SEC:
- case BLE_STORE_OBJ_TYPE_PEER_SEC:
- case BLE_STORE_OBJ_TYPE_CCCD:
- return ble_gap_unpair_oldest_peer();
-
- default:
- return BLE_HS_EUNKNOWN;
+ case BLE_STORE_OBJ_TYPE_OUR_SEC:
+ case BLE_STORE_OBJ_TYPE_PEER_SEC:
+ return ble_gap_unpair_oldest_peer();
+ case BLE_STORE_OBJ_TYPE_CCCD:
+ /* Try unpairing oldest peer except current peer */
+ return ble_gap_unpair_oldest_except(&event->overflow.value->cccd.peer_addr);
+
+ default:
+ return BLE_HS_EUNKNOWN;
}
case BLE_STORE_EVENT_FULL:
diff --git a/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c
index ce60d1fb..cc1d59af 100644
--- a/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c
+++ b/src/libs/mynewt-nimble/nimble/host/store/config/src/ble_store_config.c
@@ -23,7 +23,6 @@
#include "sysinit/sysinit.h"
#include "syscfg/syscfg.h"
#include "host/ble_hs.h"
-#include "config/config.h"
#include "base64/base64.h"
#include "store/config/ble_store_config.h"
#include "ble_store_config_priv.h"
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h b/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h
index 842fb5f3..19372f17 100644
--- a/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h
@@ -17,6 +17,11 @@
* under the License.
*/
+/* This package has been deprecated and you should
+ * use the store/config package. For a RAM-only BLE store,
+ * use store/config and set BLE_STORE_CONFIG_PERSIST to 0.
+ */
+
#ifndef H_BLE_STORE_RAM_
#define H_BLE_STORE_RAM_
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c b/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c
index ab5cdb9f..b912ea47 100644
--- a/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/src/ble_store_ram.c
@@ -23,6 +23,11 @@
* contents are lost when the application terminates.
*/
+/* This package has been deprecated and you should
+ * use the store/config package. For a RAM-only BLE store,
+ * use store/config and set BLE_STORE_CONFIG_PERSIST to 0.
+ */
+
#include <inttypes.h>
#include <string.h>
diff --git a/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml b/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml
index 442211dd..91c55fd8 100644
--- a/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml
+++ b/src/libs/mynewt-nimble/nimble/host/store/ram/syscfg.yml
@@ -20,4 +20,13 @@ syscfg.defs:
description: >
Sysinit stage for the RAM BLE store.
value: 500
+ BLE_STORE_RAM_DEPRECATED_FLAG:
+ description: >
+ Package store/ram is deprecated and store/config shall be used with BLE_STORE_CONFIG_PERSIST set to 0
+ value: 0
+ deprecated: 1
+
+
+syscfg.vals:
+ BLE_STORE_RAM_DEPRECATED_FLAG: 1
diff --git a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c
index 3962bacc..7496e316 100644
--- a/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c
+++ b/src/libs/mynewt-nimble/nimble/host/test/src/ble_gap_test.c
@@ -2050,70 +2050,6 @@ ble_gap_test_util_update_l2cap(struct ble_gap_upd_params *params,
}
static void
-ble_gap_test_util_update_no_l2cap_tmo(struct ble_gap_upd_params *params,
- int master)
-{
- struct ble_hs_conn *conn;
- int rc;
-
- uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
-
- ble_gap_test_util_init();
-
- ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
- NULL);
-
- if (!master) {
- ble_hs_lock();
- conn = ble_hs_conn_find(2);
- TEST_ASSERT_FATAL(conn != NULL);
- conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
- ble_hs_unlock();
- }
-
- /* Erase callback info reported during connection establishment; we only
- * care about updates.
- */
- ble_gap_test_util_reset_cb_info();
-
- TEST_ASSERT(!ble_gap_master_in_progress());
-
- rc = ble_hs_test_util_conn_update(2, params, 0);
- TEST_ASSERT(rc == 0);
- TEST_ASSERT(!ble_gap_master_in_progress());
-
- /* Verify tx of connection update command. */
- ble_gap_test_util_verify_tx_update_conn(params);
-
- /* Ensure no update event reported. */
- TEST_ASSERT(ble_gap_test_event.type == 0xff);
-
- /* Advance 39 seconds; ensure no timeout reported. */
- os_time_advance(39 * OS_TICKS_PER_SEC);
- ble_gap_timer();
- TEST_ASSERT(ble_gap_test_event.type == 0xff);
-
- /* Advance 40th second; ensure timeout reported. */
- os_time_advance(1 * OS_TICKS_PER_SEC);
-
- /* Timeout will result in a terminate HCI command being sent; schedule ack
- * from controller.
- */
- ble_hs_test_util_hci_ack_set_disconnect(0);
-
- ble_gap_timer();
-
- /* Verify terminate was sent. */
- ble_gap_test_util_verify_tx_disconnect();
-
- TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
- TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_ETIMEOUT);
- TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
- TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr.val,
- peer_addr, 6) == 0);
-}
-
-static void
ble_gap_test_util_update_l2cap_tmo(struct ble_gap_upd_params *params,
uint8_t hci_status, uint8_t event_status,
int rx_l2cap)
@@ -2982,9 +2918,6 @@ TEST_CASE_SELF(ble_gap_test_case_update_timeout)
.max_ce_len = 456,
};
- /* No L2CAP. */
- ble_gap_test_util_update_no_l2cap_tmo(&params, 1);
-
/* L2CAP - Local unsupported; L2CAP timeout. */
ble_gap_test_util_update_l2cap_tmo(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 0);