Bluetooth: Mesh: Encapsulate feature config

Moves mesh feature configuration to a separate module, deprecating the
bt_mesh_cfg_srv structure. The initial values for the features should
now be enabled through KConfig, where new config entries have been added
for each feature.

This removes the upward dependency on the config server from the core
stack, and makes the config server a pure frontend for the configuration
states, as all spec mandated behavior around the feature states is now
encapsulated.

Signed-off-by: Trond Einar Snekvik <Trond.Einar.Snekvik@nordicsemi.no>
This commit is contained in:
Trond Einar Snekvik 2020-08-18 13:36:38 +02:00 committed by Johan Hedberg
commit ad2fd44d7a
36 changed files with 645 additions and 634 deletions

View file

@ -38,10 +38,7 @@
#include "foundation.h"
#include "friend.h"
#include "settings.h"
#define DEFAULT_TTL 7
static struct bt_mesh_cfg_srv *conf;
#include "cfg.h"
static int comp_add_elem(struct net_buf_simple *buf, struct bt_mesh_elem *elem,
bool primary)
@ -470,7 +467,7 @@ static void beacon_get(struct bt_mesh_model *model,
bt_hex(buf->data, buf->len));
bt_mesh_model_msg_init(&msg, OP_BEACON_STATUS);
net_buf_simple_add_u8(&msg, bt_mesh_beacon_get());
net_buf_simple_add_u8(&msg, bt_mesh_beacon_enabled());
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send Config Beacon Status response");
@ -482,33 +479,20 @@ static void beacon_set(struct bt_mesh_model *model,
struct net_buf_simple *buf)
{
BT_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",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
bt_hex(buf->data, buf->len));
if (buf->data[0] == 0x00 || buf->data[0] == 0x01) {
if (buf->data[0] != cfg->beacon) {
cfg->beacon = buf->data[0];
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cfg();
}
if (cfg->beacon) {
bt_mesh_beacon_enable();
} else {
bt_mesh_beacon_disable();
}
}
} else {
if (buf->data[0] != 0x00 && buf->data[0] != 0x01) {
BT_WARN("Invalid Config Beacon value 0x%02x", buf->data[0]);
return;
}
bt_mesh_beacon_set(buf->data[0]);
bt_mesh_model_msg_init(&msg, OP_BEACON_STATUS);
net_buf_simple_add_u8(&msg, bt_mesh_beacon_get());
net_buf_simple_add_u8(&msg, buf->data[0]);
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send Config Beacon Status response");
@ -538,27 +522,20 @@ static void default_ttl_set(struct bt_mesh_model *model,
struct net_buf_simple *buf)
{
BT_MESH_MODEL_BUF_DEFINE(msg, OP_DEFAULT_TTL_STATUS, 1);
struct bt_mesh_cfg_srv *cfg = model->user_data;
int err;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
bt_hex(buf->data, buf->len));
if (buf->data[0] <= BT_MESH_TTL_MAX && buf->data[0] != 0x01) {
if (cfg->default_ttl != buf->data[0]) {
cfg->default_ttl = buf->data[0];
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cfg();
}
}
} else {
err = bt_mesh_default_ttl_set(buf->data[0]);
if (err) {
BT_WARN("Prohibited Default TTL value 0x%02x", buf->data[0]);
return;
}
bt_mesh_model_msg_init(&msg, OP_DEFAULT_TTL_STATUS);
net_buf_simple_add_u8(&msg, bt_mesh_default_ttl_get());
net_buf_simple_add_u8(&msg, buf->data[0]);
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send Default TTL Status response");
@ -593,8 +570,6 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
bt_hex(buf->data, buf->len));
@ -604,26 +579,8 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
return;
}
if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) ||
bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
goto send_status;
}
(void)bt_mesh_gatt_proxy_set(buf->data[0]);
BT_DBG("GATT Proxy 0x%02x -> 0x%02x", cfg->gatt_proxy, buf->data[0]);
if (cfg->gatt_proxy == buf->data[0]) {
goto send_status;
}
cfg->gatt_proxy = buf->data[0];
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cfg();
}
bt_mesh_hb_feature_changed(BT_MESH_FEAT_PROXY);
send_status:
send_gatt_proxy_status(model, ctx);
}
@ -650,7 +607,6 @@ static void net_transmit_set(struct bt_mesh_model *model,
struct net_buf_simple *buf)
{
BT_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",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
@ -660,14 +616,10 @@ static void net_transmit_set(struct bt_mesh_model *model,
BT_MESH_TRANSMIT_COUNT(buf->data[0]),
BT_MESH_TRANSMIT_INT(buf->data[0]));
cfg->net_transmit = buf->data[0];
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cfg();
}
bt_mesh_net_transmit_set(buf->data[0]);
bt_mesh_model_msg_init(&msg, OP_NET_TRANSMIT_STATUS);
net_buf_simple_add_u8(&msg, bt_mesh_net_transmit_get());
net_buf_simple_add_u8(&msg, buf->data[0]);
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send Network Transmit Status");
@ -698,39 +650,18 @@ static void relay_set(struct bt_mesh_model *model,
struct net_buf_simple *buf)
{
BT_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",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
bt_hex(buf->data, buf->len));
if (buf->data[0] == 0x00 || buf->data[0] == 0x01) {
bool change;
if (cfg->relay == BT_MESH_RELAY_NOT_SUPPORTED) {
change = false;
} else {
change = (cfg->relay != buf->data[0]);
cfg->relay = buf->data[0];
cfg->relay_retransmit = buf->data[1];
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cfg();
}
}
BT_DBG("Relay 0x%02x (%s) xmit 0x%02x (count %u interval %u)",
cfg->relay, change ? "changed" : "not changed",
cfg->relay_retransmit,
BT_MESH_TRANSMIT_COUNT(cfg->relay_retransmit),
BT_MESH_TRANSMIT_INT(cfg->relay_retransmit));
bt_mesh_hb_feature_changed(BT_MESH_FEAT_RELAY);
} else {
if (buf->data[0] != 0x00 && buf->data[0] != 0x01) {
BT_WARN("Invalid Relay value 0x%02x", buf->data[0]);
return;
}
(void)bt_mesh_relay_set(buf->data[0], buf->data[1]);
bt_mesh_model_msg_init(&msg, OP_RELAY_STATUS);
net_buf_simple_add_u8(&msg, bt_mesh_relay_get());
net_buf_simple_add_u8(&msg, bt_mesh_relay_retransmit_get());
@ -2070,10 +2001,9 @@ static void send_friend_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx)
{
BT_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);
net_buf_simple_add_u8(&msg, cfg->frnd);
net_buf_simple_add_u8(&msg, bt_mesh_friend_get());
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
BT_ERR("Unable to send Friend Status");
@ -2095,8 +2025,6 @@ static void friend_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
ctx->net_idx, ctx->app_idx, ctx->addr, buf->len,
bt_hex(buf->data, buf->len));
@ -2106,27 +2034,8 @@ static void friend_set(struct bt_mesh_model *model,
return;
}
BT_DBG("Friend 0x%02x -> 0x%02x", cfg->frnd, buf->data[0]);
(void)bt_mesh_friend_set(buf->data[0]);
if (cfg->frnd == buf->data[0]) {
goto send_status;
}
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
cfg->frnd = buf->data[0];
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_cfg();
}
if (cfg->frnd == BT_MESH_FRIEND_DISABLED) {
bt_mesh_friends_clear();
}
}
bt_mesh_hb_feature_changed(BT_MESH_FEAT_FRIEND);
send_status:
send_friend_status(model, ctx);
}
@ -2472,85 +2381,19 @@ const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
BT_MESH_MODEL_OP_END,
};
static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg)
{
if (cfg->relay > 0x02) {
return false;
}
if (cfg->frnd > 0x02) {
return false;
}
if (cfg->gatt_proxy > 0x02) {
return false;
}
if (cfg->beacon > 0x01) {
return false;
}
if (cfg->default_ttl > BT_MESH_TTL_MAX) {
return false;
}
return true;
}
static void (*hb_sub_cb)(uint8_t hops, uint16_t features);
static struct bt_mesh_hb_cb hb_cb;
static void hb_recv_wrapper(const struct bt_mesh_hb_sub *sub, uint8_t hops, uint16_t features)
{
hb_sub_cb(hops, features);
}
static int cfg_srv_init(struct bt_mesh_model *model)
{
struct bt_mesh_cfg_srv *cfg = model->user_data;
if (!bt_mesh_model_in_primary(model)) {
BT_ERR("Configuration Server only allowed in primary element");
return -EINVAL;
}
if (!cfg) {
BT_ERR("No Configuration Server context provided");
return -EINVAL;
}
if (!conf_is_valid(cfg)) {
BT_ERR("Invalid values in configuration");
return -EINVAL;
}
if (cfg->hb_sub.func) {
hb_sub_cb = cfg->hb_sub.func;
hb_cb.recv = hb_recv_wrapper;
}
/*
* Configuration Model security is device-key based and only the local
* device-key is allowed to access this model.
*/
model->keys[0] = BT_MESH_KEY_DEV_LOCAL;
if (!IS_ENABLED(CONFIG_BT_MESH_RELAY)) {
cfg->relay = BT_MESH_RELAY_NOT_SUPPORTED;
}
if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
cfg->frnd = BT_MESH_FRIEND_NOT_SUPPORTED;
}
if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
cfg->gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED;
}
cfg->model = model;
conf = cfg;
return 0;
}
@ -2586,72 +2429,3 @@ void bt_mesh_cfg_reset(void)
{
bt_mesh_model_foreach(mod_reset, NULL);
}
uint8_t bt_mesh_net_transmit_get(void)
{
if (conf) {
return conf->net_transmit;
}
return 0;
}
uint8_t bt_mesh_relay_get(void)
{
if (conf) {
return conf->relay;
}
return BT_MESH_RELAY_NOT_SUPPORTED;
}
uint8_t bt_mesh_friend_get(void)
{
if (conf) {
BT_DBG("conf %p conf->frnd 0x%02x", conf, conf->frnd);
return conf->frnd;
}
return BT_MESH_FRIEND_NOT_SUPPORTED;
}
uint8_t bt_mesh_relay_retransmit_get(void)
{
if (conf) {
return conf->relay_retransmit;
}
return 0;
}
uint8_t bt_mesh_beacon_get(void)
{
if (conf) {
return conf->beacon;
}
return BT_MESH_BEACON_DISABLED;
}
uint8_t bt_mesh_gatt_proxy_get(void)
{
if (conf) {
return conf->gatt_proxy;
}
return BT_MESH_GATT_PROXY_NOT_SUPPORTED;
}
uint8_t bt_mesh_default_ttl_get(void)
{
if (conf) {
return conf->default_ttl;
}
return DEFAULT_TTL;
}
struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void)
{
return conf;
}