* [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
* [RFC 02/15] android/client-audio: Add open/close output stream
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 opening and closing output stream.
---
android/client/if-audio.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/android/client/if-audio.c b/android/client/if-audio.c
index 203e088..4c1efce 100644
--- a/android/client/if-audio.c
+++ b/android/client/if-audio.c
@@ -19,6 +19,9 @@
#include "../hal-utils.h"
audio_hw_device_t *if_audio = NULL;
+struct audio_stream_out *stream_out = NULL;
+
+static size_t buffer_size = 0;
static void init_p(int argc, const char **argv)
{
@@ -34,12 +37,46 @@ static void init_p(int argc, const char **argv)
}
err = audio_hw_device_open(module, &device);
- if (err)
+ if (err) {
haltest_error("audio_hw_device_open returned %d\n", err);
+ return;
+ }
if_audio = device;
}
+static void open_output_stream_p(int argc, const char **argv)
+{
+ int err;
+
+ RETURN_IF_NULL(if_audio);
+
+ err = if_audio->open_output_stream(if_audio,
+ 0,
+ AUDIO_DEVICE_OUT_ALL_A2DP,
+ AUDIO_OUTPUT_FLAG_NONE,
+ NULL,
+ &stream_out);
+ if (err < 0) {
+ haltest_error("open output stream returned %d\n", err);
+ return;
+ }
+
+ buffer_size = stream_out->common.get_buffer_size(&stream_out->common);
+ if (buffer_size == 0)
+ haltest_error("Invalid buffer size received!\n");
+ else
+ haltest_info("Using buffer size: %d\n", buffer_size);
+}
+
+static void close_output_stream_p(int argc, const char **argv)
+{
+ RETURN_IF_NULL(if_audio);
+ RETURN_IF_NULL(stream_out);
+
+ if_audio->close_output_stream(if_audio, stream_out);
+}
+
static void cleanup_p(int argc, const char **argv)
{
int err;
@@ -58,6 +95,8 @@ static void cleanup_p(int argc, const char **argv)
static struct method methods[] = {
STD_METHOD(init),
STD_METHOD(cleanup),
+ STD_METHOD(open_output_stream),
+ STD_METHOD(close_output_stream),
END_METHOD
};
--
1.8.5.2
^ permalink raw reply related
* [RFC 01/15] android/client-av: Fix checking for a2dp interface
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>
---
android/client/if-av.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/android/client/if-av.c b/android/client/if-av.c
index 0470e0d..8d1f69b 100644
--- a/android/client/if-av.c
+++ b/android/client/if-av.c
@@ -80,7 +80,7 @@ static void connect_p(int argc, const char **argv)
{
bt_bdaddr_t addr;
- RETURN_IF_NULL(if_hh);
+ RETURN_IF_NULL(if_av);
VERIFY_ADDR_ARG(2, &addr);
EXEC(if_av->connect, &addr);
@@ -101,7 +101,7 @@ static void disconnect_p(int argc, const char **argv)
{
bt_bdaddr_t addr;
- RETURN_IF_NULL(if_hh);
+ RETURN_IF_NULL(if_av);
VERIFY_ADDR_ARG(2, &addr);
EXEC(if_av->disconnect, &addr);
--
1.8.5.2
^ permalink raw reply related
* [RFC 00/15] android/client: Add audio support
From: Jakub Tyszkowski @ 2014-01-30 11:23 UTC (permalink / raw)
To: linux-bluetooth
This patch set adds audio support for haltest tool. It provides basic audio HAL
functionality and adds ability to play PCM audio files.
I've also added sound generator when no file path is provided for "play"
command. We can leave that be or push sample audio file to the tree, and/or
hardcode the path. I think that leaving audio file selection to the user and
providing fallback to sound generator is the right solution. Please let me know
what is yours preference.
Regards.
Jakub Tyszkowski (15):
android/client-av: Fix checking for a2dp interface
android/client-audio: Add open/close output stream
android/client-audio: Add audio file playback
android/client-audio: Add playback suspend/resume
android/client-audio: Add get_latency for output
android/client-audio: Add get_buffer_size for output
android/client-audio: Add get_channels
android/client-audio: Add getting audio format
android/client-audio: Add getting sample rate
android/client-audio: Add get_parameters for output
android/client-audio: Add set_parameters
android/client-audio: Add setting sample rate
android/client-audio: Add init_check
android/client-audio: Add sine generator as fallback
android/client-audio: Fix getting audio module on Android
android/Makefile.am | 2 +-
android/client/if-audio.c | 477 +++++++++++++++++++++++++++++++++++++++++++++-
android/client/if-av.c | 4 +-
3 files changed, 479 insertions(+), 4 deletions(-)
--
1.8.5.2
^ permalink raw reply
* [PATCHv3] hog: Use HoG device name as uHID input device name
From: Petri Gynther @ 2014-01-30 3:55 UTC (permalink / raw)
To: linux-bluetooth
If HoG BLE device name is known, use it when creating uHID input device.
Pass adapter and device addresses to uHID as well.
---
profiles/input/hog.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index ded6303..030dc91 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -392,7 +392,15 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
/* create uHID device */
memset(&ev, 0, sizeof(ev));
ev.type = UHID_CREATE;
- strcpy((char *) ev.u.create.name, "bluez-hog-device");
+ if (device_name_known(hogdev->device)) {
+ device_get_name(hogdev->device, (char *) ev.u.create.name,
+ sizeof(ev.u.create.name) - 1);
+ } else {
+ strcpy((char *) ev.u.create.name, "bluez-hog-device");
+ }
+ ba2str(btd_adapter_get_address(device_get_adapter(hogdev->device)),
+ (char *) ev.u.create.phys);
+ ba2str(device_get_address(hogdev->device), (char *) ev.u.create.uniq);
ev.u.create.vendor = vendor;
ev.u.create.product = product;
ev.u.create.version = version;
--
1.8.5.3
^ permalink raw reply related
* [PATCHv2] hog: Use HoG device name as uHID input device name
From: Petri Gynther @ 2014-01-30 2:55 UTC (permalink / raw)
To: linux-bluetooth
If HoG BLE device name is known, use it when creating uHID input device.
Pass BLE device address to uHID as well.
---
profiles/input/hog.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index ded6303..7ad184a 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -392,7 +392,13 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
/* create uHID device */
memset(&ev, 0, sizeof(ev));
ev.type = UHID_CREATE;
- strcpy((char *) ev.u.create.name, "bluez-hog-device");
+ if (device_name_known(hogdev->device)) {
+ device_get_name(hogdev->device, (char *) ev.u.create.name,
+ sizeof(ev.u.create.name) - 1);
+ } else {
+ strcpy((char *) ev.u.create.name, "bluez-hog-device");
+ }
+ ba2str(device_get_address(hogdev->device), (char *) ev.u.create.phys);
ev.u.create.vendor = vendor;
ev.u.create.product = product;
ev.u.create.version = version;
--
1.8.5.3
^ permalink raw reply related
* Re: [PATCH] hog: Use HoG device name as uHID input device name
From: Petri Gynther @ 2014-01-30 2:50 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <20140129053008.829BC100AC4@puck.mtv.corp.google.com>
On Tue, Jan 28, 2014 at 9:30 PM, Petri Gynther <pgynther@google.com> wrote:
> If HoG BLE device name is known, use it when creating uHID input device.
> ---
> profiles/input/hog.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/profiles/input/hog.c b/profiles/input/hog.c
> index ded6303..3af0406 100644
> --- a/profiles/input/hog.c
> +++ b/profiles/input/hog.c
> @@ -392,7 +392,12 @@ static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
> /* create uHID device */
> memset(&ev, 0, sizeof(ev));
> ev.type = UHID_CREATE;
> - strcpy((char *) ev.u.create.name, "bluez-hog-device");
> + if (device_name_known(hogdev->device)) {
> + device_get_name(hogdev->device, (char *) ev.u.create.name,
> + sizeof(ev.u.create.name) - 1);
> + } else {
> + strcpy((char *) ev.u.create.name, "bluez-hog-device");
> + }
> ev.u.create.vendor = vendor;
> ev.u.create.product = product;
> ev.u.create.version = version;
> --
> 1.8.5.3
>
I'll add the BLE device address to ev.u.create.phys. New patch coming soon.
^ permalink raw reply
* Re: [PATCHv2 0/3] AVCTP test cases
From: Luiz Augusto von Dentz @ 2014-01-29 23:29 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1390999274-15631-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Wed, Jan 29, 2014 at 4:41 AM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Set of test cases which are feasible to implement with socketpair.
> Fragmentation of AVCTP is not supported yet.
>
> Andrei Emeltchenko (3):
> unit/avctp: Add AVCTP unit test skeleton and first test
> unit/avctp: Add TP/NFR/BV-02-C test
> unit/avctp: Add TP/NFR/BI-01-C test
>
> Makefile.am | 8 ++
> unit/test-avctp.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 283 insertions(+)
> create mode 100644 unit/test-avctp.c
>
> --
> 1.8.3.2
Applied, thanks.
--
Luiz Augusto von Dentz
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox