All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH BlueZ 00/10] Convert tools to use ELL library
@ 2020-11-07  7:03 Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 01/10] shared/tester-ell: Create ell-based version of tester code Inga Stotland
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This patch set is a part of ongoing effort to remove GLib dependencies
from BlueZ in favor of using ELL library.

bluez/tools subdirectory is chosen as a first candidate since
it provides standalone functionality making it easier to adress the
issues discovered during the conversion process.

The patch set is a snapshot of *some* tools converted to use ELL as well
as ELL based versions of emulator/hciemu-ell.c and shared/tester-ell.c.

Inga Stotland (10):
  shared/tester-ell: Create ell-based version of tester code
  emulator/hciemu: Create ELL based version of hciemu
  tools/gap-tester: Convert to use ELL library
  tools/sco-tester: Convert to use ELL library
  tools/userchan-tester: Convert to use ELL library
  tools/smp-tester: Convert to use ELL library
  tools/bnep-tester: Convert to use ELL library
  tools/l2cap-tester: Convert to use ELL library
  tools/mgmt-tester: Convert to use ELL library
  tools/rfcomm-tester: Convert to use ELL library

 Makefile.am             |   8 +-
 Makefile.tools          |  34 +-
 emulator/hciemu-ell.c   | 564 ++++++++++++++++++++++++++
 src/shared/tester-ell.c | 875 ++++++++++++++++++++++++++++++++++++++++
 tools/bnep-tester.c     |   9 +-
 tools/gap-tester.c      |  87 ++--
 tools/l2cap-tester.c    | 256 ++++++------
 tools/mgmt-tester.c     |   5 +-
 tools/rfcomm-tester.c   |  92 +++--
 tools/sco-tester.c      |  33 +-
 tools/smp-tester.c      |  24 +-
 tools/userchan-tester.c |   2 -
 12 files changed, 1715 insertions(+), 274 deletions(-)
 create mode 100644 emulator/hciemu-ell.c
 create mode 100644 src/shared/tester-ell.c

-- 
2.26.2


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

* [RFC PATCH BlueZ 01/10] shared/tester-ell: Create ell-based version of tester code
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-07  7:26   ` Convert tools to use ELL library bluez.test.bot
  2020-11-07  7:03 ` [RFC PATCH BlueZ 02/10] emulator/hciemu: Create ELL based version of hciemu Inga Stotland
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

Create a version of tester that uses ell primitives instead of glib:
tester-ell.c. This source is included to generate lishared-ell library.
The original tester.c is built as part of libshared-glib library.
---
 Makefile.am             |   8 +-
 src/shared/tester-ell.c | 875 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 880 insertions(+), 3 deletions(-)
 create mode 100644 src/shared/tester-ell.c

diff --git a/Makefile.am b/Makefile.am
index 69b95828f..952b9cc5b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -191,7 +191,7 @@ shared_sources = src/shared/io.h src/shared/timeout.h \
 			src/shared/crypto.h src/shared/crypto.c \
 			src/shared/ecc.h src/shared/ecc.c \
 			src/shared/ringbuf.h src/shared/ringbuf.c \
-			src/shared/tester.h src/shared/tester.c \
+			src/shared/tester.h\
 			src/shared/hci.h src/shared/hci.c \
 			src/shared/hci-crypto.h src/shared/hci-crypto.c \
 			src/shared/hfp.h src/shared/hfp.c \
@@ -218,7 +218,8 @@ src_libshared_glib_la_SOURCES = $(shared_sources) \
 				src/shared/timeout-glib.c \
 				src/shared/mainloop-glib.c \
 				src/shared/mainloop-notify.h \
-				src/shared/mainloop-notify.c
+				src/shared/mainloop-notify.c \
+				src/shared/tester.c
 
 src_libshared_mainloop_la_SOURCES = $(shared_sources) \
 				src/shared/io-mainloop.c \
@@ -232,7 +233,8 @@ src_libshared_ell_la_SOURCES = $(shared_sources) \
 				src/shared/io-ell.c \
 				src/shared/timeout-ell.c \
 				src/shared/mainloop.h \
-				src/shared/mainloop-ell.c
+				src/shared/mainloop-ell.c \
+				src/shared/tester-ell.c
 endif
 
 attrib_sources = attrib/att.h attrib/att-database.h attrib/att.c \
diff --git a/src/shared/tester-ell.c b/src/shared/tester-ell.c
new file mode 100644
index 000000000..4d7b794b9
--- /dev/null
+++ b/src/shared/tester-ell.c
@@ -0,0 +1,875 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012-2014, 2020  Intel Corporation. All rights reserved.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <stdio.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/signalfd.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <ell/ell.h>
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+#include <valgrind/memcheck.h>
+#endif
+
+#include "src/shared/mainloop.h"
+#include "src/shared/util.h"
+#include "src/shared/tester.h"
+#include "src/shared/log.h"
+
+#define COLOR_OFF	"\x1B[0m"
+#define COLOR_BLACK	"\x1B[0;30m"
+#define COLOR_RED	"\x1B[0;31m"
+#define COLOR_GREEN	"\x1B[0;32m"
+#define COLOR_YELLOW	"\x1B[0;33m"
+#define COLOR_BLUE	"\x1B[0;34m"
+#define COLOR_MAGENTA	"\x1B[0;35m"
+#define COLOR_CYAN	"\x1B[0;36m"
+#define COLOR_WHITE	"\x1B[0;37m"
+#define COLOR_HIGHLIGHT	"\x1B[1;39m"
+
+#define print_text(color, fmt, args...) \
+		tester_log(color fmt COLOR_OFF, ## args)
+
+#define print_summary(label, color, value, fmt, args...) \
+		tester_log("%-52s " color "%-10s" COLOR_OFF fmt, \
+							label, value, ## args)
+
+#define print_progress(name, color, fmt, args...) \
+		tester_log(COLOR_HIGHLIGHT "%s" COLOR_OFF " - " \
+				color fmt COLOR_OFF, name, ## args)
+
+enum test_result {
+	TEST_RESULT_NOT_RUN,
+	TEST_RESULT_PASSED,
+	TEST_RESULT_FAILED,
+	TEST_RESULT_TIMED_OUT,
+};
+
+enum test_stage {
+	TEST_STAGE_INVALID,
+	TEST_STAGE_PRE_SETUP,
+	TEST_STAGE_SETUP,
+	TEST_STAGE_RUN,
+	TEST_STAGE_TEARDOWN,
+	TEST_STAGE_POST_TEARDOWN,
+};
+
+struct test_case {
+	char *name;
+	enum test_result result;
+	enum test_stage stage;
+	const void *test_data;
+	tester_data_func_t pre_setup_func;
+	tester_data_func_t setup_func;
+	tester_data_func_t test_func;
+	tester_data_func_t teardown_func;
+	tester_data_func_t post_teardown_func;
+	double start_time;
+	double end_time;
+	unsigned int timeout;
+	struct l_timeout *run_timer;
+	tester_destroy_func_t destroy;
+	void *user_data;
+	bool teardown;
+};
+
+static char *tester_name;
+
+static struct l_queue *test_list;
+static const struct l_queue_entry *test_entry;
+static struct timeval tester_start;
+
+static bool option_quiet;
+static bool option_debug;
+static bool option_monitor;
+static bool option_list;
+static const char *option_prefix;
+
+struct monitor_hdr {
+	uint16_t opcode;
+	uint16_t index;
+	uint16_t len;
+	uint8_t  priority;
+	uint8_t  ident_len;
+} __attribute__((packed));
+
+struct monitor_l2cap_hdr {
+	uint16_t cid;
+	uint16_t psm;
+} __attribute__((packed));
+
+static void test_destroy(void *data)
+{
+	struct test_case *test = data;
+
+	l_timeout_remove(test->run_timer);
+
+	if (test->destroy)
+		test->destroy(test->user_data);
+
+	l_free(test->name);
+	l_free(test);
+}
+
+static void tester_vprintf(const char *format, va_list ap)
+{
+	if (tester_use_quiet())
+		return;
+
+	printf("  %s", COLOR_WHITE);
+	vprintf(format, ap);
+	printf("%s\n", COLOR_OFF);
+}
+
+static void tester_log(const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+	vprintf(format, ap);
+	printf("\n");
+	va_end(ap);
+
+	va_start(ap, format);
+	bt_log_vprintf(HCI_DEV_NONE, tester_name, LOG_INFO, format, ap);
+	va_end(ap);
+}
+
+void tester_print(const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+	tester_vprintf(format, ap);
+	va_end(ap);
+
+	va_start(ap, format);
+	bt_log_vprintf(HCI_DEV_NONE, tester_name, LOG_INFO, format, ap);
+	va_end(ap);
+}
+
+void tester_debug(const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+	tester_vprintf(format, ap);
+	va_end(ap);
+
+	va_start(ap, format);
+	bt_log_vprintf(HCI_DEV_NONE, tester_name, LOG_DEBUG, format, ap);
+	va_end(ap);
+}
+
+void tester_warn(const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+	tester_vprintf(format, ap);
+	va_end(ap);
+
+	va_start(ap, format);
+	bt_log_vprintf(HCI_DEV_NONE, tester_name, LOG_WARNING, format, ap);
+	va_end(ap);
+}
+
+static void monitor_debug(const char *str, void *user_data)
+{
+	const char *label = user_data;
+
+	tester_debug("%s: %s", label, str);
+}
+
+static void monitor_log(char dir, uint16_t cid, uint16_t psm, const void *data,
+								size_t len)
+{
+	struct iovec iov[3];
+	struct monitor_l2cap_hdr hdr;
+	uint8_t term = 0x00;
+	char label[16];
+
+	if (snprintf(label, sizeof(label), "%c %s", dir, tester_name) < 0)
+		return;
+
+	hdr.cid = cpu_to_le16(cid);
+	hdr.psm = cpu_to_le16(psm);
+
+	iov[0].iov_base = &hdr;
+	iov[0].iov_len = sizeof(hdr);
+
+	iov[1].iov_base = (void *) data;
+	iov[1].iov_len = len;
+
+	/* Kernel won't forward if data is no NULL terminated */
+	iov[2].iov_base = &term;
+	iov[2].iov_len = sizeof(term);
+
+	bt_log_sendmsg(HCI_DEV_NONE, label, LOG_INFO, iov, 3);
+}
+
+void tester_monitor(char dir, uint16_t cid, uint16_t psm, const void *data,
+								size_t len)
+{
+	monitor_log(dir, cid, psm, data, len);
+
+	if (!tester_use_debug())
+		return;
+
+	util_hexdump(dir, data, len, monitor_debug, (void *) tester_name);
+}
+
+static void default_pre_setup(const void *test_data)
+{
+	tester_pre_setup_complete();
+}
+
+static void default_setup(const void *test_data)
+{
+	tester_setup_complete();
+}
+
+static void default_teardown(const void *test_data)
+{
+	tester_teardown_complete();
+}
+
+static void default_post_teardown(const void *test_data)
+{
+	tester_post_teardown_complete();
+}
+
+void tester_add_full(const char *name, const void *test_data,
+				tester_data_func_t pre_setup_func,
+				tester_data_func_t setup_func,
+				tester_data_func_t test_func,
+				tester_data_func_t teardown_func,
+				tester_data_func_t post_teardown_func,
+				unsigned int timeout,
+				void *user_data, tester_destroy_func_t destroy)
+{
+	struct test_case *test;
+
+	if (!test_func)
+		return;
+
+	if (option_prefix && !l_str_has_prefix(name, option_prefix)) {
+		if (destroy)
+			destroy(user_data);
+		return;
+	}
+
+	if (option_list) {
+		tester_log("%s", name);
+		if (destroy)
+			destroy(user_data);
+		return;
+	}
+
+	test = l_new(struct test_case, 1);
+	test->name = l_strdup(name);
+	test->result = TEST_RESULT_NOT_RUN;
+	test->stage = TEST_STAGE_INVALID;
+
+	test->test_data = test_data;
+
+	if (pre_setup_func)
+		test->pre_setup_func = pre_setup_func;
+	else
+		test->pre_setup_func = default_pre_setup;
+
+	if (setup_func)
+		test->setup_func = setup_func;
+	else
+		test->setup_func = default_setup;
+
+	test->test_func = test_func;
+
+	if (teardown_func)
+		test->teardown_func = teardown_func;
+	else
+		test->teardown_func = default_teardown;
+
+	if (post_teardown_func)
+		test->post_teardown_func = post_teardown_func;
+	else
+		test->post_teardown_func = default_post_teardown;
+
+	test->timeout = timeout;
+
+	test->destroy = destroy;
+	test->user_data = user_data;
+
+	l_queue_push_tail(test_list, test);
+}
+
+void tester_add(const char *name, const void *test_data,
+					tester_data_func_t setup_func,
+					tester_data_func_t test_func,
+					tester_data_func_t teardown_func)
+{
+	tester_add_full(name, test_data, NULL, setup_func, test_func,
+					teardown_func, NULL, 0, NULL, NULL);
+}
+
+void *tester_get_data(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return NULL;
+
+	test = test_entry->data;
+
+	return test->user_data;
+}
+
+static double get_elapsed_time(struct timeval *base)
+{
+	static struct timeval now, elapsed;
+
+	gettimeofday(&now, NULL);
+	timersub(&now, base, &elapsed);
+
+	return elapsed.tv_sec + ((double) elapsed.tv_usec) / 1000000;
+}
+
+static int tester_summarize(void)
+{
+	unsigned int not_run = 0, passed = 0, failed = 0;
+	double execution_time;
+	const struct l_queue_entry *entry;
+
+	tester_log("");
+	print_text(COLOR_HIGHLIGHT, "");
+	print_text(COLOR_HIGHLIGHT, "Test Summary");
+	print_text(COLOR_HIGHLIGHT, "------------");
+
+	entry = l_queue_get_entries(test_list);
+
+	for (; entry; entry = entry->next) {
+		struct test_case *test = entry->data;
+		double exec_time;
+
+		exec_time = test->end_time - test->start_time;
+
+		switch (test->result) {
+		case TEST_RESULT_NOT_RUN:
+			print_summary(test->name, COLOR_YELLOW, "Not Run", "");
+			not_run++;
+			break;
+		case TEST_RESULT_PASSED:
+			print_summary(test->name, COLOR_GREEN, "Passed",
+						"%8.3f seconds", exec_time);
+			passed++;
+			break;
+		case TEST_RESULT_FAILED:
+			print_summary(test->name, COLOR_RED, "Failed",
+						"%8.3f seconds", exec_time);
+			failed++;
+			break;
+		case TEST_RESULT_TIMED_OUT:
+			print_summary(test->name, COLOR_RED, "Timed out",
+						"%8.3f seconds", exec_time);
+			failed++;
+			break;
+		}
+	}
+
+	tester_log("Total: %d, "
+		COLOR_GREEN "Passed: %d (%.1f%%)" COLOR_OFF ", "
+		COLOR_RED "Failed: %d" COLOR_OFF ", "
+		COLOR_YELLOW "Not Run: %d" COLOR_OFF,
+			not_run + passed + failed, passed,
+			(not_run + passed + failed) ?
+			(float) passed * 100 / (not_run + passed + failed) : 0,
+			failed, not_run);
+
+	execution_time = get_elapsed_time(&tester_start);
+	tester_log("Overall execution time: %.3g seconds", execution_time);
+
+	return failed;
+}
+
+static void teardown_callback(void *user_data)
+{
+	struct test_case *test = user_data;
+
+	test->stage = TEST_STAGE_TEARDOWN;
+	test->teardown = false;
+
+	print_progress(test->name, COLOR_MAGENTA, "teardown");
+	test->teardown_func(test->test_data);
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+	VALGRIND_DO_ADDED_LEAK_CHECK;
+#endif
+}
+
+static void test_timeout(struct l_timeout *timer, void *user_data)
+{
+	struct test_case *test = user_data;
+
+	l_timeout_remove(timer);
+	test->run_timer = NULL;
+
+	test->result = TEST_RESULT_TIMED_OUT;
+	print_progress(test->name, COLOR_RED, "test timed out");
+
+	l_idle_oneshot(teardown_callback, test, NULL);
+}
+
+static void next_test_case(void)
+{
+	struct test_case *test;
+
+	if (test_entry)
+		test_entry = test_entry->next;
+	else
+		test_entry = l_queue_get_entries(test_list);
+
+	if (!test_entry) {
+		mainloop_quit();
+		return;
+	}
+
+	test = test_entry->data;
+
+	tester_log("");
+	print_progress(test->name, COLOR_BLACK, "init");
+
+	test->start_time = get_elapsed_time(&tester_start);
+
+	if (test->timeout > 0)
+		test->run_timer = l_timeout_create(test->timeout, test_timeout,
+								test, NULL);
+
+	test->stage = TEST_STAGE_PRE_SETUP;
+
+	test->pre_setup_func(test->test_data);
+}
+
+static void setup_callback(void *user_data)
+{
+	struct test_case *test = user_data;
+
+	test->stage = TEST_STAGE_SETUP;
+
+	print_progress(test->name, COLOR_BLUE, "setup");
+	test->setup_func(test->test_data);
+}
+
+static void run_callback(void *user_data)
+{
+	struct test_case *test = user_data;
+
+	test->stage = TEST_STAGE_RUN;
+
+	print_progress(test->name, COLOR_BLACK, "run");
+	test->test_func(test->test_data);
+}
+
+static void done_callback(void *user_data)
+{
+	struct test_case *test = user_data;
+
+	test->end_time = get_elapsed_time(&tester_start);
+
+	print_progress(test->name, COLOR_BLACK, "done");
+	next_test_case();
+}
+
+void tester_pre_setup_complete(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_PRE_SETUP)
+		return;
+
+	l_idle_oneshot(setup_callback, test, NULL);
+}
+
+void tester_pre_setup_failed(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_PRE_SETUP)
+		return;
+
+	print_progress(test->name, COLOR_RED, "pre setup failed");
+
+	l_idle_oneshot(done_callback, test, NULL);
+}
+
+void tester_setup_complete(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_SETUP)
+		return;
+
+	print_progress(test->name, COLOR_BLUE, "setup complete");
+
+	l_idle_oneshot(run_callback, test, NULL);
+}
+
+void tester_setup_failed(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_SETUP)
+		return;
+
+	test->stage = TEST_STAGE_POST_TEARDOWN;
+
+	l_timeout_remove(test->run_timer);
+	test->run_timer = NULL;
+
+	print_progress(test->name, COLOR_RED, "setup failed");
+	print_progress(test->name, COLOR_MAGENTA, "teardown");
+
+	test->post_teardown_func(test->test_data);
+}
+
+static void test_result(enum test_result result)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_RUN)
+		return;
+
+	l_timeout_remove(test->run_timer);
+	test->run_timer = NULL;
+
+	test->result = result;
+	switch (result) {
+	case TEST_RESULT_PASSED:
+		print_progress(test->name, COLOR_GREEN, "test passed");
+		break;
+	case TEST_RESULT_FAILED:
+		print_progress(test->name, COLOR_RED, "test failed");
+		break;
+	case TEST_RESULT_NOT_RUN:
+		print_progress(test->name, COLOR_YELLOW, "test not run");
+		break;
+	case TEST_RESULT_TIMED_OUT:
+		print_progress(test->name, COLOR_RED, "test timed out");
+		break;
+	}
+
+	if (test->teardown)
+		return;
+
+	test->teardown = true;
+
+	l_idle_oneshot(teardown_callback, test, NULL);
+}
+
+void tester_test_passed(void)
+{
+	test_result(TEST_RESULT_PASSED);
+}
+
+void tester_test_failed(void)
+{
+	test_result(TEST_RESULT_FAILED);
+}
+
+void tester_test_abort(void)
+{
+	test_result(TEST_RESULT_NOT_RUN);
+}
+
+void tester_teardown_complete(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_TEARDOWN)
+		return;
+
+	test->stage = TEST_STAGE_POST_TEARDOWN;
+
+	test->post_teardown_func(test->test_data);
+}
+
+void tester_teardown_failed(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_TEARDOWN)
+		return;
+
+	test->stage = TEST_STAGE_POST_TEARDOWN;
+
+	tester_post_teardown_failed();
+}
+
+void tester_post_teardown_complete(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_POST_TEARDOWN)
+		return;
+
+	print_progress(test->name, COLOR_MAGENTA, "teardown complete");
+
+	l_idle_oneshot(done_callback, test, NULL);
+}
+
+void tester_post_teardown_failed(void)
+{
+	struct test_case *test;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	if (test->stage != TEST_STAGE_POST_TEARDOWN)
+		return;
+
+	print_progress(test->name, COLOR_RED, "teardown failed");
+
+	l_idle_oneshot(done_callback, test, NULL);
+}
+
+static void start_tester(void *user_data)
+{
+	gettimeofday(&tester_start, NULL);
+	next_test_case();
+}
+
+struct wait_data {
+	unsigned int seconds;
+	struct test_case *test;
+	tester_wait_func_t func;
+	void *user_data;
+};
+
+static void wait_callback(struct l_timeout *timer, void *user_data)
+{
+	struct wait_data *wait = user_data;
+	struct test_case *test = wait->test;
+
+	wait->seconds--;
+
+	if (wait->seconds > 0) {
+		print_progress(test->name, COLOR_BLACK, "%u seconds left",
+								wait->seconds);
+		return;
+	}
+
+	print_progress(test->name, COLOR_BLACK, "waiting done");
+
+	wait->func(wait->user_data);
+
+	free(wait);
+
+	l_timeout_remove(timer);
+}
+
+void tester_wait(unsigned int seconds, tester_wait_func_t func,
+							void *user_data)
+{
+	struct test_case *test;
+	struct wait_data *wait;
+
+	if (!func || seconds < 1)
+		return;
+
+	if (!test_entry)
+		return;
+
+	test = test_entry->data;
+
+	wait = new0(struct wait_data, 1);
+	wait->seconds = seconds;
+	wait->test = test;
+	wait->func = func;
+	wait->user_data = user_data;
+
+	l_timeout_create(1000, wait_callback, wait, NULL);
+
+	print_progress(test->name, COLOR_BLACK, "waiting %u seconds", seconds);
+}
+
+static void signal_callback(int signum, void *user_data)
+{
+	static bool terminated = false;
+
+	switch (signum) {
+	case SIGINT:
+	case SIGTERM:
+		if (!terminated)
+			mainloop_quit();
+
+		terminated = true;
+		break;
+	}
+}
+
+bool tester_use_quiet(void)
+{
+	return option_quiet;
+}
+
+bool tester_use_debug(void)
+{
+	return option_debug;
+}
+
+static const struct option options[] = {
+	{ "version",	no_argument,		NULL, 'v' },
+	{ "quiet",	no_argument,		NULL, 'q' },
+	{ "debug",	no_argument,		NULL, 'd' },
+	{ "monitor",	no_argument,		NULL, 'm' },
+	{ "list",	no_argument,		NULL, 'l' },
+	{ "prefix",	required_argument,	NULL, 'p' },
+	{ }
+};
+
+static void usage(void)
+{
+	fprintf(stderr,
+		"Usage:\n"
+		"\%s [options]\n", tester_name);
+	fprintf(stderr,
+		"Options:\n"
+		"\t--version	Show version information and exit\n"
+		"\t--quiet	Run tests without logging\n"
+		"\t--debug	Run tests with debug output\n"
+		"\t--monitor	Enable monitor output\n"
+		"\t--list	Only list the tests to be run\n"
+		"\t--prefix	Run tests matching provided prefix\n");
+}
+
+void tester_init(int *argc, char ***argv)
+{
+	tester_name = strrchr(*argv[0], '/');
+	if (!tester_name)
+		tester_name = strdup(*argv[0]);
+	else
+		tester_name = strdup(++tester_name);
+
+	for (;;) {
+		int opt;
+
+		opt = getopt_long(*argc, *argv, "p:vqdml", options, NULL);
+		if (opt < 0)
+			break;
+
+		switch (opt) {
+		case 'v':
+			printf("%s\n", VERSION);
+			exit(EXIT_SUCCESS);
+		case 'q':
+			option_quiet = true;
+			break;
+		case 'd':
+			option_debug = true;
+			break;
+		case 'm':
+			option_monitor = true;
+			break;
+		case 'l':
+			option_list = true;
+			break;
+		case 'p':
+			option_prefix = optarg;
+			break;
+		default:
+			usage();
+			exit(EXIT_SUCCESS);
+		}
+	}
+
+	mainloop_init();
+
+	test_list = l_queue_new();
+}
+
+int tester_run(void)
+{
+	int ret;
+
+	if (option_list) {
+		mainloop_quit();
+		return EXIT_SUCCESS;
+	}
+
+	l_idle_oneshot(start_tester, NULL, NULL);
+
+	mainloop_run_with_signal(signal_callback, NULL);
+
+	ret = tester_summarize();
+
+	l_queue_destroy(test_list, test_destroy);
+
+	if (option_monitor)
+		bt_log_close();
+
+	return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
-- 
2.26.2


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

* [RFC PATCH BlueZ 02/10] emulator/hciemu: Create ELL based version of hciemu
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 01/10] shared/tester-ell: Create ell-based version of tester code Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-09 18:04   ` Luiz Augusto von Dentz
  2020-11-07  7:03 ` [RFC PATCH BlueZ 03/10] tools/gap-tester: Convert to use ELL library Inga Stotland
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This adds a separate implementtion of hciemu code, hciemu-ell.c,
that uses ELL library primitives.
---
 emulator/hciemu-ell.c | 564 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 564 insertions(+)
 create mode 100644 emulator/hciemu-ell.c

diff --git a/emulator/hciemu-ell.c b/emulator/hciemu-ell.c
new file mode 100644
index 000000000..40342e99b
--- /dev/null
+++ b/emulator/hciemu-ell.c
@@ -0,0 +1,564 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012-2014, 2020  Intel Corporation. All rights reserved.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <sys/socket.h>
+
+#include <ell/ell.h>
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+
+#include "monitor/bt.h"
+#include "emulator/btdev.h"
+#include "emulator/bthost.h"
+#include "src/shared/util.h"
+#include "src/shared/queue.h"
+#include "emulator/hciemu.h"
+
+struct hciemu {
+	int ref_count;
+	enum btdev_type btdev_type;
+	struct bthost *host_stack;
+	struct btdev *master_dev;
+	struct btdev *client_dev;
+	struct l_io *host_io;
+	struct l_io *master_io;
+	struct l_io *client_io;
+	struct queue *post_command_hooks;
+	char bdaddr_str[18];
+
+	hciemu_debug_func_t debug_callback;
+	hciemu_destroy_func_t debug_destroy;
+	void *debug_data;
+};
+
+struct hciemu_command_hook {
+	hciemu_command_func_t function;
+	void *user_data;
+};
+
+static void destroy_command_hook(void *data)
+{
+	struct hciemu_command_hook *hook = data;
+
+	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,
+				const void *data, uint8_t len,
+				btdev_callback callback, void *user_data)
+{
+	struct hciemu *hciemu = user_data;
+	struct run_data run_data = { .opcode = opcode,
+						.data = data, .len = len };
+
+	btdev_command_default(callback);
+
+	queue_foreach(hciemu->post_command_hooks, run_command_hook, &run_data);
+}
+
+static void client_command_callback(uint16_t opcode,
+				const void *data, uint8_t len,
+				btdev_callback callback, void *user_data)
+{
+	btdev_command_default(callback);
+}
+
+static void writev_callback(const struct iovec *iov, int iovlen,
+								void *user_data)
+{
+	struct l_io *io = user_data;
+	ssize_t written;
+	int fd;
+
+	fd = l_io_get_fd(io);
+
+	written = writev(fd, iov, iovlen);
+	if (written < 0)
+		return;
+}
+
+static bool receive_bthost(struct l_io *io, void *user_data)
+{
+	struct bthost *bthost = user_data;
+	unsigned char buf[4096];
+	ssize_t len;
+	int fd;
+
+	fd = l_io_get_fd(io);
+
+	len = read(fd, buf, sizeof(buf));
+	if (len < 0)
+		return false;
+
+	bthost_receive_h4(bthost, buf, len);
+
+	return true;
+}
+
+static struct l_io *create_io_bthost(int fd, struct bthost *bthost)
+{
+	struct l_io *io;
+
+	io = l_io_new(fd);
+
+	l_io_set_close_on_destroy(io, true);
+
+	bthost_set_send_handler(bthost, writev_callback, io);
+
+	l_io_set_read_handler(io, receive_bthost, bthost, NULL);
+
+	return io;
+}
+
+static bool receive_btdev(struct l_io *io, void *user_data)
+
+{
+	struct btdev *btdev = user_data;
+	unsigned char buf[4096];
+	ssize_t len;
+	int fd;
+
+	fd = l_io_get_fd(io);
+
+	len = read(fd, buf, sizeof(buf));
+	if (len < 0) {
+		if (errno == EAGAIN || errno == EINTR)
+			return true;
+
+		return false;
+	}
+
+	if (len < 1)
+		return false;
+
+	switch (buf[0]) {
+	case BT_H4_CMD_PKT:
+	case BT_H4_ACL_PKT:
+	case BT_H4_SCO_PKT:
+		btdev_receive_h4(btdev, buf, len);
+		break;
+	}
+
+	return true;
+}
+
+static struct l_io *create_io_btdev(int fd, struct btdev *btdev)
+{
+	struct l_io *io;
+
+	io = l_io_new(fd);
+
+	l_io_set_close_on_destroy(io, true);
+
+	btdev_set_send_handler(btdev, writev_callback, io);
+
+	l_io_set_read_handler(io, receive_btdev, btdev, NULL);
+
+	return io;
+}
+
+static bool create_vhci(struct hciemu *hciemu)
+{
+	struct btdev *btdev;
+	uint8_t create_req[2];
+	ssize_t written;
+	int fd;
+
+	btdev = btdev_create(hciemu->btdev_type, 0x00);
+	if (!btdev)
+		return false;
+
+	btdev_set_command_handler(btdev, master_command_callback, hciemu);
+
+	fd = open("/dev/vhci", O_RDWR | O_NONBLOCK | O_CLOEXEC);
+	if (fd < 0) {
+		perror("Opening /dev/vhci failed");
+		btdev_destroy(btdev);
+		return false;
+	}
+
+	create_req[0] = HCI_VENDOR_PKT;
+	create_req[1] = HCI_PRIMARY;
+
+	written = write(fd, create_req, sizeof(create_req));
+	if (written < 0) {
+		close(fd);
+		btdev_destroy(btdev);
+		return false;
+	}
+
+	hciemu->master_dev = btdev;
+
+	hciemu->master_io = create_io_btdev(fd, btdev);
+
+	return true;
+}
+
+struct bthost *hciemu_client_get_host(struct hciemu *hciemu)
+{
+	if (!hciemu)
+		return NULL;
+
+	return hciemu->host_stack;
+}
+
+static bool create_stack(struct hciemu *hciemu)
+{
+	struct btdev *btdev;
+	struct bthost *bthost;
+	int sv[2];
+
+	btdev = btdev_create(hciemu->btdev_type, 0x00);
+	if (!btdev)
+		return false;
+
+	bthost = bthost_create();
+	if (!bthost) {
+		btdev_destroy(btdev);
+		return false;
+	}
+
+	btdev_set_command_handler(btdev, client_command_callback, hciemu);
+
+	if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC,
+								0, sv) < 0) {
+		bthost_destroy(bthost);
+		btdev_destroy(btdev);
+		return false;
+	}
+
+	hciemu->client_dev = btdev;
+	hciemu->host_stack = bthost;
+
+	hciemu->client_io = create_io_btdev(sv[0], btdev);
+	hciemu->host_io = create_io_bthost(sv[1], bthost);
+
+	return true;
+}
+
+static void start_stack(void *user_data)
+{
+	struct hciemu *hciemu = user_data;
+
+	bthost_start(hciemu->host_stack);
+}
+
+struct hciemu *hciemu_new(enum hciemu_type type)
+{
+	struct hciemu *hciemu;
+
+	hciemu = new0(struct hciemu, 1);
+	if (!hciemu)
+		return NULL;
+
+	switch (type) {
+	case HCIEMU_TYPE_BREDRLE:
+		hciemu->btdev_type = BTDEV_TYPE_BREDRLE;
+		break;
+	case HCIEMU_TYPE_BREDR:
+		hciemu->btdev_type = BTDEV_TYPE_BREDR;
+		break;
+	case HCIEMU_TYPE_LE:
+		hciemu->btdev_type = BTDEV_TYPE_LE;
+		break;
+	case HCIEMU_TYPE_LEGACY:
+		hciemu->btdev_type = BTDEV_TYPE_BREDR20;
+		break;
+	case HCIEMU_TYPE_BREDRLE50:
+		hciemu->btdev_type = BTDEV_TYPE_BREDRLE50;
+		break;
+	case HCIEMU_TYPE_BREDRLE52:
+		hciemu->btdev_type = BTDEV_TYPE_BREDRLE52;
+		break;
+	default:
+		return NULL;
+	}
+
+	hciemu->post_command_hooks = queue_new();
+	if (!hciemu->post_command_hooks) {
+		free(hciemu);
+		return NULL;
+	}
+
+	if (!create_vhci(hciemu)) {
+		queue_destroy(hciemu->post_command_hooks, NULL);
+		free(hciemu);
+		return NULL;
+	}
+
+	if (!create_stack(hciemu)) {
+		l_io_destroy(hciemu->master_io);
+		btdev_destroy(hciemu->master_dev);
+		queue_destroy(hciemu->post_command_hooks, NULL);
+		free(hciemu);
+		return NULL;
+	}
+
+	l_idle_oneshot(start_stack, hciemu, NULL);
+
+	return hciemu_ref(hciemu);
+}
+
+struct hciemu *hciemu_ref(struct hciemu *hciemu)
+{
+	if (!hciemu)
+		return NULL;
+
+	__sync_fetch_and_add(&hciemu->ref_count, 1);
+
+	return hciemu;
+}
+
+void hciemu_unref(struct hciemu *hciemu)
+{
+	if (!hciemu)
+		return;
+
+	if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
+		return;
+
+	queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
+
+	l_io_destroy(hciemu->host_io);
+	l_io_destroy(hciemu->client_io);
+	l_io_destroy(hciemu->master_io);
+
+	bthost_destroy(hciemu->host_stack);
+	btdev_destroy(hciemu->client_dev);
+	btdev_destroy(hciemu->master_dev);
+
+	free(hciemu);
+}
+
+static void bthost_debug(const char *str, void *user_data)
+{
+	struct hciemu *hciemu = user_data;
+
+	util_debug(hciemu->debug_callback, hciemu->debug_data,
+					"bthost: %s", str);
+}
+
+static void btdev_master_debug(const char *str, void *user_data)
+{
+	struct hciemu *hciemu = user_data;
+
+	util_debug(hciemu->debug_callback, hciemu->debug_data,
+					"btdev: %s", str);
+}
+
+static void btdev_client_debug(const char *str, void *user_data)
+{
+	struct hciemu *hciemu = user_data;
+
+	util_debug(hciemu->debug_callback, hciemu->debug_data,
+					"btdev[bthost]: %s", str);
+}
+
+bool hciemu_set_debug(struct hciemu *hciemu, hciemu_debug_func_t callback,
+			void *user_data, hciemu_destroy_func_t destroy)
+{
+	if (!hciemu)
+		return false;
+
+	if (hciemu->debug_destroy)
+		hciemu->debug_destroy(hciemu->debug_data);
+
+	hciemu->debug_callback = callback;
+	hciemu->debug_destroy = destroy;
+	hciemu->debug_data = user_data;
+
+	btdev_set_debug(hciemu->master_dev, btdev_master_debug, hciemu, NULL);
+	btdev_set_debug(hciemu->client_dev, btdev_client_debug, hciemu, NULL);
+	bthost_set_debug(hciemu->host_stack, bthost_debug, hciemu, NULL);
+
+	return true;
+}
+
+const char *hciemu_get_address(struct hciemu *hciemu)
+{
+	const uint8_t *addr;
+
+	if (!hciemu || !hciemu->master_dev)
+		return NULL;
+
+	addr = btdev_get_bdaddr(hciemu->master_dev);
+	sprintf(hciemu->bdaddr_str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+			addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
+	return hciemu->bdaddr_str;
+}
+
+uint8_t *hciemu_get_features(struct hciemu *hciemu)
+{
+	if (!hciemu || !hciemu->master_dev)
+		return NULL;
+
+	return btdev_get_features(hciemu->master_dev);
+}
+
+const uint8_t *hciemu_get_master_bdaddr(struct hciemu *hciemu)
+{
+	if (!hciemu || !hciemu->master_dev)
+		return NULL;
+
+	return btdev_get_bdaddr(hciemu->master_dev);
+}
+
+const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
+{
+	if (!hciemu || !hciemu->client_dev)
+		return NULL;
+
+	return btdev_get_bdaddr(hciemu->client_dev);
+}
+
+uint8_t hciemu_get_master_scan_enable(struct hciemu *hciemu)
+{
+	if (!hciemu || !hciemu->master_dev)
+		return 0;
+
+	return btdev_get_scan_enable(hciemu->master_dev);
+}
+
+uint8_t hciemu_get_master_le_scan_enable(struct hciemu *hciemu)
+{
+	if (!hciemu || !hciemu->master_dev)
+		return 0;
+
+	return btdev_get_le_scan_enable(hciemu->master_dev);
+}
+
+void hciemu_set_master_le_states(struct hciemu *hciemu,
+						const uint8_t *le_states)
+{
+	if (!hciemu || !hciemu->master_dev)
+		return;
+
+	btdev_set_le_states(hciemu->master_dev, le_states);
+}
+
+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 = new0(struct hciemu_command_hook, 1);
+	if (!hook)
+		return false;
+
+	hook->function = function;
+	hook->user_data = user_data;
+
+	if (!queue_push_tail(hciemu->post_command_hooks, hook)) {
+		free(hook);
+		return false;
+	}
+
+	return true;
+}
+
+bool hciemu_clear_master_post_command_hooks(struct hciemu *hciemu)
+{
+	if (!hciemu)
+		return false;
+
+	queue_remove_all(hciemu->post_command_hooks,
+					NULL, NULL, destroy_command_hook);
+	return true;
+}
+
+int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
+				uint16_t opcode, hciemu_hook_func_t function,
+				void *user_data)
+{
+	enum btdev_hook_type hook_type;
+
+	if (!hciemu)
+		return -1;
+
+	switch (type) {
+	case HCIEMU_HOOK_PRE_CMD:
+		hook_type = BTDEV_HOOK_PRE_CMD;
+		break;
+	case HCIEMU_HOOK_POST_CMD:
+		hook_type = BTDEV_HOOK_POST_CMD;
+		break;
+	case HCIEMU_HOOK_PRE_EVT:
+		hook_type = BTDEV_HOOK_PRE_EVT;
+		break;
+	case HCIEMU_HOOK_POST_EVT:
+		hook_type = BTDEV_HOOK_POST_EVT;
+		break;
+	default:
+		return -1;
+	}
+
+	return btdev_add_hook(hciemu->master_dev, hook_type, opcode, function,
+								user_data);
+}
+
+bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
+								uint16_t opcode)
+{
+	enum btdev_hook_type hook_type;
+
+	if (!hciemu)
+		return false;
+
+	switch (type) {
+	case HCIEMU_HOOK_PRE_CMD:
+		hook_type = BTDEV_HOOK_PRE_CMD;
+		break;
+	case HCIEMU_HOOK_POST_CMD:
+		hook_type = BTDEV_HOOK_POST_CMD;
+		break;
+	case HCIEMU_HOOK_PRE_EVT:
+		hook_type = BTDEV_HOOK_PRE_EVT;
+		break;
+	case HCIEMU_HOOK_POST_EVT:
+		hook_type = BTDEV_HOOK_POST_EVT;
+		break;
+	default:
+		return false;
+	}
+
+	return btdev_del_hook(hciemu->master_dev, hook_type, opcode);
+}
-- 
2.26.2


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

* [RFC PATCH BlueZ 03/10] tools/gap-tester: Convert to use ELL library
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 01/10] shared/tester-ell: Create ell-based version of tester code Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 02/10] emulator/hciemu: Create ELL based version of hciemu Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 04/10] tools/sco-tester: " Inga Stotland
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This reworks the source code to use ELL primitives and removes
dependecies on GLib.
---
 Makefile.tools     |  6 ++--
 tools/gap-tester.c | 87 ++++++++++++++++++++++++++--------------------
 2 files changed, 51 insertions(+), 42 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index d5fdf2d89..259427443 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -146,14 +146,12 @@ tools_smp_tester_LDADD = lib/libbluetooth-internal.la \
 				src/libshared-glib.la $(GLIB_LIBS)
 
 tools_gap_tester_SOURCES = tools/gap-tester.c monitor/bt.h \
-				emulator/hciemu.h emulator/hciemu.c \
+				emulator/hciemu.h emulator/hciemu-ell.c \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
 				emulator/smp.c
 tools_gap_tester_LDADD =  lib/libbluetooth-internal.la \
-				gdbus/libgdbus-internal.la \
-				src/libshared-glib.la \
-				$(GLIB_LIBS) $(DBUS_LIBS)
+				src/libshared-ell.la $(ell_ldadd)
 
 tools_sco_tester_SOURCES = tools/sco-tester.c monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu.c \
diff --git a/tools/gap-tester.c b/tools/gap-tester.c
index 942c37d27..2797a60a8 100644
--- a/tools/gap-tester.c
+++ b/tools/gap-tester.c
@@ -12,60 +12,72 @@
 #include <config.h>
 #endif
 
-#include "gdbus/gdbus.h"
+#include <ell/ell.h>
 
 #include "src/shared/tester.h"
 #include "emulator/hciemu.h"
 
-static DBusConnection *dbus_conn = NULL;
-static GDBusClient *dbus_client = NULL;
-static GDBusProxy *adapter_proxy = NULL;
+static struct l_dbus *dbus_conn;
+struct l_dbus_client *dbus_client;
+struct l_dbus_proxy *adapter_proxy;
 
-static struct hciemu *hciemu_stack = NULL;
+static struct hciemu *hciemu_stack;
 
-static void connect_handler(DBusConnection *connection, void *user_data)
+static void connect_handler(struct l_dbus *connection, void *user_data)
 {
 	tester_print("Connected to daemon");
 
 	hciemu_stack = hciemu_new(HCIEMU_TYPE_BREDRLE);
 }
 
-static void disconnect_handler(DBusConnection *connection, void *user_data)
+static void destroy_client(void *data)
 {
-	tester_print("Disconnected from daemon");
+	l_dbus_client_destroy(dbus_client);
+	dbus_client = NULL;
+}
 
-	dbus_connection_unref(dbus_conn);
+static void destroy_conn(void *data)
+{
+	l_dbus_destroy(dbus_conn);
 	dbus_conn = NULL;
+}
 
-	tester_teardown_complete();
+static void service_disconnect_handler(struct l_dbus *connection,
+							void *user_data)
+{
+	tester_print("Daemon disconnected");
 }
 
-static gboolean compare_string_property(GDBusProxy *proxy, const char *name,
-							const char *value)
+static void client_destroy_handler(void *user_data)
 {
-	DBusMessageIter iter;
-	const char *str;
+	tester_print("Disconnected from daemon");
 
-	if (g_dbus_proxy_get_property(proxy, name, &iter) == FALSE)
-		return FALSE;
+	if (dbus_conn)
+		l_idle_oneshot(destroy_conn, NULL, NULL);
 
-	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-		return FALSE;
+	tester_teardown_complete();
+}
 
-	dbus_message_iter_get_basic(&iter, &str);
+static bool compare_string_property(struct l_dbus_proxy *proxy,
+					const char *name, const char *value)
+{
+	const char *str;
 
-	return g_str_equal(str, value);
+	if (!l_dbus_proxy_get_property(proxy, name, "s", &str))
+		return false;
+
+	return !strcmp(str, value);
 }
 
-static void proxy_added(GDBusProxy *proxy, void *user_data)
+static void proxy_added(struct l_dbus_proxy *proxy, void *user_data)
 {
 	const char *interface;
 
-	interface = g_dbus_proxy_get_interface(proxy);
+	interface = l_dbus_proxy_get_interface(proxy);
 
-	if (g_str_equal(interface, "org.bluez.Adapter1") == TRUE) {
+	if (!strcmp(interface, "org.bluez.Adapter1")) {
 		if (compare_string_property(proxy, "Address",
-				hciemu_get_address(hciemu_stack)) == TRUE) {
+				hciemu_get_address(hciemu_stack))) {
 			adapter_proxy = proxy;
 			tester_print("Found adapter");
 
@@ -74,35 +86,34 @@ static void proxy_added(GDBusProxy *proxy, void *user_data)
 	}
 }
 
-static void proxy_removed(GDBusProxy *proxy, void *user_data)
+static void proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
 {
 	const char *interface;
 
-	interface = g_dbus_proxy_get_interface(proxy);
+	interface = l_dbus_proxy_get_interface(proxy);
 
-	if (g_str_equal(interface, "org.bluez.Adapter1") == TRUE) {
+	if (!strcmp(interface, "org.bluez.Adapter1")) {
 		if (adapter_proxy == proxy) {
 			adapter_proxy = NULL;
 			tester_print("Adapter removed");
-
-			g_dbus_client_unref(dbus_client);
-			dbus_client = NULL;
+			l_idle_oneshot(destroy_client, NULL, NULL);
 		}
 	}
 }
 
 static void test_setup(const void *test_data)
 {
-	dbus_conn = g_dbus_setup_private(DBUS_BUS_SYSTEM, NULL, NULL);
-
-	dbus_client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+	dbus_conn = l_dbus_new_default(L_DBUS_SYSTEM_BUS);
 
-	g_dbus_client_set_connect_watch(dbus_client, connect_handler, NULL);
-	g_dbus_client_set_disconnect_watch(dbus_client,
-						disconnect_handler, NULL);
+	dbus_client = l_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+	l_dbus_client_set_connect_handler(dbus_client, connect_handler, NULL,
+									NULL);
+	l_dbus_client_set_disconnect_handler(dbus_client,
+						service_disconnect_handler,
+						NULL, client_destroy_handler);
 
-	g_dbus_client_set_proxy_handlers(dbus_client, proxy_added,
-						proxy_removed, NULL, NULL);
+	l_dbus_client_set_proxy_handlers(dbus_client, proxy_added,
+					proxy_removed, NULL, NULL, NULL);
 }
 
 static void test_run(const void *test_data)
-- 
2.26.2


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

* [RFC PATCH BlueZ 04/10] tools/sco-tester: Convert to use ELL library
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
                   ` (2 preceding siblings ...)
  2020-11-07  7:03 ` [RFC PATCH BlueZ 03/10] tools/gap-tester: Convert to use ELL library Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 05/10] tools/userchan-tester: " Inga Stotland
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This reworks the source code to use ELL primitives and removes
dependecies on GLib.
---
 Makefile.tools     |  4 ++--
 tools/sco-tester.c | 33 ++++++++++++++-------------------
 2 files changed, 16 insertions(+), 21 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 259427443..15613a5c9 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -154,12 +154,12 @@ tools_gap_tester_LDADD =  lib/libbluetooth-internal.la \
 				src/libshared-ell.la $(ell_ldadd)
 
 tools_sco_tester_SOURCES = tools/sco-tester.c monitor/bt.h \
-				emulator/hciemu.h emulator/hciemu.c \
+				emulator/hciemu.h emulator/hciemu-ell.c \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
 				emulator/smp.c
 tools_sco_tester_LDADD = lib/libbluetooth-internal.la \
-				src/libshared-glib.la $(GLIB_LIBS)
+				src/libshared-ell.la $(ell_ldadd)
 
 tools_hci_tester_SOURCES = tools/hci-tester.c monitor/bt.h
 tools_hci_tester_LDADD = src/libshared-glib.la $(GLIB_LIBS)
diff --git a/tools/sco-tester.c b/tools/sco-tester.c
index 2b8dc0d4a..c3c43a1c3 100644
--- a/tools/sco-tester.c
+++ b/tools/sco-tester.c
@@ -17,7 +17,7 @@
 #include <errno.h>
 #include <stdbool.h>
 
-#include <glib.h>
+#include <ell/ell.h>
 
 #include "lib/bluetooth.h"
 #include "lib/sco.h"
@@ -36,7 +36,7 @@ struct test_data {
 	uint16_t mgmt_index;
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
-	unsigned int io_id;
+	struct l_io *io;
 	bool disable_esco;
 };
 
@@ -196,20 +196,21 @@ static void test_data_free(void *test_data)
 {
 	struct test_data *data = test_data;
 
-	if (data->io_id > 0)
-		g_source_remove(data->io_id);
+	if (data->io) {
+		l_io_destroy(data->io);
+		data->io = NULL;
+	}
 
-	free(data);
+	l_free(data);
 }
 
 #define test_sco_full(name, data, setup, func, _disable_esco) \
 	do { \
 		struct test_data *user; \
-		user = malloc(sizeof(struct test_data)); \
+		user = l_new(struct test_data, 1); \
 		if (!user) \
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_BREDRLE; \
-		user->io_id = 0; \
 		user->test_data = data; \
 		user->disable_esco = _disable_esco; \
 		tester_add_full(name, data, \
@@ -474,17 +475,14 @@ static int connect_sco_sock(struct test_data *data, int sk)
 	return 0;
 }
 
-static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool sco_connect_cb(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct sco_client_data *scodata = data->test_data;
 	int err, sk_err, sk;
 	socklen_t len = sizeof(sk_err);
 
-	data->io_id = 0;
-
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 
 	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
 		err = -errno;
@@ -501,13 +499,12 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond,
 	else
 		tester_test_passed();
 
-	return FALSE;
+	return false;
 }
 
 static void test_connect(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
-	GIOChannel *io;
 	int sk;
 
 	sk = create_sco_sock(data);
@@ -522,12 +519,10 @@ static void test_connect(const void *test_data)
 		return;
 	}
 
-	io = g_io_channel_unix_new(sk);
-	g_io_channel_set_close_on_unref(io, TRUE);
-
-	data->io_id = g_io_add_watch(io, G_IO_OUT, sco_connect_cb, NULL);
+	data->io = l_io_new(sk);
+	l_io_set_close_on_destroy(data->io, true);
 
-	g_io_channel_unref(io);
+	l_io_set_write_handler(data->io, sco_connect_cb, NULL, NULL);
 
 	tester_print("Connect in progress");
 }
-- 
2.26.2


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

* [RFC PATCH BlueZ 05/10] tools/userchan-tester: Convert to use ELL library
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
                   ` (3 preceding siblings ...)
  2020-11-07  7:03 ` [RFC PATCH BlueZ 04/10] tools/sco-tester: " Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 06/10] tools/smp-tester: " Inga Stotland
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This reworks the source code to use ELL primitives and removes
dependecies on GLib.
---
 Makefile.tools          | 4 ++--
 tools/userchan-tester.c | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 15613a5c9..7c29e115b 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -165,12 +165,12 @@ tools_hci_tester_SOURCES = tools/hci-tester.c monitor/bt.h
 tools_hci_tester_LDADD = src/libshared-glib.la $(GLIB_LIBS)
 
 tools_userchan_tester_SOURCES = tools/userchan-tester.c monitor/bt.h \
-				emulator/hciemu.h emulator/hciemu.c \
+				emulator/hciemu.h emulator/hciemu-ell.c \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
 				emulator/smp.c
 tools_userchan_tester_LDADD = lib/libbluetooth-internal.la \
-				src/libshared-glib.la $(GLIB_LIBS)
+				src/libshared-ell.la $(ell_ldadd)
 endif
 
 if TOOLS
diff --git a/tools/userchan-tester.c b/tools/userchan-tester.c
index c17644fb8..21c853221 100644
--- a/tools/userchan-tester.c
+++ b/tools/userchan-tester.c
@@ -18,8 +18,6 @@
 #include <errno.h>
 #include <stdbool.h>
 
-#include <glib.h>
-
 #include "lib/bluetooth.h"
 #include "lib/hci.h"
 #include "lib/mgmt.h"
-- 
2.26.2


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

* [RFC PATCH BlueZ 06/10] tools/smp-tester: Convert to use ELL library
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
                   ` (4 preceding siblings ...)
  2020-11-07  7:03 ` [RFC PATCH BlueZ 05/10] tools/userchan-tester: " Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 07/10] tools/bnep-tester: " Inga Stotland
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This reworks the source code to use ELL primitives and removes
dependecies on GLib.
---
 Makefile.tools     |  4 ++--
 tools/smp-tester.c | 24 +++++++++---------------
 2 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 7c29e115b..83c30252d 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -138,12 +138,12 @@ tools_bnep_tester_LDADD = lib/libbluetooth-internal.la \
 				src/libshared-glib.la $(GLIB_LIBS)
 
 tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
-				emulator/hciemu.h emulator/hciemu.c \
+				emulator/hciemu.h emulator/hciemu-ell.c \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
 				emulator/smp.c
 tools_smp_tester_LDADD = lib/libbluetooth-internal.la \
-				src/libshared-glib.la $(GLIB_LIBS)
+				src/libshared-ell.la $(ell_ldadd)
 
 tools_gap_tester_SOURCES = tools/gap-tester.c monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu-ell.c \
diff --git a/tools/smp-tester.c b/tools/smp-tester.c
index 7823b6b17..b7843c73d 100644
--- a/tools/smp-tester.c
+++ b/tools/smp-tester.c
@@ -18,7 +18,7 @@
 #include <stdbool.h>
 #include <sys/socket.h>
 
-#include <glib.h>
+#include <ell/ell.h>
 
 #include "lib/bluetooth.h"
 #include "lib/hci.h"
@@ -41,7 +41,6 @@ struct test_data {
 	uint16_t mgmt_index;
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
-	unsigned int io_id;
 	uint8_t ia[6];
 	uint8_t ia_type;
 	uint8_t ra[6];
@@ -223,11 +222,6 @@ static void test_post_teardown(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
-	if (data->io_id > 0) {
-		g_source_remove(data->io_id);
-		data->io_id = 0;
-	}
-
 	if (data->crypto) {
 		bt_crypto_unref(data->crypto);
 		data->crypto = NULL;
@@ -287,7 +281,7 @@ static const struct smp_req_rsp nval_req_1[] = {
 
 static const struct smp_data smp_server_nval_req_1_test = {
 	.req = nval_req_1,
-	.req_count = G_N_ELEMENTS(nval_req_1),
+	.req_count = L_ARRAY_SIZE(nval_req_1),
 };
 
 static const uint8_t smp_nval_req_2[7] = { 0x01 };
@@ -300,7 +294,7 @@ static const struct smp_req_rsp srv_nval_req_1[] = {
 
 static const struct smp_data smp_server_nval_req_2_test = {
 	.req = srv_nval_req_1,
-	.req_count = G_N_ELEMENTS(srv_nval_req_1),
+	.req_count = L_ARRAY_SIZE(srv_nval_req_1),
 };
 
 static const uint8_t smp_nval_req_3[] = { 0x01, 0xff };
@@ -313,7 +307,7 @@ static const struct smp_req_rsp srv_nval_req_2[] = {
 
 static const struct smp_data smp_server_nval_req_3_test = {
 	.req = srv_nval_req_2,
-	.req_count = G_N_ELEMENTS(srv_nval_req_2),
+	.req_count = L_ARRAY_SIZE(srv_nval_req_2),
 };
 
 static const uint8_t smp_basic_req_1[] = {	0x01,	/* Pairing Request */
@@ -347,7 +341,7 @@ static const struct smp_req_rsp srv_basic_req_1[] = {
 
 static const struct smp_data smp_server_basic_req_1_test = {
 	.req = srv_basic_req_1,
-	.req_count = G_N_ELEMENTS(srv_basic_req_1),
+	.req_count = L_ARRAY_SIZE(srv_basic_req_1),
 };
 
 static const struct smp_req_rsp cli_basic_req_1[] = {
@@ -361,7 +355,7 @@ static const struct smp_req_rsp cli_basic_req_1[] = {
 
 static const struct smp_data smp_client_basic_req_1_test = {
 	.req = cli_basic_req_1,
-	.req_count = G_N_ELEMENTS(cli_basic_req_1),
+	.req_count = L_ARRAY_SIZE(cli_basic_req_1),
 };
 
 static const uint8_t smp_basic_req_2[] = {	0x01,	/* Pairing Request */
@@ -384,7 +378,7 @@ static const struct smp_req_rsp cli_basic_req_2[] = {
 
 static const struct smp_data smp_client_basic_req_2_test = {
 	.req = cli_basic_req_2,
-	.req_count = G_N_ELEMENTS(cli_basic_req_1),
+	.req_count = L_ARRAY_SIZE(cli_basic_req_1),
 	.mitm = true,
 };
 
@@ -423,7 +417,7 @@ static const struct smp_req_rsp cli_sc_req_1[] = {
 
 static const struct smp_data smp_client_sc_req_1_test = {
 	.req = cli_sc_req_1,
-	.req_count = G_N_ELEMENTS(cli_sc_req_1),
+	.req_count = L_ARRAY_SIZE(cli_sc_req_1),
 	.sc = true,
 };
 
@@ -449,7 +443,7 @@ static const struct smp_req_rsp cli_sc_req_2[] = {
 
 static const struct smp_data smp_client_sc_req_2_test = {
 	.req = cli_sc_req_2,
-	.req_count = G_N_ELEMENTS(cli_sc_req_2),
+	.req_count = L_ARRAY_SIZE(cli_sc_req_2),
 	.sc = true,
 };
 
-- 
2.26.2


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

* [RFC PATCH BlueZ 07/10] tools/bnep-tester: Convert to use ELL library
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
                   ` (5 preceding siblings ...)
  2020-11-07  7:03 ` [RFC PATCH BlueZ 06/10] tools/smp-tester: " Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 08/10] tools/l2cap-tester: " Inga Stotland
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This reworks the source code to use ELL primitives and removes
dependecies on GLib.
---
 Makefile.tools      | 4 ++--
 tools/bnep-tester.c | 9 +--------
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 83c30252d..8c79a528d 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -130,12 +130,12 @@ tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la \
 				src/libshared-glib.la $(GLIB_LIBS)
 
 tools_bnep_tester_SOURCES = tools/bnep-tester.c monitor/bt.h \
-				emulator/hciemu.h emulator/hciemu.c \
+				emulator/hciemu.h emulator/hciemu-ell.c \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
 				emulator/smp.c
 tools_bnep_tester_LDADD = lib/libbluetooth-internal.la \
-				src/libshared-glib.la $(GLIB_LIBS)
+				src/libshared-ell.la $(ell_ldadd)
 
 tools_smp_tester_SOURCES = tools/smp-tester.c monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu-ell.c \
diff --git a/tools/bnep-tester.c b/tools/bnep-tester.c
index 5e4d7fb6d..dab913862 100644
--- a/tools/bnep-tester.c
+++ b/tools/bnep-tester.c
@@ -18,7 +18,7 @@
 #include <errno.h>
 #include <stdbool.h>
 
-#include <glib.h>
+#include <ell/ell.h>
 
 #include "lib/bluetooth.h"
 #include "lib/bnep.h"
@@ -37,7 +37,6 @@ struct test_data {
 	struct hciemu *hciemu;
 	enum hciemu_type hciemu_type;
 	const void *test_data;
-	unsigned int io_id;
 	uint16_t conn_handle;
 };
 
@@ -192,11 +191,6 @@ static void test_post_teardown(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
-	if (data->io_id > 0) {
-		g_source_remove(data->io_id);
-		data->io_id = 0;
-	}
-
 	hciemu_unref(data->hciemu);
 	data->hciemu = NULL;
 }
@@ -282,7 +276,6 @@ static void test_basic(const void *test_data)
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_BREDR; \
 		user->test_data = data; \
-		user->io_id = 0; \
 		tester_add_full(name, data, \
 				test_pre_setup, setup, func, NULL, \
 				test_post_teardown, 2, user, test_data_free); \
-- 
2.26.2


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

* [RFC PATCH BlueZ 08/10] tools/l2cap-tester: Convert to use ELL library
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
                   ` (6 preceding siblings ...)
  2020-11-07  7:03 ` [RFC PATCH BlueZ 07/10] tools/bnep-tester: " Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 09/10] tools/mgmt-tester: " Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 10/10] tools/rfcomm-tester: " Inga Stotland
  9 siblings, 0 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This reworks the source code to use ELL primitives and removes
dependecies on GLib.
---
 Makefile.tools       |   4 +-
 tools/l2cap-tester.c | 256 +++++++++++++++++++++----------------------
 2 files changed, 130 insertions(+), 130 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 8c79a528d..03264cff9 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -114,12 +114,12 @@ tools_mgmt_tester_LDADD = lib/libbluetooth-internal.la \
 				src/libshared-glib.la $(GLIB_LIBS)
 
 tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
-				emulator/hciemu.h emulator/hciemu.c \
+				emulator/hciemu.h emulator/hciemu-ell.c \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
 				emulator/smp.c
 tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la \
-				src/libshared-glib.la $(GLIB_LIBS)
+				src/libshared-ell.la $(ell_ldadd)
 
 tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu.c \
diff --git a/tools/l2cap-tester.c b/tools/l2cap-tester.c
index ff641ba1d..6f55cf6f2 100644
--- a/tools/l2cap-tester.c
+++ b/tools/l2cap-tester.c
@@ -4,6 +4,7 @@
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2013  Intel Corporation. All rights reserved.
+
  *
  *
  */
@@ -17,7 +18,7 @@
 #include <errno.h>
 #include <stdbool.h>
 
-#include <glib.h>
+#include <ell/ell.h>
 
 #include "lib/bluetooth.h"
 #include "lib/l2cap.h"
@@ -35,8 +36,9 @@ struct test_data {
 	struct mgmt *mgmt;
 	uint16_t mgmt_index;
 	struct hciemu *hciemu;
+	struct l_io *io;
+	struct l_io *io2;
 	enum hciemu_type hciemu_type;
-	unsigned int io_id;
 	uint16_t handle;
 	uint16_t scid;
 	uint16_t dcid;
@@ -218,9 +220,14 @@ static void test_post_teardown(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
-	if (data->io_id > 0) {
-		g_source_remove(data->io_id);
-		data->io_id = 0;
+	if (data->io) {
+		l_io_destroy(data->io);
+		data->io = NULL;
+	}
+
+	if (data->io2) {
+		l_io_destroy(data->io2);
+		data->io2 = NULL;
 	}
 
 	hciemu_unref(data->hciemu);
@@ -230,18 +237,16 @@ static void test_post_teardown(const void *test_data)
 static void test_data_free(void *test_data)
 {
 	struct test_data *data = test_data;
-
-	free(data);
+	l_free(data);
 }
 
 #define test_l2cap_bredr(name, data, setup, func) \
 	do { \
 		struct test_data *user; \
-		user = malloc(sizeof(struct test_data)); \
+		user = l_new(struct test_data, 1);	\
 		if (!user) \
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_BREDR; \
-		user->io_id = 0; \
 		user->test_data = data; \
 		tester_add_full(name, data, \
 				test_pre_setup, setup, func, NULL, \
@@ -251,11 +256,10 @@ static void test_data_free(void *test_data)
 #define test_l2cap_le(name, data, setup, func) \
 	do { \
 		struct test_data *user; \
-		user = malloc(sizeof(struct test_data)); \
+		user = l_new(struct test_data, 1);	\
 		if (!user) \
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_LE; \
-		user->io_id = 0; \
 		user->test_data = data; \
 		tester_add_full(name, data, \
 				test_pre_setup, setup, func, NULL, \
@@ -886,19 +890,18 @@ static void test_basic(const void *test_data)
 	tester_test_passed();
 }
 
-static gboolean client_received_data(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool client_received_data(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	char buf[1024];
 	int sk;
 
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 	if (read(sk, buf, l2data->data_len) != l2data->data_len) {
 		tester_warn("Unable to read %u bytes", l2data->data_len);
 		tester_test_failed();
-		return FALSE;
+		return false;
 	}
 
 	if (memcmp(buf, l2data->read_data, l2data->data_len))
@@ -906,22 +909,22 @@ static gboolean client_received_data(GIOChannel *io, GIOCondition cond,
 	else
 		tester_test_passed();
 
-	return FALSE;
+	return true;
 }
 
-static gboolean server_received_data(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool server_received_data(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	char buf[1024];
 	int sk;
 
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 	if (read(sk, buf, l2data->data_len) != l2data->data_len) {
 		tester_warn("Unable to read %u bytes", l2data->data_len);
 		tester_test_failed();
-		return FALSE;
+		l_io_destroy(io);
+		return false;
 	}
 
 	if (memcmp(buf, l2data->read_data, l2data->data_len))
@@ -929,7 +932,9 @@ static gboolean server_received_data(GIOChannel *io, GIOCondition cond,
 	else
 		tester_test_passed();
 
-	return FALSE;
+	l_io_destroy(io);
+
+	return true;
 }
 
 static void bthost_received_data(const void *buf, uint16_t len,
@@ -966,27 +971,6 @@ static void server_bthost_received_data(const void *buf, uint16_t len,
 		tester_test_passed();
 }
 
-static gboolean socket_closed_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
-{
-	struct test_data *data = tester_get_data();
-	const struct l2cap_data *l2data = data->test_data;
-
-	if (l2data->shut_sock_wr) {
-		/* if socket is closed using SHUT_WR, L2CAP disconnection
-		 * response must be received first before G_IO_HUP event.
-		 */
-		if (data->host_disconnected)
-			tester_test_passed();
-		else {
-			tester_warn("G_IO_HUP received before receiving L2CAP disconnection");
-			tester_test_failed();
-		}
-	}
-
-	return FALSE;
-}
-
 static bool check_mtu(struct test_data *data, int sk)
 {
 	const struct l2cap_data *l2data = data->test_data;
@@ -1029,17 +1013,52 @@ static bool check_mtu(struct test_data *data, int sk)
 	return true;
 }
 
-static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static void l2cap_disconnect_cb(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	int err, sk_err, sk;
 	socklen_t len = sizeof(sk_err);
 
-	data->io_id = 0;
+	tester_print("Disconnect callback");
+	if (l2data->shut_sock_wr) {
+		/* if socket is closed using SHUT_WR, L2CAP disconnection
+		 * response must be received first before EPOLLHUP event.
+		 */
+		if (data->host_disconnected)
+			tester_test_passed();
+		else {
+			tester_warn("HUP received before L2CAP disconnection");
+			tester_test_failed();
+		}
+
+		return;
+	}
+
+	sk = l_io_get_fd(io);
 
-	sk = g_io_channel_unix_get_fd(io);
+	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
+		err = -errno;
+	else
+		err = -sk_err;
+
+	if (l2data->expect_err) {
+
+		if (-err == l2data->expect_err)
+			tester_test_passed();
+		else
+			tester_test_failed();
+	}
+}
+
+static bool l2cap_connect_cb(struct l_io *io, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct l2cap_data *l2data = data->test_data;
+	int err, sk_err, sk;
+	socklen_t len = sizeof(sk_err);
+
+	sk = l_io_get_fd(io);
 
 	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
 		err = -errno;
@@ -1055,19 +1074,19 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 
 	if (!check_mtu(data, sk)) {
 		tester_test_failed();
-		return FALSE;
+		return false;
 	}
 
 	if (l2data->read_data) {
 		struct bthost *bthost;
 
 		bthost = hciemu_client_get_host(data->hciemu);
-		g_io_add_watch(io, G_IO_IN, client_received_data, NULL);
+		l_io_set_read_handler(io, client_received_data, NULL, NULL);
 
 		bthost_send_cid(bthost, data->handle, data->dcid,
 					l2data->read_data, l2data->data_len);
 
-		return FALSE;
+		return false;
 	} else if (l2data->write_data) {
 		struct bthost *bthost;
 		ssize_t ret;
@@ -1082,12 +1101,11 @@ static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond,
 			tester_test_failed();
 		}
 
-		return FALSE;
+		return false;
 	} else if (l2data->shut_sock_wr) {
-		g_io_add_watch(io, G_IO_HUP, socket_closed_cb, NULL);
 		shutdown(sk, SHUT_WR);
 
-		return FALSE;
+		return false;
 	}
 
 failed:
@@ -1096,7 +1114,7 @@ failed:
 	else
 		tester_test_passed();
 
-	return FALSE;
+	return false;
 }
 
 static int create_l2cap_sock(struct test_data *data, uint16_t psm,
@@ -1281,7 +1299,6 @@ static void test_connect(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
-	GIOChannel *io;
 	int sk;
 
 	if (l2data->server_psm) {
@@ -1321,12 +1338,12 @@ static void test_connect(const void *test_data)
 		return;
 	}
 
-	io = g_io_channel_unix_new(sk);
-	g_io_channel_set_close_on_unref(io, TRUE);
+	data->io = l_io_new(sk);
 
-	data->io_id = g_io_add_watch(io, G_IO_OUT, l2cap_connect_cb, NULL);
+	l_io_set_close_on_destroy(data->io, true);
 
-	g_io_channel_unref(io);
+	l_io_set_disconnect_handler(data->io, l2cap_disconnect_cb, NULL, NULL);
+	l_io_set_write_handler(data->io, l2cap_connect_cb, NULL, NULL);
 
 	tester_print("Connect in progress");
 }
@@ -1353,12 +1370,12 @@ static void test_connect_reject(const void *test_data)
 	close(sk);
 }
 
-static int connect_socket(const uint8_t *client_bdaddr, GIOFunc connect_cb,
-								bool defer)
+static struct l_io *connect_socket(const uint8_t *client_bdaddr,
+					l_io_write_cb_t connect_cb, bool defer)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
-	GIOChannel *io;
+	struct l_io *io;
 	int sk;
 
 	sk = create_l2cap_sock(data, 0, l2data->cid, l2data->sec_level,
@@ -1369,7 +1386,7 @@ static int connect_socket(const uint8_t *client_bdaddr, GIOFunc connect_cb,
 			tester_test_abort();
 		else
 			tester_test_failed();
-		return -1;
+		return NULL;
 	}
 
 	if (defer) {
@@ -1380,7 +1397,7 @@ static int connect_socket(const uint8_t *client_bdaddr, GIOFunc connect_cb,
 			tester_print("Can't enable deferred setup: %s (%d)",
 						strerror(errno), errno);
 			tester_test_failed();
-			return -1;
+			return NULL;
 		}
 	}
 
@@ -1389,25 +1406,20 @@ static int connect_socket(const uint8_t *client_bdaddr, GIOFunc connect_cb,
 		tester_print("Error in connect_l2cap_sock");
 		close(sk);
 		tester_test_failed();
-		return -1;
+		return NULL;
 	}
 
-	if (connect_cb) {
-		io = g_io_channel_unix_new(sk);
-		g_io_channel_set_close_on_unref(io, TRUE);
-
-		data->io_id = g_io_add_watch(io, G_IO_OUT, connect_cb, NULL);
-
-		g_io_channel_unref(io);
-	}
+	io = l_io_new(sk);
+	l_io_set_close_on_destroy(io, true);
+	l_io_set_write_handler(io, connect_cb, NULL, NULL);
 
 	tester_print("Connect in progress, sk = %d %s", sk,
 				defer ? "(deferred)" : "");
 
-	return sk;
+	return io;
 }
 
-static gboolean test_close_socket_1_part_3(gpointer arg)
+static void test_close_socket_1_part_3(void *arg)
 {
 	struct test_data *data = tester_get_data();
 
@@ -1416,20 +1428,19 @@ static gboolean test_close_socket_1_part_3(gpointer arg)
 	if (data->sk != -1) {
 		tester_print("Error - scan was not enabled yet");
 		tester_test_failed();
-		return FALSE;
+		return;
 	}
 
 	if (hciemu_get_master_le_scan_enable(data->hciemu)) {
 		tester_print("Delayed check whether scann is off failed");
 		tester_test_failed();
-		return FALSE;
+		return;
 	}
 
 	tester_test_passed();
-	return FALSE;
 }
 
-static gboolean test_close_socket_1_part_2(gpointer args)
+static void test_close_socket_1_part_2(void *args)
 {
 	struct test_data *data = tester_get_data();
 	int sk = data->sk;
@@ -1443,7 +1454,7 @@ static gboolean test_close_socket_1_part_2(gpointer args)
 	if (!hciemu_get_master_le_scan_enable(data->hciemu)) {
 		tester_print("Error - should be still scanning");
 		tester_test_failed();
-		return FALSE;
+		return;
 	}
 
 	/* Calling close() should remove device from  whitelist, and stop
@@ -1452,15 +1463,14 @@ static gboolean test_close_socket_1_part_2(gpointer args)
 	if (close(sk) < 0) {
 		tester_print("Error when closing socket");
 		tester_test_failed();
-		return FALSE;
+		return;
 	}
 
 	data->sk = -1;
 	/* tester_test_passed will be called when scan is stopped. */
-	return FALSE;
 }
 
-static gboolean test_close_socket_2_part_3(gpointer arg)
+static void test_close_socket_2_part_3(void *arg)
 {
 	struct test_data *data = tester_get_data();
 	int sk = data->sk;
@@ -1470,7 +1480,7 @@ static gboolean test_close_socket_2_part_3(gpointer arg)
 	if (hciemu_get_master_le_scan_enable(data->hciemu)) {
 		tester_print("Error - should no longer scan");
 		tester_test_failed();
-		return FALSE;
+		return;
 	}
 
 	/* Calling close() should eventually cause CMD_LE_CREATE_CONN_CANCEL */
@@ -1478,11 +1488,10 @@ static gboolean test_close_socket_2_part_3(gpointer arg)
 	if (err < 0) {
 		tester_print("Error when closing socket");
 		tester_test_failed();
-		return FALSE;
+		return;
 	}
 
 	/* CMD_LE_CREATE_CONN_CANCEL will trigger test pass. */
-	return FALSE;
 }
 
 static bool test_close_socket_cc_hook(const void *data, uint16_t len,
@@ -1491,7 +1500,7 @@ static bool test_close_socket_cc_hook(const void *data, uint16_t len,
 	return false;
 }
 
-static gboolean test_close_socket_2_part_2(gpointer arg)
+static void test_close_socket_2_part_2(void *arg)
 {
 	struct test_data *data = tester_get_data();
 	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
@@ -1507,7 +1516,6 @@ static gboolean test_close_socket_2_part_2(gpointer arg)
 	 */
 	bthost_set_adv_enable(bthost, 0x01);
 	bthost_set_adv_enable(bthost, 0x00);
-	return FALSE;
 }
 
 static void test_close_socket_scan_enabled(void)
@@ -1516,9 +1524,9 @@ static void test_close_socket_scan_enabled(void)
 	const struct l2cap_data *l2data = data->test_data;
 
 	if (l2data == &le_client_close_socket_test_1)
-		g_idle_add(test_close_socket_1_part_2, NULL);
+		l_idle_oneshot(test_close_socket_1_part_2, NULL, NULL);
 	else if (l2data == &le_client_close_socket_test_2)
-		g_idle_add(test_close_socket_2_part_2, NULL);
+		l_idle_oneshot(test_close_socket_2_part_2, NULL, NULL);
 }
 
 static void test_close_socket_scan_disabled(void)
@@ -1527,9 +1535,9 @@ static void test_close_socket_scan_disabled(void)
 	const struct l2cap_data *l2data = data->test_data;
 
 	if (l2data == &le_client_close_socket_test_1)
-		g_idle_add(test_close_socket_1_part_3, NULL);
+		l_idle_oneshot(test_close_socket_1_part_3, NULL, NULL);
 	else if (l2data == &le_client_close_socket_test_2)
-		g_idle_add(test_close_socket_2_part_3, NULL);
+		l_idle_oneshot(test_close_socket_2_part_3, NULL, NULL);
 }
 
 static void test_close_socket_conn_cancel(void)
@@ -1571,21 +1579,19 @@ static void test_close_socket(const void *test_data)
 	else
 		client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
 
-	data->sk = connect_socket(client_bdaddr, NULL, false);
+	data->io = connect_socket(client_bdaddr, NULL, false);
+	data->sk = l_io_get_fd(data->io);
 }
 
 static uint8_t test_2_connect_cb_cnt;
-static gboolean test_2_connect_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool test_2_connect_cb(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	int err, sk_err, sk;
 	socklen_t len = sizeof(sk_err);
 
-	data->io_id = 0;
-
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 
 	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
 		err = -errno;
@@ -1595,7 +1601,7 @@ static gboolean test_2_connect_cb(GIOChannel *io, GIOCondition cond,
 	if (err < 0) {
 		tester_warn("Connect failed: %s (%d)", strerror(-err), -err);
 		tester_test_failed();
-		return FALSE;
+		return false;
 	}
 
 	tester_print("Successfully connected");
@@ -1612,16 +1618,15 @@ static gboolean test_2_connect_cb(GIOChannel *io, GIOCondition cond,
 		tester_test_passed();
 	}
 
-	return FALSE;
+	return true;
 }
 
-static gboolean enable_advertising(gpointer args)
+static void enable_advertising(void *args)
 {
 	struct test_data *data = tester_get_data();
 	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
 
 	bthost_set_adv_enable(bthost, 0x01);
-	return FALSE;
 }
 
 static void test_connect_2_part_2(void)
@@ -1631,14 +1636,15 @@ static void test_connect_2_part_2(void)
 	const uint8_t *client_bdaddr;
 
 	client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
-	data->sk2 = connect_socket(client_bdaddr, test_2_connect_cb, false);
+	data->io2 = connect_socket(client_bdaddr, test_2_connect_cb, false);
+	data->sk2 = l_io_get_fd(data->io2);
 
 	if (l2data->close_1) {
 		tester_print("Closing first socket! %d", data->sk);
 		close(data->sk);
 	}
 
-	g_idle_add(enable_advertising, NULL);
+	l_idle_oneshot(enable_advertising, NULL, NULL);
 }
 
 static uint8_t test_scan_enable_counter;
@@ -1654,7 +1660,7 @@ static void test_connect_2_router(uint16_t opcode, const void *param,
 		if (test_scan_enable_counter == 1)
 			test_connect_2_part_2();
 		else if (test_scan_enable_counter == 2)
-			g_idle_add(enable_advertising, NULL);
+			l_idle_oneshot(enable_advertising, NULL, NULL);
 	}
 }
 
@@ -1683,50 +1689,47 @@ static void test_connect_2(const void *test_data)
 
 	client_bdaddr = hciemu_get_client_bdaddr(data->hciemu);
 	if (l2data->close_1)
-		data->sk = connect_socket(client_bdaddr, NULL, defer);
+		data->io = connect_socket(client_bdaddr, NULL, defer);
 	else
-		data->sk = connect_socket(client_bdaddr, test_2_connect_cb,
+		data->io = connect_socket(client_bdaddr, test_2_connect_cb,
 								defer);
+	data->sk = l_io_get_fd(data->io);
 }
 
-static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool l2cap_listen_cb(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct l2cap_data *l2data = data->test_data;
 	int sk, new_sk;
 
-	data->io_id = 0;
-
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 
 	new_sk = accept(sk, NULL, NULL);
 	if (new_sk < 0) {
 		tester_warn("accept failed: %s (%u)", strerror(errno), errno);
 		tester_test_failed();
-		return FALSE;
+		return false;
 	}
 
 	if (!check_mtu(data, new_sk)) {
 		tester_test_failed();
-		return FALSE;
+		return false;
 	}
 
 	if (l2data->read_data) {
 		struct bthost *bthost;
-		GIOChannel *new_io;
+		struct l_io *new_io;
+
+		new_io = l_io_new(new_sk);
 
-		new_io = g_io_channel_unix_new(new_sk);
-		g_io_channel_set_close_on_unref(new_io, TRUE);
+		l_io_set_close_on_destroy(new_io, true);
 
 		bthost = hciemu_client_get_host(data->hciemu);
-		g_io_add_watch(new_io, G_IO_IN, server_received_data, NULL);
+		l_io_set_read_handler(new_io, server_received_data, NULL, NULL);
 		bthost_send_cid(bthost, data->handle, data->dcid,
 					l2data->read_data, l2data->data_len);
 
-		g_io_channel_unref(new_io);
-
-		return FALSE;
+		return false;
 	} else if (l2data->write_data) {
 		struct bthost *bthost;
 		ssize_t ret;
@@ -1743,7 +1746,7 @@ static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
 			tester_test_failed();
 		}
 
-		return FALSE;
+		return false;
 	}
 
 	tester_print("Successfully connected");
@@ -1752,7 +1755,7 @@ static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
 
 	tester_test_passed();
 
-	return FALSE;
+	return false;
 }
 
 static void client_l2cap_rsp(uint8_t code, const void *data, uint16_t len,
@@ -1839,7 +1842,6 @@ static void test_server(const void *test_data)
 	const uint8_t *master_bdaddr;
 	uint8_t addr_type;
 	struct bthost *bthost;
-	GIOChannel *io;
 	int sk;
 
 	if (l2data->server_psm || l2data->cid) {
@@ -1859,12 +1861,10 @@ static void test_server(const void *test_data)
 			return;
 		}
 
-		io = g_io_channel_unix_new(sk);
-		g_io_channel_set_close_on_unref(io, TRUE);
+		data->io = l_io_new(sk);
 
-		data->io_id = g_io_add_watch(io, G_IO_IN, l2cap_listen_cb,
-									NULL);
-		g_io_channel_unref(io);
+		l_io_set_close_on_destroy(data->io, true);
+		l_io_set_read_handler(data->io, l2cap_listen_cb, NULL, NULL);
 
 		tester_print("Listening for connections");
 	}
-- 
2.26.2


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

* [RFC PATCH BlueZ 09/10] tools/mgmt-tester: Convert to use ELL library
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
                   ` (7 preceding siblings ...)
  2020-11-07  7:03 ` [RFC PATCH BlueZ 08/10] tools/l2cap-tester: " Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  2020-11-07  7:03 ` [RFC PATCH BlueZ 10/10] tools/rfcomm-tester: " Inga Stotland
  9 siblings, 0 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This reworks the source code to use ELL primitives and removes
dependecies on GLib.
---
 Makefile.tools      | 4 ++--
 tools/mgmt-tester.c | 5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index 03264cff9..e65547c3f 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -106,12 +106,12 @@ tools_3dsp_SOURCES = tools/3dsp.c monitor/bt.h
 tools_3dsp_LDADD = src/libshared-mainloop.la
 
 tools_mgmt_tester_SOURCES = tools/mgmt-tester.c monitor/bt.h \
-				emulator/hciemu.h emulator/hciemu.c \
+				emulator/hciemu.h emulator/hciemu-ell.c \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
 				emulator/smp.c
 tools_mgmt_tester_LDADD = lib/libbluetooth-internal.la \
-				src/libshared-glib.la $(GLIB_LIBS)
+				src/libshared-ell.la $(ell_ldadd)
 
 tools_l2cap_tester_SOURCES = tools/l2cap-tester.c monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu-ell.c \
diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index d8554411f..75f6457d2 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -18,7 +18,7 @@
 #include <errno.h>
 #include <unistd.h>
 
-#include <glib.h>
+#include <ell/ell.h>
 
 #include "lib/bluetooth.h"
 #include "lib/hci.h"
@@ -130,7 +130,8 @@ static void read_info_callback(uint8_t status, uint16_t length,
 	tester_print("  Name: %s", rp->name);
 	tester_print("  Short name: %s", rp->short_name);
 
-	if (strcmp(hciemu_get_address(data->hciemu), addr)) {
+	if (!hciemu_get_address(data->hciemu) ||
+			(strcmp(hciemu_get_address(data->hciemu), addr))) {
 		tester_pre_setup_failed();
 		return;
 	}
-- 
2.26.2


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

* [RFC PATCH BlueZ 10/10] tools/rfcomm-tester: Convert to use ELL library
  2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
                   ` (8 preceding siblings ...)
  2020-11-07  7:03 ` [RFC PATCH BlueZ 09/10] tools/mgmt-tester: " Inga Stotland
@ 2020-11-07  7:03 ` Inga Stotland
  9 siblings, 0 replies; 14+ messages in thread
From: Inga Stotland @ 2020-11-07  7:03 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: luiz.von.dentz, Inga Stotland

This reworks the source code to use ELL primitives and removes
dependecies on GLib.
---
 Makefile.tools        |  4 +-
 tools/rfcomm-tester.c | 92 ++++++++++++++++++++++++-------------------
 2 files changed, 53 insertions(+), 43 deletions(-)

diff --git a/Makefile.tools b/Makefile.tools
index e65547c3f..2f86c839c 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -122,12 +122,12 @@ tools_l2cap_tester_LDADD = lib/libbluetooth-internal.la \
 				src/libshared-ell.la $(ell_ldadd)
 
 tools_rfcomm_tester_SOURCES = tools/rfcomm-tester.c monitor/bt.h \
-				emulator/hciemu.h emulator/hciemu.c \
+				emulator/hciemu.h emulator/hciemu-ell.c \
 				emulator/btdev.h emulator/btdev.c \
 				emulator/bthost.h emulator/bthost.c \
 				emulator/smp.c
 tools_rfcomm_tester_LDADD = lib/libbluetooth-internal.la \
-				src/libshared-glib.la $(GLIB_LIBS)
+				src/libshared-ell.la $(ell_ldadd)
 
 tools_bnep_tester_SOURCES = tools/bnep-tester.c monitor/bt.h \
 				emulator/hciemu.h emulator/hciemu-ell.c \
diff --git a/tools/rfcomm-tester.c b/tools/rfcomm-tester.c
index 9bae5b9d5..516dd3f82 100644
--- a/tools/rfcomm-tester.c
+++ b/tools/rfcomm-tester.c
@@ -18,7 +18,7 @@
 #include <errno.h>
 #include <stdbool.h>
 
-#include <glib.h>
+#include <ell/ell.h>
 
 #include "lib/bluetooth.h"
 #include "lib/rfcomm.h"
@@ -35,9 +35,9 @@ struct test_data {
 	struct mgmt *mgmt;
 	uint16_t mgmt_index;
 	struct hciemu *hciemu;
+	struct l_io *io;
 	enum hciemu_type hciemu_type;
 	const void *test_data;
-	unsigned int io_id;
 	uint16_t conn_handle;
 };
 
@@ -192,9 +192,9 @@ static void test_post_teardown(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 
-	if (data->io_id > 0) {
-		g_source_remove(data->io_id);
-		data->io_id = 0;
+	if (data->io) {
+		l_io_destroy(data->io);
+		data->io = NULL;
 	}
 
 	hciemu_unref(data->hciemu);
@@ -395,8 +395,7 @@ static int connect_rfcomm_sock(int sk, const bdaddr_t *bdaddr, uint8_t channel)
 	return 0;
 }
 
-static gboolean client_received_data(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool client_received_data(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct rfcomm_client_data *cli = data->test_data;
@@ -404,7 +403,7 @@ static gboolean client_received_data(GIOChannel *io, GIOCondition cond,
 	ssize_t ret;
 	char buf[248];
 
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 
 	ret = read(sk, buf, cli->data_len);
 	if (cli->data_len != ret) {
@@ -420,19 +419,38 @@ static gboolean client_received_data(GIOChannel *io, GIOCondition cond,
 	return false;
 }
 
-static gboolean rc_connect_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static void rc_disconnect_cb(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct rfcomm_client_data *cli = data->test_data;
 	socklen_t len = sizeof(int);
 	int sk, err, sk_err;
 
-	tester_print("Connected");
+	tester_print("Disconnected");
+
+	sk = l_io_get_fd(io);
+
+	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
+		err = -errno;
+	else
+		err = -sk_err;
+
+	if (cli->expected_connect_err && err == cli->expected_connect_err)
+		tester_test_passed();
+	else
+		tester_test_failed();
+}
 
-	data->io_id = 0;
+static bool rc_connect_cb(struct l_io *io, void *user_data)
+{
+	struct test_data *data = tester_get_data();
+	const struct rfcomm_client_data *cli = data->test_data;
+	socklen_t len = sizeof(int);
+	int sk, err, sk_err;
+
+	tester_print("Connected");
 
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 
 	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0)
 		err = -errno;
@@ -458,7 +476,7 @@ static gboolean rc_connect_cb(GIOChannel *io, GIOCondition cond,
 
 		return false;
 	} else if (cli->read_data) {
-		g_io_add_watch(io, G_IO_IN, client_received_data, NULL);
+		l_io_set_read_handler(io, client_received_data, NULL, NULL);
 		bthost_send_rfcomm_data(hciemu_client_get_host(data->hciemu),
 						data->conn_handle,
 						cli->client_channel,
@@ -535,7 +553,6 @@ static void test_connect(const void *test_data)
 	struct bthost *bthost = hciemu_client_get_host(data->hciemu);
 	const struct rfcomm_client_data *cli = data->test_data;
 	const uint8_t *client_addr, *master_addr;
-	GIOChannel *io;
 	int sk;
 
 	bthost_add_l2cap_server(bthost, 0x0003, NULL, NULL, NULL);
@@ -554,18 +571,19 @@ static void test_connect(const void *test_data)
 		return;
 	}
 
-	io = g_io_channel_unix_new(sk);
-	g_io_channel_set_close_on_unref(io, TRUE);
-
-	data->io_id = g_io_add_watch(io, G_IO_OUT, rc_connect_cb, NULL);
+	data->io = l_io_new(sk);
+	l_io_set_close_on_destroy(data->io, true);
+	l_io_set_disconnect_handler(data->io, rc_disconnect_cb, NULL, NULL);
 
-	g_io_channel_unref(io);
+	if (!l_io_set_write_handler(data->io, rc_connect_cb, NULL, NULL)) {
+		tester_test_failed();
+		return;
+	}
 
 	tester_print("Connect in progress %d", sk);
 }
 
-static gboolean server_received_data(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool server_received_data(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct rfcomm_server_data *srv = data->test_data;
@@ -573,7 +591,7 @@ static gboolean server_received_data(GIOChannel *io, GIOCondition cond,
 	ssize_t ret;
 	int sk;
 
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 
 	ret = read(sk, buf, srv->data_len);
 	if (ret != srv->data_len) {
@@ -589,16 +607,14 @@ static gboolean server_received_data(GIOChannel *io, GIOCondition cond,
 	return false;
 }
 
-static gboolean rfcomm_listen_cb(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
+static bool rfcomm_listen_cb(struct l_io *io, void *user_data)
 {
 	struct test_data *data = tester_get_data();
 	const struct rfcomm_server_data *srv = data->test_data;
 	int sk, new_sk;
 
-	data->io_id = 0;
 
-	sk = g_io_channel_unix_get_fd(io);
+	sk = l_io_get_fd(io);
 
 	new_sk = accept(sk, NULL, NULL);
 	if (new_sk < 0) {
@@ -616,15 +632,12 @@ static gboolean rfcomm_listen_cb(GIOChannel *io, GIOCondition cond,
 		close(new_sk);
 		return false;
 	} else if (srv->read_data) {
-		GIOChannel *new_io;
-
-		new_io = g_io_channel_unix_new(new_sk);
-		g_io_channel_set_close_on_unref(new_io, TRUE);
+		struct l_io *new_io;
 
-		data->io_id = g_io_add_watch(new_io, G_IO_IN,
-						server_received_data, NULL);
+		new_io = l_io_new(new_sk);
+		l_io_set_close_on_destroy(new_io, true);
+		l_io_set_read_handler(new_io, server_received_data, NULL, NULL);
 
-		g_io_channel_unref(new_io);
 		return false;
 	}
 
@@ -677,7 +690,6 @@ static void test_server(const void *test_data)
 	const struct rfcomm_server_data *srv = data->test_data;
 	const uint8_t *master_addr;
 	struct bthost *bthost;
-	GIOChannel *io;
 	int sk;
 
 	master_addr = hciemu_get_master_bdaddr(data->hciemu);
@@ -696,11 +708,10 @@ static void test_server(const void *test_data)
 		return;
 	}
 
-	io = g_io_channel_unix_new(sk);
-	g_io_channel_set_close_on_unref(io, TRUE);
+	data->io = l_io_new(sk);
+	l_io_set_close_on_destroy(data->io, true);
 
-	data->io_id = g_io_add_watch(io, G_IO_IN, rfcomm_listen_cb, NULL);
-	g_io_channel_unref(io);
+	l_io_set_read_handler(data->io, rfcomm_listen_cb, NULL, NULL);
 
 	tester_print("Listening for connections");
 
@@ -713,12 +724,11 @@ static void test_server(const void *test_data)
 #define test_rfcomm(name, data, setup, func) \
 	do { \
 		struct test_data *user; \
-		user = malloc(sizeof(struct test_data)); \
+		user = l_new(struct test_data, 1);	\
 		if (!user) \
 			break; \
 		user->hciemu_type = HCIEMU_TYPE_BREDR; \
 		user->test_data = data; \
-		user->io_id = 0; \
 		tester_add_full(name, data, \
 				test_pre_setup, setup, func, NULL, \
 				test_post_teardown, 2, user, test_data_free); \
-- 
2.26.2


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

* RE: Convert tools to use ELL library
  2020-11-07  7:03 ` [RFC PATCH BlueZ 01/10] shared/tester-ell: Create ell-based version of tester code Inga Stotland
@ 2020-11-07  7:26   ` bluez.test.bot
  0 siblings, 0 replies; 14+ messages in thread
From: bluez.test.bot @ 2020-11-07  7:26 UTC (permalink / raw)
  To: linux-bluetooth, inga.stotland

[-- Attachment #1: Type: text/plain, Size: 1336 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=379479

---Test result---

##############################
Test: CheckPatch - FAIL
Output:
shared/tester-ell: Create ell-based version of tester code
ERROR:INITIALISED_STATIC: do not initialise statics to false
#809: FILE: src/shared/tester-ell.c:761:
+	static bool terminated = false;

- total: 1 errors, 0 warnings, 901 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.

"[PATCH] shared/tester-ell: Create ell-based version of tester code" has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: CheckGitLint - PASS

##############################
Test: CheckBuild - PASS

##############################
Test: MakeCheck - PASS



---
Regards,
Linux Bluetooth


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

* Re: [RFC PATCH BlueZ 02/10] emulator/hciemu: Create ELL based version of hciemu
  2020-11-07  7:03 ` [RFC PATCH BlueZ 02/10] emulator/hciemu: Create ELL based version of hciemu Inga Stotland
@ 2020-11-09 18:04   ` Luiz Augusto von Dentz
       [not found]     ` <72f314b5d2b631213d10c48bfd7612e0484e3280.camel@intel.com>
  0 siblings, 1 reply; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2020-11-09 18:04 UTC (permalink / raw)
  To: Inga Stotland; +Cc: linux-bluetooth, Luiz Augusto Von Dentz

Hi Inga,

On Fri, Nov 6, 2020 at 11:06 PM Inga Stotland <inga.stotland@intel.com> wrote:
>
> This adds a separate implementtion of hciemu code, hciemu-ell.c,
> that uses ELL library primitives.

I wonder if this should really be separated like this or we just make
use of struct io instead of l_io, that way we don't need to keep
duplicating things on the emulator, the other option would be to drop
entirely the glib version but I guess you haven't done that because
there are quite a few dependencies to get rid in order to run the
tester with ell.

> ---
>  emulator/hciemu-ell.c | 564 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 564 insertions(+)
>  create mode 100644 emulator/hciemu-ell.c
>
> diff --git a/emulator/hciemu-ell.c b/emulator/hciemu-ell.c
> new file mode 100644
> index 000000000..40342e99b
> --- /dev/null
> +++ b/emulator/hciemu-ell.c
> @@ -0,0 +1,564 @@
> +// SPDX-License-Identifier: LGPL-2.1-or-later
> +/*
> + *
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2012-2014, 2020  Intel Corporation. All rights reserved.
> + *
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdbool.h>
> +#include <errno.h>
> +#include <sys/socket.h>
> +
> +#include <ell/ell.h>
> +
> +#include "lib/bluetooth.h"
> +#include "lib/hci.h"
> +
> +#include "monitor/bt.h"
> +#include "emulator/btdev.h"
> +#include "emulator/bthost.h"
> +#include "src/shared/util.h"
> +#include "src/shared/queue.h"
> +#include "emulator/hciemu.h"
> +
> +struct hciemu {
> +       int ref_count;
> +       enum btdev_type btdev_type;
> +       struct bthost *host_stack;
> +       struct btdev *master_dev;
> +       struct btdev *client_dev;
> +       struct l_io *host_io;
> +       struct l_io *master_io;
> +       struct l_io *client_io;
> +       struct queue *post_command_hooks;
> +       char bdaddr_str[18];
> +
> +       hciemu_debug_func_t debug_callback;
> +       hciemu_destroy_func_t debug_destroy;
> +       void *debug_data;
> +};
> +
> +struct hciemu_command_hook {
> +       hciemu_command_func_t function;
> +       void *user_data;
> +};
> +
> +static void destroy_command_hook(void *data)
> +{
> +       struct hciemu_command_hook *hook = data;
> +
> +       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,
> +                               const void *data, uint8_t len,
> +                               btdev_callback callback, void *user_data)
> +{
> +       struct hciemu *hciemu = user_data;
> +       struct run_data run_data = { .opcode = opcode,
> +                                               .data = data, .len = len };
> +
> +       btdev_command_default(callback);
> +
> +       queue_foreach(hciemu->post_command_hooks, run_command_hook, &run_data);
> +}
> +
> +static void client_command_callback(uint16_t opcode,
> +                               const void *data, uint8_t len,
> +                               btdev_callback callback, void *user_data)
> +{
> +       btdev_command_default(callback);
> +}
> +
> +static void writev_callback(const struct iovec *iov, int iovlen,
> +                                                               void *user_data)
> +{
> +       struct l_io *io = user_data;
> +       ssize_t written;
> +       int fd;
> +
> +       fd = l_io_get_fd(io);
> +
> +       written = writev(fd, iov, iovlen);
> +       if (written < 0)
> +               return;
> +}
> +
> +static bool receive_bthost(struct l_io *io, void *user_data)
> +{
> +       struct bthost *bthost = user_data;
> +       unsigned char buf[4096];
> +       ssize_t len;
> +       int fd;
> +
> +       fd = l_io_get_fd(io);
> +
> +       len = read(fd, buf, sizeof(buf));
> +       if (len < 0)
> +               return false;
> +
> +       bthost_receive_h4(bthost, buf, len);
> +
> +       return true;
> +}
> +
> +static struct l_io *create_io_bthost(int fd, struct bthost *bthost)
> +{
> +       struct l_io *io;
> +
> +       io = l_io_new(fd);
> +
> +       l_io_set_close_on_destroy(io, true);
> +
> +       bthost_set_send_handler(bthost, writev_callback, io);
> +
> +       l_io_set_read_handler(io, receive_bthost, bthost, NULL);
> +
> +       return io;
> +}
> +
> +static bool receive_btdev(struct l_io *io, void *user_data)
> +
> +{
> +       struct btdev *btdev = user_data;
> +       unsigned char buf[4096];
> +       ssize_t len;
> +       int fd;
> +
> +       fd = l_io_get_fd(io);
> +
> +       len = read(fd, buf, sizeof(buf));
> +       if (len < 0) {
> +               if (errno == EAGAIN || errno == EINTR)
> +                       return true;
> +
> +               return false;
> +       }
> +
> +       if (len < 1)
> +               return false;
> +
> +       switch (buf[0]) {
> +       case BT_H4_CMD_PKT:
> +       case BT_H4_ACL_PKT:
> +       case BT_H4_SCO_PKT:
> +               btdev_receive_h4(btdev, buf, len);
> +               break;
> +       }
> +
> +       return true;
> +}
> +
> +static struct l_io *create_io_btdev(int fd, struct btdev *btdev)
> +{
> +       struct l_io *io;
> +
> +       io = l_io_new(fd);
> +
> +       l_io_set_close_on_destroy(io, true);
> +
> +       btdev_set_send_handler(btdev, writev_callback, io);
> +
> +       l_io_set_read_handler(io, receive_btdev, btdev, NULL);
> +
> +       return io;
> +}
> +
> +static bool create_vhci(struct hciemu *hciemu)
> +{
> +       struct btdev *btdev;
> +       uint8_t create_req[2];
> +       ssize_t written;
> +       int fd;
> +
> +       btdev = btdev_create(hciemu->btdev_type, 0x00);
> +       if (!btdev)
> +               return false;
> +
> +       btdev_set_command_handler(btdev, master_command_callback, hciemu);
> +
> +       fd = open("/dev/vhci", O_RDWR | O_NONBLOCK | O_CLOEXEC);
> +       if (fd < 0) {
> +               perror("Opening /dev/vhci failed");
> +               btdev_destroy(btdev);
> +               return false;
> +       }
> +
> +       create_req[0] = HCI_VENDOR_PKT;
> +       create_req[1] = HCI_PRIMARY;
> +
> +       written = write(fd, create_req, sizeof(create_req));
> +       if (written < 0) {
> +               close(fd);
> +               btdev_destroy(btdev);
> +               return false;
> +       }
> +
> +       hciemu->master_dev = btdev;
> +
> +       hciemu->master_io = create_io_btdev(fd, btdev);
> +
> +       return true;
> +}
> +
> +struct bthost *hciemu_client_get_host(struct hciemu *hciemu)
> +{
> +       if (!hciemu)
> +               return NULL;
> +
> +       return hciemu->host_stack;
> +}
> +
> +static bool create_stack(struct hciemu *hciemu)
> +{
> +       struct btdev *btdev;
> +       struct bthost *bthost;
> +       int sv[2];
> +
> +       btdev = btdev_create(hciemu->btdev_type, 0x00);
> +       if (!btdev)
> +               return false;
> +
> +       bthost = bthost_create();
> +       if (!bthost) {
> +               btdev_destroy(btdev);
> +               return false;
> +       }
> +
> +       btdev_set_command_handler(btdev, client_command_callback, hciemu);
> +
> +       if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC,
> +                                                               0, sv) < 0) {
> +               bthost_destroy(bthost);
> +               btdev_destroy(btdev);
> +               return false;
> +       }
> +
> +       hciemu->client_dev = btdev;
> +       hciemu->host_stack = bthost;
> +
> +       hciemu->client_io = create_io_btdev(sv[0], btdev);
> +       hciemu->host_io = create_io_bthost(sv[1], bthost);
> +
> +       return true;
> +}
> +
> +static void start_stack(void *user_data)
> +{
> +       struct hciemu *hciemu = user_data;
> +
> +       bthost_start(hciemu->host_stack);
> +}
> +
> +struct hciemu *hciemu_new(enum hciemu_type type)
> +{
> +       struct hciemu *hciemu;
> +
> +       hciemu = new0(struct hciemu, 1);
> +       if (!hciemu)
> +               return NULL;
> +
> +       switch (type) {
> +       case HCIEMU_TYPE_BREDRLE:
> +               hciemu->btdev_type = BTDEV_TYPE_BREDRLE;
> +               break;
> +       case HCIEMU_TYPE_BREDR:
> +               hciemu->btdev_type = BTDEV_TYPE_BREDR;
> +               break;
> +       case HCIEMU_TYPE_LE:
> +               hciemu->btdev_type = BTDEV_TYPE_LE;
> +               break;
> +       case HCIEMU_TYPE_LEGACY:
> +               hciemu->btdev_type = BTDEV_TYPE_BREDR20;
> +               break;
> +       case HCIEMU_TYPE_BREDRLE50:
> +               hciemu->btdev_type = BTDEV_TYPE_BREDRLE50;
> +               break;
> +       case HCIEMU_TYPE_BREDRLE52:
> +               hciemu->btdev_type = BTDEV_TYPE_BREDRLE52;
> +               break;
> +       default:
> +               return NULL;
> +       }
> +
> +       hciemu->post_command_hooks = queue_new();
> +       if (!hciemu->post_command_hooks) {
> +               free(hciemu);
> +               return NULL;
> +       }
> +
> +       if (!create_vhci(hciemu)) {
> +               queue_destroy(hciemu->post_command_hooks, NULL);
> +               free(hciemu);
> +               return NULL;
> +       }
> +
> +       if (!create_stack(hciemu)) {
> +               l_io_destroy(hciemu->master_io);
> +               btdev_destroy(hciemu->master_dev);
> +               queue_destroy(hciemu->post_command_hooks, NULL);
> +               free(hciemu);
> +               return NULL;
> +       }
> +
> +       l_idle_oneshot(start_stack, hciemu, NULL);
> +
> +       return hciemu_ref(hciemu);
> +}
> +
> +struct hciemu *hciemu_ref(struct hciemu *hciemu)
> +{
> +       if (!hciemu)
> +               return NULL;
> +
> +       __sync_fetch_and_add(&hciemu->ref_count, 1);
> +
> +       return hciemu;
> +}
> +
> +void hciemu_unref(struct hciemu *hciemu)
> +{
> +       if (!hciemu)
> +               return;
> +
> +       if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
> +               return;
> +
> +       queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
> +
> +       l_io_destroy(hciemu->host_io);
> +       l_io_destroy(hciemu->client_io);
> +       l_io_destroy(hciemu->master_io);
> +
> +       bthost_destroy(hciemu->host_stack);
> +       btdev_destroy(hciemu->client_dev);
> +       btdev_destroy(hciemu->master_dev);
> +
> +       free(hciemu);
> +}
> +
> +static void bthost_debug(const char *str, void *user_data)
> +{
> +       struct hciemu *hciemu = user_data;
> +
> +       util_debug(hciemu->debug_callback, hciemu->debug_data,
> +                                       "bthost: %s", str);
> +}
> +
> +static void btdev_master_debug(const char *str, void *user_data)
> +{
> +       struct hciemu *hciemu = user_data;
> +
> +       util_debug(hciemu->debug_callback, hciemu->debug_data,
> +                                       "btdev: %s", str);
> +}
> +
> +static void btdev_client_debug(const char *str, void *user_data)
> +{
> +       struct hciemu *hciemu = user_data;
> +
> +       util_debug(hciemu->debug_callback, hciemu->debug_data,
> +                                       "btdev[bthost]: %s", str);
> +}
> +
> +bool hciemu_set_debug(struct hciemu *hciemu, hciemu_debug_func_t callback,
> +                       void *user_data, hciemu_destroy_func_t destroy)
> +{
> +       if (!hciemu)
> +               return false;
> +
> +       if (hciemu->debug_destroy)
> +               hciemu->debug_destroy(hciemu->debug_data);
> +
> +       hciemu->debug_callback = callback;
> +       hciemu->debug_destroy = destroy;
> +       hciemu->debug_data = user_data;
> +
> +       btdev_set_debug(hciemu->master_dev, btdev_master_debug, hciemu, NULL);
> +       btdev_set_debug(hciemu->client_dev, btdev_client_debug, hciemu, NULL);
> +       bthost_set_debug(hciemu->host_stack, bthost_debug, hciemu, NULL);
> +
> +       return true;
> +}
> +
> +const char *hciemu_get_address(struct hciemu *hciemu)
> +{
> +       const uint8_t *addr;
> +
> +       if (!hciemu || !hciemu->master_dev)
> +               return NULL;
> +
> +       addr = btdev_get_bdaddr(hciemu->master_dev);
> +       sprintf(hciemu->bdaddr_str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
> +                       addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
> +       return hciemu->bdaddr_str;
> +}
> +
> +uint8_t *hciemu_get_features(struct hciemu *hciemu)
> +{
> +       if (!hciemu || !hciemu->master_dev)
> +               return NULL;
> +
> +       return btdev_get_features(hciemu->master_dev);
> +}
> +
> +const uint8_t *hciemu_get_master_bdaddr(struct hciemu *hciemu)
> +{
> +       if (!hciemu || !hciemu->master_dev)
> +               return NULL;
> +
> +       return btdev_get_bdaddr(hciemu->master_dev);
> +}
> +
> +const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
> +{
> +       if (!hciemu || !hciemu->client_dev)
> +               return NULL;
> +
> +       return btdev_get_bdaddr(hciemu->client_dev);
> +}
> +
> +uint8_t hciemu_get_master_scan_enable(struct hciemu *hciemu)
> +{
> +       if (!hciemu || !hciemu->master_dev)
> +               return 0;
> +
> +       return btdev_get_scan_enable(hciemu->master_dev);
> +}
> +
> +uint8_t hciemu_get_master_le_scan_enable(struct hciemu *hciemu)
> +{
> +       if (!hciemu || !hciemu->master_dev)
> +               return 0;
> +
> +       return btdev_get_le_scan_enable(hciemu->master_dev);
> +}
> +
> +void hciemu_set_master_le_states(struct hciemu *hciemu,
> +                                               const uint8_t *le_states)
> +{
> +       if (!hciemu || !hciemu->master_dev)
> +               return;
> +
> +       btdev_set_le_states(hciemu->master_dev, le_states);
> +}
> +
> +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 = new0(struct hciemu_command_hook, 1);
> +       if (!hook)
> +               return false;
> +
> +       hook->function = function;
> +       hook->user_data = user_data;
> +
> +       if (!queue_push_tail(hciemu->post_command_hooks, hook)) {
> +               free(hook);
> +               return false;
> +       }
> +
> +       return true;
> +}
> +
> +bool hciemu_clear_master_post_command_hooks(struct hciemu *hciemu)
> +{
> +       if (!hciemu)
> +               return false;
> +
> +       queue_remove_all(hciemu->post_command_hooks,
> +                                       NULL, NULL, destroy_command_hook);
> +       return true;
> +}
> +
> +int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
> +                               uint16_t opcode, hciemu_hook_func_t function,
> +                               void *user_data)
> +{
> +       enum btdev_hook_type hook_type;
> +
> +       if (!hciemu)
> +               return -1;
> +
> +       switch (type) {
> +       case HCIEMU_HOOK_PRE_CMD:
> +               hook_type = BTDEV_HOOK_PRE_CMD;
> +               break;
> +       case HCIEMU_HOOK_POST_CMD:
> +               hook_type = BTDEV_HOOK_POST_CMD;
> +               break;
> +       case HCIEMU_HOOK_PRE_EVT:
> +               hook_type = BTDEV_HOOK_PRE_EVT;
> +               break;
> +       case HCIEMU_HOOK_POST_EVT:
> +               hook_type = BTDEV_HOOK_POST_EVT;
> +               break;
> +       default:
> +               return -1;
> +       }
> +
> +       return btdev_add_hook(hciemu->master_dev, hook_type, opcode, function,
> +                                                               user_data);
> +}
> +
> +bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
> +                                                               uint16_t opcode)
> +{
> +       enum btdev_hook_type hook_type;
> +
> +       if (!hciemu)
> +               return false;
> +
> +       switch (type) {
> +       case HCIEMU_HOOK_PRE_CMD:
> +               hook_type = BTDEV_HOOK_PRE_CMD;
> +               break;
> +       case HCIEMU_HOOK_POST_CMD:
> +               hook_type = BTDEV_HOOK_POST_CMD;
> +               break;
> +       case HCIEMU_HOOK_PRE_EVT:
> +               hook_type = BTDEV_HOOK_PRE_EVT;
> +               break;
> +       case HCIEMU_HOOK_POST_EVT:
> +               hook_type = BTDEV_HOOK_POST_EVT;
> +               break;
> +       default:
> +               return false;
> +       }
> +
> +       return btdev_del_hook(hciemu->master_dev, hook_type, opcode);
> +}
> --
> 2.26.2
>


-- 
Luiz Augusto von Dentz

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

* Re: [RFC PATCH BlueZ 02/10] emulator/hciemu: Create ELL based version of hciemu
       [not found]     ` <72f314b5d2b631213d10c48bfd7612e0484e3280.camel@intel.com>
@ 2020-11-10 22:10       ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2020-11-10 22:10 UTC (permalink / raw)
  To: Stotland, Inga; +Cc: Von Dentz, Luiz, linux-bluetooth

Hi Inga,

On Tue, Nov 10, 2020 at 1:55 PM Stotland, Inga <inga.stotland@intel.com> wrote:
>
> Hi Luiz,
>
> On Mon, 2020-11-09 at 10:04 -0800, Luiz Augusto von Dentz wrote:
>
> Hi Inga,
>
>
> On Fri, Nov 6, 2020 at 11:06 PM Inga Stotland <
>
> inga.stotland@intel.com
>
> > wrote:
>
>
> This adds a separate implementtion of hciemu code, hciemu-ell.c,
>
> that uses ELL library primitives.
>
>
> I wonder if this should really be separated like this or we just make
>
> use of struct io instead of l_io, that way we don't need to keep
>
> duplicating things on the emulator, the other option would be to drop
>
> entirely the glib version but I guess you haven't done that because
>
> there are quite a few dependencies to get rid in order to run the
>
> tester with ell.
>
>
> I would've made one version of hciemu.c with the unified io, but there's a reference to g_idel_add that has equivalent in ELL, but not the internal bluez libs.
>
> Also, hciemu is linked with android test build (android/Makefile.am) and android is a completely different animal: from what I can see it relies heavily on GLib
>
> and I wouldn't know how to test the android stuff once I make the changes. So I chose to err on the side of caution and create a duplicate.

Im planning to remove android actually, just need to move a few things
around since some unit test uses the android version.

>
>
>
>
>
> ---
>
>  emulator/hciemu-ell.c | 564 ++++++++++++++++++++++++++++++++++++++++++
>
>  1 file changed, 564 insertions(+)
>
>  create mode 100644 emulator/hciemu-ell.c
>
>
> diff --git a/emulator/hciemu-ell.c b/emulator/hciemu-ell.c
>
> new file mode 100644
>
> index 000000000..40342e99b
>
> --- /dev/null
>
> +++ b/emulator/hciemu-ell.c
>
> @@ -0,0 +1,564 @@
>
> +// SPDX-License-Identifier: LGPL-2.1-or-later
>
> +/*
>
> + *
>
> + *  BlueZ - Bluetooth protocol stack for Linux
>
> + *
>
> + *  Copyright (C) 2012-2014, 2020  Intel Corporation. All rights reserved.
>
> + *
>
> + *
>
> + */
>
> +
>
> +#ifdef HAVE_CONFIG_H
>
> +#include <config.h>
>
> +#endif
>
> +
>
> +#define _GNU_SOURCE
>
> +#include <stdio.h>
>
> +#include <fcntl.h>
>
> +#include <unistd.h>
>
> +#include <stdlib.h>
>
> +#include <string.h>
>
> +#include <stdbool.h>
>
> +#include <errno.h>
>
> +#include <sys/socket.h>
>
> +
>
> +#include <ell/ell.h>
>
> +
>
> +#include "lib/bluetooth.h"
>
> +#include "lib/hci.h"
>
> +
>
> +#include "monitor/bt.h"
>
> +#include "emulator/btdev.h"
>
> +#include "emulator/bthost.h"
>
> +#include "src/shared/util.h"
>
> +#include "src/shared/queue.h"
>
> +#include "emulator/hciemu.h"
>
> +
>
> +struct hciemu {
>
> +       int ref_count;
>
> +       enum btdev_type btdev_type;
>
> +       struct bthost *host_stack;
>
> +       struct btdev *master_dev;
>
> +       struct btdev *client_dev;
>
> +       struct l_io *host_io;
>
> +       struct l_io *master_io;
>
> +       struct l_io *client_io;
>
> +       struct queue *post_command_hooks;
>
> +       char bdaddr_str[18];
>
> +
>
> +       hciemu_debug_func_t debug_callback;
>
> +       hciemu_destroy_func_t debug_destroy;
>
> +       void *debug_data;
>
> +};
>
> +
>
> +struct hciemu_command_hook {
>
> +       hciemu_command_func_t function;
>
> +       void *user_data;
>
> +};
>
> +
>
> +static void destroy_command_hook(void *data)
>
> +{
>
> +       struct hciemu_command_hook *hook = data;
>
> +
>
> +       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,
>
> +                               const void *data, uint8_t len,
>
> +                               btdev_callback callback, void *user_data)
>
> +{
>
> +       struct hciemu *hciemu = user_data;
>
> +       struct run_data run_data = { .opcode = opcode,
>
> +                                               .data = data, .len = len };
>
> +
>
> +       btdev_command_default(callback);
>
> +
>
> +       queue_foreach(hciemu->post_command_hooks, run_command_hook, &run_data);
>
> +}
>
> +
>
> +static void client_command_callback(uint16_t opcode,
>
> +                               const void *data, uint8_t len,
>
> +                               btdev_callback callback, void *user_data)
>
> +{
>
> +       btdev_command_default(callback);
>
> +}
>
> +
>
> +static void writev_callback(const struct iovec *iov, int iovlen,
>
> +                                                               void *user_data)
>
> +{
>
> +       struct l_io *io = user_data;
>
> +       ssize_t written;
>
> +       int fd;
>
> +
>
> +       fd = l_io_get_fd(io);
>
> +
>
> +       written = writev(fd, iov, iovlen);
>
> +       if (written < 0)
>
> +               return;
>
> +}
>
> +
>
> +static bool receive_bthost(struct l_io *io, void *user_data)
>
> +{
>
> +       struct bthost *bthost = user_data;
>
> +       unsigned char buf[4096];
>
> +       ssize_t len;
>
> +       int fd;
>
> +
>
> +       fd = l_io_get_fd(io);
>
> +
>
> +       len = read(fd, buf, sizeof(buf));
>
> +       if (len < 0)
>
> +               return false;
>
> +
>
> +       bthost_receive_h4(bthost, buf, len);
>
> +
>
> +       return true;
>
> +}
>
> +
>
> +static struct l_io *create_io_bthost(int fd, struct bthost *bthost)
>
> +{
>
> +       struct l_io *io;
>
> +
>
> +       io = l_io_new(fd);
>
> +
>
> +       l_io_set_close_on_destroy(io, true);
>
> +
>
> +       bthost_set_send_handler(bthost, writev_callback, io);
>
> +
>
> +       l_io_set_read_handler(io, receive_bthost, bthost, NULL);
>
> +
>
> +       return io;
>
> +}
>
> +
>
> +static bool receive_btdev(struct l_io *io, void *user_data)
>
> +
>
> +{
>
> +       struct btdev *btdev = user_data;
>
> +       unsigned char buf[4096];
>
> +       ssize_t len;
>
> +       int fd;
>
> +
>
> +       fd = l_io_get_fd(io);
>
> +
>
> +       len = read(fd, buf, sizeof(buf));
>
> +       if (len < 0) {
>
> +               if (errno == EAGAIN || errno == EINTR)
>
> +                       return true;
>
> +
>
> +               return false;
>
> +       }
>
> +
>
> +       if (len < 1)
>
> +               return false;
>
> +
>
> +       switch (buf[0]) {
>
> +       case BT_H4_CMD_PKT:
>
> +       case BT_H4_ACL_PKT:
>
> +       case BT_H4_SCO_PKT:
>
> +               btdev_receive_h4(btdev, buf, len);
>
> +               break;
>
> +       }
>
> +
>
> +       return true;
>
> +}
>
> +
>
> +static struct l_io *create_io_btdev(int fd, struct btdev *btdev)
>
> +{
>
> +       struct l_io *io;
>
> +
>
> +       io = l_io_new(fd);
>
> +
>
> +       l_io_set_close_on_destroy(io, true);
>
> +
>
> +       btdev_set_send_handler(btdev, writev_callback, io);
>
> +
>
> +       l_io_set_read_handler(io, receive_btdev, btdev, NULL);
>
> +
>
> +       return io;
>
> +}
>
> +
>
> +static bool create_vhci(struct hciemu *hciemu)
>
> +{
>
> +       struct btdev *btdev;
>
> +       uint8_t create_req[2];
>
> +       ssize_t written;
>
> +       int fd;
>
> +
>
> +       btdev = btdev_create(hciemu->btdev_type, 0x00);
>
> +       if (!btdev)
>
> +               return false;
>
> +
>
> +       btdev_set_command_handler(btdev, master_command_callback, hciemu);
>
> +
>
> +       fd = open("/dev/vhci", O_RDWR | O_NONBLOCK | O_CLOEXEC);
>
> +       if (fd < 0) {
>
> +               perror("Opening /dev/vhci failed");
>
> +               btdev_destroy(btdev);
>
> +               return false;
>
> +       }
>
> +
>
> +       create_req[0] = HCI_VENDOR_PKT;
>
> +       create_req[1] = HCI_PRIMARY;
>
> +
>
> +       written = write(fd, create_req, sizeof(create_req));
>
> +       if (written < 0) {
>
> +               close(fd);
>
> +               btdev_destroy(btdev);
>
> +               return false;
>
> +       }
>
> +
>
> +       hciemu->master_dev = btdev;
>
> +
>
> +       hciemu->master_io = create_io_btdev(fd, btdev);
>
> +
>
> +       return true;
>
> +}
>
> +
>
> +struct bthost *hciemu_client_get_host(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu)
>
> +               return NULL;
>
> +
>
> +       return hciemu->host_stack;
>
> +}
>
> +
>
> +static bool create_stack(struct hciemu *hciemu)
>
> +{
>
> +       struct btdev *btdev;
>
> +       struct bthost *bthost;
>
> +       int sv[2];
>
> +
>
> +       btdev = btdev_create(hciemu->btdev_type, 0x00);
>
> +       if (!btdev)
>
> +               return false;
>
> +
>
> +       bthost = bthost_create();
>
> +       if (!bthost) {
>
> +               btdev_destroy(btdev);
>
> +               return false;
>
> +       }
>
> +
>
> +       btdev_set_command_handler(btdev, client_command_callback, hciemu);
>
> +
>
> +       if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC,
>
> +                                                               0, sv) < 0) {
>
> +               bthost_destroy(bthost);
>
> +               btdev_destroy(btdev);
>
> +               return false;
>
> +       }
>
> +
>
> +       hciemu->client_dev = btdev;
>
> +       hciemu->host_stack = bthost;
>
> +
>
> +       hciemu->client_io = create_io_btdev(sv[0], btdev);
>
> +       hciemu->host_io = create_io_bthost(sv[1], bthost);
>
> +
>
> +       return true;
>
> +}
>
> +
>
> +static void start_stack(void *user_data)
>
> +{
>
> +       struct hciemu *hciemu = user_data;
>
> +
>
> +       bthost_start(hciemu->host_stack);
>
> +}
>
> +
>
> +struct hciemu *hciemu_new(enum hciemu_type type)
>
> +{
>
> +       struct hciemu *hciemu;
>
> +
>
> +       hciemu = new0(struct hciemu, 1);
>
> +       if (!hciemu)
>
> +               return NULL;
>
> +
>
> +       switch (type) {
>
> +       case HCIEMU_TYPE_BREDRLE:
>
> +               hciemu->btdev_type = BTDEV_TYPE_BREDRLE;
>
> +               break;
>
> +       case HCIEMU_TYPE_BREDR:
>
> +               hciemu->btdev_type = BTDEV_TYPE_BREDR;
>
> +               break;
>
> +       case HCIEMU_TYPE_LE:
>
> +               hciemu->btdev_type = BTDEV_TYPE_LE;
>
> +               break;
>
> +       case HCIEMU_TYPE_LEGACY:
>
> +               hciemu->btdev_type = BTDEV_TYPE_BREDR20;
>
> +               break;
>
> +       case HCIEMU_TYPE_BREDRLE50:
>
> +               hciemu->btdev_type = BTDEV_TYPE_BREDRLE50;
>
> +               break;
>
> +       case HCIEMU_TYPE_BREDRLE52:
>
> +               hciemu->btdev_type = BTDEV_TYPE_BREDRLE52;
>
> +               break;
>
> +       default:
>
> +               return NULL;
>
> +       }
>
> +
>
> +       hciemu->post_command_hooks = queue_new();
>
> +       if (!hciemu->post_command_hooks) {
>
> +               free(hciemu);
>
> +               return NULL;
>
> +       }
>
> +
>
> +       if (!create_vhci(hciemu)) {
>
> +               queue_destroy(hciemu->post_command_hooks, NULL);
>
> +               free(hciemu);
>
> +               return NULL;
>
> +       }
>
> +
>
> +       if (!create_stack(hciemu)) {
>
> +               l_io_destroy(hciemu->master_io);
>
> +               btdev_destroy(hciemu->master_dev);
>
> +               queue_destroy(hciemu->post_command_hooks, NULL);
>
> +               free(hciemu);
>
> +               return NULL;
>
> +       }
>
> +
>
> +       l_idle_oneshot(start_stack, hciemu, NULL);
>
> +
>
> +       return hciemu_ref(hciemu);
>
> +}
>
> +
>
> +struct hciemu *hciemu_ref(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu)
>
> +               return NULL;
>
> +
>
> +       __sync_fetch_and_add(&hciemu->ref_count, 1);
>
> +
>
> +       return hciemu;
>
> +}
>
> +
>
> +void hciemu_unref(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu)
>
> +               return;
>
> +
>
> +       if (__sync_sub_and_fetch(&hciemu->ref_count, 1))
>
> +               return;
>
> +
>
> +       queue_destroy(hciemu->post_command_hooks, destroy_command_hook);
>
> +
>
> +       l_io_destroy(hciemu->host_io);
>
> +       l_io_destroy(hciemu->client_io);
>
> +       l_io_destroy(hciemu->master_io);
>
> +
>
> +       bthost_destroy(hciemu->host_stack);
>
> +       btdev_destroy(hciemu->client_dev);
>
> +       btdev_destroy(hciemu->master_dev);
>
> +
>
> +       free(hciemu);
>
> +}
>
> +
>
> +static void bthost_debug(const char *str, void *user_data)
>
> +{
>
> +       struct hciemu *hciemu = user_data;
>
> +
>
> +       util_debug(hciemu->debug_callback, hciemu->debug_data,
>
> +                                       "bthost: %s", str);
>
> +}
>
> +
>
> +static void btdev_master_debug(const char *str, void *user_data)
>
> +{
>
> +       struct hciemu *hciemu = user_data;
>
> +
>
> +       util_debug(hciemu->debug_callback, hciemu->debug_data,
>
> +                                       "btdev: %s", str);
>
> +}
>
> +
>
> +static void btdev_client_debug(const char *str, void *user_data)
>
> +{
>
> +       struct hciemu *hciemu = user_data;
>
> +
>
> +       util_debug(hciemu->debug_callback, hciemu->debug_data,
>
> +                                       "btdev[bthost]: %s", str);
>
> +}
>
> +
>
> +bool hciemu_set_debug(struct hciemu *hciemu, hciemu_debug_func_t callback,
>
> +                       void *user_data, hciemu_destroy_func_t destroy)
>
> +{
>
> +       if (!hciemu)
>
> +               return false;
>
> +
>
> +       if (hciemu->debug_destroy)
>
> +               hciemu->debug_destroy(hciemu->debug_data);
>
> +
>
> +       hciemu->debug_callback = callback;
>
> +       hciemu->debug_destroy = destroy;
>
> +       hciemu->debug_data = user_data;
>
> +
>
> +       btdev_set_debug(hciemu->master_dev, btdev_master_debug, hciemu, NULL);
>
> +       btdev_set_debug(hciemu->client_dev, btdev_client_debug, hciemu, NULL);
>
> +       bthost_set_debug(hciemu->host_stack, bthost_debug, hciemu, NULL);
>
> +
>
> +       return true;
>
> +}
>
> +
>
> +const char *hciemu_get_address(struct hciemu *hciemu)
>
> +{
>
> +       const uint8_t *addr;
>
> +
>
> +       if (!hciemu || !hciemu->master_dev)
>
> +               return NULL;
>
> +
>
> +       addr = btdev_get_bdaddr(hciemu->master_dev);
>
> +       sprintf(hciemu->bdaddr_str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
>
> +                       addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
>
> +       return hciemu->bdaddr_str;
>
> +}
>
> +
>
> +uint8_t *hciemu_get_features(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu || !hciemu->master_dev)
>
> +               return NULL;
>
> +
>
> +       return btdev_get_features(hciemu->master_dev);
>
> +}
>
> +
>
> +const uint8_t *hciemu_get_master_bdaddr(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu || !hciemu->master_dev)
>
> +               return NULL;
>
> +
>
> +       return btdev_get_bdaddr(hciemu->master_dev);
>
> +}
>
> +
>
> +const uint8_t *hciemu_get_client_bdaddr(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu || !hciemu->client_dev)
>
> +               return NULL;
>
> +
>
> +       return btdev_get_bdaddr(hciemu->client_dev);
>
> +}
>
> +
>
> +uint8_t hciemu_get_master_scan_enable(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu || !hciemu->master_dev)
>
> +               return 0;
>
> +
>
> +       return btdev_get_scan_enable(hciemu->master_dev);
>
> +}
>
> +
>
> +uint8_t hciemu_get_master_le_scan_enable(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu || !hciemu->master_dev)
>
> +               return 0;
>
> +
>
> +       return btdev_get_le_scan_enable(hciemu->master_dev);
>
> +}
>
> +
>
> +void hciemu_set_master_le_states(struct hciemu *hciemu,
>
> +                                               const uint8_t *le_states)
>
> +{
>
> +       if (!hciemu || !hciemu->master_dev)
>
> +               return;
>
> +
>
> +       btdev_set_le_states(hciemu->master_dev, le_states);
>
> +}
>
> +
>
> +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 = new0(struct hciemu_command_hook, 1);
>
> +       if (!hook)
>
> +               return false;
>
> +
>
> +       hook->function = function;
>
> +       hook->user_data = user_data;
>
> +
>
> +       if (!queue_push_tail(hciemu->post_command_hooks, hook)) {
>
> +               free(hook);
>
> +               return false;
>
> +       }
>
> +
>
> +       return true;
>
> +}
>
> +
>
> +bool hciemu_clear_master_post_command_hooks(struct hciemu *hciemu)
>
> +{
>
> +       if (!hciemu)
>
> +               return false;
>
> +
>
> +       queue_remove_all(hciemu->post_command_hooks,
>
> +                                       NULL, NULL, destroy_command_hook);
>
> +       return true;
>
> +}
>
> +
>
> +int hciemu_add_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
>
> +                               uint16_t opcode, hciemu_hook_func_t function,
>
> +                               void *user_data)
>
> +{
>
> +       enum btdev_hook_type hook_type;
>
> +
>
> +       if (!hciemu)
>
> +               return -1;
>
> +
>
> +       switch (type) {
>
> +       case HCIEMU_HOOK_PRE_CMD:
>
> +               hook_type = BTDEV_HOOK_PRE_CMD;
>
> +               break;
>
> +       case HCIEMU_HOOK_POST_CMD:
>
> +               hook_type = BTDEV_HOOK_POST_CMD;
>
> +               break;
>
> +       case HCIEMU_HOOK_PRE_EVT:
>
> +               hook_type = BTDEV_HOOK_PRE_EVT;
>
> +               break;
>
> +       case HCIEMU_HOOK_POST_EVT:
>
> +               hook_type = BTDEV_HOOK_POST_EVT;
>
> +               break;
>
> +       default:
>
> +               return -1;
>
> +       }
>
> +
>
> +       return btdev_add_hook(hciemu->master_dev, hook_type, opcode, function,
>
> +                                                               user_data);
>
> +}
>
> +
>
> +bool hciemu_del_hook(struct hciemu *hciemu, enum hciemu_hook_type type,
>
> +                                                               uint16_t opcode)
>
> +{
>
> +       enum btdev_hook_type hook_type;
>
> +
>
> +       if (!hciemu)
>
> +               return false;
>
> +
>
> +       switch (type) {
>
> +       case HCIEMU_HOOK_PRE_CMD:
>
> +               hook_type = BTDEV_HOOK_PRE_CMD;
>
> +               break;
>
> +       case HCIEMU_HOOK_POST_CMD:
>
> +               hook_type = BTDEV_HOOK_POST_CMD;
>
> +               break;
>
> +       case HCIEMU_HOOK_PRE_EVT:
>
> +               hook_type = BTDEV_HOOK_PRE_EVT;
>
> +               break;
>
> +       case HCIEMU_HOOK_POST_EVT:
>
> +               hook_type = BTDEV_HOOK_POST_EVT;
>
> +               break;
>
> +       default:
>
> +               return false;
>
> +       }
>
> +
>
> +       return btdev_del_hook(hciemu->master_dev, hook_type, opcode);
>
> +}
>
> --
>
> 2.26.2
>
>
>
>


-- 
Luiz Augusto von Dentz

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

end of thread, other threads:[~2020-11-10 22:10 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-07  7:03 [RFC PATCH BlueZ 00/10] Convert tools to use ELL library Inga Stotland
2020-11-07  7:03 ` [RFC PATCH BlueZ 01/10] shared/tester-ell: Create ell-based version of tester code Inga Stotland
2020-11-07  7:26   ` Convert tools to use ELL library bluez.test.bot
2020-11-07  7:03 ` [RFC PATCH BlueZ 02/10] emulator/hciemu: Create ELL based version of hciemu Inga Stotland
2020-11-09 18:04   ` Luiz Augusto von Dentz
     [not found]     ` <72f314b5d2b631213d10c48bfd7612e0484e3280.camel@intel.com>
2020-11-10 22:10       ` Luiz Augusto von Dentz
2020-11-07  7:03 ` [RFC PATCH BlueZ 03/10] tools/gap-tester: Convert to use ELL library Inga Stotland
2020-11-07  7:03 ` [RFC PATCH BlueZ 04/10] tools/sco-tester: " Inga Stotland
2020-11-07  7:03 ` [RFC PATCH BlueZ 05/10] tools/userchan-tester: " Inga Stotland
2020-11-07  7:03 ` [RFC PATCH BlueZ 06/10] tools/smp-tester: " Inga Stotland
2020-11-07  7:03 ` [RFC PATCH BlueZ 07/10] tools/bnep-tester: " Inga Stotland
2020-11-07  7:03 ` [RFC PATCH BlueZ 08/10] tools/l2cap-tester: " Inga Stotland
2020-11-07  7:03 ` [RFC PATCH BlueZ 09/10] tools/mgmt-tester: " Inga Stotland
2020-11-07  7:03 ` [RFC PATCH BlueZ 10/10] tools/rfcomm-tester: " Inga Stotland

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.