linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ v2 0/4] Add options to Models and VendorModels
@ 2020-06-30 18:56 Inga Stotland
  2020-06-30 18:56 ` [PATCH BlueZ v2 1/4] doc/mesh-api: Add dictionary to model properties Inga Stotland
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Inga Stotland @ 2020-06-30 18:56 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, michal.lowas-rzechonek, Inga Stotland

v2:

Changes constaned to patch 0002:

- Fixed returned status in config pub/sub model calls
- Consistent use of pub_enabled & sub_enabled in the code

************
If a model does not support either subscription mechanism,
Config Server is supposed to return "Not a Subscribe Model" if a Config Client sends
a subscription add/overwrite message.

Similarly, if a model does not support publication, "Invalid Publish Parameters"
should be returned in response to Publication Set message.

Since config server is running even when an app is not attached, the only way to collect
these model capabilities is on Attach, Join, Create, Import methods when the
object manager collects app info.

To address this issue, signatures for properties "Models" and "VendorModels" on Element
interface change to include "options" dictionary:
    Models: signature change "aq" -> "a(qa{sv})"
    VendorModels: signature change "a(qq)" -> "a(qqa{sv})"
    
The defined keywords for the options dictionary are:
    "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.

Inga Stotland (4):
  doc/mesh-api: Add dictionary to model properties
  mesh: Check app model settings of pub/sub support
  tools/mesh-cfgclient: Add options to "Models" property
  test/test-mesh: Add options to "Models" property

 doc/mesh-api.txt        |  40 ++++++++--
 mesh/mesh-config-json.c |  76 +++++++++++++++++-
 mesh/mesh-config.h      |   8 ++
 mesh/model.c            |  98 +++++++++++++++++++----
 mesh/model.h            |   6 ++
 mesh/node.c             | 168 ++++++++++++++++++++++++++++++++--------
 test/test-mesh          |  21 ++---
 tools/mesh-cfgclient.c  |  25 ++++--
 8 files changed, 374 insertions(+), 68 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH BlueZ v2 1/4] doc/mesh-api: Add dictionary to model properties
  2020-06-30 18:56 [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Inga Stotland
@ 2020-06-30 18:56 ` Inga Stotland
  2020-06-30 18:56 ` [PATCH BlueZ v2 2/4] mesh: Check app model settings of pub/sub support Inga Stotland
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Inga Stotland @ 2020-06-30 18:56 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, michal.lowas-rzechonek, Inga Stotland

This changes the signature of "Models" and "VendorModels" properties
on org.bluez.mesh.Element1 interface to contain a dictionary with
model options.

Models: signature change "aq" -> "a(qa{sv})"
VendorModels: signature change "a(qq)" -> "a(qqa{sv})"

Currently, the defined keywords for the options dictionary are
"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.

The dictionary allowed to be empty.
---
 doc/mesh-api.txt | 40 ++++++++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
index 3be11e342..495f95b0b 100644
--- a/doc/mesh-api.txt
+++ b/doc/mesh-api.txt
@@ -888,15 +888,43 @@ Properties:
 		Element index. It is required that the application follows
 		sequential numbering scheme for the elements, starting with 0.
 
-	array{uint16} Models [read-only]
+	array{(uint16 id, dict caps)} Models [read-only]
 
-		An array of SIG Model Identifiers. The array may be empty.
+		An array of SIG Models:
 
-	array{(uint16, uint16)} VendorModels [read-only]
+			id - SIG Model Identifier
 
-		An array of pairs (vendor, model ID): vendor is a 16-bit
-		Bluetooth-assigned Company ID as defined by Bluetooth SIG.
-		model ID is a 16-bit vendor-assigned Model Identifier
+			options - a dictionary that may contain additional model
+			info. The following keys are defined:
+
+				boolean Publish - indicates whether the model
+					supports publication mechanism. If not
+					present, publication is enabled.
+
+				boolean Subscribe - indicates whether the model
+					supports subscription mechanism. If not
+					present, subscriptons are enabled.
+
+		The array may be empty.
+
+
+	array{(uint16 vendor, uint16 id, dict options)} VendorModels [read-only]
+
+		An array of Vendor Models:
+
+			vendor - a 16-bit Bluetooth-assigned Company ID as
+			defined by Bluetooth SIG.
+
+			id - a 16-bit vendor-assigned Model Identifier
+
+			options - a dictionary that may contain additional model
+			info. The following keys are defined:
+
+				boolean Publish - indicates whether the model
+					supports publication mechanism
+
+				boolean Subscribe - indicates whether the model
+					supports subscription mechanism
 
 		The array may be empty.
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BlueZ v2 2/4] mesh: Check app model settings of pub/sub support
  2020-06-30 18:56 [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Inga Stotland
  2020-06-30 18:56 ` [PATCH BlueZ v2 1/4] doc/mesh-api: Add dictionary to model properties Inga Stotland
@ 2020-06-30 18:56 ` Inga Stotland
  2020-06-30 18:56 ` [PATCH BlueZ v2 3/4] tools/mesh-cfgclient: Add options to "Models" property Inga Stotland
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Inga Stotland @ 2020-06-30 18:56 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, michal.lowas-rzechonek, Inga Stotland

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.
---
 mesh/mesh-config-json.c |  76 +++++++++++++++++-
 mesh/mesh-config.h      |   8 ++
 mesh/model.c            |  98 +++++++++++++++++++----
 mesh/model.h            |   6 ++
 mesh/node.c             | 168 ++++++++++++++++++++++++++++++++--------
 5 files changed, 309 insertions(+), 47 deletions(-)

diff --git a/mesh/mesh-config-json.c b/mesh/mesh-config-json.c
index 05b2a5651..661775f95 100644
--- a/mesh/mesh-config-json.c
+++ b/mesh/mesh-config-json.c
@@ -1096,6 +1096,16 @@ static bool parse_models(json_object *jmodels, struct mesh_config_element *ele)
 				goto fail;
 		}
 
+		if (json_object_object_get_ex(jmodel, "pubEnabled", &jvalue))
+			mod->pub_enabled = json_object_get_boolean(jvalue);
+		else
+			mod->pub_enabled = true;
+
+		if (json_object_object_get_ex(jmodel, "subEnabled", &jvalue))
+			mod->sub_enabled = json_object_get_boolean(jvalue);
+		else
+			mod->sub_enabled = true;
+
 		if (json_object_object_get_ex(jmodel, "publish", &jvalue)) {
 			mod->pub = parse_model_publication(jvalue);
 			if (!mod->pub)
@@ -1562,7 +1572,7 @@ bool mesh_config_write_iv_index(struct mesh_config *cfg, uint32_t idx,
 static void add_model(void *a, void *b)
 {
 	struct mesh_config_model *mod = a;
-	json_object *jmodels = b, *jmodel;
+	json_object *jmodels = b, *jmodel, *jval;
 
 	jmodel = json_object_new_object();
 	if (!jmodel)
@@ -1574,6 +1584,12 @@ static void add_model(void *a, void *b)
 	else
 		write_uint32_hex(jmodel, "modelId", mod->id);
 
+	jval = json_object_new_boolean(mod->sub_enabled);
+	json_object_object_add(jmodel, "subEnabled", jval);
+
+	jval = json_object_new_boolean(mod->pub_enabled);
+	json_object_object_add(jmodel, "pubEnabled", jval);
+
 	json_object_array_add(jmodels, jmodel);
 }
 
@@ -1974,6 +1990,64 @@ bool mesh_config_model_sub_del_all(struct mesh_config *cfg, uint16_t addr,
 	return save_config(cfg->jnode, cfg->node_dir_path);
 }
 
+bool mesh_config_model_pub_enable(struct mesh_config *cfg, uint16_t ele_addr,
+						uint32_t mod_id, bool vendor,
+						bool enable)
+{
+	json_object *jmodel, *jval;
+	int ele_idx;
+
+	if (!cfg)
+		return false;
+
+	ele_idx = get_element_index(cfg->jnode, ele_addr);
+	if (ele_idx < 0)
+		return false;
+
+	jmodel = get_element_model(cfg->jnode, ele_idx, mod_id, vendor);
+	if (!jmodel)
+		return false;
+
+	json_object_object_del(jmodel, "pubDisabled");
+
+	jval = json_object_new_boolean(!enable);
+	json_object_object_add(jmodel, "pubDisabled", jval);
+
+	if (!enable)
+		json_object_object_del(jmodel, "publish");
+
+	return save_config(cfg->jnode, cfg->node_dir_path);
+}
+
+bool mesh_config_model_sub_enable(struct mesh_config *cfg, uint16_t ele_addr,
+						uint32_t mod_id, bool vendor,
+						bool enable)
+{
+	json_object *jmodel, *jval;
+	int ele_idx;
+
+	if (!cfg)
+		return false;
+
+	ele_idx = get_element_index(cfg->jnode, ele_addr);
+	if (ele_idx < 0)
+		return false;
+
+	jmodel = get_element_model(cfg->jnode, ele_idx, mod_id, vendor);
+	if (!jmodel)
+		return false;
+
+	json_object_object_del(jmodel, "subEnabled");
+
+	jval = json_object_new_boolean(enable);
+	json_object_object_add(jmodel, "subEnabled", jval);
+
+	if (!enable)
+		json_object_object_del(jmodel, "subscribe");
+
+	return save_config(cfg->jnode, cfg->node_dir_path);
+}
+
 bool mesh_config_write_seq_number(struct mesh_config *cfg, uint32_t seq,
 								bool cache)
 {
diff --git a/mesh/mesh-config.h b/mesh/mesh-config.h
index 8ff7b63c7..9f30e693b 100644
--- a/mesh/mesh-config.h
+++ b/mesh/mesh-config.h
@@ -45,6 +45,8 @@ struct mesh_config_model {
 	uint16_t *bindings;
 	uint32_t id;
 	bool vendor;
+	bool sub_enabled;
+	bool pub_enabled;
 	uint32_t num_bindings;
 	uint32_t num_subs;
 };
@@ -156,6 +158,12 @@ bool mesh_config_model_sub_del(struct mesh_config *cfg, uint16_t ele_addr,
 						struct mesh_config_sub *sub);
 bool mesh_config_model_sub_del_all(struct mesh_config *cfg, uint16_t ele_addr,
 						uint32_t mod_id, bool vendor);
+bool mesh_config_model_pub_enable(struct mesh_config *cfg, uint16_t ele_addr,
+						uint32_t mod_id, bool vendor,
+						bool enable);
+bool mesh_config_model_sub_enable(struct mesh_config *cfg, uint16_t ele_addr,
+						uint32_t mod_id, bool vendor,
+						bool enable);
 bool mesh_config_app_key_add(struct mesh_config *cfg, uint16_t net_idx,
 				uint16_t app_idx, const uint8_t key[16]);
 bool mesh_config_app_key_update(struct mesh_config *cfg, uint16_t app_idx,
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();
diff --git a/mesh/model.h b/mesh/model.h
index f8e0f9d37..f717fb00c 100644
--- a/mesh/model.h
+++ b/mesh/model.h
@@ -112,5 +112,11 @@ bool mesh_model_opcode_get(const uint8_t *buf, uint16_t size, uint32_t *opcode,
 								uint16_t *n);
 void model_build_config(void *model, void *msg_builder);
 
+void mesh_model_enable_pub(struct mesh_model *mod, bool enable);
+bool mesh_model_is_pub_enabled(struct mesh_model *mod);
+void mesh_model_enable_sub(struct mesh_node *node, struct mesh_model *mod,
+								bool enable);
+bool mesh_model_is_sub_enabled(struct mesh_model *mod);
+
 void mesh_model_init(void);
 void mesh_model_cleanup(void);
diff --git a/mesh/node.c b/mesh/node.c
index ee6d1833f..9f0f15070 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -386,6 +386,12 @@ static bool add_models_from_storage(struct mesh_node *node,
 		if (!mod)
 			return false;
 
+		if (!db_mod->pub_enabled)
+			mesh_model_enable_pub(mod, false);
+
+		if (!db_mod->sub_enabled)
+			mesh_model_enable_sub(node, mod, false);
+
 		l_queue_insert(ele->models, mod, compare_model_id, NULL);
 	}
 
@@ -1041,65 +1047,99 @@ static void app_disc_cb(struct l_dbus *bus, void *user_data)
 	free_node_dbus_resources(node);
 }
 
-static bool get_sig_models_from_properties(struct node_element *ele,
+static bool get_model_options(struct mesh_node *node, struct mesh_model *mod,
+					struct l_dbus_message_iter *opts)
+{
+	const char *key;
+	struct l_dbus_message_iter var;
+	bool opt;
+
+	while (l_dbus_message_iter_next_entry(opts, &key, &var)) {
+
+		if (!strcmp(key, "Publish")) {
+			if (!l_dbus_message_iter_get_variant(&var, "b", &opt))
+				return false;
+			mesh_model_enable_pub(mod, opt);
+		} else if (!strcmp(key, "Subscribe")) {
+			if (!l_dbus_message_iter_get_variant(&var, "b", &opt))
+				return false;
+			mesh_model_enable_sub(node, mod, opt);
+		} else
+			return false;
+	}
+
+	return true;
+}
+
+static bool generate_model(struct mesh_node *node, struct node_element *ele,
+				uint32_t id, struct l_dbus_message_iter *opts)
+{
+	struct mesh_model *mod;
+
+	/* Disallow duplicates */
+	if (l_queue_find(ele->models, match_model_id,
+			 L_UINT_TO_PTR(id)))
+		return false;
+
+	mod = mesh_model_new(ele->idx, id);
+
+	if (!get_model_options(node, mod, opts)) {
+		l_free(mod);
+		return false;
+	}
+
+	l_queue_insert(ele->models, mod, compare_model_id, NULL);
+
+	return true;
+}
+
+static bool get_sig_models_from_properties(struct mesh_node *node,
+					struct node_element *ele,
 					struct l_dbus_message_iter *property)
 {
-	struct l_dbus_message_iter ids;
-	uint16_t mod_id;
+	struct l_dbus_message_iter mods, var;
+	uint16_t m_id;
 
 	if (!ele->models)
 		ele->models = l_queue_new();
 
-	if (!l_dbus_message_iter_get_variant(property, "aq", &ids))
+	if (!l_dbus_message_iter_get_variant(property, "a(qa{sv})", &mods))
 		return false;
 
 	/* Bluetooth SIG defined models */
-	while (l_dbus_message_iter_next_entry(&ids, &mod_id)) {
-		struct mesh_model *mod;
-		uint32_t id = mod_id | VENDOR_ID_MASK;
+	while (l_dbus_message_iter_next_entry(&mods, &m_id, &var)) {
+		uint32_t id = m_id | VENDOR_ID_MASK;
 
 		/* Allow Config Server Model only on the primary element */
 		if (ele->idx != PRIMARY_ELE_IDX && id == CONFIG_SRV_MODEL)
 			return false;
 
-		/* Disallow duplicates */
-		if (l_queue_find(ele->models, match_model_id,
-						L_UINT_TO_PTR(id)))
+		if (!generate_model(node, ele, id, &var))
 			return false;
-
-		mod = mesh_model_new(ele->idx, id);
-
-		l_queue_insert(ele->models, mod, compare_model_id, NULL);
 	}
 
 	return true;
 }
 
-static bool get_vendor_models_from_properties(struct node_element *ele,
+static bool get_vendor_models_from_properties(struct mesh_node *node,
+					struct node_element *ele,
 					struct l_dbus_message_iter *property)
 {
-	struct l_dbus_message_iter ids;
-	uint16_t mod_id, vendor_id;
+	struct l_dbus_message_iter mods, var;
+	uint16_t m_id, v_id;
 
 	if (!ele->models)
 		ele->models = l_queue_new();
 
-	if (!l_dbus_message_iter_get_variant(property, "a(qq)", &ids))
+	if (!l_dbus_message_iter_get_variant(property, "a(qqa{sv})", &mods))
 		return false;
 
 	/* Vendor defined models */
-	while (l_dbus_message_iter_next_entry(&ids, &vendor_id, &mod_id)) {
-		struct mesh_model *mod;
-		uint32_t id = mod_id | (vendor_id << 16);
+	while (l_dbus_message_iter_next_entry(&mods, &v_id, &m_id, &var)) {
+		uint32_t id = m_id | (v_id << 16);
 
-		/* Disallow duplicates */
-		if (l_queue_find(ele->models, match_model_id,
-							L_UINT_TO_PTR(id)))
+		if (!generate_model(node, ele, id, &var))
 			return false;
-
-		mod = mesh_model_new(ele->idx, id);
-
-		l_queue_insert(ele->models, mod, compare_model_id, NULL);
 	}
 
 	return true;
@@ -1130,14 +1170,19 @@ static bool get_element_properties(struct mesh_node *node, const char *path,
 
 		} else if (!strcmp(key, "Models")) {
 
-			if (mods || !get_sig_models_from_properties(ele, &var))
+			if (mods)
+				goto fail;
+
+			if (!get_sig_models_from_properties(node, ele, &var))
 				goto fail;
 
 			mods = true;
 		} else if (!strcmp(key, "VendorModels")) {
 
-			if (vendor_mods ||
-				!get_vendor_models_from_properties(ele, &var))
+			if (vendor_mods)
+				goto fail;
+
+			if (!get_vendor_models_from_properties(node, ele, &var))
 				goto fail;
 
 			vendor_mods = true;
@@ -1225,7 +1270,8 @@ static void convert_node_to_storage(struct mesh_node *node,
 			db_mod->id = mod_id;
 			db_mod->vendor = ((mod_id & VENDOR_ID_MASK)
 							!= VENDOR_ID_MASK);
-
+			db_mod->pub_enabled = mesh_model_is_pub_enabled(mod);
+			db_mod->sub_enabled = mesh_model_is_sub_enabled(mod);
 			l_queue_push_tail(db_ele->models, db_mod);
 		}
 		l_queue_push_tail(db_node->elements, db_ele);
@@ -1381,6 +1427,63 @@ static void update_composition(struct mesh_node *node, struct mesh_node *attach)
 	attach->comp = node->comp;
 }
 
+static void update_model_options(struct mesh_node *node,
+						struct mesh_node *attach)
+{
+	uint32_t len, i;
+	struct node_element *ele, *ele_attach;
+
+	len = l_queue_length(node->elements);
+
+	for (i = 0; i < len; i++) {
+		const struct l_queue_entry *entry;
+
+		ele = l_queue_find(node->elements, match_element_idx,
+							L_UINT_TO_PTR(i));
+		ele_attach = l_queue_find(attach->elements, match_element_idx,
+							L_UINT_TO_PTR(i));
+		if (!ele || !ele_attach)
+			continue;
+
+		entry = l_queue_get_entries(ele->models);
+
+		for (; entry; entry = entry->next) {
+			struct mesh_model *mod, *updated_mod = entry->data;
+			uint32_t id = mesh_model_get_model_id(updated_mod);
+			bool opt, updated_opt;
+			bool vendor = id < VENDOR_ID_MASK;
+
+			mod = l_queue_find(ele_attach->models, match_model_id,
+							L_UINT_TO_PTR(id));
+			if (!mod)
+				continue;
+
+			if (!vendor)
+				id &= ~VENDOR_ID_MASK;
+
+			opt = mesh_model_is_pub_enabled(mod);
+			updated_opt = mesh_model_is_pub_enabled(updated_mod);
+
+			if (updated_opt != opt) {
+				mesh_model_enable_pub(mod, updated_opt);
+				mesh_config_model_pub_enable(attach->cfg,
+							attach->primary + i, id,
+							vendor, updated_opt);
+			}
+
+			opt = mesh_model_is_sub_enabled(mod);
+			updated_opt = mesh_model_is_sub_enabled(updated_mod);
+
+			if (updated_opt != opt) {
+				mesh_model_enable_sub(node, mod, updated_opt);
+				mesh_config_model_sub_enable(attach->cfg,
+							attach->primary + i, id,
+							vendor, updated_opt);
+			}
+		}
+	}
+}
+
 static bool check_req_node(struct managed_obj_request *req)
 {
 	uint8_t node_comp[MAX_MSG_LEN - 2];
@@ -1452,6 +1555,7 @@ static bool attach_req_node(struct mesh_node *attach, struct mesh_node *node)
 	node->owner = NULL;
 
 	update_composition(node, attach);
+	update_model_options(node, attach);
 
 	node_remove(node);
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BlueZ v2 3/4] tools/mesh-cfgclient: Add options to "Models" property
  2020-06-30 18:56 [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Inga Stotland
  2020-06-30 18:56 ` [PATCH BlueZ v2 1/4] doc/mesh-api: Add dictionary to model properties Inga Stotland
  2020-06-30 18:56 ` [PATCH BlueZ v2 2/4] mesh: Check app model settings of pub/sub support Inga Stotland
@ 2020-06-30 18:56 ` Inga Stotland
  2020-06-30 18:56 ` [PATCH BlueZ v2 4/4] test/test-mesh: " Inga Stotland
  2020-07-01 19:11 ` [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Gix, Brian
  4 siblings, 0 replies; 6+ messages in thread
From: Inga Stotland @ 2020-06-30 18:56 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, michal.lowas-rzechonek, Inga Stotland

This adds options dictionary to "Models" property to stay
in sync with mesh-api changes.
---
 tools/mesh-cfgclient.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/tools/mesh-cfgclient.c b/tools/mesh-cfgclient.c
index 0dd02fad8..59f079213 100644
--- a/tools/mesh-cfgclient.c
+++ b/tools/mesh-cfgclient.c
@@ -1448,14 +1448,26 @@ static void proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
 	}
 }
 
+static void build_model(struct l_dbus_message_builder *builder, uint16_t mod_id,
+					bool pub_enable, bool sub_enable)
+{
+	l_dbus_message_builder_enter_struct(builder, "qa{sv}");
+	l_dbus_message_builder_append_basic(builder, 'q', &mod_id);
+	l_dbus_message_builder_enter_array(builder, "{sv}");
+	append_dict_entry_basic(builder, "Subscribe", "b", &sub_enable);
+	append_dict_entry_basic(builder, "Publish", "b", &pub_enable);
+	l_dbus_message_builder_leave_array(builder);
+	l_dbus_message_builder_leave_struct(builder);
+}
+
 static bool mod_getter(struct l_dbus *dbus,
 				struct l_dbus_message *message,
 				struct l_dbus_message_builder *builder,
 				void *user_data)
 {
-	l_dbus_message_builder_enter_array(builder, "q");
-	l_dbus_message_builder_append_basic(builder, 'q', &app.ele.mods[0]);
-	l_dbus_message_builder_append_basic(builder, 'q', &app.ele.mods[1]);
+	l_dbus_message_builder_enter_array(builder, "(qa{sv})");
+	build_model(builder, app.ele.mods[0], false, false);
+	build_model(builder, app.ele.mods[1], false, false);
 	l_dbus_message_builder_leave_array(builder);
 
 	return true;
@@ -1466,7 +1478,7 @@ static bool vmod_getter(struct l_dbus *dbus,
 				struct l_dbus_message_builder *builder,
 				void *user_data)
 {
-	l_dbus_message_builder_enter_array(builder, "(qq)");
+	l_dbus_message_builder_enter_array(builder, "(qqa{sv})");
 	l_dbus_message_builder_leave_array(builder);
 
 	return true;
@@ -1517,9 +1529,10 @@ static void setup_ele_iface(struct l_dbus_interface *iface)
 	/* Properties */
 	l_dbus_interface_property(iface, "Index", 0, "y", ele_idx_getter,
 									NULL);
-	l_dbus_interface_property(iface, "VendorModels", 0, "a(qq)",
+	l_dbus_interface_property(iface, "VendorModels", 0, "a(qqa{sv})",
 							vmod_getter, NULL);
-	l_dbus_interface_property(iface, "Models", 0, "aq", mod_getter, NULL);
+	l_dbus_interface_property(iface, "Models", 0, "a(qa{sv})", mod_getter,
+									NULL);
 
 	/* Methods */
 	l_dbus_interface_method(iface, "DevKeyMessageReceived", 0,
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BlueZ v2 4/4] test/test-mesh: Add options to "Models" property
  2020-06-30 18:56 [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Inga Stotland
                   ` (2 preceding siblings ...)
  2020-06-30 18:56 ` [PATCH BlueZ v2 3/4] tools/mesh-cfgclient: Add options to "Models" property Inga Stotland
@ 2020-06-30 18:56 ` Inga Stotland
  2020-07-01 19:11 ` [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Gix, Brian
  4 siblings, 0 replies; 6+ messages in thread
From: Inga Stotland @ 2020-06-30 18:56 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: brian.gix, michal.lowas-rzechonek, Inga Stotland

This adds options dictionary to "Models" property to stay
in sync with mesh-api changes.
---
 test/test-mesh | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/test/test-mesh b/test/test-mesh
index 7c8a25482..5da0278d6 100755
--- a/test/test-mesh
+++ b/test/test-mesh
@@ -430,32 +430,35 @@ class Element(dbus.service.Object):
 		dbus.service.Object.__init__(self, bus, self.path)
 
 	def _get_sig_models(self):
-		ids = []
+		mods = []
 		for model in self.models:
+			opts = []
 			id = model.get_id()
 			vendor = model.get_vendor()
 			if vendor == VENDOR_ID_NONE:
-				ids.append(id)
-		return ids
+				mod = (id, opts)
+				mods.append(mod)
+		return mods
 
 	def _get_v_models(self):
-		ids = []
+		mods = []
 		for model in self.models:
+			opts = []
 			id = model.get_id()
 			v = model.get_vendor()
 			if v != VENDOR_ID_NONE:
-				vendor_id = (v, id)
-				ids.append(vendor_id)
-		return ids
+				mod = (v, id, opts)
+				mods.append(mod)
+		return mods
 
 	def get_properties(self):
 		vendor_models = self._get_v_models()
 		sig_models = self._get_sig_models()
 
 		props = {'Index' : dbus.Byte(self.index)}
-		props['Models'] = dbus.Array(sig_models, signature='q')
+		props['Models'] = dbus.Array(sig_models, signature='(qa{sv})')
 		props['VendorModels'] = dbus.Array(vendor_models,
-							signature='(qq)')
+							signature='(qqa{sv})')
 		#print(props)
 		return { MESH_ELEMENT_IFACE: props }
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH BlueZ v2 0/4] Add options to Models and VendorModels
  2020-06-30 18:56 [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Inga Stotland
                   ` (3 preceding siblings ...)
  2020-06-30 18:56 ` [PATCH BlueZ v2 4/4] test/test-mesh: " Inga Stotland
@ 2020-07-01 19:11 ` Gix, Brian
  4 siblings, 0 replies; 6+ messages in thread
From: Gix, Brian @ 2020-07-01 19:11 UTC (permalink / raw)
  To: linux-bluetooth, Stotland, Inga; +Cc: michal.lowas-rzechonek

Patchset Applied
On Tue, 2020-06-30 at 11:56 -0700, Inga Stotland wrote:
> v2:
> 
> Changes constaned to patch 0002:
> 
> - Fixed returned status in config pub/sub model calls
> - Consistent use of pub_enabled & sub_enabled in the code
> 
> ************
> If a model does not support either subscription mechanism,
> Config Server is supposed to return "Not a Subscribe Model" if a Config Client sends
> a subscription add/overwrite message.
> 
> Similarly, if a model does not support publication, "Invalid Publish Parameters"
> should be returned in response to Publication Set message.
> 
> Since config server is running even when an app is not attached, the only way to collect
> these model capabilities is on Attach, Join, Create, Import methods when the
> object manager collects app info.
> 
> To address this issue, signatures for properties "Models" and "VendorModels" on Element
> interface change to include "options" dictionary:
>     Models: signature change "aq" -> "a(qa{sv})"
>     VendorModels: signature change "a(qq)" -> "a(qqa{sv})"
>     
> The defined keywords for the options dictionary are:
>     "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.
> 
> Inga Stotland (4):
>   doc/mesh-api: Add dictionary to model properties
>   mesh: Check app model settings of pub/sub support
>   tools/mesh-cfgclient: Add options to "Models" property
>   test/test-mesh: Add options to "Models" property
> 
>  doc/mesh-api.txt        |  40 ++++++++--
>  mesh/mesh-config-json.c |  76 +++++++++++++++++-
>  mesh/mesh-config.h      |   8 ++
>  mesh/model.c            |  98 +++++++++++++++++++----
>  mesh/model.h            |   6 ++
>  mesh/node.c             | 168 ++++++++++++++++++++++++++++++++--------
>  test/test-mesh          |  21 ++---
>  tools/mesh-cfgclient.c  |  25 ++++--
>  8 files changed, 374 insertions(+), 68 deletions(-)
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-07-01 19:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-30 18:56 [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Inga Stotland
2020-06-30 18:56 ` [PATCH BlueZ v2 1/4] doc/mesh-api: Add dictionary to model properties Inga Stotland
2020-06-30 18:56 ` [PATCH BlueZ v2 2/4] mesh: Check app model settings of pub/sub support Inga Stotland
2020-06-30 18:56 ` [PATCH BlueZ v2 3/4] tools/mesh-cfgclient: Add options to "Models" property Inga Stotland
2020-06-30 18:56 ` [PATCH BlueZ v2 4/4] test/test-mesh: " Inga Stotland
2020-07-01 19:11 ` [PATCH BlueZ v2 0/4] Add options to Models and VendorModels Gix, Brian

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).