Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] android/pts: PTS test results for AVCTP
From: Szymon Janc @ 2014-01-30 16:28 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1391002025-15997-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Wednesday 29 of January 2014 15:27:04 Sebastian Chlad wrote:
> ---
>  android/pts-avctp.txt | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/android/pts-avctp.txt b/android/pts-avctp.txt
> index c057a10..a57ecee 100644
> --- a/android/pts-avctp.txt
> +++ b/android/pts-avctp.txt
> @@ -1,7 +1,7 @@
>  PTS test results for AVCTP
> 
>  PTS version: 5.0
> -Tested: --not yet tested--
> +Tested: 29.01.2014
> 
>  Results:
>  PASS	test passed
> @@ -29,13 +29,13 @@ TC_CT_FRA_BV_04_C	N/A
>  ---------------------------------------------------------------------------
> ---- Test Name		Result	Notes
>  ---------------------------------------------------------------------------
> ---- -TC_TG_CCM_BV_01_C	INC
> -TC_TG_CCM_BV_02_C	INC
> -TC_TG_CCM_BV_03_C	INC
> -TC_TG_CCM_BV_04_C	INC
> -TC_TG_NFR_BV_02_C	INC
> -TC_TG_NFR_BV_03_C	INC
> -TC_TG_NFR_BI_01_C	INC
> -TC_TG_FRA_BV_02_C	INC
> +TC_TG_CCM_BV_01_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_CCM_BV_02_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_CCM_BV_03_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_CCM_BV_04_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_NFR_BV_02_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_NFR_BV_03_C	PASS	avtest --device hci0 --avctp --send x 
<bdaddr>
> +TC_TG_NFR_BI_01_C	PASS
> +TC_TG_FRA_BV_02_C	FAIL
>  TC_TG_FRA_BV_03_C	INC
>  ---------------------------------------------------------------------------
> ----

Patch 1/2 pushed, for 2/2 please mark version as 4.4.2 as discussed. Thanks.

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH] android: Add avtest to debug builds
From: Szymon Janc @ 2014-01-30 16:25 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1390999219-15012-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Wednesday 29 of January 2014 14:40:19 Sebastian Chlad wrote:
> ---
>  android/Android.mk | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/android/Android.mk b/android/Android.mk
> index 1d12da5..238bb7c 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -354,6 +354,34 @@ LOCAL_MODULE := l2ping
>  include $(BUILD_EXECUTABLE)
> 
>  #
> +# avtest
> +#
> +
> +include $(CLEAR_VARS)
> +
> +LOCAL_SRC_FILES := \
> +	bluez/tools/avtest.c \
> +	bluez/lib/bluetooth.c \
> +	bluez/lib/hci.c \
> +
> +LOCAL_C_INCLUDES := \
> +	$(LOCAL_PATH)/bluez/lib \
> +
> +lib_headers := \
> +	bluetooth.h \
> +	hci.h \
> +
> +$(foreach file,$(lib_headers), $(shell ln -sf ../$(file)
> $(LOCAL_PATH)/bluez/lib/bluetooth/$(file))) +

Why is this need? Please compare on how other tools were added to Android.mk 

> +LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS)
> +
> +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
> +LOCAL_MODULE_TAGS := debug
> +LOCAL_MODULE := avtest
> +
> +include $(BUILD_EXECUTABLE)
> +
> +#
>  # libsbc
>  #

-- 
BR
Szymon Janc

^ permalink raw reply

* Re: [PATCH] Bluetooth: Enable LTK distribution to slave devices
From: Vinicius Costa Gomes @ 2014-01-30 16:14 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1391032559-25183-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

On 13:55 Wed 29 Jan, johan.hedberg@gmail.com wrote:
> From: Johan Hedberg <johan.hedberg@intel.com>
>
> So far we've only been requesting the LTK to be distributed to the
> master (initiator) of pairing, which is usually enough since it's the
> master that will establish future connections and initiate encryption.
> However, in the case that both devices support switching to the opposing
> role (which seems to be increasingly common) pairing will have to
> performed again since the "new" master will not have all information.
>
> As there is no real harm in it, this patch updates the code to always
> try distributing the LTK also to the slave device, thereby enabling role
> switches for future connections.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---

Looks good. Ack.


Cheers,
--
Vinicius

^ permalink raw reply

* [PATCH 3/3] avrcp: Fix possible buffer overflow and correct length
From: Andrei Emeltchenko @ 2014-01-30 16:12 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391098376-26834-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Wrong length was given and it was also possible to crash.
---
 profiles/audio/avrcp.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 128f7d3..f9fce5c 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -1899,8 +1899,12 @@ static void avrcp_get_current_player_value(struct avrcp *session,
 {
 	uint8_t buf[AVRCP_HEADER_LENGTH + 5];
 	struct avrcp_header *pdu = (void *) buf;
+	uint16_t length = AVRCP_HEADER_LENGTH + count + 1;
 	int i;
 
+	if (count + 1 > 5)
+		return;
+
 	memset(buf, 0, sizeof(buf));
 
 	set_company_id(pdu->company_id, IEEEID_BTSIG);
@@ -1913,7 +1917,7 @@ static void avrcp_get_current_player_value(struct avrcp *session,
 		pdu->params[i + 1] = attrs[i];
 
 	avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
-					AVC_SUBUNIT_PANEL, buf, sizeof(buf),
+					AVC_SUBUNIT_PANEL, buf, length,
 					avrcp_player_value_rsp, session);
 }
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 2/3] avrcp: Fix using incorrect buffer for SetVolume
From: Andrei Emeltchenko @ 2014-01-30 16:12 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391098376-26834-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

The command requires one parameter.
---
 profiles/audio/avrcp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 2e1a940..128f7d3 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -3706,7 +3706,7 @@ int avrcp_set_volume(struct btd_device *dev, uint8_t volume)
 {
 	struct avrcp_server *server;
 	struct avrcp *session;
-	uint8_t buf[AVRCP_HEADER_LENGTH + 2];
+	uint8_t buf[AVRCP_HEADER_LENGTH + 1];
 	struct avrcp_header *pdu = (void *) buf;
 
 	server = find_server(servers, device_get_adapter(dev));
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 1/3] avrcp: Avoid unneeded calculation
From: Andrei Emeltchenko @ 2014-01-30 16:12 UTC (permalink / raw)
  To: linux-bluetooth

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

There no need to calculate those values
---
 profiles/audio/avrcp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index fa5adab..2e1a940 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -3177,7 +3177,7 @@ static void avrcp_register_notification(struct avrcp *session, uint8_t event)
 	pdu->params[0] = event;
 	pdu->params_len = htons(AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH);
 
-	length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
+	length = AVRCP_HEADER_LENGTH + AVRCP_REGISTER_NOTIFICATION_PARAM_LENGTH;
 
 	avctp_send_vendordep_req(session->conn, AVC_CTYPE_NOTIFY,
 					AVC_SUBUNIT_PANEL, buf, length,
@@ -3250,7 +3250,7 @@ static void avrcp_get_capabilities(struct avrcp *session)
 	pdu->params[0] = CAP_EVENTS_SUPPORTED;
 	pdu->params_len = htons(AVRCP_GET_CAPABILITIES_PARAM_LENGTH);
 
-	length = AVRCP_HEADER_LENGTH + ntohs(pdu->params_len);
+	length = AVRCP_HEADER_LENGTH + AVRCP_GET_CAPABILITIES_PARAM_LENGTH;
 
 	avctp_send_vendordep_req(session->conn, AVC_CTYPE_STATUS,
 					AVC_SUBUNIT_PANEL, buf, length,
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH] android/pts: PTS test results for L2CAP
From: Szymon Janc @ 2014-01-30 15:43 UTC (permalink / raw)
  To: Sebastian Chlad; +Cc: linux-bluetooth
In-Reply-To: <1390991606-13576-1-git-send-email-sebastianx.chlad@intel.com>

Hi Sebastian,

On Wednesday 29 of January 2014 12:33:26 Sebastian Chlad wrote:
> ---
>  android/pts-l2cap.txt | 20 +++++++++++---------
>  1 file changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/android/pts-l2cap.txt b/android/pts-l2cap.txt
> index 51eedf5..3e46309 100644
> --- a/android/pts-l2cap.txt
> +++ b/android/pts-l2cap.txt
> @@ -1,7 +1,7 @@
>  PTS test results for L2CAP
> 
>  PTS version: 5.0
> -Tested: 10.01.2014
> +Tested: 29.01.2014
> 
>  Results:
>  PASS   test passed
> @@ -87,16 +87,18 @@ TC_ERM_BV_06_C         PASS
>  TC_ERM_BV_07_C         PASS    l2test -X ertm -P 33 &
>  TC_ERM_BV_08_C         PASS
>  TC_ERM_BV_09_C         PASS    l2test -X ertm -P 33 &
> -TC_ERM_BV_10_C         INC
> -TC_ERM_BV_11_C         INC
> -TC_ERM_BV_12_C         INC
> +TC_ERM_BV_10_C         PASS    l2test -x -X ertm -P 33 -D 35000 -Q 1 -R -N
> 1 & +				btmgmt disconnect
> +TC_ERM_BV_11_C         PASS    l2test -x -X ertm -P 33 -D 35000 -Q 1 -R -N
> 1 & +				btmgmt disconnect
> +TC_ERM_BV_12_C         PASS    l2test -x -X ertm -P 33 -R -N 1
>  TC_ERM_BV_13_C         PASS
>  TC_ERM_BV_14_C         PASS
>  TC_ERM_BV_15_C         PASS
>  TC_ERM_BV_16_C         PASS
>  TC_ERM_BV_17_C         PASS
> -TC_ERM_BV_18_C         INC
> -TC_ERM_BV_19_C         INC
> +TC_ERM_BV_18_C         PASS    l2test -x -X ertm -P 33 -R -N 1
> +TC_ERM_BV_19_C         PASS    l2test -x -X ertm -P 33 -R -N 1
>  TC_ERM_BV_20_C         PASS
>  TC_ERM_BV_21_C         PASS
>  TC_ERM_BV_22_C         PASS
> @@ -106,9 +108,9 @@ TC_ERM_BI_02_C         PASS
>  TC_ERM_BI_03_C         PASS
>  TC_ERM_BI_04_C         PASS
>  TC_ERM_BI_05_C         PASS
> -TC_STM_BV_01_C         INC
> -TC_STM_BV_02_C         INC
> -TC_STM_BV_03_C         INC
> +TC_STM_BV_01_C         PASS    l2test -x -X ertm -P 33 -R -N 1 -Y 3 &
> +TC_STM_BV_02_C         PASS    l2test -x -X ertm -P 33 -R -N 1 -Y 3 &
> +TC_STM_BV_03_C         PASS    l2test -x -X ertm -P 33 -R -N 1 -Y 3 &
>  TC_STM_BV_11_C         N/A
>  TC_STM_BV_12_C         N/A
>  TC_STM_BV_13_C         N/A

Applied, thanks.

-- 
BR
Szymon Janc

^ permalink raw reply

* [RFC] unit/avrcp: First unit test for AVRCP profile
From: Andrei Emeltchenko @ 2014-01-30 15:38 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 | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 334 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..2030b22
--- /dev/null
+++ b/unit/test-avrcp.c
@@ -0,0 +1,325 @@
+/*
+ *
+ *  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_sent_set_addr_player(struct context *context)
+{
+	uint8_t buf[AVRCP_HEADER_LENGTH + 2];
+	struct avrcp_header *pdu = (void *) buf;
+
+	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(context->dev->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);
+
+	avrcp_sent_set_addr_player(context);
+
+	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

* [PATCH] android/avrcp: Decouple AVRCP logic from btio
From: Andrei Emeltchenko @ 2014-01-30 14:38 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 | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 android/avrcp-lib.h | 32 ++++++++++++++++++++
 android/avrcp.c     | 46 ++--------------------------
 5 files changed, 124 insertions(+), 43 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 1d12da5..09b54d6 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/src/log.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index e065c0c..29cbf79 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -34,6 +34,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..33d03d9
--- /dev/null
+++ b/android/avrcp-lib.c
@@ -0,0 +1,87 @@
+/*
+ *
+ *  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_free(void *data)
+{
+	struct avrcp_device *dev = data;
+
+	if (dev->session)
+		avctp_shutdown(dev->session);
+
+	devices = g_slist_remove(devices, dev);
+	g_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(bdaddr_t *dst)
+{
+	GSList *l;
+
+	l = g_slist_find_custom(devices, dst, device_cmp);
+	if (l) {
+		error("Unexpected connection");
+		return NULL;
+	}
+
+	return l->data;
+}
diff --git a/android/avrcp-lib.h b/android/avrcp-lib.h
new file mode 100644
index 0000000..a7213fb
--- /dev/null
+++ b/android/avrcp-lib.h
@@ -0,0 +1,32 @@
+/*
+ *
+ *  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;
+};
+
+struct avrcp_device *avrcp_device_new(const bdaddr_t *dst);
+void avrcp_device_free(void *data);
+void avrcp_free_all(void);
+struct avrcp_device *avrcp_find(bdaddr_t *dst);
diff --git a/android/avrcp.c b/android/avrcp.c
index ef833df..0518faa 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,14 +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;
-};
-
 static const struct ipc_handler cmd_handlers[] = {
 };
 
@@ -127,36 +122,6 @@ static sdp_record_t *avrcp_record(void)
 	return record;
 }
 
-static void avrcp_device_free(void *data)
-{
-	struct avrcp_device *dev = data;
-
-	if (dev->session)
-		avctp_shutdown(dev->session);
-
-	devices = g_slist_remove(devices, dev);
-	g_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;
@@ -175,7 +140,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) {
@@ -199,11 +163,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	ba2str(&dst, address);
 	DBG("Incoming connection from %s", address);
 
-	l = g_slist_find_custom(devices, &dst, device_cmp);
-	if (l) {
-		error("Unexpected connection");
+	if (!avrcp_find(&dst))
 		return;
-	}
 
 	fd = g_io_channel_unix_get_fd(chan);
 
@@ -274,8 +235,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);
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH] gitignore: Add unit/avctp to .gitignore
From: Andrei Emeltchenko @ 2014-01-30 14:34 UTC (permalink / raw)
  To: linux-bluetooth

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

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index e2b23fc..2210e03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -110,6 +110,7 @@ unit/test-gobex-header
 unit/test-gobex-packet
 unit/test-gobex-transfer
 unit/test-avdtp
+unit/test-avctp
 unit/test-*.log
 unit/test-*.trs
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH] android/avrcp: Close AVRCP channel on error
From: Andrei Emeltchenko @ 2014-01-30 13:23 UTC (permalink / raw)
  To: linux-bluetooth

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

This fixes resource leak.
---
 android/avrcp.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/android/avrcp.c b/android/avrcp.c
index 485b485..ef833df 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -248,13 +248,13 @@ bool bt_avrcp_register(const bdaddr_t *addr)
 	rec = avrcp_record();
 	if (!rec) {
 		error("Failed to allocate AVRCP record");
-		return false;
+		goto fail;
 	}
 
 	if (bt_adapter_add_record(rec, 0) < 0) {
 		error("Failed to register AVRCP record");
 		sdp_record_free(rec);
-		return false;
+		goto fail;
 	}
 	record_id = rec->handle;
 
@@ -262,6 +262,12 @@ bool bt_avrcp_register(const bdaddr_t *addr)
 						G_N_ELEMENTS(cmd_handlers));
 
 	return true;
+fail:
+	g_io_channel_shutdown(server, TRUE, NULL);
+	g_io_channel_unref(server);
+	server = NULL;
+
+	return false;
 }
 
 void bt_avrcp_unregister(void)
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH v3 0/4] Regression fixes for rfcomm/tty.c
From: Alexander Holler @ 2014-01-30 13:09 UTC (permalink / raw)
  To: Gianluca Anzolin, Marcel Holtmann
  Cc: Gustavo F. Padovan, peter,
	linux-bluetooth@vger.kernel.org development, Greg KH, jslaby,
	stable
In-Reply-To: <20140128083154.GA29060@sottospazio.it>

Am 28.01.2014 09:31, schrieb Gianluca Anzolin:

> Unfortunately it seems I overlooked the fact that rfcomm_dev_activate() is
> called with the port->mutex held. So patches 2/3/4 cause a regression I missed
> because I didn't turn on the appropriate debug options (circular locking
> dependency, a bug report already appeared on this list).
>
> I'm afraid this all stems from my partial knowledge of the tty_port code and
> unfortunately I don't know how to solve the problem right now.

Understandable, it's like a mine field. ;) Maybe it might make sense to 
add Alan Cox to Cc, I think he's active again and knows a lot about 
tty_port.

> I think it's better to revert those patches for the moment.

I prefer to still use those patches because without them, I have a more 
serious problem (at least for my use cases, which happily haven't run 
into that deadlock).

But thanks for notifying me/us about the possibility of a deadlock when 
using your patches.

Regards,

Alexander Holler

^ permalink raw reply

* [RFC 15/15] android/client-audio: Fix getting audio module on Android
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Getting audio module results with -EADDRINUSE on socket binding when
running on Android. Therefore we need to stop mediaserver for
successfull connection.
---
 android/client/if-audio.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 66f8364..71f9dad 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -99,6 +99,9 @@ static void init_p(int argc, const char **argv)
 	int err;
 	const hw_module_t *module;
 	audio_hw_device_t *device;
+	int timeout = 1500; /* in ms */
+	int t = 300;
+
 
 	err = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID,
 					AUDIO_HARDWARE_MODULE_ID_A2DP, &module);
@@ -107,8 +110,27 @@ static void init_p(int argc, const char **argv)
 		return;
 	}
 
+init_audio:
 	err = audio_hw_device_open(module, &device);
 	if (err) {
+		if (err == -EADDRINUSE && t < timeout) {
+			int err2;
+
+			/* We need to Stop media server to bind to socket. */
+			haltest_info("Trying to stop media server...\n");
+
+			err2 = system("/system/bin/setprop ctl.stop media");
+			if (err2) {
+				haltest_error("audio_hw_device_open returned",
+								" %d\n", err);
+				return;
+			}
+
+			usleep(t);
+			t += t;
+			goto init_audio;
+		}
+
 		haltest_error("audio_hw_device_open returned %d\n", err);
 		return;
 	}
@@ -358,6 +380,9 @@ static void cleanup_p(int argc, const char **argv)
 	}
 
 	if_audio = NULL;
+
+	/* get the media server back up and running */
+	err = system("/system/bin/setprop ctl.start media");
 }
 
 static void suspend_p(int argc, const char **argv)
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 14/15] android/client-audio: Add sine generator as fallback
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

When no audio file path is provided use sine generator.

---
 android/Makefile.am       |  2 +-
 android/client/if-audio.c | 58 ++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/android/Makefile.am b/android/Makefile.am
index e065c0c..322210c 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -99,7 +99,7 @@ android_haltest_SOURCES = android/client/haltest.c \
 android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android \
 				-DPLUGINDIR=\""$(android_plugindir)"\"
 
-android_haltest_LDFLAGS = -pthread -ldl
+android_haltest_LDFLAGS = -pthread -ldl -lm
 
 noinst_PROGRAMS += android/android-tester
 
diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index b481461..66f8364 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -19,6 +19,7 @@
 #include "../hal-utils.h"
 #include "pthread.h"
 #include "unistd.h"
+#include <math.h>
 
 audio_hw_device_t *if_audio = NULL;
 struct audio_stream_out *stream_out = NULL;
@@ -89,6 +90,10 @@ ENDMAP
 
 static int current_state = STATE_STOPPED;
 
+#define SAMPLERATE 44100
+static short sample[SAMPLERATE];
+static uint16_t sample_pos;
+
 static void init_p(int argc, const char **argv)
 {
 	int err;
@@ -126,6 +131,50 @@ static int feed_from_file(short *buffer, void *data)
 	return fread(buffer, buffer_size, 1, in);
 }
 
+static int feed_from_generator(short *buffer, void *data)
+{
+	size_t i = 0;
+	float volume = 0.5;
+	float *freq = data;
+	float f = 1;
+
+	if (freq)
+		f = *freq;
+
+	/* buffer_size is in bytes but we are using buffer of shorts (2 bytes)*/
+	for (i = 0; i < buffer_size / sizeof(*buffer) - 1;) {
+		if (sample_pos >= SAMPLERATE)
+			sample_pos = sample_pos % SAMPLERATE;
+
+		/* Use the same sample for both channels */
+		buffer[i++] = sample[sample_pos] * volume;
+		buffer[i++] = sample[sample_pos] * volume;
+
+		sample_pos += f;
+	}
+
+	return buffer_size;
+}
+
+static void prepare_sample(void)
+{
+	int x;
+	double s;
+
+	haltest_info("Preparing audio sample...\n");
+
+	for (x = 0; x < SAMPLERATE; x++) {
+		/* prepare sinusoidal 1Hz sample */
+		s = (2.0 * 3.14159) * ((double)x / SAMPLERATE);
+		s = sin(s);
+
+		/* remap <-1, 1> to signed 16bit PCM range */
+		sample[x] = s * 32767;
+	}
+
+	sample_pos = 0;
+}
+
 static void *playback_thread(void *data)
 {
 	int (*filbuff_cb) (short*, void*);
@@ -134,6 +183,7 @@ static void *playback_thread(void *data)
 	size_t w_len = 0;
 	FILE *in = data;
 	void *cb_data = NULL;
+	float freq = 440.0;
 
 	pthread_cleanup_push(playthread_cleanup, NULL);
 
@@ -142,8 +192,9 @@ static void *playback_thread(void *data)
 		filbuff_cb = feed_from_file;
 		cb_data = in;
 	} else {
-		/* TODO: Use generator */
-		goto end;
+		prepare_sample();
+		filbuff_cb = feed_from_generator;
+		cb_data = &freq;
 	}
 
 	pthread_mutex_lock(&state_mutex);
@@ -178,7 +229,7 @@ static void *playback_thread(void *data)
 		fclose(in);
 		in = NULL;
 	}
-end:
+
 	pthread_cleanup_pop(1);
 	return NULL;
 }
@@ -193,6 +244,7 @@ static void play_p(int argc, const char **argv)
 
 	if (argc < 3) {
 		haltest_error("Invalid audio file path.\n");
+		haltest_info("Using sound generator.\n");
 	} else {
 		fname = argv[2];
 		in = fopen(fname, "r");
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 13/15] android/client-audio: Add init_check
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Add calling init check for audio device.

---
 android/client/if-audio.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 48b973b..b481461 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -431,6 +431,13 @@ static void set_sample_rate_p(int argc, const char **argv)
 	stream_out->common.set_sample_rate(&stream_out->common, atoi(argv[2]));
 }
 
+static void init_check_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_audio);
+
+	haltest_info("Init check result: %d\n", if_audio->init_check(if_audio));
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -448,6 +455,7 @@ static struct method methods[] = {
 	STD_METHODH(get_parameters, "<A2dpSuspended;closing>"),
 	STD_METHODH(set_parameters, "<A2dpSuspended=value;closing=value>"),
 	STD_METHODH(set_sample_rate, "<sample rate>"),
+	STD_METHOD(init_check),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 12/15] android/client-audio: Add setting sample rate
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Add setting sample rate for output stream.

---
 android/client/if-audio.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index bbd6a8c..48b973b 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -420,6 +420,17 @@ static void set_parameters_p(int argc, const char **argv)
 	stream_out->common.set_parameters(&stream_out->common, argv[2]);
 }
 
+static void set_sample_rate_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	if (argc < 3)
+		return;
+
+	stream_out->common.set_sample_rate(&stream_out->common, atoi(argv[2]));
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -436,6 +447,7 @@ static struct method methods[] = {
 	STD_METHOD(get_sample_rate),
 	STD_METHODH(get_parameters, "<A2dpSuspended;closing>"),
 	STD_METHODH(set_parameters, "<A2dpSuspended=value;closing=value>"),
+	STD_METHODH(set_sample_rate, "<sample rate>"),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 11/15] android/client-audio: Add set_parameters
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Add seting output stream parameters using key=value pairs string
(key1=value1;key2=value2).

---
 android/client/if-audio.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 0746124..bbd6a8c 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -407,6 +407,19 @@ static void get_parameters_p(int argc, const char **argv)
 								keystr));
 }
 
+static void set_parameters_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	if (argc < 3) {
+		haltest_error("No key=value; pairs given.\n");
+		return;
+	}
+
+	stream_out->common.set_parameters(&stream_out->common, argv[2]);
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -422,6 +435,7 @@ static struct method methods[] = {
 	STD_METHOD(get_format),
 	STD_METHOD(get_sample_rate),
 	STD_METHODH(get_parameters, "<A2dpSuspended;closing>"),
+	STD_METHODH(set_parameters, "<A2dpSuspended=value;closing=value>"),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 10/15] android/client-audio: Add get_parameters for output
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Get current parameters for the audio stream.

---
 android/client/if-audio.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 4a45cac..0746124 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -388,6 +388,25 @@ static void get_sample_rate_p(int argc, const char **argv)
 		stream_out->common.get_sample_rate(&stream_out->common));
 }
 
+static void get_parameters_p(int argc, const char **argv)
+{
+	const char *keystr;
+
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	if (argc < 3) {
+		haltest_info("No keys given.\n");
+		keystr = "";
+	} else {
+		keystr = argv[2];
+	}
+
+	haltest_info("Current parameters: %s\n",
+			stream_out->common.get_parameters(&stream_out->common,
+								keystr));
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -402,6 +421,7 @@ static struct method methods[] = {
 	STD_METHOD(get_channels),
 	STD_METHOD(get_format),
 	STD_METHOD(get_sample_rate),
+	STD_METHODH(get_parameters, "<A2dpSuspended;closing>"),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 09/15] android/client-audio: Add getting sample rate
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Get current sample rate for output stream.

---
 android/client/if-audio.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 45c00f3..4a45cac 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -379,6 +379,15 @@ static void get_format_p(int argc, const char **argv)
 	haltest_info("Format: %s\n", audio_format_t2str(format));
 }
 
+static void get_sample_rate_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	haltest_info("Current sample rate: %d\n",
+		stream_out->common.get_sample_rate(&stream_out->common));
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -392,6 +401,7 @@ static struct method methods[] = {
 	STD_METHOD(get_buffer_size),
 	STD_METHOD(get_channels),
 	STD_METHOD(get_format),
+	STD_METHOD(get_sample_rate),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 08/15] android/client-audio: Add getting audio format
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Get current audio format for output stream.

---
 android/client/if-audio.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 1c9baff..45c00f3 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -69,6 +69,24 @@ SINTMAP(audio_channel_mask_t, -1, "(AUDIO_CHANNEL_INVALID)")
 	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
 ENDMAP
 
+SINTMAP(audio_format_t, -1, "(AUDIO_FORMAT_INVALID)")
+	DELEMENT(AUDIO_FORMAT_DEFAULT),
+	DELEMENT(AUDIO_FORMAT_PCM),
+	DELEMENT(AUDIO_FORMAT_MP3),
+	DELEMENT(AUDIO_FORMAT_AMR_NB),
+	DELEMENT(AUDIO_FORMAT_AMR_WB),
+	DELEMENT(AUDIO_FORMAT_AAC),
+	DELEMENT(AUDIO_FORMAT_HE_AAC_V1),
+	DELEMENT(AUDIO_FORMAT_HE_AAC_V2),
+	DELEMENT(AUDIO_FORMAT_VORBIS),
+	DELEMENT(AUDIO_FORMAT_MAIN_MASK),
+	DELEMENT(AUDIO_FORMAT_SUB_MASK),
+	DELEMENT(AUDIO_FORMAT_PCM_16_BIT),
+	DELEMENT(AUDIO_FORMAT_PCM_8_BIT),
+	DELEMENT(AUDIO_FORMAT_PCM_32_BIT),
+	DELEMENT(AUDIO_FORMAT_PCM_8_24_BIT),
+ENDMAP
+
 static int current_state = STATE_STOPPED;
 
 static void init_p(int argc, const char **argv)
@@ -349,6 +367,18 @@ static void get_channels_p(int argc, const char **argv)
 	haltest_info("Channels: %s\n", audio_channel_mask_t2str(channels));
 }
 
+static void get_format_p(int argc, const char **argv)
+{
+	audio_format_t format;
+
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	format = stream_out->common.get_format(&stream_out->common);
+
+	haltest_info("Format: %s\n", audio_format_t2str(format));
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -361,6 +391,7 @@ static struct method methods[] = {
 	STD_METHOD(get_latency),
 	STD_METHOD(get_buffer_size),
 	STD_METHOD(get_channels),
+	STD_METHOD(get_format),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 07/15] android/client-audio: Add get_channels
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Get audio channels configuration.

---
 android/client/if-audio.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 2b158a5..1c9baff 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -36,6 +36,39 @@ enum state {
 	STATE_MAX
 };
 
+SINTMAP(audio_channel_mask_t, -1, "(AUDIO_CHANNEL_INVALID)")
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_RIGHT),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_CENTER),
+	DELEMENT(AUDIO_CHANNEL_OUT_LOW_FREQUENCY),
+	DELEMENT(AUDIO_CHANNEL_OUT_BACK_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_BACK_RIGHT),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
+	DELEMENT(AUDIO_CHANNEL_OUT_BACK_CENTER),
+	DELEMENT(AUDIO_CHANNEL_OUT_SIDE_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_SIDE_RIGHT),
+	DELEMENT(AUDIO_CHANNEL_OUT_TOP_CENTER),
+	DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER),
+	DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT),
+	DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_CENTER),
+	DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
+	DELEMENT(AUDIO_CHANNEL_OUT_MONO),
+	DELEMENT(AUDIO_CHANNEL_OUT_STEREO),
+	DELEMENT(AUDIO_CHANNEL_OUT_QUAD),
+	DELEMENT(AUDIO_CHANNEL_OUT_SURROUND),
+	DELEMENT(AUDIO_CHANNEL_OUT_5POINT1),
+	DELEMENT(AUDIO_CHANNEL_OUT_7POINT1),
+	DELEMENT(AUDIO_CHANNEL_OUT_ALL),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
+	DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
+ENDMAP
+
 static int current_state = STATE_STOPPED;
 
 static void init_p(int argc, const char **argv)
@@ -304,6 +337,18 @@ static void get_buffer_size_p(int argc, const char **argv)
 		stream_out->common.get_buffer_size(&stream_out->common));
 }
 
+static void get_channels_p(int argc, const char **argv)
+{
+	audio_channel_mask_t channels;
+
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	channels = stream_out->common.get_channels(&stream_out->common);
+
+	haltest_info("Channels: %s\n", audio_channel_mask_t2str(channels));
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -315,6 +360,7 @@ static struct method methods[] = {
 	STD_METHOD(resume),
 	STD_METHOD(get_latency),
 	STD_METHOD(get_buffer_size),
+	STD_METHOD(get_channels),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 06/15] android/client-audio: Add get_buffer_size for output
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Get buffer size for output stream.

---
 android/client/if-audio.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 1ca84f5..2b158a5 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -295,6 +295,15 @@ static void get_latency_p(int argc, const char **argv)
 					stream_out->get_latency(stream_out));
 }
 
+static void get_buffer_size_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	haltest_info("Current output buffer size: %d\n",
+		stream_out->common.get_buffer_size(&stream_out->common));
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -305,6 +314,7 @@ static struct method methods[] = {
 	STD_METHOD(suspend),
 	STD_METHOD(resume),
 	STD_METHOD(get_latency),
+	STD_METHOD(get_buffer_size),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 05/15] android/client-audio: Add get_latency for output
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Get output stream latency.

---
 android/client/if-audio.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 985b60c..1ca84f5 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -286,6 +286,15 @@ static void resume_p(int argc, const char **argv)
 	pthread_mutex_unlock(&state_mutex);
 }
 
+static void get_latency_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	haltest_info("Output audio stream latency: %d\n",
+					stream_out->get_latency(stream_out));
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -295,6 +304,7 @@ static struct method methods[] = {
 	STD_METHOD(stop),
 	STD_METHOD(suspend),
 	STD_METHOD(resume),
+	STD_METHOD(get_latency),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 04/15] android/client-audio: Add playback suspend/resume
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

Add audio stream suspending and resuming.

---
 android/client/if-audio.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index cd0a851..985b60c 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -104,6 +104,10 @@ static void *playback_thread(void *data)
 		if (current_state == STATE_STOPPING) {
 			pthread_mutex_unlock(&state_mutex);
 			break;
+		} else if (current_state == STATE_SUSPENDED) {
+				pthread_mutex_unlock(&state_mutex);
+				usleep(500);
+				continue;
 		}
 		pthread_mutex_unlock(&state_mutex);
 
@@ -253,6 +257,35 @@ static void cleanup_p(int argc, const char **argv)
 	if_audio = NULL;
 }
 
+static void suspend_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	pthread_mutex_lock(&state_mutex);
+	if (current_state != STATE_PLAYING) {
+		pthread_mutex_unlock(&state_mutex);
+		return;
+	}
+	current_state = STATE_SUSPENDED;
+	pthread_mutex_unlock(&state_mutex);
+
+	pthread_mutex_lock(&outstream_mutex);
+	stream_out->common.standby(&stream_out->common);
+	pthread_mutex_unlock(&outstream_mutex);
+}
+
+static void resume_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	pthread_mutex_lock(&state_mutex);
+	if (current_state == STATE_SUSPENDED)
+		current_state = STATE_PLAYING;
+	pthread_mutex_unlock(&state_mutex);
+}
+
 static struct method methods[] = {
 	STD_METHOD(init),
 	STD_METHOD(cleanup),
@@ -260,6 +293,8 @@ static struct method methods[] = {
 	STD_METHOD(close_output_stream),
 	STD_METHODH(play, "<path to pcm file>"),
 	STD_METHOD(stop),
+	STD_METHOD(suspend),
+	STD_METHOD(resume),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related

* [RFC 03/15] android/client-audio: Add audio file playback
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391081001-30723-1-git-send-email-jakub.tyszkowski@tieto.com>

This patch adds audio file playback capability. Proper 16-bit signed
float stereo PCM file is needed.

---
 android/client/if-audio.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)

diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 4c1efce..cd0a851 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -17,11 +17,26 @@
 
 #include "if-main.h"
 #include "../hal-utils.h"
+#include "pthread.h"
+#include "unistd.h"
 
 audio_hw_device_t *if_audio = NULL;
 struct audio_stream_out *stream_out = NULL;
 
 static size_t buffer_size = 0;
+static pthread_t play_thread = 0;
+static pthread_mutex_t outstream_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+enum state {
+	STATE_STOPPED,
+	STATE_STOPPING,
+	STATE_PLAYING,
+	STATE_SUSPENDED,
+	STATE_MAX
+};
+
+static int current_state = STATE_STOPPED;
 
 static void init_p(int argc, const char **argv)
 {
@@ -45,12 +60,142 @@ static void init_p(int argc, const char **argv)
 	if_audio = device;
 }
 
+static void playthread_cleanup(void *arg)
+{
+	pthread_mutex_lock(&state_mutex);
+	current_state = STATE_STOPPED;
+	pthread_mutex_unlock(&state_mutex);
+
+	haltest_info("Done playing.\n");
+}
+
+static int feed_from_file(short *buffer, void *data)
+{
+	FILE *in = data;
+	return fread(buffer, buffer_size, 1, in);
+}
+
+static void *playback_thread(void *data)
+{
+	int (*filbuff_cb) (short*, void*);
+	short buffer[buffer_size / sizeof(short)];
+	size_t len = 0;
+	size_t w_len = 0;
+	FILE *in = data;
+	void *cb_data = NULL;
+
+	pthread_cleanup_push(playthread_cleanup, NULL);
+
+	/* Use file or fall back to generator */
+	if (in) {
+		filbuff_cb = feed_from_file;
+		cb_data = in;
+	} else {
+		/* TODO: Use generator */
+		goto end;
+	}
+
+	pthread_mutex_lock(&state_mutex);
+	current_state = STATE_PLAYING;
+	pthread_mutex_unlock(&state_mutex);
+
+	do {
+		pthread_mutex_lock(&state_mutex);
+		if (current_state == STATE_STOPPING) {
+			pthread_mutex_unlock(&state_mutex);
+			break;
+		}
+		pthread_mutex_unlock(&state_mutex);
+
+		len = filbuff_cb(buffer, cb_data);
+
+		pthread_mutex_lock(&outstream_mutex);
+		if (!stream_out) {
+			pthread_mutex_unlock(&outstream_mutex);
+			break;
+		}
+
+		w_len = stream_out->write(stream_out, buffer, buffer_size);
+		pthread_mutex_unlock(&outstream_mutex);
+	} while (len && w_len);
+
+	if (in) {
+		fclose(in);
+		in = NULL;
+	}
+end:
+	pthread_cleanup_pop(1);
+	return NULL;
+}
+
+static void play_p(int argc, const char **argv)
+{
+	const char *fname = NULL;
+	FILE *in = NULL;
+
+	RETURN_IF_NULL(if_audio);
+	RETURN_IF_NULL(stream_out);
+
+	if (argc < 3) {
+		haltest_error("Invalid audio file path.\n");
+	} else {
+		fname = argv[2];
+		in = fopen(fname, "r");
+
+		if (in == NULL) {
+			haltest_error("Cannot open file: %s\n", fname);
+			return;
+		}
+		haltest_info("Playing file: %s\n", fname);
+	}
+
+	if (buffer_size == 0) {
+		haltest_error("Invalid buffer size. Was stream_out opened?\n");
+		return;
+	}
+
+	pthread_mutex_lock(&state_mutex);
+	if (current_state != STATE_STOPPED) {
+		haltest_error("Already playing or stream suspended!\n");
+		pthread_mutex_unlock(&state_mutex);
+		return;
+	}
+	pthread_mutex_unlock(&state_mutex);
+
+	if (pthread_create(&play_thread, NULL, playback_thread, in) != 0)
+		haltest_error("Cannot create playback thread!\n");
+}
+
+static void stop_p(int argc, const char **argv)
+{
+	pthread_mutex_lock(&state_mutex);
+	if (current_state == STATE_STOPPED || current_state == STATE_STOPPING) {
+		pthread_mutex_unlock(&state_mutex);
+		return;
+	}
+
+	current_state = STATE_STOPPING;
+	pthread_mutex_unlock(&state_mutex);
+
+	pthread_mutex_lock(&outstream_mutex);
+	stream_out->common.standby(&stream_out->common);
+	pthread_mutex_unlock(&outstream_mutex);
+}
+
 static void open_output_stream_p(int argc, const char **argv)
 {
 	int err;
 
 	RETURN_IF_NULL(if_audio);
 
+	pthread_mutex_lock(&state_mutex);
+	if (current_state == STATE_PLAYING) {
+		haltest_error("Already playing!\n");
+		pthread_mutex_unlock(&state_mutex);
+		return;
+	}
+	pthread_mutex_unlock(&state_mutex);
+
 	err = if_audio->open_output_stream(if_audio,
 						0,
 						AUDIO_DEVICE_OUT_ALL_A2DP,
@@ -74,7 +219,15 @@ static void close_output_stream_p(int argc, const char **argv)
 	RETURN_IF_NULL(if_audio);
 	RETURN_IF_NULL(stream_out);
 
+	stop_p(argc, argv);
+
+	haltest_info("Waiting for playback thread...\n");
+	pthread_join(play_thread, NULL);
+
 	if_audio->close_output_stream(if_audio, stream_out);
+
+	stream_out = NULL;
+	buffer_size = 0;
 }
 
 static void cleanup_p(int argc, const char **argv)
@@ -83,6 +236,14 @@ static void cleanup_p(int argc, const char **argv)
 
 	RETURN_IF_NULL(if_audio);
 
+	pthread_mutex_lock(&state_mutex);
+	if (current_state != STATE_STOPPED) {
+		pthread_mutex_unlock(&state_mutex);
+		close_output_stream_p(0, NULL);
+	} else {
+		pthread_mutex_unlock(&state_mutex);
+	}
+
 	err = audio_hw_device_close(if_audio);
 	if (err < 0) {
 		haltest_error("audio_hw_device_close returned %d\n", err);
@@ -97,6 +258,8 @@ static struct method methods[] = {
 	STD_METHOD(cleanup),
 	STD_METHOD(open_output_stream),
 	STD_METHOD(close_output_stream),
+	STD_METHODH(play, "<path to pcm file>"),
+	STD_METHOD(stop),
 	END_METHOD
 };
 
-- 
1.8.5.2


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox