summaryrefslogtreecommitdiff
path: root/mesh/model.c
diff options
context:
space:
mode:
authorInga Stotland <inga.stotland@intel.com>2020-06-30 11:56:15 -0700
committerBrian Gix <brian.gix@intel.com>2020-07-01 12:06:07 -0700
commite803b54864aa2d222eabc02f4814af9b467de34a (patch)
treeb01c71488ab6807ba2296411ae2df48a0fb91a34 /mesh/model.c
parent807886eb5717902cd10ff8ad13e91d9200f0549d (diff)
downloadbluez-e803b54864aa2d222eabc02f4814af9b467de34a.tar.gz
mesh: Check app model settings of pub/sub support
This adds handling of new options dictionary included with "Models" and "VendorModels" properties on org.bluez.mesh.Element1 interface. Supported (optional) dictionary entries: "Publish" - indicates whether the model supports publication mechanism. If not present, publication is enabled. "Subscribe" - indicates whether the model supports subscription mechanism. If not present, subscriptions are enabled. If a config message related to subscription state is received for a model that does not support subscription mechanism, an error code 0x08, ("Not A Subscribe Model") is sent in response. If a config message related to publication state is received for a model that does not support publication mechanism, an error code 0x07 ("Invalid Publish Parameters") is sent in response.
Diffstat (limited to 'mesh/model.c')
-rw-r--r--mesh/model.c98
1 files changed, 84 insertions, 14 deletions
diff --git a/mesh/model.c b/mesh/model.c
index 5ed95afac..afac6ec69 100644
--- a/mesh/model.c
+++ b/mesh/model.c
@@ -51,6 +51,8 @@ struct mesh_model {
struct l_queue *subs;
struct l_queue *virtuals;
struct mesh_model_pub *pub;
+ bool sub_enabled;
+ bool pub_enabled;
uint32_t id;
uint8_t ele_idx;
};
@@ -1097,7 +1099,7 @@ int mesh_model_pub_set(struct mesh_node *node, uint16_t addr, uint32_t id,
if (!mod)
return status;
- if (id == CONFIG_SRV_MODEL || id == CONFIG_CLI_MODEL)
+ if (!mod->pub_enabled || (mod->cbs && !(mod->cbs->pub)))
return MESH_STATUS_INVALID_PUB_PARAM;
if (!appkey_have_key(node_get_net(node), idx))
@@ -1134,9 +1136,11 @@ int mesh_model_pub_set(struct mesh_node *node, uint16_t addr, uint32_t id,
/* External model */
config_update_model_pub_period(node, mod->ele_idx, id,
pub_period_to_ms(period));
- else
+ else {
/* Internal model, call registered callbacks */
- mod->cbs->pub(mod->pub);
+ if (mod->cbs->pub)
+ mod->cbs->pub(mod->pub);
+ }
return MESH_STATUS_SUCCESS;
}
@@ -1150,6 +1154,11 @@ struct mesh_model_pub *mesh_model_pub_get(struct mesh_node *node, uint16_t addr,
if (!mod)
return NULL;
+ if (!mod->pub_enabled || (mod->cbs && !(mod->cbs->pub)))
+ *status = MESH_STATUS_INVALID_PUB_PARAM;
+ else
+ *status = MESH_STATUS_SUCCESS;
+
return mod->pub;
}
@@ -1171,6 +1180,13 @@ struct mesh_model *mesh_model_new(uint8_t ele_idx, uint32_t id)
mod->id = id;
mod->ele_idx = ele_idx;
mod->virtuals = l_queue_new();
+
+ /*
+ * Unless specifically indicated by an app, subscriptions and
+ * publications are enabled by default
+ */
+ mod->sub_enabled = true;
+ mod->pub_enabled = true;
return mod;
}
@@ -1318,6 +1334,9 @@ int mesh_model_sub_get(struct mesh_node *node, uint16_t addr, uint32_t id,
if (!mod)
return status;
+ if (!mod->sub_enabled || (mod->cbs && !(mod->cbs->sub)))
+ return MESH_STATUS_NOT_SUB_MOD;
+
entry = l_queue_get_entries(mod->subs);
*size = 0;
n = 0;
@@ -1358,6 +1377,9 @@ int mesh_model_sub_add(struct mesh_node *node, uint16_t addr, uint32_t id,
if (!mod)
return status;
+ if (!mod->sub_enabled || (mod->cbs && !(mod->cbs->sub)))
+ return MESH_STATUS_NOT_SUB_MOD;
+
status = add_sub(node_get_net(node), mod, group, is_virt, dst);
if (status != MESH_STATUS_SUCCESS)
@@ -1381,6 +1403,9 @@ int mesh_model_sub_ovr(struct mesh_node *node, uint16_t addr, uint32_t id,
if (!mod)
return status;
+ if (!mod->sub_enabled || (mod->cbs && !(mod->cbs->sub)))
+ return MESH_STATUS_NOT_SUB_MOD;
+
subs = mod->subs;
virtuals = mod->virtuals;
mod->subs = l_queue_new();
@@ -1430,6 +1455,9 @@ int mesh_model_sub_del(struct mesh_node *node, uint16_t addr, uint32_t id,
if (!mod)
return status;
+ if (!mod->sub_enabled || (mod->cbs && !(mod->cbs->sub)))
+ return MESH_STATUS_NOT_SUB_MOD;
+
if (is_virt) {
struct mesh_virtual *virt;
@@ -1448,27 +1476,22 @@ int mesh_model_sub_del(struct mesh_node *node, uint16_t addr, uint32_t id,
*dst = grp;
- if (l_queue_remove(mod->subs, L_UINT_TO_PTR(grp)))
+ if (l_queue_remove(mod->subs, L_UINT_TO_PTR(grp))) {
mesh_net_dst_unreg(node_get_net(node), grp);
- if (!mod->cbs)
- /* External models */
- config_update_model_subscriptions(node, mod);
+ if (!mod->cbs)
+ /* External models */
+ config_update_model_subscriptions(node, mod);
+ }
return MESH_STATUS_SUCCESS;
}
-int mesh_model_sub_del_all(struct mesh_node *node, uint16_t addr, uint32_t id)
+static void remove_subs(struct mesh_node *node, struct mesh_model *mod)
{
- int status;
- struct mesh_model *mod;
const struct l_queue_entry *entry;
struct mesh_net *net = node_get_net(node);
- mod = find_model(node, addr, id, &status);
- if (!mod)
- return status;
-
entry = l_queue_get_entries(mod->subs);
for (; entry; entry = entry->next)
@@ -1476,6 +1499,21 @@ int mesh_model_sub_del_all(struct mesh_node *node, uint16_t addr, uint32_t id)
l_queue_clear(mod->subs, NULL);
l_queue_clear(mod->virtuals, unref_virt);
+}
+
+int mesh_model_sub_del_all(struct mesh_node *node, uint16_t addr, uint32_t id)
+{
+ int status;
+ struct mesh_model *mod;
+
+ mod = find_model(node, addr, id, &status);
+ if (!mod)
+ return status;
+
+ if (!mod->sub_enabled || (mod->cbs && !(mod->cbs->sub)))
+ return MESH_STATUS_NOT_SUB_MOD;
+
+ remove_subs(node, mod);
if (!mod->cbs)
/* External models */
@@ -1677,6 +1715,38 @@ void model_build_config(void *model, void *msg_builder)
l_dbus_message_builder_leave_struct(builder);
}
+void mesh_model_enable_pub(struct mesh_model *mod, bool enable)
+{
+ mod->pub_enabled = enable;
+
+ if (!mod->pub_enabled && mod->pub) {
+ if (mod->pub->virt)
+ unref_virt(mod->pub->virt);
+
+ l_free(mod->pub);
+ mod->pub = NULL;
+ }
+}
+
+bool mesh_model_is_pub_enabled(struct mesh_model *mod)
+{
+ return mod->pub_enabled;
+}
+
+void mesh_model_enable_sub(struct mesh_node *node, struct mesh_model *mod,
+ bool enable)
+{
+ mod->sub_enabled = enable;
+
+ if (!mod->sub_enabled)
+ remove_subs(node, mod);
+}
+
+bool mesh_model_is_sub_enabled(struct mesh_model *mod)
+{
+ return mod->sub_enabled;
+}
+
void mesh_model_init(void)
{
mesh_virtuals = l_queue_new();