diff mbox series

[3/7] mesh: Add common MGMT command accessors

Message ID 20220224020624.159247-4-brian.gix@intel.com (mailing list archive)
State Queued, archived
Headers show
Series Kernel based mesh functionality | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
tedd_an/checkpatch fail [3/7] mesh: Add common MGMT command accessors WARNING:TYPO_SPELLING: 'accross' may be misspelled - perhaps 'across'? #69: a single socket, shared accross all consumers. ^^^^^^^ ERROR:FUNCTION_WITHOUT_ARGS: Bad function definition - void mesh_mgmt_destroy() should probably be void mesh_mgmt_destroy(void) #285: FILE: mesh/mesh-mgmt.c:226: +void mesh_mgmt_destroy() /github/workspace/src/12757783.patch total: 1 errors, 1 warnings, 243 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/12757783.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS.
tedd_an/gitlint success Gitlint PASS
tedd_an/incremental_build fail Make FAIL: tools/mgmt-tester.c: In function ‘main’: tools/mgmt-tester.c:12364:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without 12364 | int main(int argc, char *argv[]) | ^~~~ unit/test-avdtp.c: In function ‘main’: unit/test-avdtp.c:766:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without 766 | int main(int argc, char *argv[]) | ^~~~ unit/test-avrcp.c: In function ‘main’: unit/test-avrcp.c:989:5: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without 989 | int main(int argc, char *argv[]) | ^~~~ In file included from mesh/mesh-io-generic.c:26: ./mesh/mesh-mgmt.h:18:5: error: unknown type name ‘mgmt_request_func_t’ 18 | mgmt_request_func_t callback, | ^~~~~~~~~~~~~~~~~~~ ./mesh/mesh-mgmt.h:19:22: error: unknown type name ‘mgmt_destroy_func_t’; did you mean ‘bt_hci_destroy_func_t’? 19 | void *user_data, mgmt_destroy_func_t destroy); | ^~~~~~~~~~~~~~~~~~~ | bt_hci_destroy_func_t ./mesh/mesh-mgmt.h:21:5: error: unknown type name ‘mgmt_notify_func_t’ 21 | mgmt_notify_func_t callback, | ^~~~~~~~~~~~~~~~~~ ./mesh/mesh-mgmt.h:22:22: error: unknown type name ‘mgmt_destroy_func_t’; did you mean ‘bt_hci_destroy_func_t’? 22 | void *user_data, mgmt_destroy_func_t destroy); | ^~~~~~~~~~~~~~~~~~~ | bt_hci_destroy_func_t mesh/mesh-io-generic.c: In function ‘dev_init’: mesh/mesh-io-generic.c:448:25: error: passing argument 1 of ‘mesh_mgmt_list’ from incompatible pointer type [-Werror=incompatible-pointer-types] 448 | return mesh_mgmt_list(read_info, io); | ^~~~~~~~~ | | | void (*)(int, void *) In file included from mesh/mesh-io-generic.c:26: ./mesh/mesh-mgmt.h:15:48: note: expected ‘mesh_mgmt_read_info_func_t’ {aka ‘void (*)(int, _Bool, _Bool, _Bool, void *)’} but argument is of type ‘void (*)(int, void *)’ 15 | bool mesh_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~ cc1: all warnings being treated as errors make[1]: *** [Makefile:7271: mesh/mesh-io-generic.o] Error 1 make: *** [Makefile:4307: all] Error 2

Commit Message

Brian Gix Feb. 24, 2022, 2:06 a.m. UTC
While mesh-io-mgmt is the main consumer of MGMT services, we also use
MGMT to identify controllers and their capabilities, when determining
the appropriate Mesh IO carrier. This centralizes all MGMT access to
a single socket, shared accross all consumers.

Also fixes the Controller added/removed handling so that a controller
disappearing or reappearing gets handled rationally.
---
 mesh/mesh-mgmt.c | 149 ++++++++++++++++++++++++++++++++++++-----------
 mesh/mesh-mgmt.h |  12 +++-
 2 files changed, 125 insertions(+), 36 deletions(-)
diff mbox series

Patch

diff --git a/mesh/mesh-mgmt.c b/mesh/mesh-mgmt.c
index 754093dbc..e878a4f11 100644
--- a/mesh/mesh-mgmt.c
+++ b/mesh/mesh-mgmt.c
@@ -12,35 +12,63 @@ 
 #include <config.h>
 #endif
 
+#include <ell/ell.h>
+
 #include "lib/bluetooth.h"
 #include "lib/mgmt.h"
 #include "src/shared/mgmt.h"
 
-#include "ell/queue.h"
-#include "ell/log.h"
-#include "ell/util.h"
-
 #include "mesh/mesh-mgmt.h"
 
-struct read_info_reg {
-	mesh_mgmt_read_info_func_t cb;
-	void *user_data;
-};
-
-struct read_info_req {
-	int index;
-	struct mesh_io *io;
+struct mesh_controler {
+	int	index;
+	bool	mesh_support;
+	bool	powered;
 };
 
+static mesh_mgmt_read_info_func_t ctl_info;
 static struct mgmt *mgmt_mesh;
-static struct l_queue *read_info_regs;
+static struct l_queue *ctl_list;
+static void *list_user_data;
+static bool mesh_detected;
+
+static bool by_index(const void *a, const void *b)
+{
+	const struct mesh_controler *ctl = a;
+	int index = L_PTR_TO_UINT(b);
 
-static void process_read_info_req(void *data, void *user_data)
+	return ctl->index == index;
+}
+
+static void index_removed(uint16_t index, uint16_t length, const void *param,
+							void *user_data);
+static void features_cb(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
 {
-	struct read_info_reg *reg = data;
 	int index = L_PTR_TO_UINT(user_data);
+	struct mesh_controler *ctl;
+
 
-	reg->cb(index, reg->user_data);
+	ctl = l_queue_find(ctl_list, by_index, L_UINT_TO_PTR(index));
+	if (!ctl)
+		return;
+
+	l_debug("Status: %d, Length: %d", status, length);
+	if (status != MGMT_STATUS_NOT_SUPPORTED &&
+					status != MGMT_STATUS_UNKNOWN_COMMAND) {
+		ctl->mesh_support = true;
+		if (!mesh_detected) {
+			mgmt_register(mgmt_mesh, MGMT_EV_INDEX_REMOVED,
+					MGMT_INDEX_NONE, index_removed,
+					NULL, NULL);
+		}
+		mesh_detected = true;
+	} else
+		l_debug("Kernel mesh not supported for hci%u", index);
+
+	if (ctl_info)
+		ctl_info(index, true, ctl->powered, ctl->mesh_support,
+							list_user_data);
 }
 
 static void read_info_cb(uint8_t status, uint16_t length,
@@ -49,12 +77,25 @@  static void read_info_cb(uint8_t status, uint16_t length,
 	int index = L_PTR_TO_UINT(user_data);
 	const struct mgmt_rp_read_info *rp = param;
 	uint32_t current_settings, supported_settings;
+	struct mesh_controler *ctl;
 
 	l_debug("hci %u status 0x%02x", index, status);
 
+	ctl = l_queue_find(ctl_list, by_index, L_UINT_TO_PTR(index));
+	if (!ctl)
+		return;
+
 	if (status != MGMT_STATUS_SUCCESS) {
+		ctl = l_queue_remove_if(ctl_list, by_index,
+						L_UINT_TO_PTR(index));
 		l_error("Failed to read info for hci index %u: %s (0x%02x)",
 				index, mgmt_errstr(status), status);
+
+		l_warn("Hci dev %d removal detected", index);
+		if (ctl && ctl_info)
+			ctl_info(index, false, false, false, list_user_data);
+
+		l_free(ctl);
 		return;
 	}
 
@@ -69,23 +110,34 @@  static void read_info_cb(uint8_t status, uint16_t length,
 	l_debug("settings: supp %8.8x curr %8.8x",
 					supported_settings, current_settings);
 
-	if (current_settings & MGMT_SETTING_POWERED) {
-		l_info("Controller hci %u is in use", index);
-		return;
-	}
-
 	if (!(supported_settings & MGMT_SETTING_LE)) {
 		l_info("Controller hci %u does not support LE", index);
+		l_queue_remove(ctl_list, ctl);
+		l_free(ctl);
 		return;
 	}
 
-	l_queue_foreach(read_info_regs, process_read_info_req,
-							L_UINT_TO_PTR(index));
+	if (current_settings & MGMT_SETTING_POWERED)
+		ctl->powered = true;
+
+	mesh_mgmt_send(MGMT_OP_MESH_READ_FEATURES, index, 0, NULL,
+				features_cb, L_UINT_TO_PTR(index), NULL);
 }
 
 static void index_added(uint16_t index, uint16_t length, const void *param,
 							void *user_data)
 {
+	struct mesh_controler *ctl = l_queue_find(ctl_list, by_index,
+							L_UINT_TO_PTR(index));
+
+	if (!ctl) {
+		ctl = l_new(struct mesh_controler, 1);
+		ctl->index = index;
+		l_queue_push_head(ctl_list, ctl);
+	} else {
+		ctl->mesh_support = ctl->powered = false;
+	}
+
 	mgmt_send(mgmt_mesh, MGMT_OP_READ_INFO, index, 0, NULL,
 				read_info_cb, L_UINT_TO_PTR(index), NULL);
 }
@@ -93,7 +145,9 @@  static void index_added(uint16_t index, uint16_t length, const void *param,
 static void index_removed(uint16_t index, uint16_t length, const void *param,
 							void *user_data)
 {
-	l_warn("Hci dev %4.4x removed", index);
+	mgmt_send(mgmt_mesh, MGMT_OP_READ_INFO, index, 0, NULL,
+				read_info_cb, L_UINT_TO_PTR(index), NULL);
+
 }
 
 static void read_index_list_cb(uint8_t status, uint16_t length,
@@ -133,8 +187,8 @@  static void read_index_list_cb(uint8_t status, uint16_t length,
 
 static bool mesh_mgmt_init(void)
 {
-	if (!read_info_regs)
-		read_info_regs = l_queue_new();
+	if (!ctl_list)
+		ctl_list = l_queue_new();
 
 	if (!mgmt_mesh) {
 		mgmt_mesh = mgmt_new_default();
@@ -146,8 +200,6 @@  static bool mesh_mgmt_init(void)
 
 		mgmt_register(mgmt_mesh, MGMT_EV_INDEX_ADDED,
 				MGMT_INDEX_NONE, index_added, NULL, NULL);
-		mgmt_register(mgmt_mesh, MGMT_EV_INDEX_REMOVED,
-				MGMT_INDEX_NONE, index_removed, NULL, NULL);
 	}
 
 	return true;
@@ -155,16 +207,11 @@  static bool mesh_mgmt_init(void)
 
 bool mesh_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data)
 {
-	struct read_info_reg *reg;
-
 	if (!mesh_mgmt_init())
 		return false;
 
-	reg = l_new(struct read_info_reg, 1);
-	reg->cb = cb;
-	reg->user_data = user_data;
-
-	l_queue_push_tail(read_info_regs, reg);
+	ctl_info = cb;
+	list_user_data = user_data;
 
 	/* Use MGMT to find a candidate controller */
 	l_debug("send read index_list");
@@ -175,3 +222,35 @@  bool mesh_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data)
 
 	return true;
 }
+
+void mesh_mgmt_destroy()
+{
+	mgmt_unref(mgmt_mesh);
+	mgmt_mesh = NULL;
+	ctl_info = NULL;
+	list_user_data = NULL;
+	l_queue_destroy(ctl_list, l_free);
+	ctl_list = NULL;
+}
+
+unsigned int mesh_mgmt_send(uint16_t opcode, uint16_t index,
+				uint16_t length, const void *param,
+				mgmt_request_func_t callback,
+				void *user_data, mgmt_destroy_func_t destroy)
+{
+	return mgmt_send_timeout(mgmt_mesh, opcode, index, length, param,
+					callback, user_data, destroy, 0);
+}
+
+unsigned int mesh_mgmt_register(uint16_t event, uint16_t index,
+				mgmt_notify_func_t callback,
+				void *user_data, mgmt_destroy_func_t destroy)
+{
+	return mgmt_register(mgmt_mesh, event, index, callback,
+						user_data, destroy);
+}
+
+bool mesh_mgmt_unregister(unsigned int id)
+{
+	return mgmt_unregister(mgmt_mesh, id);
+}
diff --git a/mesh/mesh-mgmt.h b/mesh/mesh-mgmt.h
index 90ac14e73..a3cd72faf 100644
--- a/mesh/mesh-mgmt.h
+++ b/mesh/mesh-mgmt.h
@@ -9,6 +9,16 @@ 
  */
 #include <stdbool.h>
 
-typedef void (*mesh_mgmt_read_info_func_t)(int index, void *user_data);
+typedef void (*mesh_mgmt_read_info_func_t)(int index, bool added, bool powered,
+						bool mesh, void *user_data);
 
 bool mesh_mgmt_list(mesh_mgmt_read_info_func_t cb, void *user_data);
+unsigned int mesh_mgmt_send(uint16_t opcode, uint16_t index,
+				uint16_t length, const void *param,
+				mgmt_request_func_t callback,
+				void *user_data, mgmt_destroy_func_t destroy);
+unsigned int mesh_mgmt_register(uint16_t event, uint16_t index,
+				mgmt_notify_func_t callback,
+				void *user_data, mgmt_destroy_func_t destroy);
+bool mesh_mgmt_unregister(unsigned int id);
+void mesh_mgmt_destroy(void);