Bluetooth: Mesh: Fix model publication
Model publication was broken in a couple of ways: - The Publish Retransmit State was not taken into account at all - Health Server used a single publish state for all elements To implement Publish Retransmit properly, one has to use a callback to track when the message has been sent. The problem with the transport layer sending APIs was that giving a callback would cause the transport layer to assume that segmentation (with acks) is desired, which is not the case for Model Publication (unless the message itself is too large, of course). Because of this, the message sending context receives a new send_rel ("Send Reliable") boolean member that an app can use to force reliable sending. Another challenge with the Publish Retransmit state is that a buffer is needed for storing the AppKey-encrypted SDU once it has been sent out for the first time.To solve this, a new new net_buf_simple member is added to the model publication context. The separate 'msg' input parameter of the bt_mesh_model_publish() API is removed, since the application is now expected to pre-fill pub->msg instead. To help with the publishing API change, the Health Server model gets a new helper macro for initializing the publishing context with a right-sized publishing message. The API for creating Health Server instances is also redesigned since it was so far using a single model publishing state, which would result in erratic behavior in case of multiple elements with the Health Server Model. Now, the application needs to provide a unique publishing context for each Health Server instance. The changes are heavily intertwined, so it's not easily possible to split them into multiple patches, hence the large(ish) patch. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
f9fad553ac
commit
e7bb76e2b6
14 changed files with 358 additions and 185 deletions
|
@ -131,7 +131,10 @@ struct bt_mesh_msg_ctx {
|
|||
u16_t addr;
|
||||
|
||||
/** Received TTL value. Not used for sending. */
|
||||
u8_t recv_ttl;
|
||||
u8_t recv_ttl:7;
|
||||
|
||||
/** Force sending reliably by using segment acknowledgement */
|
||||
u8_t send_rel:1;
|
||||
|
||||
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
|
||||
u8_t send_ttl;
|
||||
|
@ -264,7 +267,11 @@ struct bt_mesh_model_pub {
|
|||
u8_t retransmit; /* Retransmit Count & Interval Steps */
|
||||
u8_t period; /* Publish Period */
|
||||
u8_t period_div:4, /* Divisor for the Period */
|
||||
cred:1; /* Friendship Credentials Flag */
|
||||
cred:1, /* Friendship Credentials Flag */
|
||||
count:3; /* Retransmissions left */
|
||||
|
||||
/* Buffer containing the publication message */
|
||||
struct net_buf_simple *msg;
|
||||
|
||||
/* Publish callback */
|
||||
void (*func)(struct bt_mesh_model *mod);
|
||||
|
@ -334,13 +341,15 @@ int bt_mesh_model_send(struct bt_mesh_model *model,
|
|||
/**
|
||||
* @brief Send a model publication message.
|
||||
*
|
||||
* Before calling this function, the user needs to ensure that the model
|
||||
* publication message ('msg' member of struct bt_mesh_model_pub) contains
|
||||
* a valid message to be sent.
|
||||
*
|
||||
* @param model Mesh (client) Model that's publishing the message.
|
||||
* @param msg Access Layer message to publish.
|
||||
*
|
||||
* @return 0 on success, or (negative) error code on failure.
|
||||
*/
|
||||
int bt_mesh_model_publish(struct bt_mesh_model *model,
|
||||
struct net_buf_simple *msg);
|
||||
int bt_mesh_model_publish(struct bt_mesh_model *model);
|
||||
|
||||
/** Node Composition */
|
||||
struct bt_mesh_comp {
|
||||
|
|
|
@ -17,10 +17,7 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/** Mesh Health Server Model Context */
|
||||
struct bt_mesh_health_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
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,
|
||||
|
@ -38,23 +35,54 @@ struct bt_mesh_health_srv {
|
|||
int (*fault_test)(struct bt_mesh_model *model, u8_t test_id,
|
||||
u16_t company_id);
|
||||
|
||||
/* Attention on */
|
||||
void (*attn_on)(struct bt_mesh_model *model);
|
||||
|
||||
/* Attention off */
|
||||
void (*attn_off)(struct bt_mesh_model *model);
|
||||
};
|
||||
|
||||
/** @def BT_MESH_HEALTH_FAULT_MSG
|
||||
*
|
||||
* A helper to define a health fault message.
|
||||
*
|
||||
* @param max_faults Maximum number of faults the element can have.
|
||||
*
|
||||
* @return a New net_buf_simple of the needed size.
|
||||
*/
|
||||
#define BT_MESH_HEALTH_FAULT_MSG(max_faults) \
|
||||
NET_BUF_SIMPLE(1 + 3 + (max_faults))
|
||||
|
||||
/** Mesh Health Server Model Context */
|
||||
struct bt_mesh_health_srv {
|
||||
struct bt_mesh_model *model;
|
||||
|
||||
/* Optional callback struct */
|
||||
const struct bt_mesh_health_srv_cb *cb;
|
||||
|
||||
/* Attention Timer state */
|
||||
struct {
|
||||
struct k_delayed_work timer;
|
||||
void (*on)(struct bt_mesh_model *model);
|
||||
void (*off)(struct bt_mesh_model *model);
|
||||
} attention;
|
||||
struct k_delayed_work attn_timer;
|
||||
};
|
||||
|
||||
int bt_mesh_fault_update(struct bt_mesh_elem *elem);
|
||||
|
||||
extern const struct bt_mesh_model_op bt_mesh_health_srv_op[];
|
||||
extern struct bt_mesh_model_pub bt_mesh_health_pub;
|
||||
|
||||
#define BT_MESH_MODEL_HEALTH_SRV(srv_data) \
|
||||
/** @def BT_MESH_MODEL_HEALTH_SRV
|
||||
*
|
||||
* Define a new health server model. Note that this API needs to be
|
||||
* repeated for each element that the application wants to have a
|
||||
* health server model on. Each instance also needs a unique
|
||||
* bt_mesh_health_srv and bt_mesh_model_pub context.
|
||||
*
|
||||
* @param srv Pointer to a unique struct bt_mesh_health_srv.
|
||||
* @param pub Pointer to a unique struct bt_mesh_model_pub.
|
||||
*
|
||||
* @return New mesh model instance.
|
||||
*/
|
||||
#define BT_MESH_MODEL_HEALTH_SRV(srv, pub) \
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_HEALTH_SRV, \
|
||||
bt_mesh_health_srv_op, &bt_mesh_health_pub, \
|
||||
srv_data)
|
||||
bt_mesh_health_srv_op, pub, srv)
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
|
|
@ -38,6 +38,10 @@ static struct bt_mesh_cfg_srv cfg_srv = {
|
|||
static struct bt_mesh_health_srv health_srv = {
|
||||
};
|
||||
|
||||
static struct bt_mesh_model_pub health_pub = {
|
||||
.msg = BT_MESH_HEALTH_FAULT_MSG(0),
|
||||
};
|
||||
|
||||
static struct bt_mesh_model_pub gen_level_pub;
|
||||
static struct bt_mesh_model_pub gen_onoff_pub;
|
||||
|
||||
|
@ -121,7 +125,7 @@ static const struct bt_mesh_model_op gen_level_op[] = {
|
|||
|
||||
static struct bt_mesh_model root_models[] = {
|
||||
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv),
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_op,
|
||||
&gen_onoff_pub, NULL),
|
||||
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, gen_level_op,
|
||||
|
|
|
@ -86,15 +86,23 @@ static void attention_off(struct bt_mesh_model *model)
|
|||
board_attention(false);
|
||||
}
|
||||
|
||||
static const struct bt_mesh_health_srv_cb health_srv_cb = {
|
||||
.attn_on = attention_on,
|
||||
.attn_off = attention_off,
|
||||
};
|
||||
|
||||
static struct bt_mesh_health_srv health_srv = {
|
||||
.attention.on = attention_on,
|
||||
.attention.off = attention_off,
|
||||
.cb = &health_srv_cb,
|
||||
};
|
||||
|
||||
static struct bt_mesh_model_pub health_pub = {
|
||||
.msg = BT_MESH_HEALTH_FAULT_MSG(0),
|
||||
};
|
||||
|
||||
static struct bt_mesh_model root_models[] = {
|
||||
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
|
||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv),
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
|
||||
};
|
||||
|
||||
static void vnd_publish(struct bt_mesh_model *mod)
|
||||
|
|
|
@ -97,6 +97,62 @@ s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
|
|||
return period >> mod->pub->period_div;
|
||||
}
|
||||
|
||||
static void publish_sent(int err, void *user_data)
|
||||
{
|
||||
struct bt_mesh_model *mod = user_data;
|
||||
s32_t delay;
|
||||
|
||||
BT_DBG("err %d", err);
|
||||
|
||||
if (mod->pub->count) {
|
||||
delay = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit);
|
||||
} else {
|
||||
delay = bt_mesh_model_pub_period_get(mod);
|
||||
}
|
||||
|
||||
BT_DBG("Publishing next time in %dms", delay);
|
||||
|
||||
k_delayed_work_submit(&mod->pub->timer, delay);
|
||||
}
|
||||
|
||||
static const struct bt_mesh_send_cb pub_sent_cb = {
|
||||
.end = publish_sent,
|
||||
};
|
||||
|
||||
static int publish_retransmit(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct net_buf_simple *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,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.ctx = &ctx,
|
||||
.src = mod->elem->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = pub->cred,
|
||||
};
|
||||
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
if (!key) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
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->data, pub->msg->len);
|
||||
|
||||
pub->count--;
|
||||
|
||||
return bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod);
|
||||
}
|
||||
|
||||
static void mod_publish(struct k_work *work)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = CONTAINER_OF(work,
|
||||
|
@ -108,12 +164,36 @@ static void mod_publish(struct k_work *work)
|
|||
|
||||
period_ms = bt_mesh_model_pub_period_get(pub->mod);
|
||||
BT_DBG("period %u ms", period_ms);
|
||||
|
||||
if (pub->count) {
|
||||
int err;
|
||||
|
||||
err = publish_retransmit(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("Failed to retransmit (err %d)", err);
|
||||
|
||||
pub->count = 0;
|
||||
|
||||
/* Continue with normal publication */
|
||||
if (period_ms) {
|
||||
k_delayed_work_submit(&pub->timer, period_ms);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (period_ms) {
|
||||
k_delayed_work_submit(&pub->timer, period_ms);
|
||||
}
|
||||
|
||||
if (pub->func) {
|
||||
pub->func(pub->mod);
|
||||
|
||||
if (pub->count) {
|
||||
/* Retransmissions also control the timer */
|
||||
k_delayed_work_cancel(&pub->timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,26 +520,13 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, u32_t opcode)
|
|||
net_buf_simple_add_le16(msg, opcode & 0xffff);
|
||||
}
|
||||
|
||||
/* Send using Friendship credentials */
|
||||
#define FRIEND_CRED BIT(0)
|
||||
/* Assume AppKey binding to be implicit */
|
||||
#define IMPLICIT_BIND BIT(1)
|
||||
|
||||
static int model_send(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
int flags, struct net_buf_simple *msg,
|
||||
struct bt_mesh_net_tx *tx, bool implicit_bind,
|
||||
struct net_buf_simple *msg,
|
||||
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 = model->elem->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = !!(flags & FRIEND_CRED),
|
||||
};
|
||||
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", ctx->net_idx,
|
||||
ctx->app_idx, ctx->addr);
|
||||
BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->ctx->net_idx,
|
||||
tx->ctx->app_idx, tx->ctx->addr);
|
||||
BT_DBG("len %u: %s", msg->len, bt_hex(msg->data, msg->len));
|
||||
|
||||
if (!bt_mesh_is_provisioned()) {
|
||||
|
@ -477,12 +544,12 @@ static int model_send(struct bt_mesh_model *model,
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (!(flags & IMPLICIT_BIND) && !model_has_key(model, ctx->app_idx)) {
|
||||
BT_ERR("Model not bound to AppKey 0x%04x", ctx->app_idx);
|
||||
if (!implicit_bind && !model_has_key(model, tx->ctx->app_idx)) {
|
||||
BT_ERR("Model not bound to AppKey 0x%04x", tx->ctx->app_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bt_mesh_trans_send(&tx, msg, cb, cb_data);
|
||||
return bt_mesh_trans_send(tx, msg, cb, cb_data);
|
||||
}
|
||||
|
||||
int bt_mesh_model_send(struct bt_mesh_model *model,
|
||||
|
@ -490,47 +557,79 @@ int bt_mesh_model_send(struct bt_mesh_model *model,
|
|||
struct net_buf_simple *msg,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
return model_send(model, ctx, 0, msg, cb, cb_data);
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = bt_mesh_subnet_get(ctx->net_idx),
|
||||
.ctx = ctx,
|
||||
.src = model->elem->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = 0,
|
||||
};
|
||||
|
||||
return model_send(model, &tx, false, msg, cb, cb_data);
|
||||
}
|
||||
|
||||
int bt_mesh_model_publish(struct bt_mesh_model *model,
|
||||
struct net_buf_simple *msg)
|
||||
int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
{
|
||||
struct net_buf_simple *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;
|
||||
int flags;
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.addr = pub->addr,
|
||||
.send_ttl = pub->ttl,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.ctx = &ctx,
|
||||
.src = model->elem->addr,
|
||||
.xmit = bt_mesh_net_transmit_get(),
|
||||
.friend_cred = model->pub->cred,
|
||||
};
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
if (!model->pub) {
|
||||
if (!pub) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (model->pub->key == BT_MESH_KEY_UNUSED ||
|
||||
model->pub->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
if (pub->addr == BT_MESH_ADDR_UNASSIGNED) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
key = bt_mesh_app_key_find(model->pub->key);
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
if (!key) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
ctx.addr = model->pub->addr;
|
||||
ctx.send_ttl = model->pub->ttl;
|
||||
|
||||
/* Model Publication isn't required to have an explicit
|
||||
* AppKey binding for the publication's AppKey Index.
|
||||
*/
|
||||
flags = IMPLICIT_BIND;
|
||||
|
||||
if (model->pub->cred) {
|
||||
flags |= FRIEND_CRED;
|
||||
if (pub->msg->len + 4 > BT_MESH_TX_SDU_MAX) {
|
||||
BT_ERR("Message does not fit maximum SDU size");
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
return model_send(model, &ctx, flags, msg, NULL, NULL);
|
||||
if (pub->count) {
|
||||
BT_WARN("Clearing publish retransmit timer");
|
||||
k_delayed_work_cancel(&pub->timer);
|
||||
}
|
||||
|
||||
net_buf_simple_init(sdu, 0);
|
||||
net_buf_simple_add_mem(sdu, pub->msg->data, pub->msg->len);
|
||||
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
|
||||
tx.sub = bt_mesh_subnet_get(ctx.net_idx),
|
||||
|
||||
pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
|
||||
|
||||
BT_DBG("Publish Retransmit Count %u Interval %ums", pub->count,
|
||||
BT_MESH_PUB_TRANSMIT_INT(pub->retransmit));
|
||||
|
||||
err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
|
||||
if (err) {
|
||||
pub->count = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bt_mesh_model *bt_mesh_model_find_vnd(struct bt_mesh_elem *elem,
|
||||
|
|
|
@ -262,6 +262,7 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
|
|||
model->pub->ttl = 0;
|
||||
model->pub->period = 0;
|
||||
model->pub->retransmit = 0;
|
||||
model->pub->count = 0;
|
||||
|
||||
if (model->pub->func) {
|
||||
k_delayed_work_cancel(&model->pub->timer);
|
||||
|
@ -343,7 +344,7 @@ static u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx)
|
|||
|
||||
if (model->pub && model->pub->key == key_idx) {
|
||||
_mod_pub_set(model, BT_MESH_ADDR_UNASSIGNED,
|
||||
BT_MESH_KEY_UNUSED, 0, 0, 0, 0);
|
||||
0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "crypto.h"
|
||||
|
||||
#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])
|
||||
|
@ -679,15 +680,13 @@ static void create_app_nonce(u8_t nonce[13], bool dev_key, u8_t aszmic,
|
|||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct net_buf_simple *buf, const u8_t *ad,
|
||||
u8_t mic_len, u16_t src, u16_t dst,
|
||||
u32_t seq_num, u32_t iv_index)
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
|
||||
{
|
||||
u8_t nonce[13];
|
||||
int err;
|
||||
|
||||
BT_DBG("AppKey %s", bt_hex(key, 16));
|
||||
BT_DBG("dev_key %u mic_len %u src 0x%04x dst 0x%04x", dev_key,
|
||||
mic_len, src, dst);
|
||||
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", seq_num, iv_index);
|
||||
BT_DBG("Clear: %s", bt_hex(buf->data, buf->len));
|
||||
|
||||
|
@ -696,9 +695,9 @@ int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
|||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_ccm_encrypt(key, nonce, buf->data, buf->len, ad,
|
||||
ad ? 16 : 0, buf->data, mic_len);
|
||||
ad ? 16 : 0, buf->data, APP_MIC_LEN(aszmic));
|
||||
if (!err) {
|
||||
net_buf_simple_add(buf, mic_len);
|
||||
net_buf_simple_add(buf, APP_MIC_LEN(aszmic));
|
||||
BT_DBG("Encr: %s", bt_hex(buf->data, buf->len));
|
||||
}
|
||||
|
||||
|
@ -706,9 +705,8 @@ int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
|||
}
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct net_buf_simple *buf, u8_t mic_len,
|
||||
struct net_buf_simple *out, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num,
|
||||
struct net_buf_simple *buf, struct net_buf_simple *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index)
|
||||
{
|
||||
u8_t nonce[13];
|
||||
|
@ -722,7 +720,7 @@ int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
|||
BT_DBG("Nonce %s", bt_hex(nonce, 13));
|
||||
|
||||
err = bt_mesh_ccm_decrypt(key, nonce, buf->data, buf->len, ad,
|
||||
ad ? 16 : 0, out->data, mic_len);
|
||||
ad ? 16 : 0, out->data, APP_MIC_LEN(aszmic));
|
||||
if (!err) {
|
||||
net_buf_simple_add(out, buf->len);
|
||||
}
|
||||
|
|
|
@ -129,13 +129,11 @@ int bt_mesh_net_decrypt(const u8_t key[16], struct net_buf_simple *buf,
|
|||
|
||||
int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct net_buf_simple *buf, const u8_t *ad,
|
||||
u8_t mic_len, u16_t src, u16_t dst,
|
||||
u32_t seq_num, u32_t iv_index);
|
||||
u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index);
|
||||
|
||||
int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
|
||||
struct net_buf_simple *buf, u8_t mic_len,
|
||||
struct net_buf_simple *out, const u8_t *ad,
|
||||
u16_t src, u16_t dst, u32_t seq_num,
|
||||
struct net_buf_simple *buf, struct net_buf_simple *out,
|
||||
const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
|
||||
u32_t iv_index);
|
||||
|
||||
u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len);
|
||||
|
|
|
@ -29,16 +29,6 @@
|
|||
|
||||
#define HEALTH_TEST_STANDARD 0x00
|
||||
|
||||
/* Increasing this requires also increasing the system workqueue */
|
||||
#define MAX_FAULTS 32
|
||||
#define HEALTH_STATUS_SIZE_MAX (1 + 3 + MAX_FAULTS + 4)
|
||||
|
||||
#if BT_MESH_TX_SDU_MAX < HEALTH_STATUS_SIZE_MAX
|
||||
#define HEALTH_STATUS_SIZE BT_MESH_TX_SDU_MAX
|
||||
#else
|
||||
#define HEALTH_STATUS_SIZE HEALTH_STATUS_SIZE_MAX
|
||||
#endif
|
||||
|
||||
/* Health Server context of the primary element */
|
||||
struct bt_mesh_health_srv *health_srv;
|
||||
|
||||
|
@ -59,10 +49,10 @@ static void health_get_registered(struct bt_mesh_model *mod,
|
|||
net_buf_simple_add_le16(msg, company_id);
|
||||
fault_count = net_buf_simple_tailroom(msg) - 4;
|
||||
|
||||
if (srv->fault_get_reg) {
|
||||
err = srv->fault_get_reg(mod, company_id, test_id,
|
||||
net_buf_simple_tail(msg),
|
||||
&fault_count);
|
||||
if (srv->cb && srv->cb->fault_get_reg) {
|
||||
err = srv->cb->fault_get_reg(mod, company_id, test_id,
|
||||
net_buf_simple_tail(msg),
|
||||
&fault_count);
|
||||
if (err) {
|
||||
BT_ERR("Failed to get faults (err %d)", err);
|
||||
*test_id = HEALTH_TEST_STANDARD;
|
||||
|
@ -93,10 +83,10 @@ static size_t health_get_current(struct bt_mesh_model *mod,
|
|||
|
||||
fault_count = net_buf_simple_tailroom(msg) - 4;
|
||||
|
||||
if (srv->fault_get_cur) {
|
||||
err = srv->fault_get_cur(mod, test_id, &company_id,
|
||||
net_buf_simple_tail(msg),
|
||||
&fault_count);
|
||||
if (srv->cb && srv->cb->fault_get_cur) {
|
||||
err = srv->cb->fault_get_cur(mod, test_id, &company_id,
|
||||
net_buf_simple_tail(msg),
|
||||
&fault_count);
|
||||
if (err) {
|
||||
BT_ERR("Failed to get faults (err %d)", err);
|
||||
sys_put_le16(comp->cid, company_ptr);
|
||||
|
@ -120,16 +110,16 @@ static void health_fault_get(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(HEALTH_STATUS_SIZE);
|
||||
struct net_buf_simple *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
u16_t company_id;
|
||||
|
||||
company_id = net_buf_simple_pull_le16(buf);
|
||||
|
||||
BT_DBG("company_id 0x%04x", company_id);
|
||||
|
||||
health_get_registered(model, company_id, msg);
|
||||
health_get_registered(model, company_id, sdu);
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
|
||||
if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
||||
BT_ERR("Unable to send Health Current Status response");
|
||||
}
|
||||
}
|
||||
|
@ -145,8 +135,8 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model,
|
|||
|
||||
BT_DBG("company_id 0x%04x", company_id);
|
||||
|
||||
if (srv->fault_clear) {
|
||||
srv->fault_clear(model, company_id);
|
||||
if (srv->cb && srv->cb->fault_clear) {
|
||||
srv->cb->fault_clear(model, company_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,7 +144,7 @@ static void health_fault_clear(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(HEALTH_STATUS_SIZE);
|
||||
struct net_buf_simple *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
|
||||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u16_t company_id;
|
||||
|
||||
|
@ -162,13 +152,13 @@ static void health_fault_clear(struct bt_mesh_model *model,
|
|||
|
||||
BT_DBG("company_id 0x%04x", company_id);
|
||||
|
||||
if (srv->fault_clear) {
|
||||
srv->fault_clear(model, company_id);
|
||||
if (srv->cb && srv->cb->fault_clear) {
|
||||
srv->cb->fault_clear(model, company_id);
|
||||
}
|
||||
|
||||
health_get_registered(model, company_id, msg);
|
||||
health_get_registered(model, company_id, sdu);
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
|
||||
if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
||||
BT_ERR("Unable to send Health Current Status response");
|
||||
}
|
||||
}
|
||||
|
@ -194,8 +184,8 @@ static void health_fault_test_unrel(struct bt_mesh_model *model,
|
|||
return;
|
||||
}
|
||||
|
||||
if (srv->fault_test) {
|
||||
srv->fault_test(model, test_id, company_id);
|
||||
if (srv->cb && srv->cb->fault_test) {
|
||||
srv->cb->fault_test(model, test_id, company_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +193,7 @@ static void health_fault_test(struct bt_mesh_model *model,
|
|||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(HEALTH_STATUS_SIZE);
|
||||
struct net_buf_simple *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;
|
||||
|
@ -215,19 +205,19 @@ static void health_fault_test(struct bt_mesh_model *model,
|
|||
|
||||
BT_DBG("test 0x%02x company 0x%04x", test_id, company_id);
|
||||
|
||||
if (srv->fault_test) {
|
||||
if (srv->cb && srv->cb->fault_test) {
|
||||
int err;
|
||||
|
||||
err = srv->fault_test(model, test_id, company_id);
|
||||
err = srv->cb->fault_test(model, test_id, company_id);
|
||||
if (err) {
|
||||
BT_WARN("Running fault test failed with err %d", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
health_get_registered(model, company_id, msg);
|
||||
health_get_registered(model, company_id, sdu);
|
||||
|
||||
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
|
||||
if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) {
|
||||
BT_ERR("Unable to send Health Current Status response");
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +230,7 @@ static void send_attention_status(struct bt_mesh_model *model,
|
|||
struct bt_mesh_health_srv *srv = model->user_data;
|
||||
u8_t time;
|
||||
|
||||
time = k_delayed_work_remaining_get(&srv->attention.timer) / 1000;
|
||||
time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000;
|
||||
BT_DBG("%u second%s", time, (time == 1) ? "" : "s");
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_ATTENTION_STATUS);
|
||||
|
@ -350,27 +340,23 @@ const struct bt_mesh_model_op bt_mesh_health_srv_op[] = {
|
|||
|
||||
static void health_pub(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct net_buf_simple *msg = NET_BUF_SIMPLE(HEALTH_STATUS_SIZE);
|
||||
struct bt_mesh_model_pub *pub = mod->pub;
|
||||
size_t count;
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
count = health_get_current(mod, msg);
|
||||
count = health_get_current(mod, pub->msg);
|
||||
if (!count) {
|
||||
mod->pub->period_div = 0;
|
||||
pub->period_div = 0;
|
||||
}
|
||||
|
||||
err = bt_mesh_model_publish(mod, msg);
|
||||
err = bt_mesh_model_publish(mod);
|
||||
if (err) {
|
||||
BT_ERR("Publishing failed (err %d)", err);
|
||||
}
|
||||
}
|
||||
|
||||
struct bt_mesh_model_pub bt_mesh_health_pub = {
|
||||
.func = health_pub,
|
||||
};
|
||||
|
||||
int bt_mesh_fault_update(struct bt_mesh_elem *elem)
|
||||
{
|
||||
struct bt_mesh_model *mod;
|
||||
|
@ -388,11 +374,11 @@ static void attention_off(struct k_work *work)
|
|||
{
|
||||
struct bt_mesh_health_srv *srv = CONTAINER_OF(work,
|
||||
struct bt_mesh_health_srv,
|
||||
attention.timer.work);
|
||||
attn_timer.work);
|
||||
BT_DBG("");
|
||||
|
||||
if (srv->attention.off) {
|
||||
srv->attention.off(srv->model);
|
||||
if (srv->cb && srv->cb->attn_off) {
|
||||
srv->cb->attn_off(srv->model);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,7 +395,14 @@ int bt_mesh_health_srv_init(struct bt_mesh_model *model, bool primary)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
k_delayed_work_init(&srv->attention.timer, attention_off);
|
||||
if (!model->pub) {
|
||||
BT_ERR("Health Server has no publication support");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
model->pub->func = health_pub,
|
||||
|
||||
k_delayed_work_init(&srv->attn_timer, attention_off);
|
||||
|
||||
srv->model = model;
|
||||
|
||||
|
@ -437,16 +430,16 @@ void bt_mesh_attention(struct bt_mesh_model *model, u8_t time)
|
|||
}
|
||||
|
||||
if (time) {
|
||||
if (srv->attention.on) {
|
||||
srv->attention.on(model);
|
||||
if (srv->cb && srv->cb->attn_on) {
|
||||
srv->cb->attn_on(model);
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&srv->attention.timer, time * 1000);
|
||||
k_delayed_work_submit(&srv->attn_timer, time * 1000);
|
||||
} else {
|
||||
k_delayed_work_cancel(&srv->attention.timer);
|
||||
k_delayed_work_cancel(&srv->attn_timer);
|
||||
|
||||
if (srv->attention.off) {
|
||||
srv->attention.off(model);
|
||||
if (srv->cb && srv->cb->attn_off) {
|
||||
srv->cb->attn_off(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -776,14 +776,14 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf,
|
|||
idx, &nid, &enc, &priv)) {
|
||||
BT_WARN("Falling back to master credentials");
|
||||
|
||||
tx->friend_cred = false;
|
||||
tx->friend_cred = 0;
|
||||
|
||||
nid = tx->sub->keys[idx].nid;
|
||||
enc = tx->sub->keys[idx].enc;
|
||||
priv = tx->sub->keys[idx].privacy;
|
||||
}
|
||||
} else {
|
||||
tx->friend_cred = false;
|
||||
tx->friend_cred = 0;
|
||||
nid = tx->sub->keys[idx].nid;
|
||||
enc = tx->sub->keys[idx].enc;
|
||||
priv = tx->sub->keys[idx].privacy;
|
||||
|
|
|
@ -257,7 +257,9 @@ struct bt_mesh_net_tx {
|
|||
struct bt_mesh_msg_ctx *ctx;
|
||||
u16_t src;
|
||||
u8_t xmit;
|
||||
bool friend_cred;
|
||||
u8_t friend_cred:1,
|
||||
aszmic:1,
|
||||
aid:6;
|
||||
};
|
||||
|
||||
extern struct bt_mesh_net bt_mesh;
|
||||
|
|
|
@ -58,6 +58,10 @@ static struct bt_mesh_cfg_srv cfg_srv = {
|
|||
static struct bt_mesh_health_srv health_srv = {
|
||||
};
|
||||
|
||||
static struct bt_mesh_model_pub health_pub = {
|
||||
.msg = BT_MESH_HEALTH_FAULT_MSG(0),
|
||||
};
|
||||
|
||||
static struct bt_mesh_cfg_cli cfg_cli = {
|
||||
};
|
||||
|
||||
|
@ -66,7 +70,7 @@ static const u8_t dev_uuid[16] = { 0xdd, 0xdd };
|
|||
static struct bt_mesh_model root_models[] = {
|
||||
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
|
||||
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv),
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
|
||||
};
|
||||
|
||||
static struct bt_mesh_elem elements[] = {
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
#define SEG(data) ((data)[0] >> 7)
|
||||
#define AKF(data) (((data)[0] >> 6) & 0x01)
|
||||
#define AID(data) ((data)[0] & AID_MASK)
|
||||
#define MIC_SIZE(data) (((data)[1] & 0x80) ? 8 : 4)
|
||||
#define ASZMIC(data) (((data)[1] >> 7) & 1)
|
||||
|
||||
#define SZMIC(mic_len) (mic_len == 8 ? 1 : 0)
|
||||
#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
|
||||
|
||||
#define UNSEG_HDR(akf, aid) ((akf << 6) | (aid & AID_MASK))
|
||||
#define SEG_HDR(akf, aid) (UNSEG_HDR(akf, aid) | 0x80)
|
||||
|
@ -98,8 +98,7 @@ void bt_mesh_set_hb_sub_dst(u16_t addr)
|
|||
hb_sub_dst = addr;
|
||||
}
|
||||
|
||||
static int send_unseg(struct bt_mesh_net_tx *tx, u8_t aid,
|
||||
struct net_buf_simple *sdu,
|
||||
static int send_unseg(struct bt_mesh_net_tx *tx, struct net_buf_simple *sdu,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
|
@ -120,7 +119,7 @@ static int send_unseg(struct bt_mesh_net_tx *tx, u8_t aid,
|
|||
if (tx->ctx->app_idx == BT_MESH_KEY_DEV) {
|
||||
net_buf_add_u8(buf, UNSEG_HDR(0, 0));
|
||||
} else {
|
||||
net_buf_add_u8(buf, UNSEG_HDR(1, aid));
|
||||
net_buf_add_u8(buf, UNSEG_HDR(1, tx->aid));
|
||||
}
|
||||
|
||||
net_buf_add_mem(buf, sdu->data, sdu->len);
|
||||
|
@ -251,8 +250,7 @@ static void seg_retransmit(struct k_work *work)
|
|||
seg_tx_send_unacked(tx);
|
||||
}
|
||||
|
||||
static int send_seg(struct bt_mesh_net_tx *net_tx, u8_t aid,
|
||||
u8_t mic_len, struct net_buf_simple *sdu,
|
||||
static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
u8_t seg_hdr, seg_o;
|
||||
|
@ -260,9 +258,9 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, u8_t aid,
|
|||
struct seg_tx *tx;
|
||||
int i;
|
||||
|
||||
BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x mic_len %u sdu_len %u",
|
||||
net_tx->src, net_tx->ctx->addr, net_tx->ctx->app_idx, mic_len,
|
||||
sdu->len);
|
||||
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->len);
|
||||
|
||||
if (sdu->len < 1) {
|
||||
BT_ERR("Zero-length SDU not allowed");
|
||||
|
@ -289,7 +287,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, u8_t aid,
|
|||
if (net_tx->ctx->app_idx == BT_MESH_KEY_DEV) {
|
||||
seg_hdr = SEG_HDR(0, 0);
|
||||
} else {
|
||||
seg_hdr = SEG_HDR(1, aid);
|
||||
seg_hdr = SEG_HDR(1, net_tx->aid);
|
||||
}
|
||||
|
||||
seg_o = 0;
|
||||
|
@ -326,7 +324,7 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, u8_t aid,
|
|||
net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
|
||||
|
||||
net_buf_add_u8(seg, seg_hdr);
|
||||
net_buf_add_u8(seg, (SZMIC(mic_len) << 7) | seq_zero >> 6);
|
||||
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);
|
||||
|
@ -394,19 +392,26 @@ struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx)
|
|||
int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
bool seg = (msg->len > 11 || cb);
|
||||
const u8_t *key;
|
||||
u8_t mic_len, aid, aszmic;
|
||||
u8_t *ad;
|
||||
int err;
|
||||
|
||||
if (net_buf_simple_tailroom(msg) < 4) {
|
||||
BT_ERR("Insufficient tailroom for Transport MIC");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (msg->len > 11) {
|
||||
tx->ctx->send_rel = 1;
|
||||
}
|
||||
|
||||
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->len, bt_hex(msg->data, msg->len));
|
||||
|
||||
if (tx->ctx->app_idx == BT_MESH_KEY_DEV) {
|
||||
key = bt_mesh.dev_key;
|
||||
aid = 0;
|
||||
tx->aid = 0;
|
||||
} else {
|
||||
struct bt_mesh_app_key *app_key;
|
||||
|
||||
|
@ -418,19 +423,17 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
|
|||
if (tx->sub->kr_phase == BT_MESH_KR_PHASE_2 &&
|
||||
app_key->updated) {
|
||||
key = app_key->keys[1].val;
|
||||
aid = app_key->keys[1].id;
|
||||
tx->aid = app_key->keys[1].id;
|
||||
} else {
|
||||
key = app_key->keys[0].val;
|
||||
aid = app_key->keys[0].id;
|
||||
tx->aid = app_key->keys[0].id;
|
||||
}
|
||||
}
|
||||
|
||||
if (!seg || net_buf_simple_tailroom(msg) < 8) {
|
||||
mic_len = 4;
|
||||
aszmic = 0;
|
||||
if (!tx->ctx->send_rel || net_buf_simple_tailroom(msg) < 8) {
|
||||
tx->aszmic = 0;
|
||||
} else {
|
||||
mic_len = 8;
|
||||
aszmic = 1;
|
||||
tx->aszmic = 1;
|
||||
}
|
||||
|
||||
if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
|
||||
|
@ -440,18 +443,39 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
|
|||
}
|
||||
|
||||
err = bt_mesh_app_encrypt(key, tx->ctx->app_idx == BT_MESH_KEY_DEV,
|
||||
aszmic, msg, ad, mic_len, tx->src,
|
||||
tx->aszmic, msg, ad, tx->src,
|
||||
tx->ctx->addr, bt_mesh.seq,
|
||||
BT_MESH_NET_IVI_TX);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (seg) {
|
||||
return send_seg(tx, aid, mic_len, msg, cb, cb_data);
|
||||
if (tx->ctx->send_rel) {
|
||||
err = send_seg(tx, msg, cb, cb_data);
|
||||
} else {
|
||||
err = send_unseg(tx, msg, cb, cb_data);
|
||||
}
|
||||
|
||||
return send_unseg(tx, aid, msg, cb, cb_data);
|
||||
return err;
|
||||
}
|
||||
|
||||
int bt_mesh_trans_resend(struct bt_mesh_net_tx *tx, struct net_buf_simple *msg,
|
||||
const struct bt_mesh_send_cb *cb, void *cb_data)
|
||||
{
|
||||
struct net_buf_simple_state state;
|
||||
int err;
|
||||
|
||||
net_buf_simple_save(msg, &state);
|
||||
|
||||
if (tx->ctx->send_rel || msg->len > 15) {
|
||||
err = send_seg(tx, msg, cb, cb_data);
|
||||
} else {
|
||||
err = send_unseg(tx, msg, cb, cb_data);
|
||||
}
|
||||
|
||||
net_buf_simple_restore(msg, &state);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool is_replay(struct bt_mesh_net_rx *rx)
|
||||
|
@ -489,8 +513,8 @@ static bool is_replay(struct bt_mesh_net_rx *rx)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int sdu_recv(struct bt_mesh_net_rx *rx, u8_t hdr, u8_t mic_size,
|
||||
u8_t aszmic, struct net_buf_simple *buf)
|
||||
static int sdu_recv(struct bt_mesh_net_rx *rx, u8_t hdr, u8_t aszmic,
|
||||
struct net_buf_simple *buf)
|
||||
{
|
||||
struct net_buf_simple *sdu =
|
||||
NET_BUF_SIMPLE(CONFIG_BT_MESH_RX_SDU_MAX - 4);
|
||||
|
@ -498,11 +522,10 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u8_t hdr, u8_t mic_size,
|
|||
u16_t i;
|
||||
int err;
|
||||
|
||||
BT_DBG("MIC_SIZE %u ASZMIC %u AKF %u AID 0x%02x",
|
||||
mic_size, aszmic, AKF(&hdr), AID(&hdr));
|
||||
BT_DBG("ASZMIC %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr));
|
||||
BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
|
||||
|
||||
if (buf->len < 1 + mic_size) {
|
||||
if (buf->len < 1 + APP_MIC_LEN(aszmic)) {
|
||||
BT_ERR("Too short SDU + MIC");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -519,14 +542,13 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u8_t hdr, u8_t mic_size,
|
|||
}
|
||||
|
||||
/* Adjust the length to not contain the MIC at the end */
|
||||
buf->len -= mic_size;
|
||||
buf->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,
|
||||
mic_size, sdu, ad, rx->ctx.addr,
|
||||
rx->dst, rx->seq,
|
||||
BT_MESH_NET_IVI_RX(rx));
|
||||
sdu, ad, rx->ctx.addr, rx->dst,
|
||||
rx->seq, BT_MESH_NET_IVI_RX(rx));
|
||||
if (err) {
|
||||
BT_ERR("Unable to decrypt with DevKey");
|
||||
return -EINVAL;
|
||||
|
@ -559,9 +581,8 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u8_t hdr, u8_t mic_size,
|
|||
|
||||
net_buf_simple_init(sdu, 0);
|
||||
err = bt_mesh_app_decrypt(keys->val, false, aszmic, buf,
|
||||
mic_size, sdu, ad, rx->ctx.addr,
|
||||
rx->dst, rx->seq,
|
||||
BT_MESH_NET_IVI_RX(rx));
|
||||
sdu, ad, rx->ctx.addr, rx->dst,
|
||||
rx->seq, BT_MESH_NET_IVI_RX(rx));
|
||||
if (err) {
|
||||
BT_WARN("Unable to decrypt with AppKey %u", i);
|
||||
continue;
|
||||
|
@ -803,7 +824,7 @@ static int trans_unseg(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
return sdu_recv(rx, hdr, 4, 0, buf);
|
||||
return sdu_recv(rx, hdr, 0, buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1062,8 +1083,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_DBG("MIC_SIZE %u AKF %u AID 0x%02x", MIC_SIZE(hdr), AKF(hdr),
|
||||
AID(hdr));
|
||||
BT_DBG("ASZMIC %u AKF %u AID 0x%02x", ASZMIC(hdr), AKF(hdr), AID(hdr));
|
||||
|
||||
net_buf_simple_pull(buf, 1);
|
||||
|
||||
|
@ -1207,8 +1227,7 @@ found_rx:
|
|||
if (net_rx->ctl) {
|
||||
err = ctl_recv(net_rx, *hdr, &rx->buf, seq_auth);
|
||||
} else {
|
||||
err = sdu_recv(net_rx, *hdr, MIC_SIZE(hdr),
|
||||
SZMIC(MIC_SIZE(hdr)), &rx->buf);
|
||||
err = sdu_recv(net_rx, *hdr, ASZMIC(hdr), &rx->buf);
|
||||
}
|
||||
|
||||
seg_rx_reset(rx);
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#define CID_INTEL 0x0002
|
||||
|
||||
#define MAX_FAULT 24
|
||||
|
||||
static bool has_reg_fault = true;
|
||||
|
||||
static struct bt_mesh_cfg_srv cfg_srv = {
|
||||
|
@ -44,7 +46,7 @@ static struct bt_mesh_cfg_srv cfg_srv = {
|
|||
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)
|
||||
{
|
||||
u8_t reg_faults[24] = { [0 ... 23] = 0xff };
|
||||
u8_t reg_faults[MAX_FAULT] = { [0 ... (MAX_FAULT - 1)] = 0xff };
|
||||
|
||||
printk("fault_get_cur() has_reg_fault %u\n", has_reg_fault);
|
||||
|
||||
|
@ -68,7 +70,7 @@ static int fault_get_reg(struct bt_mesh_model *model, u16_t company_id,
|
|||
*test_id = 0x00;
|
||||
|
||||
if (has_reg_fault) {
|
||||
u8_t reg_faults[24] = { [0 ... 23] = 0xff };
|
||||
u8_t reg_faults[MAX_FAULT] = { [0 ... (MAX_FAULT - 1)] = 0xff };
|
||||
|
||||
memcpy(faults, reg_faults, sizeof(reg_faults));
|
||||
*fault_count = sizeof(reg_faults);
|
||||
|
@ -103,16 +105,24 @@ static int fault_test(struct bt_mesh_model *model, uint8_t test_id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct bt_mesh_health_srv health_srv = {
|
||||
static const struct bt_mesh_health_srv_cb health_srv_cb = {
|
||||
.fault_get_cur = fault_get_cur,
|
||||
.fault_get_reg = fault_get_reg,
|
||||
.fault_clear = fault_clear,
|
||||
.fault_test = fault_test,
|
||||
};
|
||||
|
||||
static struct bt_mesh_health_srv health_srv = {
|
||||
.cb = &health_srv_cb,
|
||||
};
|
||||
|
||||
static struct bt_mesh_model_pub health_pub = {
|
||||
.msg = BT_MESH_HEALTH_FAULT_MSG(MAX_FAULT),
|
||||
};
|
||||
|
||||
static struct bt_mesh_model root_models[] = {
|
||||
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv),
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
|
||||
};
|
||||
|
||||
static void vnd_publish(struct bt_mesh_model *mod)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue