Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 2/6] android/hal-audio: Be more verbose on SBC errors
From: Andrzej Kaczmarek @ 2014-02-03 15:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek
In-Reply-To: <1391442292-4668-1-git-send-email-andrzej.kaczmarek@tieto.com>

---
 android/hal-audio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 4578c53..bccaf15 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -466,7 +466,7 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
 					&written);
 
 		if (ret < 0) {
-			error("SBC: failed to encode block");
+			error("SBC: failed to encode block (%zd)", bytes_read);
 			break;
 		}
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 1/6] android/hal-audio: Remove unsupported mono channel mode
From: Andrzej Kaczmarek @ 2014-02-03 15:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Andrzej Kaczmarek

AudioFlinger can only provide PCM 16bit Stereo data for A2DP track so
we should not advertise mono channel mode in capabilities since we
can't downmix this internally.
---
 android/hal-audio.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 8ef5bff..4578c53 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -227,8 +227,7 @@ struct a2dp_audio_dev {
 static const a2dp_sbc_t sbc_presets[] = {
 	{
 		.frequency = SBC_SAMPLING_FREQ_44100 | SBC_SAMPLING_FREQ_48000,
-		.channel_mode = SBC_CHANNEL_MODE_MONO |
-				SBC_CHANNEL_MODE_DUAL_CHANNEL |
+		.channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL |
 				SBC_CHANNEL_MODE_STEREO |
 				SBC_CHANNEL_MODE_JOINT_STEREO,
 		.subbands = SBC_SUBBANDS_4 | SBC_SUBBANDS_8,
-- 
1.8.5.3


^ permalink raw reply related

* Working with the gatt-example.c plugin
From: Sandy Chapman @ 2014-02-03 14:38 UTC (permalink / raw)
  To: linux-bluetooth

Hi All,

I'm having some difficulties getting the gatt-example plugin working.
I've checked out the latest tag (5.14) from git and have built it
using the --enable-maintainer-mode configure flag so that
gatt-example.c is compiled into a static plugin that is loaded at
runtime. I've confirmed that the plugin is compiled and is loaded at
runtime when I run bluetoothd.

My problem is with making modifications to the plugin. I've tried
something as simple as changing the UUID for the battery service,
however, every time I scan the services (using an iPhone), the same
list of UUIDs is returned (0xA002 , 0xA004, and 0xFEEE... for the
services, which match up with what's defined in the gatt-example.c
file). Any modifications I make to the file don't seem to have any
effect on the services advertised. I've even rebuilt it without
maintainer mode and have confirmed the plugin isn't loaded, but still,
the same set of services and characteristics are loaded. Is there some
sort of cache where the advertisement is loaded from that can be
cleared? It looks like a bunch of HCI Commands are sent every time I
"hciconfig hci0 up" which didn't happen when I initially ran the
hciconfig tool prior to compiling and running bluetoothd.

Some additional details:
Bluetooth adapter is a Broadcom (in a MacBook Pro) that is running
through a Linux VM (VirtualBox). Additional diagnostics can be
provided on request.

Thanks for any help you guys can provide,
Sandy

-- 


^ permalink raw reply

* Re: [PATCHv3 1/5] android/unit: Add android IPC unit tests
From: Szymon Janc @ 2014-02-03 14:33 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1389866702-30697-1-git-send-email-marcin.kraglak@tieto.com>

Hi Marcin,

On Thursday 16 of January 2014 11:04:58 Marcin Kraglak wrote:
> It will test ipc library. First test case will check
> ipc_init() call.
> ---
>  .gitignore          |   1 +
>  android/Makefile.am |   8 ++
>  android/test-ipc.c  | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 286 insertions(+)
>  create mode 100644 android/test-ipc.c
> 
> diff --git a/.gitignore b/.gitignore
> index ac76fe2..ddd562a 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -114,3 +114,4 @@ android/bluetoothd
>  android/haltest
>  android/android-tester
>  android/bluetoothd-snoop
> +android/test-ipc
> diff --git a/android/Makefile.am b/android/Makefile.am
> index cd4a526..0c61317 100644
> --- a/android/Makefile.am
> +++ b/android/Makefile.am
> @@ -117,6 +117,14 @@ android_android_tester_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
>  
>  android_android_tester_LDFLAGS = -pthread -ldl
>  
> +noinst_PROGRAMS += android/test-ipc
> +
> +android_test_ipc_SOURCES = android/test-ipc.c \
> +				src/shared/util.h src/shared/util.c \
> +				src/log.h src/log.c \
> +				android/ipc.c android/ipc.h
> +android_test_ipc_LDADD = @GLIB_LIBS@
> +
>  plugin_LTLIBRARIES += android/audio.a2dp.default.la
>  
>  android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \
> diff --git a/android/test-ipc.c b/android/test-ipc.c
> new file mode 100644
> index 0000000..6ac1175
> --- /dev/null
> +++ b/android/test-ipc.c
> @@ -0,0 +1,277 @@
> +/*
> + *
> + *  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 <stdio.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <stdbool.h>
> +#include <inttypes.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <sys/signalfd.h>
> +
> +#include <glib.h>
> +#include "src/shared/util.h"
> +#include "src/log.h"
> +#include "android/hal-msg.h"
> +#include "android/ipc.h"
> +
> +struct test_data {
> +	uint32_t expected_signal;
> +};
> +
> +struct context {
> +	GMainLoop *main_loop;
> +
> +	int sk;
> +
> +	guint source;
> +	guint cmd_source;
> +	guint notif_source;
> +
> +	GIOChannel *cmd_io;
> +	GIOChannel *notif_io;
> +	GIOChannel *signal_io;
> +
> +	guint signal_source;
> +
> +	const struct test_data *data;
> +};
> +
> +static void context_quit(struct context *context)
> +{
> +	g_main_loop_quit(context->main_loop);
> +}
> +
> +static gboolean cmd_watch(GIOChannel *io, GIOCondition cond,
> +						gpointer user_data)
> +{
> +	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> +		g_assert(FALSE);
> +		return FALSE;
> +	}
> +
> +	return TRUE;
> +}
> +
> +static gboolean notif_watch(GIOChannel *io, GIOCondition cond,
> +							gpointer user_data)
> +{
> +	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> +		g_assert(FALSE);
> +		return FALSE;
> +	}
> +
> +	return TRUE;
> +}
> +
> +static gboolean connect_handler(GIOChannel *io, GIOCondition cond,
> +						gpointer user_data)
> +{
> +	struct context *context = user_data;
> +	GIOChannel *new_io;
> +	GIOCondition watch_cond;
> +	int sk;
> +
> +	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
> +		g_assert(FALSE);
> +		return FALSE;
> +	}
> +
> +	g_assert(!context->cmd_source || !context->notif_source);
> +
> +	sk = accept(context->sk, NULL, NULL);
> +	g_assert(sk >= 0);
> +
> +	new_io = g_io_channel_unix_new(sk);
> +
> +	watch_cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
> +
> +	if (context->cmd_source && !context->notif_source) {
> +		context->notif_source = g_io_add_watch(new_io, watch_cond,
> +							notif_watch, context);
> +		g_assert(context->notif_source > 0);
> +		context->notif_io = new_io;
> +	}
> +
> +	if (!context->cmd_source) {
> +		context->cmd_source = g_io_add_watch(new_io, watch_cond,
> +							cmd_watch, context);
> +		context->cmd_io = new_io;
> +	}
> +
> +	if (context->cmd_source && context->notif_source)
> +		context_quit(context);
> +
> +	return TRUE;
> +}
> +
> +static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
> +							gpointer user_data)
> +{
> +	struct context *context = user_data;
> +	const struct test_data *test_data = context->data;
> +	struct signalfd_siginfo si;
> +	ssize_t result;
> +	int fd;
> +
> +	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
> +		return FALSE;
> +
> +	fd = g_io_channel_unix_get_fd(channel);
> +
> +	result = read(fd, &si, sizeof(si));
> +	if (result != sizeof(si))
> +		return FALSE;
> +
> +	g_assert(test_data->expected_signal == si.ssi_signo);
> +	context_quit(context);
> +	return TRUE;
> +}
> +
> +static guint setup_signalfd(gpointer user_data)
> +{
> +	GIOChannel *channel;
> +	guint source;
> +	sigset_t mask;
> +	int ret;
> +	int fd;
> +
> +	sigemptyset(&mask);
> +	sigaddset(&mask, SIGINT);
> +	sigaddset(&mask, SIGTERM);
> +
> +	ret = sigprocmask(SIG_BLOCK, &mask, NULL);
> +	g_assert(ret == 0);
> +
> +	fd = signalfd(-1, &mask, 0);
> +	g_assert(fd >= 0);
> +
> +	channel = g_io_channel_unix_new(fd);
> +
> +	g_io_channel_set_close_on_unref(channel, TRUE);
> +	g_io_channel_set_encoding(channel, NULL, NULL);
> +	g_io_channel_set_buffered(channel, FALSE);
> +
> +	source = g_io_add_watch(channel,
> +				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> +				signal_handler, user_data);
> +
> +	g_io_channel_unref(channel);
> +
> +	return source;
> +}
> +
> +static struct context *create_context(gconstpointer data)
> +{
> +	struct context *context = g_new0(struct context, 1);
> +	struct sockaddr_un addr;
> +	GIOChannel *io;
> +	int ret, sk;
> +
> +	context->main_loop = g_main_loop_new(NULL, FALSE);
> +	g_assert(context->main_loop);
> +
> +	context->signal_source = setup_signalfd(context);
> +	g_assert(context->signal_source);
> +
> +	sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
> +	g_assert(sk >= 0);
> +
> +	memset(&addr, 0, sizeof(addr));
> +	addr.sun_family = AF_UNIX;
> +
> +	memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
> +
> +	ret = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
> +	g_assert(ret == 0);
> +
> +	ret = listen(sk, 5);
> +	g_assert(ret == 0);
> +
> +	io = g_io_channel_unix_new(sk);
> +
> +	g_io_channel_set_close_on_unref(io, TRUE);
> +
> +	context->source = g_io_add_watch(io,
> +				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> +				connect_handler, context);
> +	g_assert(context->source > 0);
> +
> +	g_io_channel_unref(io);
> +
> +	context->sk = sk;
> +	context->data = data;
> +
> +	return context;
> +}
> +
> +static void execute_context(struct context *context)
> +{
> +	g_main_loop_run(context->main_loop);
> +
> +	g_io_channel_shutdown(context->notif_io, true, NULL);
> +	g_io_channel_shutdown(context->cmd_io, true, NULL);
> +	g_io_channel_unref(context->cmd_io);
> +	g_io_channel_unref(context->notif_io);
> +
> +	g_source_remove(context->notif_source);
> +	g_source_remove(context->signal_source);
> +	g_source_remove(context->cmd_source);
> +	g_source_remove(context->source);
> +
> +	g_main_loop_unref(context->main_loop);
> +
> +	g_free(context);
> +}
> +
> +static void test_init(gconstpointer data)
> +{
> +	struct context *context = create_context(data);
> +
> +	ipc_init();
> +
> +	execute_context(context);
> +
> +	ipc_cleanup();
> +}
> +
> +static const struct test_data test_init_1 = {};
> +
> +int main(int argc, char *argv[])
> +{
> +	g_test_init(&argc, &argv, NULL);
> +
> +	if (g_test_verbose())
> +		__btd_log_init("*", 0);
> +
> +	g_test_add_data_func("/android_ipc/init", &test_init_1, test_init);
> +
> +	return g_test_run();
> +}
> 

This is now applied (with some cleanups), thanks.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* Re: [RFC v6 03/14] Bluetooth: Introduce connection parameters list
From: Andre Guedes @ 2014-02-03 14:06 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: BlueZ development
In-Reply-To: <94043278-430F-4EAE-A4F1-36AB1FB614A6@holtmann.org>


Hi Marcel,

On Fri, 2014-01-31 at 17:11 -0800, Marcel Holtmann wrote:
> Hi Andre,
> 
> > This patch adds to hdev the connection parameters list (hdev->le_
> > conn_params). The elements from this list (struct hci_conn_params)
> > contains the connection parameters (for now, minimum and maximum
> > connection interval) that should be used during the connection
> > establishment.
> > 
> > The struct hci_conn_params also defines the 'auto_connect' field
> > which will be used to implement the auto connection mechanism.
> > 
> > Moreover, this patch adds helper functions to manipulate hdev->le_
> > conn_params list. Some of these functions are also declared in
> > hci_core.h since they will be used outside hci_core.c in upcoming
> > patches.
> > 
> > Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
> > ---
> > include/net/bluetooth/hci_core.h | 25 +++++++++++++
> > net/bluetooth/hci_core.c         | 80 ++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 105 insertions(+)
> > 
> > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> > index 197413b..f757b3f 100644
> > --- a/include/net/bluetooth/hci_core.h
> > +++ b/include/net/bluetooth/hci_core.h
> > @@ -269,6 +269,7 @@ struct hci_dev {
> > 	struct list_head	link_keys;
> > 	struct list_head	long_term_keys;
> > 	struct list_head	remote_oob_data;
> > +	struct list_head	le_conn_params;
> > 
> > 	struct hci_dev_stats	stat;
> > 
> > @@ -373,6 +374,22 @@ struct hci_chan {
> > 	__u8		state;
> > };
> > 
> > +struct hci_conn_params {
> > +	struct list_head list;
> > +
> > +	bdaddr_t addr;
> > +	u8 addr_type;
> > +
> > +	enum {
> > +		HCI_AUTO_CONN_DISABLED,
> > +		HCI_AUTO_CONN_ALWAYS,
> > +		HCI_AUTO_CONN_LINK_LOSS,
> > +	} auto_connect;
> 
> actually I would not include the auto_connect mode in the this stage of the patch set. We could have made more progress with this patch set and get things applied if things are not intermixed. So lets leave this out and only introduce it once we need it.

All right, I'll introduce this auto_connect mode in patch 13/14. It
clearly makes more sense.

Thanks,

Andre

^ permalink raw reply

* BlueZ 5 mouse autoconnect
From: a.mv @ 2014-02-03 13:51 UTC (permalink / raw)
  To: linux-bluetooth

I followed all possible guides to connect automatically my Apple 
MagicMouse to my Linux PC. I saw on the forums that the key is to mark 
it as "trusted". I did it in bluetoothctl and put it to "trusts" file in 
/var/lib/bluetooth/xx:xx..../.

It works fine if I connect it manually but after restart I see only 
messages like this in bluetoothctl:
[NEW] Device 84:38:35:24:08:D9 MagicMouse
[CHG] Device 84:38:35:24:08:D9 Class: 0x002580
[CHG] Device 84:38:35:24:08:D9 Icon: input-mouse
[CHG] Device 84:38:35:24:08:D9 Connected: yes
[CHG] Device 84:38:35:24:08:D9 Connected: no
[DEL] Device 84:38:35:24:08:D9 MagicMouse
[NEW] Device 84:38:35:24:08:D9 MagicMouse
[CHG] Device 84:38:35:24:08:D9 Class: 0x002580
[CHG] Device 84:38:35:24:08:D9 Icon: input-mouse
[CHG] Device 84:38:35:24:08:D9 Connected: yes
[CHG] Device 84:38:35:24:08:D9 Connected: no
[DEL] Device 84:38:35:24:08:D9 MagicMouse

Messages are printed when I click a mouse button. There is a small delay 
between "Connected: yes" and "Connected: no" and during this time I see 
a bluetooth sign in the notification area (I have Gnome).
Sometimes I see a paring request from the mouse. Sometimes authorisation 
request and if I go to the bluetooth settings it even propose to type a 
PIN code on the mouse )
Regardless my action after restart of bluez I am at the starting point.

^ permalink raw reply

* Re: [PATCH 1/3] android/pan: Fix control state change callback parameters order
From: Andrei Emeltchenko @ 2014-02-03 13:19 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1390484367-6332-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Thu, Jan 23, 2014 at 03:39:25PM +0200, Ravi kumar Veeramally wrote:
> Callback declared in bt_pan.h is
> 'typedef void (*btpan_control_state_callback)
> (btpan_control_state_t state, bt_status_t error, int local_role,
> const char* ifname);
> 
> But PanService.Java defined it wrong way.
> private void onControlStateChanged(int local_role, int state,
> int error, String ifname).
> First and third parameters are misplaced, so sending data according
> to PanService.Java, discard this fix if issue fixed in PanService.Java.
> ---
>  android/hal-pan.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/android/hal-pan.c b/android/hal-pan.c
> index 8c0f8d8..a596ffd 100644
> --- a/android/hal-pan.c
> +++ b/android/hal-pan.c
> @@ -45,9 +45,18 @@ static void handle_ctrl_state(void *buf, uint16_t len)
>  {
>  	struct hal_ev_pan_ctrl_state *ev = buf;
>  
> +	/* FIXME: Callback declared in bt_pan.h is 'typedef void
> +	 * (*btpan_control_state_callback)(btpan_control_state_t state,
> +	 * bt_status_t error, int local_role, const char* ifname);
> +	 * But PanService.Java defined it wrong way.
> +	 * private void onControlStateChanged(int local_role, int state,
> +	 * int error, String ifname).
> +	 * First and third parameters are misplaced, so sending data according
> +	 * to PanService.Java, fix this if issue fixed in PanService.Java.

Just noticed that bluedroid use this with different combination of
arguments :)

callback.control_state_cb(state, btpan_role, status, TAP_IF_NAME);

How this ended up working? Maybe because only error and last argument are
important at this moment.

Best regards 
Andrei Emeltchenko 


> +	 */
>  	if (cbs->control_state_cb)
> -		cbs->control_state_cb(ev->state, ev->status,
> -					ev->local_role, (char *)ev->name);
> +		cbs->control_state_cb(ev->local_role, ev->state, ev->status,
> +							(char *)ev->name);
>  }
>  
>  /* handlers will be called from notification thread context,
> -- 
> 1.8.3.2
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH] unit/avctp: Add connection establishment dummy tests
From: Andrei Emeltchenko @ 2014-02-03 12:23 UTC (permalink / raw)
  To: linux-bluetooth

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

Add some tests checking that L2CAP connection is established, so they
are basically dummy tests.
---
 unit/test-avctp.c | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/unit/test-avctp.c b/unit/test-avctp.c
index 041e0c0..c0d16a4 100644
--- a/unit/test-avctp.c
+++ b/unit/test-avctp.c
@@ -220,10 +220,8 @@ static struct context *create_context(uint16_t version, gconstpointer data)
 	return context;
 }
 
-static void execute_context(struct context *context)
+static void destroy_context(struct context *context)
 {
-	g_main_loop_run(context->main_loop);
-
 	if (context->source > 0)
 		g_source_remove(context->source);
 
@@ -235,6 +233,13 @@ static void execute_context(struct context *context)
 	g_free(context);
 }
 
+static void execute_context(struct context *context)
+{
+	g_main_loop_run(context->main_loop);
+
+	destroy_context(context);
+}
+
 static void test_client(gconstpointer data)
 {
 	struct context *context = create_context(0x0100, data);
@@ -253,6 +258,13 @@ static void test_server(gconstpointer data)
 	execute_context(context);
 }
 
+static void test_dummy(gconstpointer data)
+{
+	struct context *context = create_context(0x0100, data);
+
+	destroy_context(context);
+}
+
 int main(int argc, char *argv[])
 {
 	g_test_init(&argc, &argv, NULL);
@@ -260,6 +272,18 @@ int main(int argc, char *argv[])
 	if (g_test_verbose())
 		__btd_log_init("*", 0);
 
+	/* Connection Channel Management tests */
+
+	/*
+	 * Tests are checking that IUT is able to request establishing
+	 * channels, since we already have connection through socketpair
+	 * the tests are dummy.
+	 */
+	define_test("/TP/CCM/BV-01-C", test_dummy, raw_pdu(0x00));
+	define_test("/TP/CCM/BV-02-C", test_dummy, raw_pdu(0x00));
+	define_test("/TP/CCM/BV-03-C", test_dummy, raw_pdu(0x00));
+	define_test("/TP/CCM/BV-04-C", test_dummy, raw_pdu(0x00));
+
 	define_test("/TP/NFR/BV-01-C", test_client,
 				raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x00, 0x00));
 
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH] Bluetooth: hidp: make sure input buffers are big enough
From: David Herrmann @ 2014-02-03 11:27 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Marcel Holtmann, open list:HID CORE LAYER,
	linux-bluetooth@vger.kernel.org development, Gustavo F. Padovan
In-Reply-To: <alpine.LNX.2.00.1402031107310.14066@pobox.suse.cz>

Hi Jiri

On Mon, Feb 3, 2014 at 11:08 AM, Jiri Kosina <jkosina@suse.cz> wrote:
> On Wed, 29 Jan 2014, David Herrmann wrote:
>
>> >> Due to various reasons I will not have access to any testing HW for the
>> >> upcoming 2-3 days, so if you can cook something up in that timeframe, it'd
>> >> be appreciated.
>> >>
>> >> Otherwise I'll be working on it by the end of this week.
>> >
>> > David,
>> >
>> > just got back to this, finally ... did you have time to work on this at
>> > all, or should I just start from scratch?
>>
>> Sorry, no. Fosdem is this weekend and I needed to get my code ready
>> for that. But I'll finally have time again next week.
>
> Okay, thanks. I then guess we should proceed with this bandaid (double
> allocation) for 3.14

It would be really nice if we could get the HIDP patch into 3.14-rc2
and backported to stable. There have been quite a bunch of reports now
and I dislike adding a GFP_ATOMIC allocation in HID core. I am back
home now and will try to make HID core honor the length, but that's
quite invasive and shouldn't be used for stable.

Sorry for the delay,
David

^ permalink raw reply

* Re: [PATCH] Bluetooth: hidp: make sure input buffers are big enough
From: Jiri Kosina @ 2014-02-03 10:08 UTC (permalink / raw)
  To: David Herrmann
  Cc: Marcel Holtmann, open list:HID CORE LAYER,
	linux-bluetooth@vger.kernel.org development, Gustavo F. Padovan
In-Reply-To: <CANq1E4TW+GU=oaW0tXb=Tun9HMtr26u-PC3H6BsLot560ANgog@mail.gmail.com>

On Wed, 29 Jan 2014, David Herrmann wrote:

> >> Due to various reasons I will not have access to any testing HW for the
> >> upcoming 2-3 days, so if you can cook something up in that timeframe, it'd
> >> be appreciated.
> >>
> >> Otherwise I'll be working on it by the end of this week.
> >
> > David,
> >
> > just got back to this, finally ... did you have time to work on this at
> > all, or should I just start from scratch?
> 
> Sorry, no. Fosdem is this weekend and I needed to get my code ready
> for that. But I'll finally have time again next week.

Okay, thanks. I then guess we should proceed with this bandaid (double 
allocation) for 3.14

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* Re: [PATCH] avrcp: Fix wrong pointer check
From: Andrei Emeltchenko @ 2014-02-03  9:42 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, linux-bluetooth@vger.kernel.org
In-Reply-To: <20140203093651.GE2930@aemeltch-MOBL1>

On Mon, Feb 03, 2014 at 11:36:52AM +0200, Andrei Emeltchenko wrote:
> On Mon, Feb 03, 2014 at 01:20:11AM -0800, Luiz Augusto von Dentz wrote:
> > Hi Andrei,
> > 
> > On Sun, Feb 2, 2014 at 11:51 PM, Andrei Emeltchenko
> > <Andrei.Emeltchenko.news@gmail.com> wrote:
> > > Hi Luiz,
> > >
> > > On Sun, Feb 02, 2014 at 08:03:34AM -0800, Luiz Augusto von Dentz wrote:
> > >> Hi Andrei,
> > >>
> > >> On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
> > >> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > >> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> > >> >
> > >> > There is wrong assumption that handler might be NULL while it is a
> > >> > pointer to a struct table so check instead for struct members. This
> > >> > fixes accessing wrong memory.
> > >> > ---
> > >> >  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 df88138..5030ce1 100644
> > >> > --- a/profiles/audio/avrcp.c
> > >> > +++ b/profiles/audio/avrcp.c
> > >> > @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
> > >> >                         break;
> > >> >         }
> > >> >
> > >> > -       if (!handler || handler->code != *code) {
> > >> > +       if (!handler->code || handler->code != *code) {
> > >>
> > >> The code checks if  session->control_handlers is initialized and Im
> > >> not sure what is the invalid memory access you are talking about since
> > >> handle->code is no a pointer, I do agree that we should probably drop
> > >> the second check for the handler in the lines bellow.
> > >
> > > handler is a pointer, and it points to
> > >
> > > static const struct control_pdu_handler control_handlers[]
> > > table with the last element:
> > >
> > > ...
> > >                 { },
> > > };
> > > ...
> > >
> > > So checking for !handler is pointless.
> > 
> > Right, because checking for pointer is pointless, yes Im being
> > sarcastic here... Now lets be clear, you are changing a check of a
> > pointer to a value and claiming it fixes invalid accesses which does
> > not make any sense, what could make sense is to check if
> > handler->pdu_id == pdu->pdu_id since that what we check when we lookup
> > for a handle.
> 
> No, we break if handler->pdu_id == pdu->pdu_id one line above ;)

Sorry this was wrong. So my idea is to check that we are not at the end of
the table. In this case every element of a struct is zero, so it does not
matter which one to check.

Best regards 
Andrei Emeltchenko 


^ permalink raw reply

* [PATCH BlueZ] audio/AVRCP: Fix checking for handler pointer instead of pdu_id
From: Luiz Augusto von Dentz @ 2014-02-03  9:40 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

The code may not find a valid handler for the pdu_id, in that case the
handler would not be NULL because the handlers table is not NULL
terminated, instead the code should check if pdu_id really matches.
---
 profiles/audio/avrcp.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 12f7faa..4532d85 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
 			break;
 	}
 
-	if (!handler || handler->code != *code) {
+	if (handler->pdu_id != pdu->pdu_id || handler->code != *code) {
 		pdu->params[0] = AVRCP_STATUS_INVALID_COMMAND;
 		goto err_metadata;
 	}
@@ -1734,12 +1734,12 @@ static size_t handle_browsing_pdu(struct avctp *conn,
 
 	for (handler = browsing_handlers; handler->pdu_id; handler++) {
 		if (handler->pdu_id == pdu->pdu_id)
-			break;
+			goto done;
 	}
 
-	if (handler == NULL || handler->func == NULL)
-		return avrcp_browsing_general_reject(operands);
+	return avrcp_browsing_general_reject(operands);
 
+done:
 	session->transaction = transaction;
 	handler->func(session, pdu, transaction);
 	return AVRCP_BROWSING_HEADER_LENGTH + ntohs(pdu->param_len);
-- 
1.8.4.2


^ permalink raw reply related

* Re: [PATCH] avrcp: Fix wrong pointer check
From: Andrei Emeltchenko @ 2014-02-03  9:36 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZ+VPAkfgUNRu6GC9DhkP=KXpTzBC03OVW8nNC_55uaMfg@mail.gmail.com>

On Mon, Feb 03, 2014 at 01:20:11AM -0800, Luiz Augusto von Dentz wrote:
> Hi Andrei,
> 
> On Sun, Feb 2, 2014 at 11:51 PM, Andrei Emeltchenko
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > Hi Luiz,
> >
> > On Sun, Feb 02, 2014 at 08:03:34AM -0800, Luiz Augusto von Dentz wrote:
> >> Hi Andrei,
> >>
> >> On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
> >> <Andrei.Emeltchenko.news@gmail.com> wrote:
> >> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> >> >
> >> > There is wrong assumption that handler might be NULL while it is a
> >> > pointer to a struct table so check instead for struct members. This
> >> > fixes accessing wrong memory.
> >> > ---
> >> >  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 df88138..5030ce1 100644
> >> > --- a/profiles/audio/avrcp.c
> >> > +++ b/profiles/audio/avrcp.c
> >> > @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
> >> >                         break;
> >> >         }
> >> >
> >> > -       if (!handler || handler->code != *code) {
> >> > +       if (!handler->code || handler->code != *code) {
> >>
> >> The code checks if  session->control_handlers is initialized and Im
> >> not sure what is the invalid memory access you are talking about since
> >> handle->code is no a pointer, I do agree that we should probably drop
> >> the second check for the handler in the lines bellow.
> >
> > handler is a pointer, and it points to
> >
> > static const struct control_pdu_handler control_handlers[]
> > table with the last element:
> >
> > ...
> >                 { },
> > };
> > ...
> >
> > So checking for !handler is pointless.
> 
> Right, because checking for pointer is pointless, yes Im being
> sarcastic here... Now lets be clear, you are changing a check of a
> pointer to a value and claiming it fixes invalid accesses which does
> not make any sense, what could make sense is to check if
> handler->pdu_id == pdu->pdu_id since that what we check when we lookup
> for a handle.

No, we break if handler->pdu_id == pdu->pdu_id one line above ;)

Best regards 
Andrei Emeltchenko 

> 
> 
> 
> -- 
> Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH] avrcp: Fix wrong pointer check
From: Luiz Augusto von Dentz @ 2014-02-03  9:20 UTC (permalink / raw)
  To: Andrei Emeltchenko, Luiz Augusto von Dentz,
	linux-bluetooth@vger.kernel.org
In-Reply-To: <20140203074920.GA2930@aemeltch-MOBL1>

Hi Andrei,

On Sun, Feb 2, 2014 at 11:51 PM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> Hi Luiz,
>
> On Sun, Feb 02, 2014 at 08:03:34AM -0800, Luiz Augusto von Dentz wrote:
>> Hi Andrei,
>>
>> On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
>> <Andrei.Emeltchenko.news@gmail.com> wrote:
>> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>> >
>> > There is wrong assumption that handler might be NULL while it is a
>> > pointer to a struct table so check instead for struct members. This
>> > fixes accessing wrong memory.
>> > ---
>> >  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 df88138..5030ce1 100644
>> > --- a/profiles/audio/avrcp.c
>> > +++ b/profiles/audio/avrcp.c
>> > @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
>> >                         break;
>> >         }
>> >
>> > -       if (!handler || handler->code != *code) {
>> > +       if (!handler->code || handler->code != *code) {
>>
>> The code checks if  session->control_handlers is initialized and Im
>> not sure what is the invalid memory access you are talking about since
>> handle->code is no a pointer, I do agree that we should probably drop
>> the second check for the handler in the lines bellow.
>
> handler is a pointer, and it points to
>
> static const struct control_pdu_handler control_handlers[]
> table with the last element:
>
> ...
>                 { },
> };
> ...
>
> So checking for !handler is pointless.

Right, because checking for pointer is pointless, yes Im being
sarcastic here... Now lets be clear, you are changing a check of a
pointer to a value and claiming it fixes invalid accesses which does
not make any sense, what could make sense is to check if
handler->pdu_id == pdu->pdu_id since that what we check when we lookup
for a handle.



-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCHv2] android/avrcp: Decouple AVRCP logic from btio
From: Andrei Emeltchenko @ 2014-02-03  9:16 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391092704-24806-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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 | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 android/avrcp-lib.h | 32 ++++++++++++++++++++
 android/avrcp.c     | 44 ++-------------------------
 5 files changed, 122 insertions(+), 41 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 09ed32d..2772b58 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..a4bfe6d
--- /dev/null
+++ b/android/avrcp-lib.c
@@ -0,0 +1,85 @@
+/*
+ *
+ *  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)
+		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..ff923cb 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,8 +163,7 @@ 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) {
+	if (avrcp_find(&dst)) {
 		error("Unexpected connection");
 		return;
 	}
@@ -274,8 +237,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

* Re: [PATCH] android/avrcp: Decouple AVRCP logic from btio
From: Andrei Emeltchenko @ 2014-02-03  9:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1391092704-24806-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

On Thu, Jan 30, 2014 at 04:38:24PM +0200, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> The patch makes AVRCP to be channel-agnostic so that it might be used in
> unit tests. The idea is that all AVRCP logic would come to avrcp-lib and
> channel stuff got to avrcp.
> ---
>  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) {

will fix this to !l

Best regards 
Andrei Emeltchenko 

^ permalink raw reply

* Re: [PATCH 06/13] android/handsfree: Add SDP record for AG
From: Andrei Emeltchenko @ 2014-02-03  7:56 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1391375364-27106-7-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Sun, Feb 02, 2014 at 10:09:17PM +0100, Szymon Janc wrote:
> Service Name: Hands-Free Audio GatewayService RecHandle: 0x10001
> Service Class ID List:
>   "Handsfree Audio Gateway" (0x111f)
>   "Generic Audio" (0x1203)
> Protocol Descriptor List:
>   "L2CAP" (0x0100)
>   "RFCOMM" (0x0003)
>     Channel: 13
> Profile Descriptor List:
>   "Handsfree" (0x111e)
>     Version: 0x0106
> ---
>  android/handsfree.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 97 insertions(+)
> 
> diff --git a/android/handsfree.c b/android/handsfree.c
> index 3c0d52b..d2dc543 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -29,12 +29,19 @@
>  #include <glib.h>
>  
>  #include "lib/bluetooth.h"
> +#include "lib/sdp.h"
> +#include "lib/sdp_lib.h"
>  #include "handsfree.h"
> +#include "bluetooth.h"
>  #include "src/log.h"
>  #include "hal-msg.h"
>  #include "ipc.h"
>  
> +#define HFP_AG_CHANNEL 13
> +#define HFP_AG_FEATURES 0
> +
>  static bdaddr_t adapter_addr;
> +static uint32_t record_id = 0;
>  
>  static void handle_connect(const void *buf, uint16_t len)
>  {
> @@ -189,12 +196,99 @@ static const struct ipc_handler cmd_handlers[] = {
>  			sizeof(struct hal_cmd_handsfree_phone_state_change)},
>  };
>  
> +static sdp_record_t *handsfree_ag_record(void)
> +{
> +	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
> +	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
> +	uuid_t l2cap_uuid, rfcomm_uuid;
> +	sdp_profile_desc_t profile;
> +	sdp_list_t *aproto, *proto[2];
> +	sdp_record_t *record;
> +	sdp_data_t *channel, *features;
> +	uint8_t netid = 0x01;
> +	uint16_t sdpfeat;
> +	sdp_data_t *network;
> +	uint8_t ch = HFP_AG_CHANNEL;
> +
> +	record = sdp_record_alloc();
> +	if (!record)
> +		return NULL;
> +
> +	network = sdp_data_alloc(SDP_UINT8, &netid);
> +	if (!network) {
> +		sdp_record_free(record);
> +		return NULL;
> +	}
> +
> +	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> +	root = sdp_list_append(0, &root_uuid);
> +	sdp_set_browse_groups(record, root);
> +
> +	sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
> +	svclass_id = sdp_list_append(0, &svclass_uuid);
> +	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
> +	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
> +	sdp_set_service_classes(record, svclass_id);
> +
> +	sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
> +	profile.version = 0x0106;
> +	pfseq = sdp_list_append(0, &profile);
> +	sdp_set_profile_descs(record, pfseq);
> +
> +	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
> +	proto[0] = sdp_list_append(0, &l2cap_uuid);
> +	apseq = sdp_list_append(0, proto[0]);
> +
> +	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> +	proto[1] = sdp_list_append(0, &rfcomm_uuid);
> +	channel = sdp_data_alloc(SDP_UINT8, &ch);
> +	proto[1] = sdp_list_append(proto[1], channel);
> +	apseq = sdp_list_append(apseq, proto[1]);
> +
> +	sdpfeat = HFP_AG_FEATURES;
> +	features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
> +	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
> +
> +	aproto = sdp_list_append(0, apseq);
> +	sdp_set_access_protos(record, aproto);
> +
> +	sdp_set_info_attr(record, "Hands-Free Audio Gateway", 0, 0);
> +
> +	sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
> +
> +	sdp_data_free(channel);
> +	sdp_list_free(proto[0], 0);

We have agreed to use NULL for zero pointers.

Best regards 
Andrei Emeltchenko 


^ permalink raw reply

* Re: [PATCH] avrcp: Fix wrong pointer check
From: Andrei Emeltchenko @ 2014-02-03  7:51 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZ+-mc_u+ihj_FB5e89TNmBgZvyWxW4vwMCuFDh1_TjCJg@mail.gmail.com>

Hi Luiz,

On Sun, Feb 02, 2014 at 08:03:34AM -0800, Luiz Augusto von Dentz wrote:
> Hi Andrei,
> 
> On Fri, Jan 31, 2014 at 12:33 AM, Andrei Emeltchenko
> <Andrei.Emeltchenko.news@gmail.com> wrote:
> > From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> >
> > There is wrong assumption that handler might be NULL while it is a
> > pointer to a struct table so check instead for struct members. This
> > fixes accessing wrong memory.
> > ---
> >  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 df88138..5030ce1 100644
> > --- a/profiles/audio/avrcp.c
> > +++ b/profiles/audio/avrcp.c
> > @@ -1673,7 +1673,7 @@ static size_t handle_vendordep_pdu(struct avctp *conn, uint8_t transaction,
> >                         break;
> >         }
> >
> > -       if (!handler || handler->code != *code) {
> > +       if (!handler->code || handler->code != *code) {
> 
> The code checks if  session->control_handlers is initialized and Im
> not sure what is the invalid memory access you are talking about since
> handle->code is no a pointer, I do agree that we should probably drop
> the second check for the handler in the lines bellow.

handler is a pointer, and it points to

static const struct control_pdu_handler control_handlers[] 
table with the last element:

...
		{ },
};
...

So checking for !handler is pointless.

Best regards 
Andrei Emeltchenko 

^ permalink raw reply

* [PATCH] pbap: Fix PhonebookSize endianness
From: Hannu Mallat @ 2014-02-03  7:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Hannu Mallat

As g_obex_apparam_set_uint16() converts data to big-endian format
internally, do not call htons() prior to it.
---
 obexd/plugins/pbap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c
index 4740188..acac3aa 100644
--- a/obexd/plugins/pbap.c
+++ b/obexd/plugins/pbap.c
@@ -188,7 +188,7 @@ static void phonebook_size_result(const char *buffer, size_t bufsize,
 
 	DBG("vcards %d", vcards);
 
-	phonebooksize = htons(vcards);
+	phonebooksize = vcards;
 
 	pbap->obj->apparam = g_obex_apparam_set_uint16(NULL, PHONEBOOKSIZE_TAG,
 								phonebooksize);
@@ -365,7 +365,7 @@ static int generate_response(void *user_data)
 
 	if (max == 0) {
 		/* Ignore all other parameter and return PhoneBookSize */
-		uint16_t size = htons(g_slist_length(pbap->cache.entries));
+		uint16_t size = g_slist_length(pbap->cache.entries);
 
 		pbap->obj->apparam = g_obex_apparam_set_uint16(
 							pbap->obj->apparam,
-- 
1.8.5.3


^ permalink raw reply related

* AVRCP profile/plugin in bluez 5
From: Serkan Kaba @ 2014-02-03  6:52 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org

Hi,

I was trying to get my GTK-N1BT hi-fi system. It was constantly bailing "UUIDs has unsupported type" errors and disconnecting after the pairing. All the online examples were referring to bluez 4 config (audio.conf) which even in 4 it was hard to get it working. I added the following in "General" section of audio.conf
<code>
Enable=Media,Sink,Source

</code>
and got it working

I couldn't figure out enabling avrcp profile with bluez 5. Please help

^ permalink raw reply

* [PATCH 13/13] android/handsfree: Add support for AT+CMER command
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

---
 android/handsfree.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/android/handsfree.c b/android/handsfree.c
index 02135cb..bf6a575 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -63,6 +63,7 @@ static struct {
 	struct hfp_gw *gw;
 
 	uint32_t features;
+	bool ind_notif_active;
 } device;
 
 static bdaddr_t adapter_addr;
@@ -172,6 +173,30 @@ static bool at_cind(const char *at)
 	return false;
 }
 
+static bool at_cmer(const char *at)
+{
+	unsigned int mode, ind;
+	int ret;
+
+	DBG("");
+
+	ret = sscanf(at, " = %u, %*u, %*u, %u", &mode, &ind);
+	if (ret != 2 || mode != 3 || ind > 1) {
+		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
+		return false;
+	}
+
+	device.ind_notif_active = ind;
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+	/* TODO Check for 3-way calling support */
+	device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_SLC_CONNECTED);
+
+	return true;
+}
+
 static const struct {
 	const char *prefix;
 	int prefix_len;
@@ -179,6 +204,7 @@ static const struct {
 } at_cmds[] = {
 	{ "+BRSF", sizeof("+BRSF") - 1, at_brsf },
 	{ "+CIND", sizeof("+CIND") - 1, at_cind },
+	{ "+CMER", sizeof("+CMER") - 1, at_cmer },
 };
 
 static void at_command_handler(const char *command, void *user_data)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 12/13] android/handsfree: Add support for AT+CIND command
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

Android supports only fixed number of indicators so this is all static
for now.
---
 android/handsfree.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 990ba2f..02135cb 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -51,6 +51,10 @@
 
 #define AG_FEATURES 0
 
+#define CIND_SUPPORT_STR "+CIND: (\"service\",(0,1)),(\"call\",(0,1)),\
+			(\"callsetup\",(0-3)),(\"callheld\",(0-2)),\
+			(\"signal\",(0-5)),(\"roam\",(0,1)),(\"battchg\",(0,1))"
+
 static struct {
 	bdaddr_t bdaddr;
 	uint8_t state;
@@ -146,12 +150,35 @@ static bool at_brsf(const char *at)
 	return true;
 }
 
+static bool at_cind(const char *at)
+{
+	if (strcmp(at, "?")) {
+		ipc_send_notif(HAL_SERVICE_ID_HANDSFREE, HAL_EV_HANDSFREE_CIND,
+								0, NULL);
+
+		return true;
+	}
+
+	if (strcmp(at, "=?")) {
+		hfp_gw_send_info(device.gw, "%s", CIND_SUPPORT_STR);
+
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return true;
+	}
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
+	return false;
+}
+
 static const struct {
 	const char *prefix;
 	int prefix_len;
 	bool (*func)(const char *at_cmds);
 } at_cmds[] = {
 	{ "+BRSF", sizeof("+BRSF") - 1, at_brsf },
+	{ "+CIND", sizeof("+CIND") - 1, at_cind },
 };
 
 static void at_command_handler(const char *command, void *user_data)
@@ -466,12 +493,41 @@ static void handle_cops(const void *buf, uint16_t len)
 							HAL_STATUS_FAILED);
 }
 
+static unsigned int get_callsetup(uint8_t state)
+{
+	switch (state) {
+	case HAL_HANDSFREE_CALL_STATE_INCOMING:
+		return 1;
+	case HAL_HANDSFREE_CALL_STATE_DIALING:
+		return 2;
+	case HAL_HANDSFREE_CALL_STATE_ALERTING:
+		return 3;
+	default:
+		return 0;
+	}
+}
+
 static void handle_cind(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_cind_response *cmd = buf;
+
 	DBG("");
 
+	/* HAL doesn't provide CIND values directly so need to convert here */
+
+	hfp_gw_send_info(device.gw, "+CIND: %u,%u,%u,%u,%u,%u,%u",
+				cmd->svc,
+				!!(cmd->num_active + cmd->num_held),
+				get_callsetup(cmd->state),
+				cmd->num_held ? (cmd->num_active ? 1 : 2) : 0,
+				cmd->signal,
+				cmd->roam,
+				cmd->batt_chg);
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
 	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CIND_RESPONSE,
-							HAL_STATUS_FAILED);
+							HAL_STATUS_SUCCESS);
 }
 
 static void handle_formatted_at_resp(const void *buf, uint16_t len)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 11/13] android/handsfree: Add AT+BRSF command support
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

---
 android/handsfree.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 5fe7638..990ba2f 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -49,12 +49,16 @@
 #define HFP_AG_CHANNEL 13
 #define HFP_AG_FEATURES 0
 
+#define AG_FEATURES 0
+
 static struct {
 	bdaddr_t bdaddr;
 	uint8_t state;
 	GIOChannel *io;
 	guint watch;
 	struct hfp_gw *gw;
+
+	uint32_t features;
 } device;
 
 static bdaddr_t adapter_addr;
@@ -123,11 +127,69 @@ static gboolean watch_cb(GIOChannel *chan, GIOCondition cond,
 	return FALSE;
 }
 
+static bool at_brsf(const char *at)
+{
+	uint32_t feat;
+
+	if (sscanf(at, " = %u", &feat) != 1) {
+		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+		return false;
+	}
+
+	/* TODO verify features */
+	device.features = feat;
+
+	hfp_gw_send_info(device.gw, "+BRSF=%u", AG_FEATURES);
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+	return true;
+}
+
+static const struct {
+	const char *prefix;
+	int prefix_len;
+	bool (*func)(const char *at_cmds);
+} at_cmds[] = {
+	{ "+BRSF", sizeof("+BRSF") - 1, at_brsf },
+};
+
 static void at_command_handler(const char *command, void *user_data)
 {
+	unsigned int i;
+
+	if (strlen(command) < 3)
+		goto error;
+
+	if (strncmp(command, "AT", sizeof("AT") - 1))
+		goto error;
+
+	command += sizeof("AT") - 1;
+
+	for (i = 0; i < G_N_ELEMENTS(at_cmds); i++) {
+		if (strncmp(command, at_cmds[i].prefix, at_cmds[i].prefix_len))
+			continue;
+
+		command += at_cmds[i].prefix_len;
+
+		if (at_cmds[i].func(command))
+			return;
+
+		goto check_slc;
+	}
+
+error:
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 
-	g_io_channel_shutdown(device.io, TRUE, NULL);
+check_slc:
+	/* Error while establishing SLC */
+	if (device.state != HAL_EV_HANDSFREE_CONNECTION_STATE_SLC_CONNECTED)
+		g_io_channel_shutdown(device.io, TRUE, NULL);
+}
+
+static void hfp_gw_debug(const char *str, void *user_data)
+{
+	DBG("%s", str);
 }
 
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
@@ -148,6 +210,8 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	hfp_gw_set_close_on_unref(device.gw, true);
 	hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
 
+	hfp_gw_set_debug(device.gw, hfp_gw_debug, NULL, NULL);
+
 	device.watch = g_io_add_watch(chan,
 					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
 					watch_cb, NULL);
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 10/13] android/handsfree: Add disconnect command handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

---
 android/handsfree.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 79e61b4..5fe7638 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -311,10 +311,38 @@ failed:
 
 static void handle_disconnect(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_disconnect *cmd = buf;
+	bdaddr_t bdaddr;
+	uint8_t status;
+
 	DBG("");
 
+	android2bdaddr(cmd->bdaddr, &bdaddr);
+
+	if (device.state == HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED ||
+			bacmp(&device.bdaddr, &bdaddr)) {
+		status = HAL_STATUS_FAILED;
+		goto failed;
+
+	}
+
+	if (device.state == HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING) {
+		status = HAL_STATUS_SUCCESS;
+		goto failed;
+	}
+
+	if (device.io) {
+		device_set_state(HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTING);
+		g_io_channel_shutdown(device.io, TRUE, NULL);
+	} else {
+		device_cleanup();
+	}
+
+	status = HAL_STATUS_SUCCESS;
+
+failed:
 	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_DISCONNECT,
-							HAL_STATUS_FAILED);
+									status);
 }
 
 static void handle_connect_audio(const void *buf, uint16_t len)
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 09/13] android/handsfree: Add connect command handling
From: Szymon Janc @ 2014-02-02 21:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1391375364-27106-1-git-send-email-szymon.janc@tieto.com>

This allows to query SDP for RFCOMM channel and connect.
---
 android/handsfree.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 100 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index a4ce398..79e61b4 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -202,12 +202,111 @@ drop:
 	g_io_channel_shutdown(chan, TRUE, NULL);
 }
 
+static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
+{
+	sdp_list_t *protos, *classes;
+	GError *gerr = NULL;
+	GIOChannel *io;
+	uuid_t uuid;
+	int channel;
+
+	DBG("");
+
+	if (err < 0) {
+		error("handsfree: unable to get SDP record: %s", strerror(-err));
+		goto fail;
+	}
+
+	if (!recs || !recs->data) {
+		error("handsfree: no SDP records found");
+		goto fail;
+	}
+
+	if (sdp_get_service_classes(recs->data, &classes) < 0) {
+		error("handsfree: unable to get service classes from record");
+		goto fail;
+	}
+
+	if (sdp_get_access_protos(recs->data, &protos) < 0) {
+		error("handsfree: unable to get access protocols from record");
+		goto fail;
+	}
+
+	/* TODO read remote version? */
+
+	memcpy(&uuid, classes->data, sizeof(uuid));
+	sdp_list_free(classes, free);
+
+	if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
+			uuid.value.uuid16 != HANDSFREE_SVCLASS_ID) {
+		sdp_list_free(protos, NULL);
+		error("handsfree: invalid service record or not HFP");
+		goto fail;
+	}
+
+	channel = sdp_get_proto_port(protos, RFCOMM_UUID);
+	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
+	sdp_list_free(protos, NULL);
+	if (channel <= 0) {
+		error("handsfree: unable to get RFCOMM channel from record");
+		goto fail;
+	}
+
+	io = bt_io_connect(connect_cb, NULL, NULL, &gerr,
+				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+				BT_IO_OPT_DEST_BDADDR, &device.bdaddr,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+				BT_IO_OPT_CHANNEL, channel,
+				BT_IO_OPT_INVALID);
+	if (!io) {
+		error("handsfree: unable to connect: %s", gerr->message);
+		g_error_free(gerr);
+		goto fail;
+	}
+
+	g_io_channel_unref(io);
+	return;
+
+fail:
+	device_cleanup();
+}
+
 static void handle_connect(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_connect *cmd = buf;
+	char addr[18];
+	uint8_t status;
+	uuid_t uuid;
+	bdaddr_t bdaddr;
+
 	DBG("");
 
+	if (device.state != HAL_EV_HANDSFREE_CONNECTION_STATE_DISCONNECTED) {
+		status = HAL_STATUS_FAILED;
+		goto failed;
+	}
+
+	android2bdaddr(&cmd->bdaddr, &bdaddr);
+
+	ba2str(&device.bdaddr, addr);
+	DBG("connecting to %s", addr);
+
+	device_init(&bdaddr);
+
+	bt_string2uuid(&uuid, HFP_HS_UUID);
+	if (bt_search_service(&adapter_addr, &device.bdaddr, &uuid,
+					sdp_search_cb, NULL, NULL, 0) < 0) {
+		error("handsfree: SDP search failed");
+		device_cleanup();
+		status = HAL_STATUS_FAILED;
+		goto failed;
+	}
+
+	status = HAL_STATUS_SUCCESS;
+
+failed:
 	ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
-							HAL_STATUS_FAILED);
+									status);
 }
 
 static void handle_disconnect(const void *buf, uint16_t len)
-- 
1.8.5.3


^ 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