Merge branch 'bugfix/sync_zephyr_v2.0_ble_mesh_fixes' into 'master'

ble_mesh: sync Zephyr v2.0 ble mesh fixes

Closes BLEMESH-56

See merge request espressif/esp-idf!6892
This commit is contained in:
Jiang Jiang Jian 2020-01-12 20:23:57 +08:00
commit 8ec233dfd0
26 changed files with 1240 additions and 437 deletions

View file

@ -590,8 +590,7 @@ if BLE_MESH
endif # BLE_MESH_LOW_POWER
config BLE_MESH_FRIEND
bool "Support for acting as a Friend Node"
depends on BLE_MESH_NODE
bool "Support for Friend feature"
help
Enable this option to be able to act as a Friend Node.

View file

@ -356,16 +356,16 @@ typedef struct {
esp_ble_mesh_model_t *model;
uint16_t publish_addr; /*!< Publish Address. */
uint16_t app_idx; /*!< Publish AppKey Index. */
uint16_t app_idx:12, /*!< Publish AppKey Index. */
cred:1; /*!< Friendship Credentials Flag. */
uint8_t ttl; /*!< Publish Time to Live. */
uint8_t retransmit; /*!< Retransmit Count & Interval Steps. */
uint8_t period; /*!< Publish Period. */
uint16_t period_div: 4, /*!< Divisor for the Period. */
cred: 1, /*!< Friendship Credentials Flag. */
fast_period: 1, /*!< Use FastPeriodDivisor */
count: 3; /*!< Retransmissions left. */
uint8_t period_div:4, /*!< Divisor for the Period. */
fast_period:1, /*!< Use FastPeriodDivisor */
count:3; /*!< Retransmissions left. */
uint32_t period_start; /*!< Start of the current period. */
@ -491,6 +491,9 @@ typedef struct {
/** Destination address of a received message. Not used for sending. */
uint16_t recv_dst;
/** RSSI of received packet. Not used for sending. */
int8_t recv_rssi;
/** Received TTL value. Not used for sending. */
uint8_t recv_ttl: 7;

View file

@ -783,7 +783,6 @@ static void btc_ble_mesh_heartbeat_msg_recv_cb(u8_t hops, u16_t feature)
return;
}
#if CONFIG_BLE_MESH_NODE
#if CONFIG_BLE_MESH_LOW_POWER
static void btc_ble_mesh_lpn_cb(u16_t friend_addr, bool established)
{
@ -831,7 +830,6 @@ void btc_ble_mesh_friend_cb(bool establish, u16_t lpn_addr, u8_t reason)
return;
}
#endif /* CONFIG_BLE_MESH_FRIEND */
#endif /* CONFIG_BLE_MESH_NODE */
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
static void btc_ble_mesh_proxy_client_adv_recv_cb(const bt_mesh_addr_t *addr,
@ -1507,12 +1505,6 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
arg->mesh_init.prov->link_close_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_link_close_cb;
arg->mesh_init.prov->complete_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_complete_cb;
arg->mesh_init.prov->reset_cb = (esp_ble_mesh_cb_t)btc_ble_mesh_reset_cb;
#if CONFIG_BLE_MESH_LOW_POWER
bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb);
#endif /* CONFIG_BLE_MESH_LOW_POWER */
#if CONFIG_BLE_MESH_FRIEND
bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb);
#endif /* CONFIG_BLE_MESH_FRIEND */
#endif /* CONFIG_BLE_MESH_NODE */
#if CONFIG_BLE_MESH_PROVISIONER
arg->mesh_init.prov->provisioner_prov_read_oob_pub_key = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_read_oob_pub_key_cb;
@ -1523,6 +1515,12 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
arg->mesh_init.prov->provisioner_prov_comp = (esp_ble_mesh_cb_t)btc_ble_mesh_provisioner_prov_complete_cb;
bt_mesh_prov_adv_pkt_cb_register(btc_ble_mesh_provisioner_recv_unprov_adv_pkt_cb);
#endif /* CONFIG_BLE_MESH_PROVISIONER */
#if CONFIG_BLE_MESH_LOW_POWER
bt_mesh_lpn_set_cb(btc_ble_mesh_lpn_cb);
#endif /* CONFIG_BLE_MESH_LOW_POWER */
#if CONFIG_BLE_MESH_FRIEND
bt_mesh_friend_set_cb(btc_ble_mesh_friend_cb);
#endif /* CONFIG_BLE_MESH_FRIEND */
#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT
bt_mesh_proxy_client_set_adv_recv_cb(btc_ble_mesh_proxy_client_adv_recv_cb);
bt_mesh_proxy_client_set_conn_cb(btc_ble_mesh_proxy_client_connect_cb);

View file

@ -168,6 +168,19 @@ static inline void net_buf_simple_reset(struct net_buf_simple *buf)
buf->data = buf->__buf;
}
/**
* Clone buffer state, using the same data buffer.
*
* Initializes a buffer to point to the same data as an existing buffer.
* Allows operations on the same data without altering the length and
* offset of the original.
*
* @param original Buffer to clone.
* @param clone The new clone.
*/
void net_buf_simple_clone(const struct net_buf_simple *original,
struct net_buf_simple *clone);
/**
* @brief Prepare data to be added at the end of the buffer
*
@ -963,6 +976,20 @@ static inline void *net_buf_user_data(struct net_buf *buf)
*/
#define net_buf_pull(buf, len) net_buf_simple_pull(&(buf)->b, len)
/**
* @def net_buf_pull_mem
* @brief Remove data from the beginning of the buffer.
*
* Removes data from the beginning of the buffer by modifying the data
* pointer and buffer length.
*
* @param buf Buffer to update.
* @param len Number of bytes to remove.
*
* @return Pointer to the old beginning of the buffer data.
*/
#define net_buf_pull_mem(buf, len) net_buf_simple_pull_mem(&(buf)->b, len)
/**
* @def net_buf_pull_u8
* @brief Remove a 8-bit value from the beginning of the buffer
@ -1052,6 +1079,180 @@ static inline void *net_buf_user_data(struct net_buf *buf)
*/
#define net_buf_headroom(buf) net_buf_simple_headroom(&(buf)->b)
/**
* @def net_buf_tail
* @brief Get the tail pointer for a buffer.
*
* Get a pointer to the end of the data in a buffer.
*
* @param buf Buffer.
*
* @return Tail pointer for the buffer.
*/
#define net_buf_tail(buf) net_buf_simple_tail(&(buf)->b)
/**
* @brief Find the last fragment in the fragment list.
*
* @return Pointer to last fragment in the list.
*/
struct net_buf *net_buf_frag_last(struct net_buf *frags);
/**
* @brief Insert a new fragment to a chain of bufs.
*
* Insert a new fragment into the buffer fragments list after the parent.
*
* Note: This function takes ownership of the fragment reference so the
* caller is not required to unref.
*
* @param parent Parent buffer/fragment.
* @param frag Fragment to insert.
*/
void net_buf_frag_insert(struct net_buf *parent, struct net_buf *frag);
/**
* @brief Add a new fragment to the end of a chain of bufs.
*
* Append a new fragment into the buffer fragments list.
*
* Note: This function takes ownership of the fragment reference so the
* caller is not required to unref.
*
* @param head Head of the fragment chain.
* @param frag Fragment to add.
*
* @return New head of the fragment chain. Either head (if head
* was non-NULL) or frag (if head was NULL).
*/
struct net_buf *net_buf_frag_add(struct net_buf *head, struct net_buf *frag);
/**
* @brief Delete existing fragment from a chain of bufs.
*
* @param parent Parent buffer/fragment, or NULL if there is no parent.
* @param frag Fragment to delete.
*
* @return Pointer to the buffer following the fragment, or NULL if it
* had no further fragments.
*/
#if defined(CONFIG_BLE_MESH_NET_BUF_LOG)
struct net_buf *net_buf_frag_del_debug(struct net_buf *parent,
struct net_buf *frag,
const char *func, int line);
#define net_buf_frag_del(_parent, _frag) \
net_buf_frag_del_debug(_parent, _frag, __func__, __LINE__)
#else
struct net_buf *net_buf_frag_del(struct net_buf *parent, struct net_buf *frag);
#endif
/**
* @brief Copy bytes from net_buf chain starting at offset to linear buffer
*
* Copy (extract) @a len bytes from @a src net_buf chain, starting from @a
* offset in it, to a linear buffer @a dst. Return number of bytes actually
* copied, which may be less than requested, if net_buf chain doesn't have
* enough data, or destination buffer is too small.
*
* @param dst Destination buffer
* @param dst_len Destination buffer length
* @param src Source net_buf chain
* @param offset Starting offset to copy from
* @param len Number of bytes to copy
* @return number of bytes actually copied
*/
size_t net_buf_linearize(void *dst, size_t dst_len,
struct net_buf *src, size_t offset, size_t len);
/**
* @typedef net_buf_allocator_cb
* @brief Network buffer allocator callback.
*
* @details The allocator callback is called when net_buf_append_bytes
* needs to allocate a new net_buf.
*
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
* @param user_data The user data given in net_buf_append_bytes call.
* @return pointer to allocated net_buf or NULL on error.
*/
typedef struct net_buf *(*net_buf_allocator_cb)(s32_t timeout, void *user_data);
/**
* @brief Append data to a list of net_buf
*
* @details Append data to a net_buf. If there is not enough space in the
* net_buf then more net_buf will be added, unless there are no free net_buf
* and timeout occurs.
*
* @param buf Network buffer.
* @param len Total length of input data
* @param value Data to be added
* @param timeout Timeout is passed to the net_buf allocator callback.
* @param allocate_cb When a new net_buf is required, use this callback.
* @param user_data A user data pointer to be supplied to the allocate_cb.
* This pointer is can be anything from a mem_pool or a net_pkt, the
* logic is left up to the allocate_cb function.
*
* @return Length of data actually added. This may be less than input
* length if other timeout than K_FOREVER was used, and there
* were no free fragments in a pool to accommodate all data.
*/
size_t net_buf_append_bytes(struct net_buf *buf, size_t len,
const void *value, s32_t timeout,
net_buf_allocator_cb allocate_cb, void *user_data);
/**
* @brief Skip N number of bytes in a net_buf
*
* @details Skip N number of bytes starting from fragment's offset. If the total
* length of data is placed in multiple fragments, this function will skip from
* all fragments until it reaches N number of bytes. Any fully skipped buffers
* are removed from the net_buf list.
*
* @param buf Network buffer.
* @param len Total length of data to be skipped.
*
* @return Pointer to the fragment or
* NULL and pos is 0 after successful skip,
* NULL and pos is 0xffff otherwise.
*/
static inline struct net_buf *net_buf_skip(struct net_buf *buf, size_t len)
{
while (buf && len--) {
net_buf_pull_u8(buf);
if (!buf->len) {
buf = net_buf_frag_del(NULL, buf);
}
}
return buf;
}
/**
* @brief Calculate amount of bytes stored in fragments.
*
* Calculates the total amount of data stored in the given buffer and the
* fragments linked to it.
*
* @param buf Buffer to start off with.
*
* @return Number of bytes in the buffer and its fragments.
*/
static inline size_t net_buf_frags_len(struct net_buf *buf)
{
size_t bytes = 0;
while (buf) {
bytes += buf->len;
buf = buf->frags;
}
return bytes;
}
/**
* @}
*/

View file

@ -31,6 +31,12 @@ static inline struct net_buf *pool_get_uninit(struct net_buf_pool *pool,
return buf;
}
void net_buf_simple_clone(const struct net_buf_simple *original,
struct net_buf_simple *clone)
{
memcpy(clone, original, sizeof(struct net_buf_simple));
}
void *net_buf_simple_add(struct net_buf_simple *buf, size_t len)
{
u8_t *tail = net_buf_simple_tail(buf);
@ -447,4 +453,143 @@ struct net_buf *net_buf_alloc_fixed(struct net_buf_pool *pool, s32_t timeout)
return net_buf_alloc_len(pool, fixed->data_size, timeout);
}
#endif
#endif
struct net_buf *net_buf_frag_last(struct net_buf *buf)
{
NET_BUF_ASSERT(buf);
while (buf->frags) {
buf = buf->frags;
}
return buf;
}
void net_buf_frag_insert(struct net_buf *parent, struct net_buf *frag)
{
NET_BUF_ASSERT(parent);
NET_BUF_ASSERT(frag);
if (parent->frags) {
net_buf_frag_last(frag)->frags = parent->frags;
}
/* Take ownership of the fragment reference */
parent->frags = frag;
}
struct net_buf *net_buf_frag_add(struct net_buf *head, struct net_buf *frag)
{
NET_BUF_ASSERT(frag);
if (!head) {
return net_buf_ref(frag);
}
net_buf_frag_insert(net_buf_frag_last(head), frag);
return head;
}
#if defined(CONFIG_BLE_MESH_NET_BUF_LOG)
struct net_buf *net_buf_frag_del_debug(struct net_buf *parent,
struct net_buf *frag,
const char *func, int line)
#else
struct net_buf *net_buf_frag_del(struct net_buf *parent, struct net_buf *frag)
#endif
{
struct net_buf *next_frag;
NET_BUF_ASSERT(frag);
if (parent) {
NET_BUF_ASSERT(parent->frags);
NET_BUF_ASSERT(parent->frags == frag);
parent->frags = frag->frags;
}
next_frag = frag->frags;
frag->frags = NULL;
#if defined(CONFIG_BLE_MESH_NET_BUF_LOG)
net_buf_unref_debug(frag, func, line);
#else
net_buf_unref(frag);
#endif
return next_frag;
}
size_t net_buf_linearize(void *dst, size_t dst_len, struct net_buf *src,
size_t offset, size_t len)
{
struct net_buf *frag;
size_t to_copy;
size_t copied;
len = MIN(len, dst_len);
frag = src;
/* find the right fragment to start copying from */
while (frag && offset >= frag->len) {
offset -= frag->len;
frag = frag->frags;
}
/* traverse the fragment chain until len bytes are copied */
copied = 0;
while (frag && len > 0) {
to_copy = MIN(len, frag->len - offset);
memcpy((u8_t *)dst + copied, frag->data + offset, to_copy);
copied += to_copy;
/* to_copy is always <= len */
len -= to_copy;
frag = frag->frags;
/* after the first iteration, this value will be 0 */
offset = 0;
}
return copied;
}
/* This helper routine will append multiple bytes, if there is no place for
* the data in current fragment then create new fragment and add it to
* the buffer. It assumes that the buffer has at least one fragment.
*/
size_t net_buf_append_bytes(struct net_buf *buf, size_t len,
const void *value, s32_t timeout,
net_buf_allocator_cb allocate_cb, void *user_data)
{
struct net_buf *frag = net_buf_frag_last(buf);
size_t added_len = 0;
const u8_t *value8 = value;
do {
u16_t count = MIN(len, net_buf_tailroom(frag));
net_buf_add_mem(frag, value8, count);
len -= count;
added_len += count;
value8 += count;
if (len == 0) {
return added_len;
}
frag = allocate_cb(timeout, user_data);
if (!frag) {
return added_len;
}
net_buf_frag_add(buf, frag);
} while (1);
/* Unreachable */
return 0;
}

View file

@ -227,7 +227,7 @@ static s32_t next_period(struct bt_mesh_model *mod)
BT_DBG("Publishing took %ums", elapsed);
if (elapsed > period) {
if (elapsed >= period) {
BT_WARN("Publication sending took longer than the period");
/* Return smallest positive number since 0 means disabled */
return K_MSEC(1);
@ -761,21 +761,21 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, u32_t opcode)
{
net_buf_simple_init(msg, 0);
if (opcode < 0x100) {
/* 1-byte OpCode */
switch (BLE_MESH_MODEL_OP_LEN(opcode)) {
case 1:
net_buf_simple_add_u8(msg, opcode);
return;
}
if (opcode < 0x10000) {
/* 2-byte OpCode */
break;
case 2:
net_buf_simple_add_be16(msg, opcode);
return;
break;
case 3:
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
net_buf_simple_add_le16(msg, opcode & 0xffff);
break;
default:
BT_WARN("Unknown opcode format");
break;
}
/* 3-byte OpCode */
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
net_buf_simple_add_le16(msg, opcode & 0xffff);
}
static bool ready_to_send(u8_t role, u16_t dst)

View file

@ -606,7 +606,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, s8_t rssi,
{
#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \
CONFIG_BLE_MESH_GATT_PROXY_CLIENT
u16_t uuid;
u16_t uuid = 0x0;
#endif
if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) {

View file

@ -46,15 +46,10 @@ struct bt_mesh_adv {
busy: 1;
u8_t xmit;
union {
/* Address, used e.g. for Friend Queue messages */
u16_t addr;
/* For transport layer segment sending */
struct {
u8_t attempts;
} seg;
};
/* For transport layer segment sending */
struct {
u8_t attempts;
} seg;
};
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);

View file

@ -29,6 +29,9 @@
#define CID_NVAL 0xffff
/* 2 byte dummy opcode for getting compile time buffer sizes. */
#define DUMMY_2_BYTE_OP BLE_MESH_MODEL_OP_2(0xff, 0xff)
s32_t config_msg_timeout;
static bt_mesh_config_client_t *cli;
@ -685,7 +688,7 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = {
int bt_mesh_cfg_comp_data_get(struct bt_mesh_msg_ctx *ctx, u8_t page)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_DEV_COMP_DATA_GET, 1);
int err;
if (!ctx || !ctx->addr) {
@ -707,7 +710,7 @@ int bt_mesh_cfg_comp_data_get(struct bt_mesh_msg_ctx *ctx, u8_t page)
static int get_state_u8(struct bt_mesh_msg_ctx *ctx, u32_t op)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 0);
int err;
bt_mesh_model_msg_init(&msg, op);
@ -723,7 +726,7 @@ static int get_state_u8(struct bt_mesh_msg_ctx *ctx, u32_t op)
static int set_state_u8(struct bt_mesh_msg_ctx *ctx, u32_t op, u8_t new_val)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 1);
int err;
bt_mesh_model_msg_init(&msg, op);
@ -804,7 +807,7 @@ int bt_mesh_cfg_gatt_proxy_set(struct bt_mesh_msg_ctx *ctx, u8_t val)
int bt_mesh_cfg_relay_get(struct bt_mesh_msg_ctx *ctx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_GET, 0);
int err;
if (!ctx || !ctx->addr) {
@ -826,7 +829,7 @@ int bt_mesh_cfg_relay_get(struct bt_mesh_msg_ctx *ctx)
int bt_mesh_cfg_relay_set(struct bt_mesh_msg_ctx *ctx, u8_t new_relay,
u8_t new_transmit)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_SET, 2);
int err;
if (!ctx || !ctx->addr) {
@ -850,7 +853,7 @@ int bt_mesh_cfg_relay_set(struct bt_mesh_msg_ctx *ctx, u8_t new_relay,
int bt_mesh_cfg_net_key_add(struct bt_mesh_msg_ctx *ctx, u16_t key_net_idx,
const u8_t net_key[16])
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 18 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_ADD, 18);
int err;
if (!ctx || !ctx->addr || !net_key) {
@ -874,7 +877,7 @@ int bt_mesh_cfg_net_key_add(struct bt_mesh_msg_ctx *ctx, u16_t key_net_idx,
int bt_mesh_cfg_app_key_add(struct bt_mesh_msg_ctx *ctx, u16_t key_net_idx,
u16_t key_app_idx, const u8_t app_key[16])
{
NET_BUF_SIMPLE_DEFINE(msg, 1 + 19 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_ADD, 19);
int err;
if (!ctx || !ctx->addr || !app_key) {
@ -898,7 +901,7 @@ int bt_mesh_cfg_app_key_add(struct bt_mesh_msg_ctx *ctx, u16_t key_net_idx,
int bt_mesh_cfg_mod_app_bind(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
u16_t mod_app_idx, u16_t mod_id, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 8 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_BIND, 8);
int err;
if (!ctx || !ctx->addr) {
@ -926,7 +929,7 @@ int bt_mesh_cfg_mod_app_bind(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
static int mod_sub(u32_t op, struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
u16_t sub_addr, u16_t mod_id, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 8 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 8);
int err;
bt_mesh_model_msg_init(&msg, op);
@ -976,7 +979,7 @@ int bt_mesh_cfg_mod_sub_overwrite(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
static int mod_sub_va(u32_t op, struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
const u8_t label[16], u16_t mod_id, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 22 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 22);
int err;
BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x label %s",
@ -1030,7 +1033,7 @@ int bt_mesh_cfg_mod_sub_va_overwrite(struct bt_mesh_msg_ctx *ctx, u16_t elem_add
int bt_mesh_cfg_mod_pub_get(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
u16_t mod_id, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 6 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_GET, 6);
int err;
if (!ctx || !ctx->addr) {
@ -1058,7 +1061,7 @@ int bt_mesh_cfg_mod_pub_set(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
u16_t mod_id, u16_t cid,
struct bt_mesh_cfg_mod_pub *pub)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 13 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_SET, 13);
int err;
if (!ctx || !ctx->addr || !pub) {
@ -1090,7 +1093,7 @@ int bt_mesh_cfg_mod_pub_set(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
int bt_mesh_cfg_hb_sub_set(struct bt_mesh_msg_ctx *ctx,
struct bt_mesh_cfg_hb_sub *sub)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 5 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_SET, 5);
int err;
if (!ctx || !ctx->addr || !sub) {
@ -1114,7 +1117,7 @@ int bt_mesh_cfg_hb_sub_set(struct bt_mesh_msg_ctx *ctx,
int bt_mesh_cfg_hb_sub_get(struct bt_mesh_msg_ctx *ctx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_GET, 0);
int err;
if (!ctx || !ctx->addr) {
@ -1136,7 +1139,7 @@ int bt_mesh_cfg_hb_sub_get(struct bt_mesh_msg_ctx *ctx)
int bt_mesh_cfg_hb_pub_set(struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_cfg_hb_pub *pub)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_SET, 9);
int err;
if (!ctx || !ctx->addr || !pub) {
@ -1163,7 +1166,7 @@ int bt_mesh_cfg_hb_pub_set(struct bt_mesh_msg_ctx *ctx,
int bt_mesh_cfg_hb_pub_get(struct bt_mesh_msg_ctx *ctx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_PUB_GET, 0);
int err;
if (!ctx || !ctx->addr) {
@ -1184,7 +1187,7 @@ int bt_mesh_cfg_hb_pub_get(struct bt_mesh_msg_ctx *ctx)
int bt_mesh_cfg_node_reset(struct bt_mesh_msg_ctx *ctx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_RESET, 0);
int err;
if (!ctx || !ctx->addr) {
@ -1207,7 +1210,7 @@ int bt_mesh_cfg_mod_pub_va_set(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
u16_t mod_id, u16_t cid, const u8_t label[16],
struct bt_mesh_cfg_mod_pub *pub)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 27 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_VA_SET, 27);
int err;
if (!ctx || !ctx->addr || !label || !pub) {
@ -1239,7 +1242,7 @@ int bt_mesh_cfg_mod_pub_va_set(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
int bt_mesh_cfg_mod_sub_del_all(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
u16_t mod_id, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 6 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_DEL_ALL, 6);
int err;
if (!ctx || !ctx->addr) {
@ -1266,7 +1269,7 @@ int bt_mesh_cfg_mod_sub_del_all(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
static int mod_sub_get(u32_t op, struct bt_mesh_msg_ctx *ctx,
u16_t elem_addr, u16_t mod_id, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 6 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 6);
int err;
bt_mesh_model_msg_init(&msg, op);
@ -1305,7 +1308,7 @@ int bt_mesh_cfg_mod_sub_get_vnd(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
int bt_mesh_cfg_net_key_update(struct bt_mesh_msg_ctx *ctx, u16_t net_idx,
const u8_t net_key[16])
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 18 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_UPDATE, 18);
int err;
if (!ctx || !ctx->addr || !net_key) {
@ -1328,7 +1331,7 @@ int bt_mesh_cfg_net_key_update(struct bt_mesh_msg_ctx *ctx, u16_t net_idx,
int bt_mesh_cfg_net_key_delete(struct bt_mesh_msg_ctx *ctx, u16_t net_idx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_DEL, 2);
int err;
if (!ctx || !ctx->addr) {
@ -1350,7 +1353,7 @@ int bt_mesh_cfg_net_key_delete(struct bt_mesh_msg_ctx *ctx, u16_t net_idx)
int bt_mesh_cfg_net_key_get(struct bt_mesh_msg_ctx *ctx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_GET, 0);
int err;
if (!ctx || !ctx->addr) {
@ -1372,7 +1375,7 @@ int bt_mesh_cfg_net_key_get(struct bt_mesh_msg_ctx *ctx)
int bt_mesh_cfg_app_key_update(struct bt_mesh_msg_ctx *ctx, u16_t net_idx,
u16_t app_idx, const u8_t app_key[16])
{
NET_BUF_SIMPLE_DEFINE(msg, 1 + 19 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_UPDATE, 19);
int err;
if (!ctx || !ctx->addr || !app_key) {
@ -1395,7 +1398,7 @@ int bt_mesh_cfg_app_key_update(struct bt_mesh_msg_ctx *ctx, u16_t net_idx,
int bt_mesh_cfg_app_key_delete(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u16_t app_idx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_DEL, 3);
int err;
if (!ctx || !ctx->addr) {
@ -1417,7 +1420,7 @@ int bt_mesh_cfg_app_key_delete(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u16_t
int bt_mesh_cfg_app_key_get(struct bt_mesh_msg_ctx *ctx, u16_t net_idx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_GET, 2);
int err;
if (!ctx || !ctx->addr) {
@ -1440,7 +1443,7 @@ int bt_mesh_cfg_app_key_get(struct bt_mesh_msg_ctx *ctx, u16_t net_idx)
static int node_identity_op(u32_t op, struct bt_mesh_msg_ctx *ctx,
u16_t net_idx, u8_t identity)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 3);
int err;
bt_mesh_model_msg_init(&msg, op);
@ -1477,7 +1480,7 @@ int bt_mesh_cfg_node_identity_set(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u8
int bt_mesh_cfg_mod_app_unbind(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
u16_t app_idx, u16_t mod_id, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 8 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_UNBIND, 8);
int err;
if (!ctx || !ctx->addr) {
@ -1505,7 +1508,7 @@ int bt_mesh_cfg_mod_app_unbind(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
static int mod_app_get(u32_t op, struct bt_mesh_msg_ctx *ctx,
u16_t elem_addr, u16_t mod_id, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 6 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 6);
int err;
bt_mesh_model_msg_init(&msg, op);
@ -1544,7 +1547,7 @@ int bt_mesh_cfg_mod_app_get_vnd(struct bt_mesh_msg_ctx *ctx, u16_t elem_addr,
static int kr_phase_op(u32_t op, struct bt_mesh_msg_ctx *ctx,
u16_t net_idx, u8_t transition)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, DUMMY_2_BYTE_OP, 3);
int err;
bt_mesh_model_msg_init(&msg, op);
@ -1580,7 +1583,7 @@ int bt_mesh_cfg_kr_phase_set(struct bt_mesh_msg_ctx *ctx, u16_t net_idx, u8_t tr
int bt_mesh_cfg_lpn_timeout_get(struct bt_mesh_msg_ctx *ctx, u16_t lpn_addr)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_LPN_TIMEOUT_GET, 2);
int err;
if (!ctx || !ctx->addr) {

View file

@ -47,11 +47,7 @@
static struct bt_mesh_cfg_srv *conf;
static struct label {
u16_t ref;
u16_t addr;
u8_t uuid[16];
} labels[CONFIG_BLE_MESH_LABEL_COUNT];
static struct label labels[CONFIG_BLE_MESH_LABEL_COUNT];
static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem,
bool primary)
@ -451,7 +447,7 @@ static void app_key_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
u16_t key_net_idx, key_app_idx;
u8_t status;
@ -486,7 +482,7 @@ static void app_key_update(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
u16_t key_net_idx, key_app_idx;
u8_t status;
@ -549,7 +545,7 @@ static void app_key_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_STATUS, 4);
u16_t key_net_idx, key_app_idx;
struct bt_mesh_app_key *key;
u8_t status;
@ -607,8 +603,8 @@ static void app_key_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4 +
IDX_LEN(CONFIG_BLE_MESH_APP_KEY_COUNT));
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_APP_KEY_LIST,
3 + IDX_LEN(CONFIG_BLE_MESH_APP_KEY_COUNT));
u16_t get_idx, i, prev;
u8_t status;
@ -666,8 +662,7 @@ static void beacon_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_BEACON_STATUS, 1);
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->len,
@ -685,8 +680,7 @@ static void beacon_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, 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",
@ -728,8 +722,7 @@ static void default_ttl_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_STATUS, 1);
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->len,
@ -747,8 +740,7 @@ static void default_ttl_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_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",
@ -781,8 +773,7 @@ static void default_ttl_set(struct bt_mesh_model *model,
static void send_gatt_proxy_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_GATT_PROXY_STATUS, 1);
bt_mesh_model_msg_init(&msg, OP_GATT_PROXY_STATUS);
net_buf_simple_add_u8(&msg, bt_mesh_gatt_proxy_get());
@ -878,8 +869,7 @@ static void net_transmit_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_TRANSMIT_STATUS, 1);
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->len,
@ -897,8 +887,7 @@ static void net_transmit_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, 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",
@ -931,8 +920,7 @@ static void relay_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_RELAY_STATUS, 2);
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->len,
@ -951,8 +939,7 @@ static void relay_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, 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",
@ -1005,8 +992,7 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
bool vnd, struct bt_mesh_model *mod,
u8_t status, u8_t *mod_id)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 14 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_PUB_STATUS, 14);
bt_mesh_model_msg_init(&msg, OP_MOD_PUB_STATUS);
@ -1162,25 +1148,61 @@ send_status:
}
}
#if CONFIG_BLE_MESH_LABEL_COUNT > 0
static u8_t va_add(u8_t *label_uuid, u16_t *addr)
struct label *get_label(u16_t index)
{
struct label *free_slot = NULL;
if (index >= ARRAY_SIZE(labels)) {
return NULL;
}
return &labels[index];
}
#if CONFIG_BLE_MESH_LABEL_COUNT > 0
static inline void va_store(struct label *store)
{
bt_mesh_atomic_set_bit(store->flags, BLE_MESH_VA_CHANGED);
if (IS_ENABLED(CONFIG_BLE_MESH_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) {
free_slot = &labels[i];
if (labels[i].ref == 0) {
if (free_slot != NULL) {
*free_slot = &labels[i];
}
continue;
}
if (!memcmp(labels[i].uuid, label_uuid, 16)) {
*addr = labels[i].addr;
labels[i].ref++;
return STATUS_SUCCESS;
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 STATUS_SUCCESS;
}
if (!free_slot) {
return STATUS_INSUFF_RESOURCES;
}
@ -1192,23 +1214,25 @@ static u8_t va_add(u8_t *label_uuid, u16_t *addr)
free_slot->ref = 1U;
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)
{
int i;
struct label *update;
for (i = 0; i < ARRAY_SIZE(labels); i++) {
if (!memcmp(labels[i].uuid, label_uuid, 16)) {
if (addr) {
*addr = labels[i].addr;
}
update = va_find(label_uuid, NULL);
if (update) {
update->ref--;
labels[i].ref--;
return STATUS_SUCCESS;
if (addr) {
*addr = update->addr;
}
va_store(update);
return STATUS_SUCCESS;
}
if (addr) {
@ -1386,8 +1410,7 @@ static void send_mod_sub_status(struct bt_mesh_model *model,
u16_t elem_addr, u16_t sub_addr, u8_t *mod_id,
bool vnd)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_STATUS, 9);
BT_DBG("status 0x%02x elem_addr 0x%04x sub_addr 0x%04x", status,
elem_addr, sub_addr);
@ -1696,8 +1719,8 @@ static void mod_sub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 5 + 4 +
CONFIG_BLE_MESH_MODEL_GROUP_COUNT * 2);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_LIST,
5 + CONFIG_BLE_MESH_MODEL_GROUP_COUNT * 2);
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
u16_t addr, id;
@ -1752,8 +1775,8 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 7 + 4 +
CONFIG_BLE_MESH_MODEL_GROUP_COUNT * 2);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_SUB_LIST_VND,
7 + CONFIG_BLE_MESH_MODEL_GROUP_COUNT * 2);
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
u16_t company, addr, id;
@ -2145,8 +2168,7 @@ static void send_net_key_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
u16_t idx, u8_t status)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_STATUS, 3);
bt_mesh_model_msg_init(&msg, OP_NET_KEY_STATUS);
@ -2379,8 +2401,8 @@ static void net_key_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg,
2 + 4 + IDX_LEN(CONFIG_BLE_MESH_SUBNET_COUNT));
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NET_KEY_LIST,
IDX_LEN(CONFIG_BLE_MESH_SUBNET_COUNT));
u16_t prev, i;
bt_mesh_model_msg_init(&msg, OP_NET_KEY_LIST);
@ -2415,8 +2437,7 @@ static void node_identity_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4);
struct bt_mesh_subnet *sub;
u8_t node_id;
u16_t idx;
@ -2454,8 +2475,7 @@ static void node_identity_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_IDENTITY_STATUS, 4);
struct bt_mesh_subnet *sub;
u8_t node_id;
u16_t idx;
@ -2531,7 +2551,7 @@ static void mod_app_bind(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_STATUS, 9);
u16_t elem_addr, key_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
@ -2594,7 +2614,7 @@ static void mod_app_unbind(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_MOD_APP_STATUS, 9);
u16_t elem_addr, key_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
@ -2652,7 +2672,11 @@ static void mod_app_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + KEY_LIST_LEN + 4);
NET_BUF_SIMPLE_DEFINE(msg,
MAX(BLE_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST,
9 + KEY_LIST_LEN),
BLE_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST,
9 + KEY_LIST_LEN)));
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
u8_t *mod_id, status;
@ -2720,8 +2744,7 @@ static void node_reset(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_NODE_RESET_STATUS, 0);
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->len,
@ -2745,8 +2768,7 @@ static void node_reset(struct bt_mesh_model *model,
static void send_friend_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_FRIEND_STATUS, 1);
struct bt_mesh_cfg_srv *cfg = model->user_data;
bt_mesh_model_msg_init(&msg, OP_FRIEND_STATUS);
@ -2818,8 +2840,7 @@ static void lpn_timeout_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 5 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_LPN_TIMEOUT_STATUS, 5);
struct bt_mesh_friend *frnd;
u16_t lpn_addr;
s32_t timeout;
@ -2864,8 +2885,7 @@ 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)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 4 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_KRP_STATUS, 4);
bt_mesh_model_msg_init(&msg, OP_KRP_STATUS);
@ -3008,8 +3028,7 @@ 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)
{
/* Needed size: opcode (1 byte) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 1 + 10 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, 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);
@ -3147,8 +3166,7 @@ failed:
static void hb_sub_send_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx, u8_t status)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 9 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEARTBEAT_SUB_STATUS, 9);
struct bt_mesh_cfg_srv *cfg = model->user_data;
u16_t period;
s64_t uptime;

View file

@ -117,6 +117,17 @@
#define STATUS_UNSPECIFIED 0x10
#define STATUS_INVALID_BINDING 0x11
enum {
BLE_MESH_VA_CHANGED, /* Label information changed */
};
struct label {
u16_t ref;
u16_t addr;
u8_t uuid[16];
bt_mesh_atomic_t flags[1];
};
int bt_mesh_cfg_srv_init(struct bt_mesh_model *model, bool primary);
int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary);
@ -129,6 +140,8 @@ 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);

View file

@ -26,19 +26,18 @@
#include "access.h"
#include "foundation.h"
#include "friend.h"
#include "client_common.h"
#include "provisioner_main.h"
#ifdef CONFIG_BLE_MESH_FRIEND
#define FRIEND_BUF_SIZE (BLE_MESH_ADV_DATA_SIZE - BLE_MESH_NET_HDR_LEN)
/* 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.
*/
#define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \
CONFIG_BLE_MESH_FRIEND_LPN_COUNT)
#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), \
struct friend_adv, adv)
#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), struct friend_adv, adv)
/* PDUs from Friend to the LPN should only be transmitted once with the
* smallest possible interval (20ms).
@ -62,7 +61,7 @@ NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT,
static struct friend_adv {
struct bt_mesh_adv adv;
u64_t seq_auth;
u16_t app_idx;
} adv_pool[FRIEND_BUF_COUNT];
enum {
@ -75,10 +74,22 @@ enum {
static void (*friend_cb)(bool establish, u16_t lpn_addr, u8_t reason);
static struct bt_mesh_subnet *friend_subnet_get(u16_t net_idx)
{
struct bt_mesh_subnet *sub = NULL;
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
sub = bt_mesh_subnet_get(net_idx);
} else if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
sub = provisioner_subnet_get(net_idx);
}
return sub;
}
static struct bt_mesh_adv *adv_alloc(int id)
{
adv_pool[id].app_idx = BLE_MESH_KEY_UNUSED;
return &adv_pool[id].adv;
}
@ -318,13 +329,7 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd,
struct friend_pdu_info *info,
struct net_buf_simple *sdu)
{
struct bt_mesh_subnet *sub;
const u8_t *enc, *priv;
struct net_buf *buf;
u8_t nid;
sub = bt_mesh_subnet_get(frnd->net_idx);
__ASSERT_NO_MSG(sub != NULL);
buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc,
BLE_MESH_ADV_DATA,
@ -333,22 +338,7 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd,
return NULL;
}
BLE_MESH_ADV(buf)->addr = info->src;
FRIEND_ADV(buf)->seq_auth = TRANS_SEQ_AUTH_NVAL;
/* Friend Offer needs master security credentials */
if (info->ctl && TRANS_CTL_OP(sdu->data) == TRANS_CTL_OP_FRIEND_OFFER) {
enc = sub->keys[sub->kr_flag].enc;
priv = sub->keys[sub->kr_flag].privacy;
nid = sub->keys[sub->kr_flag].nid;
} else {
if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
BT_ERR("%s, friend_cred_get failed", __func__);
goto failed;
}
}
net_buf_add_u8(buf, (nid | (info->iv_index & 1) << 7));
net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */
if (info->ctl) {
net_buf_add_u8(buf, info->ttl | 0x80);
@ -363,25 +353,187 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd,
net_buf_add_mem(buf, sdu->data, sdu->len);
/* 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->b, info->iv_index, false)) {
BT_ERR("%s, Re-encrypting failed", __func__);
goto failed;
}
if (bt_mesh_net_obfuscate(buf->data, info->iv_index, priv)) {
BT_ERR("%s, Re-obfuscating failed", __func__);
goto failed;
}
return buf;
}
failed:
net_buf_unref(buf);
return NULL;
struct unseg_app_sdu_meta {
struct bt_mesh_net_rx net;
const u8_t *key;
struct bt_mesh_subnet *subnet;
bool is_dev_key;
u8_t aid;
u8_t *ad;
};
static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd,
struct net_buf *buf,
struct unseg_app_sdu_meta *meta)
{
u16_t app_idx = FRIEND_ADV(buf)->app_idx;
u8_t role;
int err;
meta->subnet = friend_subnet_get(frnd->net_idx);
if (!meta->subnet) {
BT_ERR("Invalid subnet for unseg app sdu");
return -EINVAL;
}
role = (IS_ENABLED(CONFIG_BLE_MESH_NODE) &&
bt_mesh_is_provisioned()) ? NODE : PROVISIONER;
meta->is_dev_key = (app_idx == BLE_MESH_KEY_DEV);
bt_mesh_net_header_parse(&buf->b, &meta->net);
err = bt_mesh_app_key_get(meta->subnet, app_idx, &meta->key,
&meta->aid, role, meta->net.ctx.addr);
if (err) {
BT_ERR("Failed to get AppKey");
return err;
}
if (BLE_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) {
meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst);
if (!meta->ad) {
BT_ERR("Failed to get label uuid");
return -ENOENT;
}
} else {
meta->ad = NULL;
}
return 0;
}
static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd,
struct net_buf *buf,
const struct unseg_app_sdu_meta *meta)
{
struct net_buf_simple sdu;
net_buf_simple_clone(&buf->b, &sdu);
net_buf_simple_pull(&sdu, 10);
sdu.len -= 4;
return bt_mesh_app_decrypt(meta->key, meta->is_dev_key, 0, &sdu, &sdu,
meta->ad, meta->net.ctx.addr,
meta->net.ctx.recv_dst, meta->net.seq,
BLE_MESH_NET_IVI_TX);
}
static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd,
struct net_buf *buf,
const struct unseg_app_sdu_meta *meta)
{
struct net_buf_simple sdu;
net_buf_simple_clone(&buf->b, &sdu);
net_buf_simple_pull(&sdu, 10);
sdu.len -= 4;
return bt_mesh_app_encrypt(meta->key, meta->is_dev_key, 0, &sdu,
meta->ad, meta->net.ctx.addr,
meta->net.ctx.recv_dst, bt_mesh.seq,
BLE_MESH_NET_IVI_TX);
}
static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
struct net_buf *buf)
{
struct unseg_app_sdu_meta meta;
int err;
if (FRIEND_ADV(buf)->app_idx == BLE_MESH_KEY_UNUSED) {
return 0;
}
err = unseg_app_sdu_unpack(frnd, buf, &meta);
if (err) {
return err;
}
/* No need to reencrypt the message if the sequence number is
* unchanged.
*/
if (meta.net.seq == bt_mesh.seq) {
return 0;
}
err = unseg_app_sdu_decrypt(frnd, buf, &meta);
if (err) {
BT_WARN("Decryption failed! %d", err);
return err;
}
err = unseg_app_sdu_encrypt(frnd, buf, &meta);
if (err) {
BT_WARN("Re-encryption failed! %d", err);
}
return err;
}
static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct net_buf *buf,
bool master_cred)
{
struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx);
const u8_t *enc, *priv;
u32_t iv_index;
u16_t src;
u8_t nid;
int err;
if (!sub) {
BT_ERR("Invalid subnet to encrypt friend pdu");
return -EINVAL;
}
if (master_cred) {
enc = sub->keys[sub->kr_flag].enc;
priv = sub->keys[sub->kr_flag].privacy;
nid = sub->keys[sub->kr_flag].nid;
} else {
if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
BT_ERR("friend_cred_get failed");
return -ENOENT;
}
}
src = sys_get_be16(&buf->data[5]);
if (bt_mesh_elem_find(src)) {
u32_t seq;
if (FRIEND_ADV(buf)->app_idx != BLE_MESH_KEY_UNUSED) {
err = unseg_app_sdu_prepare(frnd, buf);
if (err) {
return err;
}
}
seq = bt_mesh_next_seq();
buf->data[2] = seq >> 16;
buf->data[3] = seq >> 8;
buf->data[4] = seq;
iv_index = BLE_MESH_NET_IVI_TX;
FRIEND_ADV(buf)->app_idx = BLE_MESH_KEY_UNUSED;
} else {
u8_t ivi = (buf->data[0] >> 7);
iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi));
}
buf->data[0] = (nid | (iv_index & 1) << 7);
if (bt_mesh_net_encrypt(enc, &buf->b, iv_index, false)) {
BT_ERR("Encrypting failed");
return -EINVAL;
}
if (bt_mesh_net_obfuscate(buf->data, iv_index, priv)) {
BT_ERR("Obfuscating failed");
return -EINVAL;
}
return 0;
}
static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd,
@ -389,7 +541,6 @@ static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd,
struct net_buf_simple *sdu)
{
struct friend_pdu_info info;
u32_t seq;
BT_DBG("LPN 0x%04x", frnd->lpn);
@ -401,10 +552,7 @@ static struct net_buf *encode_friend_ctl(struct bt_mesh_friend *frnd,
info.ctl = 1U;
info.ttl = 0U;
seq = bt_mesh_next_seq();
info.seq[0] = seq >> 16;
info.seq[1] = seq >> 8;
info.seq[2] = seq;
memset(info.seq, 0, sizeof(info.seq));
info.iv_index = BLE_MESH_NET_IVI_TX;
@ -415,7 +563,7 @@ static struct net_buf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
{
struct bt_mesh_ctl_friend_update *upd;
NET_BUF_SIMPLE_DEFINE(sdu, 1 + sizeof(*upd));
struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
struct bt_mesh_subnet *sub = friend_subnet_get(frnd->net_idx);
__ASSERT_NO_MSG(sub != NULL);
@ -450,6 +598,10 @@ static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact)
return;
}
if (encrypt_friend_pdu(frnd, buf, false)) {
return;
}
if (frnd->last) {
BT_DBG("Discarding last PDU");
net_buf_unref(frnd->last);
@ -651,7 +803,7 @@ static void send_friend_clear(struct bt_mesh_friend *frnd)
.send_ttl = BLE_MESH_TTL_MAX,
};
struct bt_mesh_net_tx tx = {
.sub = &bt_mesh.sub[0],
.sub = friend_subnet_get(frnd->net_idx),
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = bt_mesh_net_transmit_get(),
@ -663,6 +815,11 @@ static void send_friend_clear(struct bt_mesh_friend *frnd)
BT_DBG("%s", __func__);
if (!tx.sub) {
BT_ERR("Invalid subnet for Friend Clear");
return;
}
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
sizeof(req), NULL, &clear_sent_cb, frnd);
}
@ -759,6 +916,10 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
return;
}
if (encrypt_friend_pdu(frnd, buf, true)) {
return;
}
frnd->counter++;
if (frnd->last) {
@ -879,7 +1040,7 @@ init_friend:
frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
frnd->lpn, rx->rssi, frnd->recv_delay, frnd->poll_to);
frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, frnd->poll_to);
/**
* Spec says:
@ -894,18 +1055,40 @@ init_friend:
}
k_delayed_work_submit(&frnd->timer,
offer_delay(frnd, rx->rssi, msg->criteria));
offer_delay(frnd, rx->ctx.recv_rssi,
msg->criteria));
friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
frnd->counter);
enqueue_offer(frnd, rx->rssi);
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)
{
struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue);
struct net_buf_simple_state state;
u16_t buf_seq_zero;
u16_t buf_src;
if (!buf) {
return false;
}
net_buf_simple_save(&buf->b, &state);
net_buf_skip(buf, 5); /* skip IVI, NID, CTL, TTL, SEQ */
buf_src = net_buf_pull_be16(buf);
net_buf_skip(buf, 3); /* skip DST, OP/AID */
buf_seq_zero = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK);
net_buf_simple_restore(&buf->b, &state);
return ((src == buf_src) && (seq_zero == buf_seq_zero));
}
static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
u16_t src, u64_t *seq_auth,
u16_t src, u16_t seq_zero,
u8_t seg_count)
{
struct bt_mesh_friend_seg *unassigned = NULL;
@ -913,14 +1096,12 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
struct bt_mesh_friend_seg *seg = &frnd->seg[i];
struct net_buf *buf = (void *)sys_slist_peek_head(&seg->queue);
if (buf && BLE_MESH_ADV(buf)->addr == src &&
FRIEND_ADV(buf)->seq_auth == *seq_auth) {
if (is_seg(seg, src, seq_zero)) {
return seg;
}
if (!unassigned && !buf) {
if (!unassigned && !sys_slist_peek_head(&seg->queue)) {
unassigned = seg;
}
}
@ -934,10 +1115,10 @@ 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,
u8_t seg_count, struct net_buf *buf)
u16_t src, u8_t seg_count,
struct net_buf *buf)
{
struct bt_mesh_friend_seg *seg;
struct friend_adv *adv;
BT_DBG("type %u", type);
@ -950,11 +1131,11 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
return;
}
adv = FRIEND_ADV(buf);
seg = get_seg(frnd, BLE_MESH_ADV(buf)->addr, &adv->seq_auth, seg_count);
u16_t seq_zero = (((buf->data[10] << 8 | buf->data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
seg = get_seg(frnd, src, seq_zero, seg_count);
if (!seg) {
BT_ERR("%s, No free friend segment RX contexts for 0x%04x",
__func__, BLE_MESH_ADV(buf)->addr);
BT_ERR("No free friend segment RX contexts for 0x%04x", src);
net_buf_unref(buf);
return;
}
@ -966,16 +1147,9 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
enqueue_update(frnd, 1);
}
/* Only acks should have a valid SeqAuth in the Friend queue
* (otherwise we can't easily detect them there), so clear
* the SeqAuth information from the segments before merging.
*/
SYS_SLIST_FOR_EACH_CONTAINER(&seg->queue, buf, node) {
FRIEND_ADV(buf)->seq_auth = TRANS_SEQ_AUTH_NVAL;
frnd->queue_size++;
}
sys_slist_merge_slist(&frnd->queue, &seg->queue);
frnd->queue_size += seg->seg_count;
seg->seg_count = 0U;
} else {
/* Mark the buffer as having more to come after it */
@ -1052,6 +1226,10 @@ static void friend_timeout(struct k_work *work)
return;
}
if (encrypt_friend_pdu(frnd, frnd->last, false)) {
return;
}
/* Clear the flag we use for segment tracking */
frnd->last->flags &= ~NET_BUF_FRAGS;
frnd->last->frags = NULL;
@ -1094,6 +1272,42 @@ int bt_mesh_friend_init(void)
return 0;
}
static bool is_segack(struct net_buf *buf, u64_t *seqauth, u16_t src)
{
struct net_buf_simple_state state;
bool found = false;
if (buf->len != 16) {
return false;
}
net_buf_simple_save(&buf->b, &state);
net_buf_skip(buf, 1); /* skip IVI, NID */
if (!(net_buf_pull_u8(buf) >> 7)) {
goto end;
}
net_buf_pull(buf, 3); /* skip SEQNUM */
if (src != net_buf_pull_be16(buf)) {
goto end;
}
net_buf_skip(buf, 2); /* skip dst */
if (TRANS_CTL_OP((u8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
goto end;
}
found = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK) ==
(*seqauth & TRANS_SEQ_ZERO_MASK);
end:
net_buf_simple_restore(&buf->b, &state);
return found;
}
static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
u16_t src)
{
@ -1105,8 +1319,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
cur != NULL; prev = cur, cur = sys_slist_peek_next(cur)) {
struct net_buf *buf = (void *)cur;
if (BLE_MESH_ADV(buf)->addr == src &&
FRIEND_ADV(buf)->seq_auth == *seq_auth) {
if (is_segack(buf, seq_auth, src)) {
BT_DBG("Removing old ack from Friend Queue");
sys_slist_remove(&frnd->queue, prev, cur);
@ -1129,6 +1342,14 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
struct friend_pdu_info info;
struct net_buf *buf;
/* Because of network loopback, tx packets will also be passed into
* this rx function. These packets have already been added to the
* queue, and should be ignored.
*/
if (bt_mesh_elem_find(rx->ctx.addr)) {
return;
}
BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, frnd->queue_size);
if (type == BLE_MESH_FRIEND_PDU_SINGLE && seq_auth) {
@ -1158,11 +1379,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
return;
}
if (seq_auth) {
FRIEND_ADV(buf)->seq_auth = *seq_auth;
}
enqueue_friend_pdu(frnd, type, seg_count, buf);
enqueue_friend_pdu(frnd, type, info.src, seg_count, buf);
BT_DBG("Queued message for LPN 0x%04x, queue_size %u",
frnd->lpn, frnd->queue_size);
@ -1176,7 +1393,6 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
{
struct friend_pdu_info info;
struct net_buf *buf;
u32_t seq;
BT_DBG("LPN 0x%04x", frnd->lpn);
@ -1190,10 +1406,9 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
info.ttl = tx->ctx->send_ttl;
info.ctl = (tx->ctx->app_idx == BLE_MESH_KEY_UNUSED);
seq = bt_mesh_next_seq();
info.seq[0] = seq >> 16;
info.seq[1] = seq >> 8;
info.seq[2] = seq;
info.seq[0] = (bt_mesh.seq >> 16);
info.seq[1] = (bt_mesh.seq >> 8);
info.seq[2] = bt_mesh.seq;
info.iv_index = BLE_MESH_NET_IVI_TX;
@ -1203,11 +1418,15 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
return;
}
if (seq_auth) {
FRIEND_ADV(buf)->seq_auth = *seq_auth;
if (type == BLE_MESH_FRIEND_PDU_SINGLE && !info.ctl) {
/* Unsegmented application packets may be reencrypted later,
* as they depend on the the sequence number being the same
* when encrypting in transport and network.
*/
FRIEND_ADV(buf)->app_idx = tx->ctx->app_idx;
}
enqueue_friend_pdu(frnd, type, seg_count, buf);
enqueue_friend_pdu(frnd, type, info.src, seg_count, buf);
BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
}
@ -1270,17 +1489,11 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr,
for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) {
struct bt_mesh_friend_seg *seg = &frnd->seg[i];
if (seq_auth) {
struct net_buf *buf;
if (seq_auth && is_seg(seg, addr, *seq_auth & TRANS_SEQ_ZERO_MASK)) {
/* If there's a segment queue for this message then the
* space verification has already happened.
*/
buf = (void *)sys_slist_peek_head(&seg->queue);
if (buf && BLE_MESH_ADV(buf)->addr == addr &&
FRIEND_ADV(buf)->seq_auth == *seq_auth) {
return true;
}
return true;
}
total += seg->seg_count;
@ -1454,18 +1667,8 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) {
struct bt_mesh_friend_seg *seg = &frnd->seg[j];
struct net_buf *buf;
buf = (void *)sys_slist_peek_head(&seg->queue);
if (!buf) {
continue;
}
if (BLE_MESH_ADV(buf)->addr != src) {
continue;
}
if (FRIEND_ADV(buf)->seq_auth != *seq_auth) {
if (!is_seg(seg, src, *seq_auth & TRANS_SEQ_ZERO_MASK)) {
continue;
}
@ -1473,8 +1676,19 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
purge_buffers(&seg->queue);
seg->seg_count = 0U;
break;
}
}
}
void bt_mesh_friend_remove_lpn(u16_t lpn_addr)
{
struct bt_mesh_friend *frnd;
frnd = bt_mesh_friend_find(BLE_MESH_KEY_ANY, lpn_addr, false, false);
if (frnd) {
friend_clear(frnd, BLE_MESH_FRIENDSHIP_TERMINATE_DISABLE);
}
}
#endif /* CONFIG_BLE_MESH_FRIEND */

View file

@ -51,4 +51,6 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
int bt_mesh_friend_init(void);
void bt_mesh_friend_remove_lpn(u16_t lpn_addr);
#endif /* _FRIEND_H_ */

View file

@ -235,7 +235,7 @@ const struct bt_mesh_model_op bt_mesh_health_cli_op[] = {
int bt_mesh_health_attention_get(struct bt_mesh_msg_ctx *ctx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_GET, 0);
int err;
if (!ctx || !ctx->addr) {
@ -257,7 +257,7 @@ int bt_mesh_health_attention_get(struct bt_mesh_msg_ctx *ctx)
int bt_mesh_health_attention_set(struct bt_mesh_msg_ctx *ctx,
u8_t attention, bool need_ack)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_SET, 1);
u32_t opcode;
int err;
@ -285,7 +285,7 @@ int bt_mesh_health_attention_set(struct bt_mesh_msg_ctx *ctx,
int bt_mesh_health_period_get(struct bt_mesh_msg_ctx *ctx)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 0 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_GET, 0);
int err;
if (!ctx || !ctx->addr) {
@ -307,7 +307,7 @@ int bt_mesh_health_period_get(struct bt_mesh_msg_ctx *ctx)
int bt_mesh_health_period_set(struct bt_mesh_msg_ctx *ctx,
u8_t divisor, bool need_ack)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_SET, 1);
u32_t opcode;
int err;
@ -336,7 +336,7 @@ int bt_mesh_health_period_set(struct bt_mesh_msg_ctx *ctx,
int bt_mesh_health_fault_test(struct bt_mesh_msg_ctx *ctx,
u16_t cid, u8_t test_id, bool need_ack)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 3 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_TEST, 3);
u32_t opcode;
int err;
@ -366,7 +366,7 @@ int bt_mesh_health_fault_test(struct bt_mesh_msg_ctx *ctx,
int bt_mesh_health_fault_clear(struct bt_mesh_msg_ctx *ctx,
u16_t cid, bool need_ack)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_CLEAR, 2);
u32_t opcode;
int err;
@ -394,7 +394,7 @@ int bt_mesh_health_fault_clear(struct bt_mesh_msg_ctx *ctx,
int bt_mesh_health_fault_get(struct bt_mesh_msg_ctx *ctx, u16_t cid)
{
NET_BUF_SIMPLE_DEFINE(msg, 2 + 2 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_FAULT_GET, 2);
int err;
if (!ctx || !ctx->addr) {

View file

@ -227,8 +227,7 @@ static void health_fault_test(struct bt_mesh_model *model,
static void send_attention_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_ATTENTION_STATUS, 1);
struct bt_mesh_health_srv *srv = model->user_data;
u8_t time;
@ -286,8 +285,7 @@ static void attention_set(struct bt_mesh_model *model,
static void send_health_period_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx)
{
/* Needed size: opcode (2 bytes) + msg + MIC */
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
BLE_MESH_MODEL_BUF_DEFINE(msg, OP_HEALTH_PERIOD_STATUS, 1);
bt_mesh_model_msg_init(&msg, OP_HEALTH_PERIOD_STATUS);
net_buf_simple_add_u8(&msg, model->pub->period_div);

View file

@ -140,6 +140,9 @@ struct bt_mesh_msg_ctx {
/** Destination address of a received message. Not used for sending. */
u16_t recv_dst;
/** RSSI of received packet. Not used for sending. */
s8_t recv_rssi;
/** Received TTL value. Not used for sending. */
u8_t recv_ttl: 7;
@ -185,6 +188,56 @@ struct bt_mesh_model_op {
/** Helper to define an empty model array */
#define BLE_MESH_MODEL_NONE ((struct bt_mesh_model []){})
/** Length of a short Mesh MIC. */
#define BLE_MESH_MIC_SHORT 4
/** Length of a long Mesh MIC. */
#define BLE_MESH_MIC_LONG 8
/** @def BLE_MESH_MODEL_OP_LEN
*
* @brief Helper to determine the length of an opcode.
*
* @param _op Opcode.
*/
#define BLE_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3)
/** @def BLE_MESH_MODEL_BUF_LEN
*
* @brief Helper for model message buffer length.
*
* Returns the length of a Mesh model message buffer, including the opcode
* length and a short MIC.
*
* @param _op Opcode of the message.
* @param _payload_len Length of the model payload.
*/
#define BLE_MESH_MODEL_BUF_LEN(_op, _payload_len) \
(BLE_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BLE_MESH_MIC_SHORT)
/** @def BLE_MESH_MODEL_BUF_LEN_LONG_MIC
*
* @brief Helper for model message buffer length.
*
* Returns the length of a Mesh model message buffer, including the opcode
* length and a long MIC.
*
* @param _op Opcode of the message.
* @param _payload_len Length of the model payload.
*/
#define BLE_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \
(BLE_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BLE_MESH_MIC_LONG)
/** @def BLE_MESH_MODEL_BUF_DEFINE
*
* @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE_DEFINE.
*
* @param _buf Buffer name.
* @param _op Opcode of the message.
* @param _payload_len Length of the model message payload.
*/
#define BLE_MESH_MODEL_BUF_DEFINE(_buf, _op, _payload_len) \
NET_BUF_SIMPLE_DEFINE(_buf, BLE_MESH_MODEL_BUF_LEN(_op, (_payload_len)))
#define BLE_MESH_MODEL(_id, _op, _pub, _user_data) \
{ \
.id = (_id), \
@ -282,15 +335,15 @@ struct bt_mesh_model_pub {
struct bt_mesh_model *mod;
u16_t addr; /**< Publish Address. */
u16_t key; /**< Publish AppKey Index. */
u16_t key:12, /**< Publish AppKey Index. */
cred:1; /**< Friendship Credentials Flag. */
u8_t ttl; /**< Publish Time to Live. */
u8_t retransmit; /**< Retransmit Count & Interval Steps. */
u8_t period; /**< Publish Period. */
u16_t period_div: 4, /**< Divisor for the Period. */
cred: 1, /**< Friendship Credentials Flag. */
fast_period: 1, /**< Use FastPeriodDivisor */
count: 3; /**< Retransmissions left. */
u8_t period_div:4, /**< Divisor for the Period. */
fast_period:1,/**< Use FastPeriodDivisor */
count:3; /**< Retransmissions left. */
u32_t period_start; /**< Start of the current period. */

View file

@ -324,7 +324,7 @@ static int send_friend_req(struct bt_mesh_lpn *lpn)
.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),
};

View file

@ -413,6 +413,10 @@ int bt_mesh_provisioner_enable(bt_mesh_prov_bearer_t bearers)
provisioner_pb_gatt_enable();
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
bt_mesh_friend_init();
}
provisioner_en = true;
return 0;
@ -437,6 +441,10 @@ int bt_mesh_provisioner_disable(bt_mesh_prov_bearer_t bearers)
bt_mesh_scan_disable();
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
bt_mesh_friend_clear_net_idx(BLE_MESH_KEY_ANY);
}
provisioner_en = false;
return 0;

View file

@ -789,12 +789,10 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf,
return err;
}
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
bt_mesh_proxy_relay(&buf->b, dst)) {
send_cb_finalize(cb, cb_data);
return 0;
}
if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&
bt_mesh_proxy_relay(&buf->b, dst)) {
send_cb_finalize(cb, cb_data);
return 0;
}
bt_mesh_adv_send(buf, cb, cb_data);
@ -935,8 +933,9 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf,
#endif
/* Deliver to local network interface if necessary */
if (bt_mesh_fixed_group_match(tx->ctx->addr) ||
bt_mesh_elem_find(tx->ctx->addr)) {
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned() &&
(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);
}
@ -1122,18 +1121,14 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
continue;
}
#if CONFIG_BLE_MESH_NODE
if (bt_mesh_is_provisioned()) {
#if (defined(CONFIG_BLE_MESH_LOW_POWER) || defined(CONFIG_BLE_MESH_FRIEND))
if (!friend_decrypt(sub, data, data_len, rx, buf)) {
rx->friend_cred = 1;
rx->ctx.net_idx = sub->net_idx;
rx->sub = sub;
return true;
}
#endif
if (!friend_decrypt(sub, data, data_len, rx, buf)) {
rx->friend_cred = 1;
rx->ctx.net_idx = sub->net_idx;
rx->sub = sub;
return true;
}
#endif /* CONFIG_BLE_MESH_NODE */
#endif
if (NID(data) == sub->keys[0].nid &&
!net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy,
@ -1308,6 +1303,17 @@ done:
#endif /* CONFIG_BLE_MESH_NODE */
void bt_mesh_net_header_parse(struct net_buf_simple *buf,
struct bt_mesh_net_rx *rx)
{
rx->old_iv = (IVI(buf->data) != (bt_mesh.iv_index & 0x01));
rx->ctl = CTL(buf->data);
rx->ctx.recv_ttl = TTL(buf->data);
rx->seq = SEQ(buf->data);
rx->ctx.addr = SRC(buf->data);
rx->ctx.recv_dst = DST(buf->data);
}
int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if,
struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
{
@ -1398,7 +1404,7 @@ void bt_mesh_net_recv(struct net_buf_simple *data, s8_t rssi,
enum bt_mesh_net_if net_if)
{
NET_BUF_SIMPLE_DEFINE(buf, 29);
struct bt_mesh_net_rx rx = { .rssi = rssi };
struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi };
struct net_buf_simple_state state;
BT_DBG("rssi %d net_if %u", rssi, net_if);

View file

@ -224,6 +224,7 @@ enum {
BLE_MESH_HB_PUB_PENDING,
BLE_MESH_CFG_PENDING,
BLE_MESH_MOD_PENDING,
BLE_MESH_VA_PENDING,
/* Don't touch - intentionally last */
BLE_MESH_FLAG_COUNT,
@ -296,7 +297,6 @@ struct bt_mesh_net_rx {
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 */
s8_t rssi;
};
/* Encoding context for Network/Transport data */
@ -366,6 +366,8 @@ u32_t bt_mesh_next_seq(void);
void bt_mesh_net_start(void);
void bt_mesh_net_init(void);
void bt_mesh_net_header_parse(struct net_buf_simple *buf,
struct bt_mesh_net_rx *rx);
/* Friendship Credential Management */
struct friend_cred {

View file

@ -28,6 +28,7 @@
#include "adv.h"
#include "net.h"
#include "access.h"
#include "friend.h"
#include "provisioner_prov.h"
#include "proxy_client.h"
@ -142,6 +143,10 @@ int provisioner_node_reset(int node_index)
}
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
bt_mesh_friend_remove_lpn(node->unicast_addr);
}
osi_free(mesh_nodes[node_index]);
mesh_nodes[node_index] = NULL;

View file

@ -917,16 +917,6 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client,
BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
if (client->filter_type == WHITELIST) {
for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
if (client->filter[i] == addr) {
return true;
}
}
return false;
}
if (client->filter_type == BLACKLIST) {
for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
if (client->filter[i] == addr) {
@ -937,6 +927,18 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client,
return true;
}
if (addr == BLE_MESH_ADDR_ALL_NODES) {
return true;
}
if (client->filter_type == WHITELIST) {
for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
if (client->filter[i] == addr) {
return true;
}
}
}
return false;
}

View file

@ -55,6 +55,8 @@
* key: "mesh/v/xxxx/b" -> write/read to set/get VENDOR MODEL Bind AppKey List
* key: "mesh/v/xxxx/s" -> write/read to set/get VENDOR MODEL Subscription List
* key: "mesh/v/xxxx/p" -> write/read to set/get VENDOR MODEL Publication
* key: "mesh/vaddr" -> write/read to set/get all virtual addresses
* key: "mesh/va/xxxx" -> write/read to set/get the "xxxx" virtual address
*/
#if CONFIG_BLE_MESH_SETTINGS
@ -142,6 +144,13 @@ struct mod_pub_val {
cred: 1;
};
/* Virtual Address information */
struct va_val {
u16_t ref;
u16_t addr;
u8_t uuid[16];
} __packed;
/* 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.
*/
@ -695,6 +704,66 @@ static int vnd_mod_set(const char *name)
return model_set(true, name);
}
#if CONFIG_BLE_MESH_LABEL_COUNT > 0
static int va_set(const char *name)
{
struct net_buf_simple *buf = NULL;
struct va_val va = {0};
char get[16] = {'\0'};
struct label *lab;
size_t length;
bool exist;
int err = 0;
u16_t i;
BT_DBG("%s", __func__);
buf = bt_mesh_get_core_settings_item(name);
if (!buf) {
return 0;
}
length = buf->len;
for (i = 0U; i < length / SETTINGS_ITEM_SIZE; i++) {
u16_t index = net_buf_simple_pull_le16(buf);
sprintf(get, "mesh/va/%04x", index);
err = bt_mesh_load_core_settings(get, (u8_t *)&va, sizeof(va), &exist);
if (err) {
BT_ERR("%s, Failed to load virtual address %s", __func__, get);
goto free;
}
if (exist == false) {
continue;
}
if (va.ref == 0) {
BT_DBG("Ignore virtual address %s with ref = 0", get);
goto free;
}
lab = get_label(index);
if (lab == NULL) {
BT_WARN("%s, Out of labels buffers", __func__);
err = -ENOBUFS;
goto free;
}
memcpy(lab->uuid, va.uuid, 16);
lab->addr = va.addr;
lab->ref = va.ref;
BT_DBG("Restore virtual address 0x%04x ref 0x%04x", index, lab->ref);
}
free:
bt_mesh_free_buf(buf);
return err;
}
#endif
const struct bt_mesh_setting {
const char *name;
int (*func)(const char *name);
@ -709,6 +778,9 @@ const struct bt_mesh_setting {
{ "mesh/cfg", cfg_set },
{ "mesh/sig", sig_mod_set },
{ "mesh/vnd", vnd_mod_set },
#if CONFIG_BLE_MESH_LABEL_COUNT > 0
{ "mesh/vaddr", va_set },
#endif
};
int settings_core_load(void)
@ -1331,6 +1403,52 @@ static void store_pending_mod(struct bt_mesh_model *model,
}
}
#define IS_VA_DEL(_label) ((_label)->ref == 0)
static void store_pending_va(void)
{
struct va_val va = {0};
char name[16] = {'\0'};
struct label *lab;
u16_t i;
int err;
for (i = 0U; (lab = get_label(i)) != NULL; i++) {
if (!bt_mesh_atomic_test_and_clear_bit(lab->flags,
BLE_MESH_VA_CHANGED)) {
continue;
}
sprintf(name, "mesh/va/%04x", i);
if (IS_VA_DEL(lab)) {
err = bt_mesh_save_core_settings(name, NULL, 0);
} else {
va.ref = lab->ref;
va.addr = lab->addr;
memcpy(va.uuid, lab->uuid, 16);
err = bt_mesh_save_core_settings(name, (const u8_t *)&va, sizeof(va));
}
if (err) {
BT_ERR("%s, Failed to %s virtual address %s", __func__,
IS_VA_DEL(lab) ? "delete" : "store", name);
return;
}
if (IS_VA_DEL(lab)) {
err = bt_mesh_remove_core_settings_item("mesh/vaddr", i);
} else {
err = bt_mesh_add_core_settings_item("mesh/vaddr", i);
}
if (err) {
BT_ERR("%s, Failed to %s 0x%04x in mesh/vaddr", __func__,
IS_VA_DEL(lab) ? "delete" : "store", i);
return;
}
BT_DBG("%s virtual address 0x%04x", IS_VA_DEL(lab) ? "Delete" : "Store", i);
}
}
static void store_pending(struct k_work *work)
{
BT_DBG("%s", __func__);
@ -1386,6 +1504,10 @@ static void store_pending(struct k_work *work)
bt_mesh_save_core_settings("mesh/vnd", NULL, 0);
}
}
if (bt_mesh_atomic_test_and_clear_bit(bt_mesh.flags, BLE_MESH_VA_PENDING)) {
store_pending_va();
}
}
void bt_mesh_store_rpl(struct bt_mesh_rpl *entry)
@ -1570,6 +1692,11 @@ void bt_mesh_store_mod_pub(struct bt_mesh_model *model)
schedule_store(BLE_MESH_MOD_PENDING);
}
void bt_mesh_store_label(void)
{
schedule_store(BLE_MESH_VA_PENDING);
}
int settings_core_init(void)
{
BT_DBG("%s", __func__);

View file

@ -28,6 +28,7 @@ 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_clear_net(void);
void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub);

View file

@ -139,32 +139,30 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu,
net_buf_add_mem(buf, sdu->data, sdu->len);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx,
tx->src, tx->ctx->addr,
NULL, 1)) {
if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
BT_ERR("Not enough space in Friend Queue");
net_buf_unref(buf);
return -ENOBUFS;
} else {
BT_WARN("No space in Friend Queue");
goto send;
}
}
if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE,
NULL, 1, &buf->b) &&
BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
/* PDUs for a specific Friend should only go
* out through the Friend Queue.
*/
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
if (!bt_mesh_friend_queue_has_space(tx->sub->net_idx,
tx->src, tx->ctx->addr,
NULL, 1)) {
if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
BT_ERR("Not enough space in Friend Queue");
net_buf_unref(buf);
send_cb_finalize(cb, cb_data);
return 0;
return -ENOBUFS;
} else {
BT_WARN("No space in Friend Queue");
goto send;
}
}
if (bt_mesh_friend_enqueue_tx(tx, BLE_MESH_FRIEND_PDU_SINGLE,
NULL, 1, &buf->b) &&
BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
/* PDUs for a specific Friend should only go
* out through the Friend Queue.
*/
net_buf_unref(buf);
send_cb_finalize(cb, cb_data);
return 0;
}
}
send:
@ -371,7 +369,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
tx->ttl = net_tx->ctx->send_ttl;
}
seq_zero = tx->seq_auth & 0x1fff;
seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK;
BT_DBG("SeqZero 0x%04x", seq_zero);
@ -413,27 +411,25 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
net_buf_add_mem(seg, sdu->data, len);
net_buf_simple_pull(sdu, len);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
enum bt_mesh_friend_pdu_type type;
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) {
enum bt_mesh_friend_pdu_type type;
if (seg_o == tx->seg_n) {
type = BLE_MESH_FRIEND_PDU_COMPLETE;
} else {
type = BLE_MESH_FRIEND_PDU_PARTIAL;
}
if (seg_o == tx->seg_n) {
type = BLE_MESH_FRIEND_PDU_COMPLETE;
} else {
type = BLE_MESH_FRIEND_PDU_PARTIAL;
}
if (bt_mesh_friend_enqueue_tx(net_tx, type,
&tx->seq_auth,
tx->seg_n + 1,
&seg->b) &&
BLE_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) {
/* PDUs for a specific Friend should only go
* out through the Friend Queue.
*/
net_buf_unref(seg);
continue;
}
if (bt_mesh_friend_enqueue_tx(net_tx, type,
&tx->seq_auth,
tx->seg_n + 1,
&seg->b) &&
BLE_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) {
/* PDUs for a specific Friend should only go
* out through the Friend Queue.
*/
net_buf_unref(seg);
continue;
}
}
@ -461,11 +457,9 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
send_cb_finalize(cb, cb_data);
}
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) &&
bt_mesh_lpn_established()) {
bt_mesh_lpn_poll();
}
if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) &&
bt_mesh_lpn_established()) {
bt_mesh_lpn_poll();
}
return 0;
@ -492,6 +486,7 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
{
const u8_t *key = NULL;
u8_t *ad, role;
u8_t aid;
int err;
if (net_buf_simple_tailroom(msg) < 4) {
@ -513,33 +508,14 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
return -EINVAL;
}
if (tx->ctx->app_idx == BLE_MESH_KEY_DEV) {
key = bt_mesh_tx_devkey_get(role, tx->ctx->addr);
if (!key) {
BT_ERR("%s, Failed to get Device Key", __func__);
return -EINVAL;
}
tx->aid = 0U;
} else {
struct bt_mesh_app_key *app_key = NULL;
app_key = bt_mesh_tx_appkey_get(role, tx->ctx->app_idx, tx->ctx->net_idx);
if (!app_key) {
BT_ERR("%s, Failed to get AppKey", __func__);
return -EINVAL;
}
if (tx->sub->kr_phase == BLE_MESH_KR_PHASE_2 &&
app_key->updated) {
key = app_key->keys[1].val;
tx->aid = app_key->keys[1].id;
} else {
key = app_key->keys[0].val;
tx->aid = app_key->keys[0].id;
}
err = bt_mesh_app_key_get(tx->sub, tx->ctx->app_idx, &key,
&aid, role, tx->ctx->addr);
if (err) {
return err;
}
tx->aid = aid;
if (!tx->ctx->send_rel || net_buf_simple_tailroom(msg) < 8) {
tx->aszmic = 0U;
} else {
@ -780,7 +756,7 @@ static struct seg_tx *seg_tx_lookup(u16_t seq_zero, u8_t obo, u16_t addr)
for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
tx = &seg_tx[i];
if ((tx->seq_auth & 0x1fff) != seq_zero) {
if ((tx->seq_auth & TRANS_SEQ_ZERO_MASK) != seq_zero) {
continue;
}
@ -818,7 +794,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
seq_zero = net_buf_simple_pull_be16(buf);
obo = seq_zero >> 15;
seq_zero = (seq_zero >> 2) & 0x1fff;
seq_zero = (seq_zero >> 2) & TRANS_SEQ_ZERO_MASK;
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match) {
BT_DBG("Ack for LPN 0x%04x of this Friend", rx->ctx.recv_dst);
@ -922,49 +898,47 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
return 0;
}
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) {
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_POLL:
return bt_mesh_friend_poll(rx, buf);
case TRANS_CTL_OP_FRIEND_REQ:
return bt_mesh_friend_req(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR:
return bt_mesh_friend_clear(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR_CFM:
return bt_mesh_friend_clear_cfm(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_ADD:
return bt_mesh_friend_sub_add(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_REM:
return bt_mesh_friend_sub_rem(rx, buf);
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) {
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_POLL:
return bt_mesh_friend_poll(rx, buf);
case TRANS_CTL_OP_FRIEND_REQ:
return bt_mesh_friend_req(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR:
return bt_mesh_friend_clear(rx, buf);
case TRANS_CTL_OP_FRIEND_CLEAR_CFM:
return bt_mesh_friend_clear_cfm(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_ADD:
return bt_mesh_friend_sub_add(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_REM:
return bt_mesh_friend_sub_rem(rx, buf);
}
}
#if defined(CONFIG_BLE_MESH_LOW_POWER)
if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) {
return bt_mesh_lpn_friend_offer(rx, buf);
}
if (rx->ctx.addr == bt_mesh.lpn.frnd) {
if (ctl_op == TRANS_CTL_OP_FRIEND_CLEAR_CFM) {
return bt_mesh_lpn_friend_clear_cfm(rx, buf);
}
if (!rx->friend_cred) {
BT_WARN("Message from friend with wrong credentials");
return -EINVAL;
}
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_UPDATE:
return bt_mesh_lpn_friend_update(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_CFM:
return bt_mesh_lpn_friend_sub_cfm(rx, buf);
}
}
#endif /* CONFIG_BLE_MESH_LOW_POWER */
if (ctl_op == TRANS_CTL_OP_FRIEND_OFFER) {
return bt_mesh_lpn_friend_offer(rx, buf);
}
if (rx->ctx.addr == bt_mesh.lpn.frnd) {
if (ctl_op == TRANS_CTL_OP_FRIEND_CLEAR_CFM) {
return bt_mesh_lpn_friend_clear_cfm(rx, buf);
}
if (!rx->friend_cred) {
BT_WARN("Message from friend with wrong credentials");
return -EINVAL;
}
switch (ctl_op) {
case TRANS_CTL_OP_FRIEND_UPDATE:
return bt_mesh_lpn_friend_update(rx, buf);
case TRANS_CTL_OP_FRIEND_SUB_CFM:
return bt_mesh_lpn_friend_sub_cfm(rx, buf);
}
}
#endif /* CONFIG_BLE_MESH_LOW_POWER */
BT_WARN("Unhandled TransOpCode 0x%02x", ctl_op);
return -ENOENT;
@ -1079,7 +1053,7 @@ 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 & 0x1fff;
u16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK;
u8_t buf[6];
BT_DBG("SeqZero 0x%04x Block 0x%08x OBO %u", seq_zero, block, obo);
@ -1287,7 +1261,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
seq_zero = net_buf_simple_pull_be16(buf);
seg_o = (seq_zero & 0x03) << 3;
seq_zero = (seq_zero >> 2) & 0x1fff;
seq_zero = (seq_zero >> 2) & TRANS_SEQ_ZERO_MASK;
seg_n = net_buf_simple_pull_u8(buf);
seg_o |= seg_n >> 5;
seg_n &= 0x1f;
@ -1499,13 +1473,11 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
* requested the Friend to send them. The messages must also
* be encrypted using the Friend Credentials.
*/
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) &&
bt_mesh_lpn_established() && rx->net_if == BLE_MESH_NET_IF_ADV &&
(!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) {
BT_WARN("Ignoring unexpected message in Low Power mode");
return -EAGAIN;
}
if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) &&
bt_mesh_lpn_established() && rx->net_if == BLE_MESH_NET_IF_ADV &&
(!bt_mesh_lpn_waiting_update() || !rx->friend_cred)) {
BT_WARN("Ignoring unexpected message in Low Power mode");
return -EAGAIN;
}
/* Save the app-level state so the buffer can later be placed in
@ -1538,25 +1510,21 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx)
* timer, in which case we want to reset the timer at this point.
*
*/
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) &&
(bt_mesh_lpn_timer() ||
(bt_mesh_lpn_established() && bt_mesh_lpn_waiting_update()))) {
bt_mesh_lpn_msg_received(rx);
}
if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) &&
(bt_mesh_lpn_timer() ||
(bt_mesh_lpn_established() && bt_mesh_lpn_waiting_update()))) {
bt_mesh_lpn_msg_received(rx);
}
net_buf_simple_restore(buf, &state);
if (IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) {
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) {
if (seq_auth == TRANS_SEQ_AUTH_NVAL) {
bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL,
seg_count, buf);
} else {
bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth,
seg_count, buf);
}
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->friend_match && !err) {
if (seq_auth == TRANS_SEQ_AUTH_NVAL) {
bt_mesh_friend_enqueue_rx(rx, pdu_type, NULL,
seg_count, buf);
} else {
bt_mesh_friend_enqueue_rx(rx, pdu_type, &seq_auth,
seg_count, buf);
}
}
@ -1664,3 +1632,41 @@ void bt_mesh_heartbeat_send(void)
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
NULL, NULL, NULL);
}
int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
const u8_t **key, u8_t *aid, u8_t role, u16_t dst)
{
struct bt_mesh_app_key *app_key;
if (app_idx == BLE_MESH_KEY_DEV) {
*key = bt_mesh_tx_devkey_get(role, dst);
if (!*key) {
BT_ERR("%s, Failed to get Device Key", __func__);
return -EINVAL;
}
*aid = 0U;
return 0;
}
if (!subnet) {
BT_ERR("%s, Invalid subnet", __func__);
return -EINVAL;
}
app_key = bt_mesh_tx_appkey_get(role, app_idx, subnet->net_idx);
if (!app_key) {
BT_ERR("%s, Failed to get AppKey", __func__);
return -ENOENT;
}
if (subnet->kr_phase == BLE_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 0;
}

View file

@ -14,6 +14,7 @@
#define BLE_MESH_TX_SDU_MAX (CONFIG_BLE_MESH_TX_SEG_MAX * 12)
#define TRANS_SEQ_ZERO_MASK ((u16_t)BIT_MASK(13))
#define TRANS_CTL_OP_MASK ((u8_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))
@ -101,4 +102,7 @@ void bt_mesh_rpl_clear(void);
void bt_mesh_heartbeat_send(void);
int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
const u8_t **key, u8_t *aid, u8_t role, u16_t dst);
#endif /* _TRANSPORT_H_ */