diff --git a/Makefile.tools b/Makefile.tools
index 338365d..7c942a3 100644
--- a/Makefile.tools
+++ b/Makefile.tools
tools_gap_tester_SOURCES = tools/gap-tester.c monitor/bt.h \
emulator/btdev.h emulator/btdev.c \
emulator/bthost.h emulator/bthost.c \
+ src/shared/util.h src/shared/util.c \
+ src/shared/queue.h src/shared/queue.c \
src/shared/hciemu.h src/shared/hciemu.c \
src/shared/tester.h src/shared/tester.c
tools_gap_tester_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@
diff --git a/src/shared/hciemu.c b/src/shared/hciemu.c
index 9f4bfaf..d2c4a2e 100644
--- a/src/shared/hciemu.c
+++ b/src/shared/hciemu.c
#include <bluetooth/hci.h>
#include "monitor/bt.h"
+#include "src/shared/util.h"
+#include "src/shared/queue.h"
#include "emulator/btdev.h"
#include "emulator/bthost.h"
guint host_source;
guint master_source;
guint client_source;
- GList *post_command_hooks;
+ struct queue *post_command_hooks;
char bdaddr_str[18];
};
void *user_data;
};
-static void destroy_command_hook(gpointer data, gpointer user_data)
+static void destroy_command_hook(void *data)
{
struct hciemu_command_hook *hook = data;
- g_free(hook);
+ free(hook);
+}
+
+struct run_data {
+ uint16_t opcode;
+ const void *data;
+ uint8_t len;
+};
+
+static void run_command_hook(void *data, void *user_data)
+{
+ struct hciemu_command_hook *hook = data;
+ struct run_data *run_data = user_data;
+
+ if (hook->function)
+ hook->function(run_data->opcode, run_data->data,
+ run_data->len, hook->user_data);
}
static void master_command_callback(uint16_t opcode,
btdev_callback callback, void *user_data)
{
struct hciemu *hciemu = user_data;
- GList *list;
+ struct run_data run_data = { .opcode = opcode,
+ .data = data, .len = len };
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);
- }
+ queue_foreach(hciemu->post_command_hooks, run_command_hook, &run_data);
}
static void client_command_callback(uint16_t opcode,
{
struct hciemu *hciemu;
- hciemu = g_try_new0(struct hciemu, 1);
+ hciemu = new0(struct hciemu, 1);
if (!hciemu)
return NULL;
return NULL;
}
+ hciemu->post_command_hooks = queue_new();
+ if (!hciemu->post_command_hooks) {
+ free(hciemu);
+ return NULL;
+ }
+
if (!create_vhci(hciemu)) {
- g_free(hciemu);
+ queue_destroy(hciemu->post_command_hooks, NULL);
+ free(hciemu);
return NULL;
}
if (!create_stack(hciemu)) {
g_source_remove(hciemu->master_source);
btdev_destroy(hciemu->master_dev);
- g_free(hciemu);
+ queue_destroy(hciemu->post_command_hooks, NULL);
+ free(hciemu);
return NULL;
}
if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
return;
- g_list_foreach(hciemu->post_command_hooks, destroy_command_hook, NULL);
- g_list_free(hciemu->post_command_hooks);
+ queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
bthost_stop(hciemu->host_stack);
btdev_destroy(hciemu->client_dev);
btdev_destroy(hciemu->master_dev);
- g_free(hciemu);
+ free(hciemu);
}
const char *hciemu_get_address(struct hciemu *hciemu)
if (!hciemu)
return false;
- hook = g_try_new0(struct hciemu_command_hook, 1);
+ hook = 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);
+ if (!queue_push_tail(hciemu->post_command_hooks, hook)) {
+ free(hook);
+ return false;
+ }
return true;
}