Diff between 41a61de78a20446722bdda69d80e313630cdc853 and 390cf7f898e8e93f3eb0e438e99e0cc163f38f6c

Changed Files

File Additions Deletions Status
tools/hciemu.c +49 -5 modified
tools/hciemu.h +8 -0 modified

Full Patch

diff --git a/tools/hciemu.c b/tools/hciemu.c
index dc83d40..0befedf 100644
--- a/tools/hciemu.c
+++ b/tools/hciemu.c
@@ -47,23 +47,43 @@ struct hciemu {
 	guint host_source;
 	guint master_source;
 	guint client_source;
+	GList *post_command_hooks;
 };
 
+struct hciemu_command_hook {
+	hciemu_command_func_t function;
+	void *user_data;
+};
+
+static void destroy_command_hook(gpointer data, gpointer user_data)
+{
+	struct hciemu_command_hook *hook = data;
+
+	g_free(hook);
+}
+
 static void master_command_callback(uint16_t opcode,
 				const void *data, uint8_t len,
 				btdev_callback callback, void *user_data)
 {
-	g_print("[master] opcode 0x%04x len %d\n", opcode, len);
+	struct hciemu *hciemu = user_data;
+	GList *list;
 
 	btdev_command_default(callback);
+
+	for (list = g_list_first(hciemu->post_command_hooks); list;
+						list = g_list_next(list)) {
+		struct hciemu_command_hook *hook = list->data;
+
+		if (hook->function)
+			hook->function(opcode, data, len, hook->user_data);
+	}
 }
 
 static void client_command_callback(uint16_t opcode,
 				const void *data, uint8_t len,
 				btdev_callback callback, void *user_data)
 {
-	g_print("[client] opcode 0x%04x len %d\n", opcode, len);
-
 	btdev_command_default(callback);
 }
 
@@ -185,7 +205,7 @@ static void create_vhci(struct hciemu *hciemu)
 		bdaddr[i] = strtol(str, NULL, 16);
 
 	btdev_set_bdaddr(btdev, bdaddr);
-	btdev_set_command_handler(btdev, master_command_callback, NULL);
+	btdev_set_command_handler(btdev, master_command_callback, hciemu);
 
 	fd = open("/dev/vhci", O_RDWR | O_NONBLOCK | O_CLOEXEC);
 	if (fd < 0) {
@@ -214,7 +234,7 @@ static void create_stack(struct hciemu *hciemu)
 		return;
 	}
 
-	btdev_set_command_handler(btdev, client_command_callback, NULL);
+	btdev_set_command_handler(btdev, client_command_callback, hciemu);
 
 	if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC,
 								0, sv) < 0) {
@@ -273,6 +293,9 @@ void hciemu_unref(struct hciemu *hciemu)
 	if (g_atomic_int_dec_and_test(&hciemu->ref_count) == FALSE)
 		return;
 
+	g_list_foreach(hciemu->post_command_hooks, destroy_command_hook, NULL);
+	g_list_free(hciemu->post_command_hooks);
+
 	bthost_stop(hciemu->host_stack);
 
 	g_source_remove(hciemu->host_source);
@@ -293,3 +316,24 @@ const char *hciemu_get_address(struct hciemu *hciemu)
 
 	return "00:FA:CE:1E:55:00";
 }
+
+bool hciemu_add_master_post_command_hook(struct hciemu *hciemu,
+			hciemu_command_func_t function, void *user_data)
+{
+	struct hciemu_command_hook *hook;
+
+	if (!hciemu)
+		return false;
+
+	hook = g_try_new0(struct hciemu_command_hook, 1);
+	if (!hook)
+		return false;
+
+	hook->function = function;
+	hook->user_data = user_data;
+
+	hciemu->post_command_hooks = g_list_append(hciemu->post_command_hooks,
+									hook);
+
+	return true;
+}
diff --git a/tools/hciemu.h b/tools/hciemu.h
index 1a7dff9..2592c3a 100644
--- a/tools/hciemu.h
+++ b/tools/hciemu.h
@@ -21,6 +21,8 @@
  *
  */
 
+#include <stdbool.h>
+
 struct hciemu;
 
 struct hciemu *hciemu_new(void);
@@ -29,3 +31,9 @@ struct hciemu *hciemu_ref(struct hciemu *hciemu);
 void hciemu_unref(struct hciemu *hciemu);
 
 const char *hciemu_get_address(struct hciemu *hciemu);
+
+typedef void (*hciemu_command_func_t)(uint16_t opcode, const void *data,
+						uint8_t len, void *user_data);
+
+bool hciemu_add_master_post_command_hook(struct hciemu *hciemu,
+			hciemu_command_func_t function, void *user_data);