All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio
@ 2014-02-06 16:06 Andrei Emeltchenko
  2014-02-06 16:06 ` [PATCH 2/4] unit/avrcp: First unit test for AVRCP profile Andrei Emeltchenko
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Andrei Emeltchenko @ 2014-02-06 16:06 UTC (permalink / raw
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

The patch makes AVRCP to be channel-agnostic so that it might be used in
unit tests. The idea is that all AVRCP logic would come to avrcp-lib and
channel stuff got to avrcp.
---
 android/Android.mk  |  1 +
 android/Makefile.am |  1 +
 android/avrcp-lib.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 android/avrcp-lib.h | 34 +++++++++++++++++++++++
 android/avrcp.c     | 60 ++++++----------------------------------
 5 files changed, 125 insertions(+), 51 deletions(-)
 create mode 100644 android/avrcp-lib.c
 create mode 100644 android/avrcp-lib.h

diff --git a/android/Android.mk b/android/Android.mk
index 20105e6..9b10cfe 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/avdtp.c \
 	bluez/android/a2dp.c \
 	bluez/android/avctp.c \
+	bluez/android/avrcp-lib.c \
 	bluez/android/avrcp.c \
 	bluez/android/pan.c \
 	bluez/android/handsfree.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 5baa8db..3032940 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -36,6 +36,7 @@ android_bluetoothd_SOURCES = android/main.c \
 				android/avdtp.h android/avdtp.c \
 				android/a2dp.h android/a2dp.c \
 				android/avctp.h android/avctp.c \
+				android/avrcp-lib.h android/avrcp-lib.c \
 				android/avrcp.h android/avrcp.c \
 				android/socket.h android/socket.c \
 				android/pan.h android/pan.c \
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
new file mode 100644
index 0000000..6dcc8ac
--- /dev/null
+++ b/android/avrcp-lib.c
@@ -0,0 +1,80 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+
+#include "src/log.h"
+
+#include "avctp.h"
+#include "avrcp-lib.h"
+
+static GSList *devices = NULL;
+
+void avrcp_device_remove(struct avrcp_device *dev)
+{
+	devices = g_slist_remove(devices, dev);
+	avrcp_device_free(dev);
+}
+
+void avrcp_free_all(void)
+{
+	g_slist_free_full(devices, avrcp_device_free);
+	devices = NULL;
+}
+
+struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
+{
+	struct avrcp_device *dev;
+
+	dev = g_new0(struct avrcp_device, 1);
+	bacpy(&dev->dst, dst);
+	devices = g_slist_prepend(devices, dev);
+
+	return dev;
+}
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct avrcp_device *dev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&dev->dst, dst);
+}
+
+struct avrcp_device *avrcp_find(const bdaddr_t *dst)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(devices, dst, device_cmp);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
new file mode 100644
index 0000000..bf6872e
--- /dev/null
+++ b/android/avrcp-lib.h
@@ -0,0 +1,34 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+struct avrcp_device {
+	bdaddr_t	dst;
+	struct avctp	*session;
+	GIOChannel      *io;
+};
+
+struct avrcp_device *avrcp_device_new(const bdaddr_t *dst);
+void avrcp_device_free(void *data);
+void avrcp_device_remove(struct avrcp_device *dev);
+void avrcp_free_all(void);
+struct avrcp_device *avrcp_find(const bdaddr_t *dst);
diff --git a/android/avrcp.c b/android/avrcp.c
index 7ee5a8a..22f0a04 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -38,6 +38,7 @@
 #include "hal-msg.h"
 #include "ipc.h"
 #include "avctp.h"
+#include "avrcp-lib.h"
 
 #define L2CAP_PSM_AVCTP 0x17
 
@@ -48,15 +49,8 @@
 
 static bdaddr_t adapter_addr;
 static uint32_t record_id = 0;
-static GSList *devices = NULL;
 static GIOChannel *server = NULL;
 
-struct avrcp_device {
-	bdaddr_t	dst;
-	struct avctp	*session;
-	GIOChannel	*io;
-};
-
 static const struct ipc_handler cmd_handlers[] = {
 };
 
@@ -128,7 +122,7 @@ static sdp_record_t *avrcp_record(void)
 	return record;
 }
 
-static void avrcp_device_free(void *data)
+void avrcp_device_free(void *data)
 {
 	struct avrcp_device *dev = data;
 
@@ -143,31 +137,6 @@ static void avrcp_device_free(void *data)
 	g_free(dev);
 }
 
-static void avrcp_device_remove(struct avrcp_device *dev)
-{
-	devices = g_slist_remove(devices, dev);
-	avrcp_device_free(dev);
-}
-
-static struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
-{
-	struct avrcp_device *dev;
-
-	dev = g_new0(struct avrcp_device, 1);
-	bacpy(&dev->dst, dst);
-	devices = g_slist_prepend(devices, dev);
-
-	return dev;
-}
-
-static int device_cmp(gconstpointer s, gconstpointer user_data)
-{
-	const struct avrcp_device *dev = s;
-	const bdaddr_t *dst = user_data;
-
-	return bacmp(&dev->dst, dst);
-}
-
 static void disconnect_cb(void *data)
 {
 	struct avrcp_device *dev = data;
@@ -186,7 +155,6 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	char address[18];
 	uint16_t imtu, omtu;
 	GError *gerr = NULL;
-	GSList *l;
 	int fd;
 
 	if (err) {
@@ -209,13 +177,9 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 
 	ba2str(&dst, address);
 
-	l = g_slist_find_custom(devices, &dst, device_cmp);
-	if (l) {
-		dev = l->data;
-		if (dev->session) {
-			error("Unexpected connection");
-			return;
-		}
+	if (avrcp_find(&dst)) {
+		error("Unexpected connection");
+		return;
 	} else {
 		DBG("Incoming connection from %s", address);
 		dev = avrcp_device_new(&dst);
@@ -293,8 +257,7 @@ void bt_avrcp_unregister(void)
 {
 	DBG("");
 
-	g_slist_free_full(devices, avrcp_device_free);
-	devices = NULL;
+	avrcp_free_all();
 
 	ipc_unregister(HAL_SERVICE_ID_AVRCP);
 
@@ -331,12 +294,10 @@ void bt_avrcp_connect(const bdaddr_t *dst)
 {
 	struct avrcp_device *dev;
 	char addr[18];
-	GSList *l;
 
 	DBG("");
 
-	l = g_slist_find_custom(devices, dst, device_cmp);
-	if (l)
+	if (avrcp_find(dst))
 		return;
 
 	dev = avrcp_device_new(dst);
@@ -352,16 +313,13 @@ void bt_avrcp_connect(const bdaddr_t *dst)
 void bt_avrcp_disconnect(const bdaddr_t *dst)
 {
 	struct avrcp_device *dev;
-	GSList *l;
 
 	DBG("");
 
-	l = g_slist_find_custom(devices, dst, device_cmp);
-	if (!l)
+	dev = avrcp_find(dst);
+	if (!dev)
 		return;
 
-	dev = l->data;
-
 	if (dev->session) {
 		avctp_shutdown(dev->session);
 		return;
-- 
1.8.3.2


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

* [PATCH 2/4] unit/avrcp: First unit test for AVRCP profile
  2014-02-06 16:06 [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
@ 2014-02-06 16:06 ` Andrei Emeltchenko
  2014-02-06 16:06 ` [PATCH 3/4] unit/avrcp: Add support for browsing AVCTP channel Andrei Emeltchenko
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Andrei Emeltchenko @ 2014-02-06 16:06 UTC (permalink / raw
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Test TP/MPS/BV-01-C [SetAddressedPlayer – CT] verifies
SetAddressedPlayer command.
---
 Makefile.am       |   9 ++
 unit/test-avrcp.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 340 insertions(+)
 create mode 100644 unit/test-avrcp.c

diff --git a/Makefile.am b/Makefile.am
index 1a44a9f..67b7167 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -281,6 +281,15 @@ unit_test_avctp_SOURCES = unit/test-avctp.c \
 				android/avctp.c android/avctp.h
 unit_test_avctp_LDADD = @GLIB_LIBS@
 
+unit_tests += unit/test-avrcp
+
+unit_test_avrcp_SOURCES = unit/test-avrcp.c \
+				src/shared/util.h src/shared/util.c \
+				src/log.h src/log.c \
+				android/avctp.c android/avctp.h \
+				android/avrcp-lib.c android/avrcp-lib.h
+unit_test_avrcp_LDADD = @GLIB_LIBS@ lib/libbluetooth-internal.la
+
 unit_tests += unit/test-gdbus-client
 
 unit_test_gdbus_client_SOURCES = unit/test-gdbus-client.c
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
new file mode 100644
index 0000000..7efdaea
--- /dev/null
+++ b/unit/test-avrcp.c
@@ -0,0 +1,331 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+
+#include <glib.h>
+
+#include "src/shared/util.h"
+#include "src/log.h"
+#include "lib/bluetooth.h"
+
+#include "android/avctp.h"
+#include "android/avrcp-lib.h"
+
+#define IEEEID_BTSIG		0x001958
+
+struct test_pdu {
+	bool valid;
+	bool fragmented;
+	const uint8_t *data;
+	size_t size;
+};
+
+struct test_data {
+	char *test_name;
+	struct test_pdu *pdu_list;
+};
+
+struct context {
+	GMainLoop *main_loop;
+	struct avrcp_device *dev;
+	guint source;
+	guint process;
+	int fd;
+	unsigned int pdu_offset;
+	const struct test_data *data;
+};
+
+#define data(args...) ((const unsigned char[]) { args })
+
+#define raw_pdu(args...)					\
+	{							\
+		.valid = true,					\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
+#define frg_pdu(args...)					\
+	{							\
+		.valid = true,					\
+		.fragmented = true,				\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
+#define define_test(name, function, args...)				\
+	do {								\
+		const struct test_pdu pdus[] = {			\
+			args, { }					\
+		};							\
+		static struct test_data data;				\
+		data.test_name = g_strdup(name);			\
+		data.pdu_list = g_malloc(sizeof(pdus));			\
+		memcpy(data.pdu_list, pdus, sizeof(pdus));		\
+		g_test_add_data_func(name, &data, function);		\
+	} while (0)
+
+static void test_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	g_print("%s%s\n", prefix, str);
+}
+
+static void test_free(gconstpointer user_data)
+{
+	const struct test_data *data = user_data;
+
+	g_free(data->test_name);
+	g_free(data->pdu_list);
+}
+
+static gboolean context_quit(gpointer user_data)
+{
+	struct context *context = user_data;
+
+	if (context->process > 0)
+		g_source_remove(context->process);
+
+	g_main_loop_quit(context->main_loop);
+
+	return FALSE;
+}
+
+static gboolean send_pdu(gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	ssize_t len;
+
+	pdu = &context->data->pdu_list[context->pdu_offset++];
+
+	len = write(context->fd, pdu->data, pdu->size);
+
+	if (g_test_verbose())
+		util_hexdump('<', pdu->data, len, test_debug, "AVCTP: ");
+
+	g_assert_cmpint(len, ==, pdu->size);
+
+	if (pdu->fragmented)
+		return send_pdu(user_data);
+
+	context->process = 0;
+	return FALSE;
+}
+
+static void context_process(struct context *context)
+{
+	if (!context->data->pdu_list[context->pdu_offset].valid) {
+		context_quit(context);
+		return;
+	}
+
+	context->process = g_idle_add(send_pdu, context);
+}
+
+static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	unsigned char buf[512];
+	ssize_t len;
+	int fd;
+
+	pdu = &context->data->pdu_list[context->pdu_offset++];
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		context->source = 0;
+		g_print("%s: cond %x\n", __func__, cond);
+		return FALSE;
+	}
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	len = read(fd, buf, sizeof(buf));
+
+	g_assert(len > 0);
+
+	if (g_test_verbose())
+		util_hexdump('>', buf, len, test_debug, "AVCTP: ");
+
+	g_assert_cmpint(len, ==, pdu->size);
+
+	g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
+
+	if (!pdu->fragmented)
+		context_process(context);
+
+	return TRUE;
+}
+
+static struct context *create_context(uint16_t version, gconstpointer data)
+{
+	struct context *context = g_new0(struct context, 1);
+	GIOChannel *channel;
+	int err, sv[2];
+	bdaddr_t dst = {};
+
+	context->main_loop = g_main_loop_new(NULL, FALSE);
+	g_assert(context->main_loop);
+
+	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
+	g_assert(err == 0);
+
+	context->dev = avrcp_device_new(&dst);
+	context->dev->session = avctp_new(sv[0], 672, 672, version);
+	g_assert(context->dev->session != NULL);
+
+	channel = g_io_channel_unix_new(sv[1]);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	context->source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				test_handler, context);
+	g_assert(context->source > 0);
+
+	g_io_channel_unref(channel);
+
+	context->fd = sv[1];
+	context->data = data;
+
+	return context;
+}
+
+static void execute_context(struct context *context)
+{
+	g_main_loop_run(context->main_loop);
+
+	if (context->source > 0)
+		g_source_remove(context->source);
+
+	avrcp_device_free(context->dev);
+
+	g_main_loop_unref(context->main_loop);
+
+	test_free(context->data);
+	g_free(context);
+}
+
+#define AVRCP_SET_ADDRESSED_PLAYER	0x60
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct avrcp_header {
+	uint8_t company_id[3];
+	uint8_t pdu_id;
+	uint8_t packet_type:2;
+	uint8_t rsvd:6;
+	uint16_t params_len;
+	uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_HEADER_LENGTH 7
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct avrcp_header {
+	uint8_t company_id[3];
+	uint8_t pdu_id;
+	uint8_t rsvd:6;
+	uint8_t packet_type:2;
+	uint16_t params_len;
+	uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_HEADER_LENGTH 7
+
+#else
+#error "Unknown byte order"
+#endif
+
+static void set_company_id(uint8_t cid[3], const uint32_t cid_in)
+{
+	cid[0] = cid_in >> 16;
+	cid[1] = cid_in >> 8;
+	cid[2] = cid_in;
+}
+
+static int avrcp_set_addr_player(struct context *context)
+{
+	uint8_t buf[AVRCP_HEADER_LENGTH + 2];
+	struct avrcp_header *pdu = (void *) buf;
+	struct avctp *session = context->dev->session;
+
+	memset(buf, 0, sizeof(buf));
+
+	set_company_id(pdu->company_id, IEEEID_BTSIG);
+
+	pdu->pdu_id = AVRCP_SET_ADDRESSED_PLAYER;
+	pdu->params[0] = 0xab;
+	pdu->params[1] = 0xcd;
+	pdu->params_len = htons(2);
+
+	return avctp_send_vendordep_req(session, AVC_CTYPE_CONTROL,
+					AVC_SUBUNIT_PANEL, buf, sizeof(buf),
+					NULL, NULL);
+}
+
+static void test_client(gconstpointer data)
+{
+	struct context *context = create_context(0x0100, data);
+	int ret = 0;
+
+	if (g_str_equal(context->data->test_name, "/TP/MPS/BV-01-C"))
+		ret = avrcp_set_addr_player(context);
+
+	DBG("ret = %d", ret);
+
+	g_assert(!ret);
+
+	execute_context(context);
+}
+
+int main(int argc, char *argv[])
+{
+	g_test_init(&argc, &argv, NULL);
+
+	if (g_test_verbose())
+		__btd_log_init("*", 0);
+
+	/* Media Player Selection Commands and Notifications tests */
+
+	define_test("/TP/MPS/BV-01-C", test_client,
+			raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x00,
+				0x00, 0x19, 0x58, 0x60, 0x00, 0x00,
+				0x02, 0xab, 0xcd));
+
+	return g_test_run();
+}
-- 
1.8.3.2


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

* [PATCH 3/4] unit/avrcp: Add support for browsing AVCTP channel
  2014-02-06 16:06 [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
  2014-02-06 16:06 ` [PATCH 2/4] unit/avrcp: First unit test for AVRCP profile Andrei Emeltchenko
@ 2014-02-06 16:06 ` Andrei Emeltchenko
  2014-02-06 16:06 ` [PATCH 4/4] unit/avrcp: Add TP/MPS/BV-03-C test case Andrei Emeltchenko
  2014-02-11 13:03 ` [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
  3 siblings, 0 replies; 7+ messages in thread
From: Andrei Emeltchenko @ 2014-02-06 16:06 UTC (permalink / raw
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 unit/test-avrcp.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 92 insertions(+), 4 deletions(-)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 7efdaea..58e4c15 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -47,6 +47,7 @@
 struct test_pdu {
 	bool valid;
 	bool fragmented;
+	bool browse;
 	const uint8_t *data;
 	size_t size;
 };
@@ -60,8 +61,10 @@ struct context {
 	GMainLoop *main_loop;
 	struct avrcp_device *dev;
 	guint source;
+	guint browse_source;
 	guint process;
 	int fd;
+	int browse_fd;
 	unsigned int pdu_offset;
 	const struct test_data *data;
 };
@@ -75,6 +78,14 @@ struct context {
 		.size = sizeof(data(args)),			\
 	}
 
+#define brs_pdu(args...)					\
+	{							\
+		.valid = true,					\
+		.browse = true,					\
+		.data = data(args),				\
+		.size = sizeof(data(args)),			\
+	}
+
 #define frg_pdu(args...)					\
 	{							\
 		.valid = true,					\
@@ -130,7 +141,10 @@ static gboolean send_pdu(gpointer user_data)
 
 	pdu = &context->data->pdu_list[context->pdu_offset++];
 
-	len = write(context->fd, pdu->data, pdu->size);
+	if (pdu->browse)
+		len = write(context->browse_fd, pdu->data, pdu->size);
+	else
+		len = write(context->fd, pdu->data, pdu->size);
 
 	if (g_test_verbose())
 		util_hexdump('<', pdu->data, len, test_debug, "AVCTP: ");
@@ -163,6 +177,8 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 	ssize_t len;
 	int fd;
 
+	DBG("");
+
 	pdu = &context->data->pdu_list[context->pdu_offset++];
 
 	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
@@ -190,23 +206,68 @@ static gboolean test_handler(GIOChannel *channel, GIOCondition cond,
 	return TRUE;
 }
 
+static gboolean browse_test_handler(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct context *context = user_data;
+	const struct test_pdu *pdu;
+	unsigned char buf[512];
+	ssize_t len;
+	int fd;
+
+	pdu = &context->data->pdu_list[context->pdu_offset++];
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		context->browse_source = 0;
+		g_print("%s: cond %x\n", __func__, cond);
+		return FALSE;
+	}
+
+	fd = g_io_channel_unix_get_fd(channel);
+
+	len = read(fd, buf, sizeof(buf));
+
+	g_assert(len > 0);
+
+	if (g_test_verbose())
+		util_hexdump('>', buf, len, test_debug, "AVCTP: ");
+
+	g_assert_cmpint(len, ==, pdu->size);
+
+	g_assert(memcmp(buf, pdu->data, pdu->size) == 0);
+
+	if (!pdu->fragmented)
+		context_process(context);
+
+	return TRUE;
+}
+
 static struct context *create_context(uint16_t version, gconstpointer data)
 {
 	struct context *context = g_new0(struct context, 1);
+	struct avctp *session;
 	GIOChannel *channel;
 	int err, sv[2];
 	bdaddr_t dst = {};
+	int ret;
+
+	DBG("");
 
 	context->main_loop = g_main_loop_new(NULL, FALSE);
 	g_assert(context->main_loop);
 
+	/* Control channel setup */
+
 	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
-	g_assert(err == 0);
+	g_assert(!err);
 
 	context->dev = avrcp_device_new(&dst);
-	context->dev->session = avctp_new(sv[0], 672, 672, version);
-	g_assert(context->dev->session != NULL);
+	g_assert(context->dev);
 
+	session = avctp_new(sv[0], 672, 672, version);
+	g_assert(session);
+
+	context->dev->session = session;
 	channel = g_io_channel_unix_new(sv[1]);
 
 	g_io_channel_set_close_on_unref(channel, TRUE);
@@ -221,6 +282,30 @@ static struct context *create_context(uint16_t version, gconstpointer data)
 	g_io_channel_unref(channel);
 
 	context->fd = sv[1];
+
+	/* Browsing channel setup */
+
+	err = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sv);
+	g_assert(!err);
+
+	ret = avctp_connect_browsing(session, sv[0], 672, 672);
+	g_assert(!ret);
+
+	channel = g_io_channel_unix_new(sv[1]);
+
+	g_io_channel_set_close_on_unref(channel, TRUE);
+	g_io_channel_set_encoding(channel, NULL, NULL);
+	g_io_channel_set_buffered(channel, FALSE);
+
+	context->browse_source = g_io_add_watch(channel,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				browse_test_handler, context);
+	g_assert(context->browse_source > 0);
+
+	g_io_channel_unref(channel);
+
+	context->browse_fd = sv[1];
+
 	context->data = data;
 
 	return context;
@@ -233,6 +318,9 @@ static void execute_context(struct context *context)
 	if (context->source > 0)
 		g_source_remove(context->source);
 
+	if (context->browse_source > 0)
+		g_source_remove(context->browse_source);
+
 	avrcp_device_free(context->dev);
 
 	g_main_loop_unref(context->main_loop);
-- 
1.8.3.2


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

* [PATCH 4/4] unit/avrcp: Add TP/MPS/BV-03-C test case
  2014-02-06 16:06 [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
  2014-02-06 16:06 ` [PATCH 2/4] unit/avrcp: First unit test for AVRCP profile Andrei Emeltchenko
  2014-02-06 16:06 ` [PATCH 3/4] unit/avrcp: Add support for browsing AVCTP channel Andrei Emeltchenko
@ 2014-02-06 16:06 ` Andrei Emeltchenko
  2014-02-11 13:03 ` [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
  3 siblings, 0 replies; 7+ messages in thread
From: Andrei Emeltchenko @ 2014-02-06 16:06 UTC (permalink / raw
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Test verifies that the Set Browsed Player command issued by the
AVRCP controller.
---
 unit/test-avrcp.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 58e4c15..211ea36 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -330,6 +330,7 @@ static void execute_context(struct context *context)
 }
 
 #define AVRCP_SET_ADDRESSED_PLAYER	0x60
+#define AVRCP_SET_BROWSED_PLAYER	0x70
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 
@@ -359,6 +360,13 @@ struct avrcp_header {
 #error "Unknown byte order"
 #endif
 
+struct avrcp_browsing_header {
+	uint8_t pdu_id;
+	uint16_t param_len;
+	uint8_t params[0];
+} __attribute__ ((packed));
+#define AVRCP_BROWSING_HEADER_LENGTH 3
+
 static void set_company_id(uint8_t cid[3], const uint32_t cid_in)
 {
 	cid[0] = cid_in >> 16;
@@ -386,6 +394,35 @@ static int avrcp_set_addr_player(struct context *context)
 					NULL, NULL);
 }
 
+static gboolean avrcp_set_browsed_player_rsp(struct avctp *conn,
+						uint8_t *operands,
+						size_t operand_count,
+						void *user_data)
+{
+	DBG("");
+
+	return FALSE;
+}
+
+static int avrcp_set_browsed_player(struct context *context)
+{
+	uint8_t buf[AVRCP_BROWSING_HEADER_LENGTH + 2];
+	struct avrcp_browsing_header *pdu = (void *) buf;
+	struct avctp *session = context->dev->session;
+
+	DBG("");
+
+	memset(buf, 0, sizeof(buf));
+
+	pdu->pdu_id = AVRCP_SET_BROWSED_PLAYER;
+	pdu->params[0] = 0xab;
+	pdu->params[1] = 0xcd;
+	pdu->param_len = htons(2);
+
+	return avctp_send_browsing_req(session, buf, sizeof(buf),
+					avrcp_set_browsed_player_rsp, session);
+}
+
 static void test_client(gconstpointer data)
 {
 	struct context *context = create_context(0x0100, data);
@@ -394,6 +431,9 @@ static void test_client(gconstpointer data)
 	if (g_str_equal(context->data->test_name, "/TP/MPS/BV-01-C"))
 		ret = avrcp_set_addr_player(context);
 
+	if (g_str_equal(context->data->test_name, "/TP/MPS/BV-03-C"))
+		ret = avrcp_set_browsed_player(context);
+
 	DBG("ret = %d", ret);
 
 	g_assert(!ret);
@@ -415,5 +455,8 @@ int main(int argc, char *argv[])
 				0x00, 0x19, 0x58, 0x60, 0x00, 0x00,
 				0x02, 0xab, 0xcd));
 
+	define_test("/TP/MPS/BV-03-C", test_client,
+			raw_pdu(0x00, 0x11, 0x0e, 0x70, 0x00, 0x02,
+				0xab, 0xcd));
 	return g_test_run();
 }
-- 
1.8.3.2


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

* Re: [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio
  2014-02-06 16:06 [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
                   ` (2 preceding siblings ...)
  2014-02-06 16:06 ` [PATCH 4/4] unit/avrcp: Add TP/MPS/BV-03-C test case Andrei Emeltchenko
@ 2014-02-11 13:03 ` Andrei Emeltchenko
  2014-02-11 14:37   ` Szymon Janc
  3 siblings, 1 reply; 7+ messages in thread
From: Andrei Emeltchenko @ 2014-02-11 13:03 UTC (permalink / raw
  To: linux-bluetooth

Hi All

On Thu, Feb 06, 2014 at 06:06:11PM +0200, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> The patch makes AVRCP to be channel-agnostic so that it might be used in
> unit tests. The idea is that all AVRCP logic would come to avrcp-lib and
> channel stuff got to avrcp.

Any comments regarding this patch?

Best regards 
Andrei Emeltchenko 


> ---
>  android/Android.mk  |  1 +
>  android/Makefile.am |  1 +
>  android/avrcp-lib.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  android/avrcp-lib.h | 34 +++++++++++++++++++++++
>  android/avrcp.c     | 60 ++++++----------------------------------
>  5 files changed, 125 insertions(+), 51 deletions(-)
>  create mode 100644 android/avrcp-lib.c
>  create mode 100644 android/avrcp-lib.h
> 
> diff --git a/android/Android.mk b/android/Android.mk
> index 20105e6..9b10cfe 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
>  	bluez/android/avdtp.c \
>  	bluez/android/a2dp.c \
>  	bluez/android/avctp.c \
> +	bluez/android/avrcp-lib.c \
>  	bluez/android/avrcp.c \
>  	bluez/android/pan.c \
>  	bluez/android/handsfree.c \
> diff --git a/android/Makefile.am b/android/Makefile.am
> index 5baa8db..3032940 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -36,6 +36,7 @@ android_bluetoothd_SOURCES = android/main.c \
>  				android/avdtp.h android/avdtp.c \
>  				android/a2dp.h android/a2dp.c \
>  				android/avctp.h android/avctp.c \
> +				android/avrcp-lib.h android/avrcp-lib.c \
>  				android/avrcp.h android/avrcp.c \
>  				android/socket.h android/socket.c \
>  				android/pan.h android/pan.c \
> diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
> new file mode 100644
> index 0000000..6dcc8ac
> --- /dev/null
> +++ b/android/avrcp-lib.c
> @@ -0,0 +1,80 @@
> +/*
> + *
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2014  Intel Corporation. All rights reserved.
> + *
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include <config.h>
> +#endif
> +
> +#include <stdbool.h>
> +#include <glib.h>
> +
> +#include "lib/bluetooth.h"
> +
> +#include "src/log.h"
> +
> +#include "avctp.h"
> +#include "avrcp-lib.h"
> +
> +static GSList *devices = NULL;
> +
> +void avrcp_device_remove(struct avrcp_device *dev)
> +{
> +	devices = g_slist_remove(devices, dev);
> +	avrcp_device_free(dev);
> +}
> +
> +void avrcp_free_all(void)
> +{
> +	g_slist_free_full(devices, avrcp_device_free);
> +	devices = NULL;
> +}
> +
> +struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
> +{
> +	struct avrcp_device *dev;
> +
> +	dev = g_new0(struct avrcp_device, 1);
> +	bacpy(&dev->dst, dst);
> +	devices = g_slist_prepend(devices, dev);
> +
> +	return dev;
> +}
> +
> +static int device_cmp(gconstpointer s, gconstpointer user_data)
> +{
> +	const struct avrcp_device *dev = s;
> +	const bdaddr_t *dst = user_data;
> +
> +	return bacmp(&dev->dst, dst);
> +}
> +
> +struct avrcp_device *avrcp_find(const bdaddr_t *dst)
> +{
> +	GSList *l;
> +
> +	l = g_slist_find_custom(devices, dst, device_cmp);
> +	if (!l)
> +		return NULL;
> +
> +	return l->data;
> +}
> diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
> new file mode 100644
> index 0000000..bf6872e
> --- /dev/null
> +++ b/android/avrcp-lib.h
> @@ -0,0 +1,34 @@
> +/*
> + *
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2014  Intel Corporation. All rights reserved.
> + *
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation; either version 2 of the License, or
> + *  (at your option) any later version.
> + *
> + *  This program is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with this program; if not, write to the Free Software
> + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> + *
> + */
> +
> +struct avrcp_device {
> +	bdaddr_t	dst;
> +	struct avctp	*session;
> +	GIOChannel      *io;
> +};
> +
> +struct avrcp_device *avrcp_device_new(const bdaddr_t *dst);
> +void avrcp_device_free(void *data);
> +void avrcp_device_remove(struct avrcp_device *dev);
> +void avrcp_free_all(void);
> +struct avrcp_device *avrcp_find(const bdaddr_t *dst);
> diff --git a/android/avrcp.c b/android/avrcp.c
> index 7ee5a8a..22f0a04 100644
> --- a/android/avrcp.c
> +++ b/android/avrcp.c
> @@ -38,6 +38,7 @@
>  #include "hal-msg.h"
>  #include "ipc.h"
>  #include "avctp.h"
> +#include "avrcp-lib.h"
>  
>  #define L2CAP_PSM_AVCTP 0x17
>  
> @@ -48,15 +49,8 @@
>  
>  static bdaddr_t adapter_addr;
>  static uint32_t record_id = 0;
> -static GSList *devices = NULL;
>  static GIOChannel *server = NULL;
>  
> -struct avrcp_device {
> -	bdaddr_t	dst;
> -	struct avctp	*session;
> -	GIOChannel	*io;
> -};
> -
>  static const struct ipc_handler cmd_handlers[] = {
>  };
>  
> @@ -128,7 +122,7 @@ static sdp_record_t *avrcp_record(void)
>  	return record;
>  }
>  
> -static void avrcp_device_free(void *data)
> +void avrcp_device_free(void *data)
>  {
>  	struct avrcp_device *dev = data;
>  
> @@ -143,31 +137,6 @@ static void avrcp_device_free(void *data)
>  	g_free(dev);
>  }
>  
> -static void avrcp_device_remove(struct avrcp_device *dev)
> -{
> -	devices = g_slist_remove(devices, dev);
> -	avrcp_device_free(dev);
> -}
> -
> -static struct avrcp_device *avrcp_device_new(const bdaddr_t *dst)
> -{
> -	struct avrcp_device *dev;
> -
> -	dev = g_new0(struct avrcp_device, 1);
> -	bacpy(&dev->dst, dst);
> -	devices = g_slist_prepend(devices, dev);
> -
> -	return dev;
> -}
> -
> -static int device_cmp(gconstpointer s, gconstpointer user_data)
> -{
> -	const struct avrcp_device *dev = s;
> -	const bdaddr_t *dst = user_data;
> -
> -	return bacmp(&dev->dst, dst);
> -}
> -
>  static void disconnect_cb(void *data)
>  {
>  	struct avrcp_device *dev = data;
> @@ -186,7 +155,6 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>  	char address[18];
>  	uint16_t imtu, omtu;
>  	GError *gerr = NULL;
> -	GSList *l;
>  	int fd;
>  
>  	if (err) {
> @@ -209,13 +177,9 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>  
>  	ba2str(&dst, address);
>  
> -	l = g_slist_find_custom(devices, &dst, device_cmp);
> -	if (l) {
> -		dev = l->data;
> -		if (dev->session) {
> -			error("Unexpected connection");
> -			return;
> -		}
> +	if (avrcp_find(&dst)) {
> +		error("Unexpected connection");
> +		return;
>  	} else {
>  		DBG("Incoming connection from %s", address);
>  		dev = avrcp_device_new(&dst);
> @@ -293,8 +257,7 @@ void bt_avrcp_unregister(void)
>  {
>  	DBG("");
>  
> -	g_slist_free_full(devices, avrcp_device_free);
> -	devices = NULL;
> +	avrcp_free_all();
>  
>  	ipc_unregister(HAL_SERVICE_ID_AVRCP);
>  
> @@ -331,12 +294,10 @@ void bt_avrcp_connect(const bdaddr_t *dst)
>  {
>  	struct avrcp_device *dev;
>  	char addr[18];
> -	GSList *l;
>  
>  	DBG("");
>  
> -	l = g_slist_find_custom(devices, dst, device_cmp);
> -	if (l)
> +	if (avrcp_find(dst))
>  		return;
>  
>  	dev = avrcp_device_new(dst);
> @@ -352,16 +313,13 @@ void bt_avrcp_connect(const bdaddr_t *dst)
>  void bt_avrcp_disconnect(const bdaddr_t *dst)
>  {
>  	struct avrcp_device *dev;
> -	GSList *l;
>  
>  	DBG("");
>  
> -	l = g_slist_find_custom(devices, dst, device_cmp);
> -	if (!l)
> +	dev = avrcp_find(dst);
> +	if (!dev)
>  		return;
>  
> -	dev = l->data;
> -
>  	if (dev->session) {
>  		avctp_shutdown(dev->session);
>  		return;
> -- 
> 1.8.3.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio
  2014-02-11 13:03 ` [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
@ 2014-02-11 14:37   ` Szymon Janc
  2014-02-12 13:13     ` [RFCV2] " Andrei Emeltchenko
  0 siblings, 1 reply; 7+ messages in thread
From: Szymon Janc @ 2014-02-11 14:37 UTC (permalink / raw
  To: Andrei Emeltchenko; +Cc: linux-bluetooth

Hi Andrei,

On Tuesday 11 of February 2014 15:03:07 Andrei Emeltchenko wrote:
> Hi All
> 
> On Thu, Feb 06, 2014 at 06:06:11PM +0200, Andrei Emeltchenko wrote:
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > 
> > The patch makes AVRCP to be channel-agnostic so that it might be used in
> > unit tests. The idea is that all AVRCP logic would come to avrcp-lib and
> > channel stuff got to avrcp.
> 
> Any comments regarding this patch?

Waiting for V2 as discussed offline.

-- 
BR
Szymon Janc

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

* [RFCV2] android/avrcp: Decouple AVRCP logic from btio
  2014-02-11 14:37   ` Szymon Janc
@ 2014-02-12 13:13     ` Andrei Emeltchenko
  0 siblings, 0 replies; 7+ messages in thread
From: Andrei Emeltchenko @ 2014-02-12 13:13 UTC (permalink / raw
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

The patch makes AVRCP to be channel-agnostic so that it might be used in
unit tests. The idea is that all AVRCP logic would come to avrcp-lib and
channel stuff got to avrcp.
---
 android/Android.mk  |  1 +
 android/Makefile.am |  1 +
 android/avrcp-lib.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 android/avrcp-lib.h | 29 +++++++++++++++++++++++++
 android/avrcp.c     | 28 ++++++++++++++++--------
 5 files changed, 112 insertions(+), 9 deletions(-)
 create mode 100644 android/avrcp-lib.c
 create mode 100644 android/avrcp-lib.h

diff --git a/android/Android.mk b/android/Android.mk
index 71d678b..fa9a86e 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -39,6 +39,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/avdtp.c \
 	bluez/android/a2dp.c \
 	bluez/android/avctp.c \
+	bluez/android/avrcp-lib.c \
 	bluez/android/avrcp.c \
 	bluez/android/pan.c \
 	bluez/android/handsfree.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 1913b42..07cc851 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -36,6 +36,7 @@ android_bluetoothd_SOURCES = android/main.c \
 				android/avdtp.h android/avdtp.c \
 				android/a2dp.h android/a2dp.c \
 				android/avctp.h android/avctp.c \
+				android/avrcp-lib.h android/avrcp-lib.c \
 				android/avrcp.h android/avrcp.c \
 				android/socket.h android/socket.c \
 				android/pan.h android/pan.c \
diff --git a/android/avrcp-lib.c b/android/avrcp-lib.c
new file mode 100644
index 0000000..080e37a
--- /dev/null
+++ b/android/avrcp-lib.c
@@ -0,0 +1,62 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <glib.h>
+
+#include "lib/bluetooth.h"
+
+#include "src/log.h"
+
+#include "avctp.h"
+#include "avrcp-lib.h"
+
+void avrcp_free(void *data)
+{
+	struct avrcp *session = data;
+
+	if (session->session)
+		avctp_shutdown(session->session);
+
+	g_free(session);
+}
+
+struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu,
+							uint16_t version)
+{
+	struct avrcp *session;
+
+	session = g_new0(struct avrcp, 1);
+
+	session->session = avctp_new(fd, imtu, omtu, version);
+	if (!session->session) {
+		g_free(session);
+		return NULL;
+	}
+
+	return session;
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
new file mode 100644
index 0000000..f1dbf0d
--- /dev/null
+++ b/android/avrcp-lib.h
@@ -0,0 +1,29 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+struct avrcp {
+	struct avctp	*session;
+};
+
+struct avrcp *avrcp_new(int fd, size_t imtu, size_t omtu, uint16_t version);
+void avrcp_free(void *data);
diff --git a/android/avrcp.c b/android/avrcp.c
index b8304f5..3d3e323 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -38,6 +38,7 @@
 #include "hal-msg.h"
 #include "ipc.h"
 #include "avctp.h"
+#include "avrcp-lib.h"
 
 #define L2CAP_PSM_AVCTP 0x17
 
@@ -53,7 +54,7 @@ static GIOChannel *server = NULL;
 
 struct avrcp_device {
 	bdaddr_t	dst;
-	struct avctp	*session;
+	struct avrcp	*session;
 	GIOChannel	*io;
 };
 
@@ -133,7 +134,7 @@ static void avrcp_device_free(void *data)
 	struct avrcp_device *dev = data;
 
 	if (dev->session)
-		avctp_shutdown(dev->session);
+		avrcp_free(dev->session);
 
 	if (dev->io) {
 		g_io_channel_shutdown(dev->io, FALSE, NULL);
@@ -168,6 +169,17 @@ static int device_cmp(gconstpointer s, gconstpointer user_data)
 	return bacmp(&dev->dst, dst);
 }
 
+static struct avrcp_device *avrcp_find(const bdaddr_t *dst)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(devices, dst, device_cmp);
+	if (!l)
+		return NULL;
+
+	return l->data;
+}
+
 static void disconnect_cb(void *data)
 {
 	struct avrcp_device *dev = data;
@@ -222,17 +234,17 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	}
 
 	fd = g_io_channel_unix_get_fd(chan);
-	dev->session = avctp_new(fd, imtu, omtu, 0x0100);
 
+	dev->session = avrcp_new(fd, imtu, omtu, 0x0100);
 	if (!dev->session) {
 		avrcp_device_free(dev);
 		return;
 	}
 
-	avctp_set_destroy_cb(dev->session, disconnect_cb, dev);
+	avctp_set_destroy_cb(dev->session->session, disconnect_cb, dev);
 
 	/* FIXME: get the real name of the device */
-	avctp_init_uinput(dev->session, "bluetooth", address);
+	avctp_init_uinput(dev->session->session, "bluetooth", address);
 
 	g_io_channel_set_close_on_unref(chan, FALSE);
 
@@ -331,12 +343,10 @@ void bt_avrcp_connect(const bdaddr_t *dst)
 {
 	struct avrcp_device *dev;
 	char addr[18];
-	GSList *l;
 
 	DBG("");
 
-	l = g_slist_find_custom(devices, dst, device_cmp);
-	if (l)
+	if (avrcp_find(dst))
 		return;
 
 	dev = avrcp_device_new(dst);
@@ -363,7 +373,7 @@ void bt_avrcp_disconnect(const bdaddr_t *dst)
 	dev = l->data;
 
 	if (dev->session) {
-		avctp_shutdown(dev->session);
+		avrcp_free(dev->session);
 		return;
 	}
 
-- 
1.8.3.2


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

end of thread, other threads:[~2014-02-12 13:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-06 16:06 [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
2014-02-06 16:06 ` [PATCH 2/4] unit/avrcp: First unit test for AVRCP profile Andrei Emeltchenko
2014-02-06 16:06 ` [PATCH 3/4] unit/avrcp: Add support for browsing AVCTP channel Andrei Emeltchenko
2014-02-06 16:06 ` [PATCH 4/4] unit/avrcp: Add TP/MPS/BV-03-C test case Andrei Emeltchenko
2014-02-11 13:03 ` [PATCH 1/4] android/avrcp: Decouple AVRCP logic from btio Andrei Emeltchenko
2014-02-11 14:37   ` Szymon Janc
2014-02-12 13:13     ` [RFCV2] " Andrei Emeltchenko

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.