Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH BlueZ 0/2] Basic [sg]etsockopt() testing in l2cap-tester
From: Anderson Lizardo @ 2014-01-25  2:50 UTC (permalink / raw)
  To: BlueZ development; +Cc: Anderson Lizardo
In-Reply-To: <CAJdJm_NYECBW1hH+PmYtQqoBL-_279_hjfgqWD8i85bi9nHJiw@mail.gmail.com>

Hi again,

On Fri, Jan 24, 2014 at 10:00 PM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> Actually I know why they fail: the tests try to use a PSM (and not
> CID) on a single mode LE adapter. I just don't understand why this is
> expected to work.

I now realise that this has to do with LE CoC. Would it be okay to
make l2cap-tester check for
/sys/module/bluetooth/parameters/enable_lecoc at test setup and if it
contains "N", skip the test?

Best Regards,
-- 
Anderson Lizardo
INdT - Manaus - Brazil

^ permalink raw reply

* [PATCH 1/3] Bluetooth: Fix BT_SECURITY socket option for fixed channels (ATT)
From: johan.hedberg @ 2014-01-25 22:10 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@intel.com>

The BT_SECURITY option should also be allowed for fixed channels, so
punch the appropriate hole for it when checking for the channel type.
The main user of fixed CID user space sockets is right now ATT (which is
broken without this patch).

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/l2cap_sock.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 3f8e2a223474..588d43b1c18e 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -513,6 +513,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
 	switch (optname) {
 	case BT_SECURITY:
 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+		    chan->chan_type != L2CAP_CHAN_FIXED &&
 		    chan->chan_type != L2CAP_CHAN_RAW) {
 			err = -EINVAL;
 			break;
@@ -769,6 +770,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 	switch (optname) {
 	case BT_SECURITY:
 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+		    chan->chan_type != L2CAP_CHAN_FIXED &&
 		    chan->chan_type != L2CAP_CHAN_RAW) {
 			err = -EINVAL;
 			break;
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 2/3] Bluetooth: Fix freeing l2cap_chan while it's locked
From: johan.hedberg @ 2014-01-25 22:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1390687809-14408-1-git-send-email-johan.hedberg@gmail.com>

From: Johan Hedberg <johan.hedberg@intel.com>

There's a race condition where it's possible that user space closes the
socket right at the moment that the kernel is inside some L2CAP
signaling channel handler with the lock held for the l2cap_chan tied to
the socket. When the race occurs it can look as follows:

 WARNING: CPU: 1 PID: 2395 at kernel/locking/mutex.c:565 __mutex_lock_slowpath+0x1ff/0x26a()
 DEBUG_LOCKS_WARN_ON(l->magic != l)
 CPU: 1 PID: 2395 Comm: kworker/u5:1 Not tainted 3.12.0+ #224
 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
 Workqueue: hci0 hci_rx_work
  00000007 00000000 ed74dcd0 c1344099 ed74dcf8 ed74dce8 c1028b29 c1346891
  ed5e0b80 00000246 f61d7600 ed74dd00 c1028b88 00000009 ed74dcf8 c13fd4cc
  ed74dd14 ed74dd50 c1346891 c13fd4e4 00000235 c13fd4cc c13fd50a 5a5a5a5a
 Call Trace:
  [<c1344099>] dump_stack+0x48/0x60
  [<c1028b29>] warn_slowpath_common+0x57/0x6e
  [<c1346891>] ? __mutex_lock_slowpath+0x1ff/0x26a
  [<c1028b88>] warn_slowpath_fmt+0x26/0x2a
  [<c1346891>] __mutex_lock_slowpath+0x1ff/0x26a
  [<c134691f>] mutex_lock+0x23/0x2f
  [<c130e79a>] l2cap_get_chan_by_scid+0x32/0x40
  [<c13143cb>] l2cap_config_req+0x6d/0x78f
  [<c1009486>] ? save_stack_trace+0x1d/0x3b
  [<c10915c2>] ? set_track+0x48/0xa7
  [<c134312b>] ? free_debug_processing+0x134/0x16b
  [<c1006019>] ? native_sched_clock+0x37/0x3a
  [<c1315107>] l2cap_recv_frame+0x2f2/0x1a85
  [<c1315107>] ? l2cap_recv_frame+0x2f2/0x1a85
  [<c1317913>] l2cap_recv_acldata+0xe8/0x239
  [<c1317913>] ? l2cap_recv_acldata+0xe8/0x239
  [<c12fa470>] hci_rx_work+0x1b0/0x295
  [<c13465d9>] ? mutex_unlock+0x8/0xa
  [<c12fa470>] ? hci_rx_work+0x1b0/0x295
  [<c103592c>] ? pwq_activate_delayed_work+0x1c/0x27
  [<c1036d25>] process_one_work+0x128/0x1df
  [<c1347401>] ? _raw_spin_unlock_irq+0x8/0x12
  [<c1036d25>] ? process_one_work+0x128/0x1df
  [<c103713a>] worker_thread+0x127/0x1c4
  [<c1037013>] ? rescuer_thread+0x216/0x216
  [<c103aec6>] kthread+0x88/0x8d
  [<c1040000>] ? task_rq_lock+0x37/0x6e
  [<c1347e77>] ret_from_kernel_thread+0x1b/0x28
  [<c103ae3e>] ? __kthread_parkme+0x50/0x50
 ---[ end trace 81d41a8e15d9559e ]---
 =============================================================================
 BUG kmalloc-1024 (Tainted: G        W   ): Poison overwritten
 -----------------------------------------------------------------------------
 INFO: 0xed5e0b80-0xed5e0b85. First byte 0xff instead of 0x6b
 INFO: Allocated in l2cap_chan_create+0x1f/0xf9 age=9986 cpu=1 pid=2395
 	__slab_alloc.constprop.66+0x1c5/0x36e
 	kmem_cache_alloc+0x54/0xb4
 	l2cap_chan_create+0x1f/0xf9
 	l2cap_sock_alloc.constprop.5+0x73/0x9b
 	l2cap_sock_new_connection_cb+0x5d/0x95
 	l2cap_connect+0x112/0x3a0
 	l2cap_recv_frame+0x534/0x1a85
 	process_pending_rx+0x48/0x56
 	process_one_work+0x128/0x1df
 	worker_thread+0x127/0x1c4
 	kthread+0x88/0x8d
 	ret_from_kernel_thread+0x1b/0x28
 INFO: Freed in l2cap_chan_destroy+0x59/0x65 age=9986 cpu=0 pid=2363
 	__slab_free+0x3c/0x260
 	kfree+0xb3/0xbc
 	l2cap_chan_destroy+0x59/0x65
 	kref_put+0x2a/0x33
 	l2cap_chan_put+0x3f/0x4a
 	l2cap_sock_destruct+0x3d/0x77
 	__sk_free+0x20/0x116
 	sk_free+0x1c/0x1f
 	l2cap_sock_kill+0x6f/0x74
 	l2cap_sock_teardown_cb+0xc1/0x119
 	l2cap_chan_close+0x186/0x192
 	l2cap_sock_shutdown+0x1af/0x214
 	l2cap_sock_release+0x56/0xa2
 	sock_release+0x10/0x55
 	sock_close+0xb/0xf
 	__fput+0xd3/0x175

This patch fixes the race by acquiring the l2cap_chan lock in
l2cap_chan_destroy before removing the channel from the global list.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/l2cap_core.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index e5c5c7427c41..3a9917be6c6e 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -442,10 +442,14 @@ static void l2cap_chan_destroy(struct kref *kref)
 
 	BT_DBG("chan %p", chan);
 
+	l2cap_chan_lock(chan);
+
 	write_lock(&chan_list_lock);
 	list_del(&chan->global_l);
 	write_unlock(&chan_list_lock);
 
+	l2cap_chan_unlock(chan);
+
 	kfree(chan);
 }
 
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH 3/3] Bluetooth: Fix CID initialization for fixed channels
From: johan.hedberg @ 2014-01-25 22:10 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1390687809-14408-1-git-send-email-johan.hedberg@gmail.com>

From: Johan Hedberg <johan.hedberg@intel.com>

Fixed channels have the same source and destination CID. Ensure that the
values get properly initialized when receiving incoming connections and
deriving values from the parent socket.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
 net/bluetooth/l2cap_core.c | 2 --
 net/bluetooth/l2cap_sock.c | 5 +++++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3a9917be6c6e..f86e98c47094 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1466,8 +1466,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 	if (!chan)
 		goto clean;
 
-	chan->dcid = L2CAP_CID_ATT;
-
 	bacpy(&chan->src, &hcon->src);
 	bacpy(&chan->dst, &hcon->dst);
 	chan->src_type = bdaddr_type(hcon, hcon->src_type);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 588d43b1c18e..304fc8589af4 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1470,6 +1470,11 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
 		chan->tx_credits = pchan->tx_credits;
 		chan->rx_credits = pchan->rx_credits;
 
+		if (chan->chan_type == L2CAP_CHAN_FIXED) {
+			chan->scid = pchan->scid;
+			chan->dcid = pchan->scid;
+		}
+
 		security_sk_clone(parent, sk);
 	} else {
 		switch (sk->sk_type) {
-- 
1.8.5.3


^ permalink raw reply related

* Re: [PATCH BlueZ 0/2] Basic [sg]etsockopt() testing in l2cap-tester
From: Johan Hedberg @ 2014-01-25 22:12 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1390614842-28379-1-git-send-email-anderson.lizardo@openbossa.org>

Hi Lizardo,

On Fri, Jan 24, 2014, Anderson Lizardo wrote:
> These patches extend existing tests in l2cap-tester to exercise two common
> operations on LE sockets:
> 
> * getsockopt(BT_SECURITY) on client side (to set security level)
> * setsockopt(L2CAP_OPTIONS) on server side (called by bt_io_get())
> 
> At the moment, there is a regression on kernel introduced by commit
> a5a1e0e6b9c1dea3696192b5ec153d03917eb7b8 ("Bluetooth: Switch ATT channels to
> use L2CAP_CHAN_FIXED") which is affecting these two operations. I'm currently
> implementing and testing fixes for this regression.

I pushed your first patch and a slightly different version of the
second one which is more thorough in its checks. I also sent fixes for
the kernel side so you don't need to spend more time on that (unless you
disagree with the fixes I sent).

Johan

^ permalink raw reply

* Re: [PATCH] Rename adapter_remove_device to btd_adapter_remove_device
From: Johan Hedberg @ 2014-01-25 22:13 UTC (permalink / raw)
  To: Petri Gynther; +Cc: linux-bluetooth
In-Reply-To: <20140125005506.7AD85100900@puck.mtv.corp.google.com>

Hi Petri,

On Fri, Jan 24, 2014, Petri Gynther wrote:
> Allow this symbol to be exported and usable from external plugins.
> ---
>  src/adapter.c | 14 +++++++-------
>  src/adapter.h |  3 +++
>  2 files changed, 10 insertions(+), 7 deletions(-)

The patch looks fine, but we usually don't export symbols without
knowing that there exists a valid use case for it. So could you perhaps
give some background (or even a follow-up patch) to explain what you
need this for?

Johan

^ permalink raw reply

* Re: [PATCH BlueZ 0/2] Basic [sg]etsockopt() testing in l2cap-tester
From: Anderson Lizardo @ 2014-01-25 22:48 UTC (permalink / raw)
  To: Anderson Lizardo, BlueZ development
In-Reply-To: <20140125221203.GA14531@x220.p-661hnu-f1>

Hi Johan,

On Sat, Jan 25, 2014 at 6:12 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> I pushed your first patch and a slightly different version of the
> second one which is more thorough in its checks. I also sent fixes for
> the kernel side so you don't need to spend more time on that (unless you
> disagree with the fixes I sent).

Thanks! I looked at the patches and I have no comments. Will do tests
and report problems (if any).

What about the suggestion to make l2cap-tester check if LE CoC is
enabled on the kernel and skip the the tests that depend on it? Right
now, the tests simply fail which is misleading (at first I thought it
was a regression).

Another option is to change the test name to mention that they require
enabling LE CoC.

Best Regards,
-- 
Anderson Lizardo
INdT - Manaus - Brazil

^ permalink raw reply

* Re: [PATCH 2/3] Bluetooth: Fix freeing l2cap_chan while it's locked
From: Johan Hedberg @ 2014-01-25 23:08 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1390687809-14408-2-git-send-email-johan.hedberg@gmail.com>

Hi,

On Sat, Jan 25, 2014, johan.hedberg@gmail.com wrote:
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -442,10 +442,14 @@ static void l2cap_chan_destroy(struct kref *kref)
>  
>  	BT_DBG("chan %p", chan);
>  
> +	l2cap_chan_lock(chan);
> +
>  	write_lock(&chan_list_lock);
>  	list_del(&chan->global_l);
>  	write_unlock(&chan_list_lock);
>  
> +	l2cap_chan_unlock(chan);
> +
>  	kfree(chan);
>  }

Please hold on a bit with this patch. The other two in the set should be
good to go though.

Since the race is hard to reproduce I'm not 100% sure this actually
fixes it. Looking at l2cap_get_chan_by_scid holding the lock should not
prevent it from returning the channel.

Johan

^ permalink raw reply

* Re: [PATCH BlueZ 0/2] Basic [sg]etsockopt() testing in l2cap-tester
From: Johan Hedberg @ 2014-01-25 23:13 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: BlueZ development
In-Reply-To: <CAJdJm_PPeA-DHfFPKi=iwjb_Kc4rrU8zY6SgX-G_O9ts3wCaZw@mail.gmail.com>

Hi Lizardo,

On Sat, Jan 25, 2014, Anderson Lizardo wrote:
> On Sat, Jan 25, 2014 at 6:12 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> > I pushed your first patch and a slightly different version of the
> > second one which is more thorough in its checks. I also sent fixes for
> > the kernel side so you don't need to spend more time on that (unless you
> > disagree with the fixes I sent).
> 
> Thanks! I looked at the patches and I have no comments. Will do tests
> and report problems (if any).
> 
> What about the suggestion to make l2cap-tester check if LE CoC is
> enabled on the kernel and skip the the tests that depend on it? Right
> now, the tests simply fail which is misleading (at first I thought it
> was a regression).
> 
> Another option is to change the test name to mention that they require
> enabling LE CoC.

This has never bothered me much since the assumption is that mainly
developers would be running these tools and therefore know the
implications and requirements. I have a feeling that adding this kind of
checks might be a bit overkill, especially since this debugfs entry will
disappear as soon as we do one more test run at the UPF next week. After
that LE CoC support will always be there if you've got a new enough
kernel.

Johan

^ permalink raw reply

* Re: [PATCH BlueZ 0/2] Basic [sg]etsockopt() testing in l2cap-tester
From: Anderson Lizardo @ 2014-01-25 23:16 UTC (permalink / raw)
  To: Anderson Lizardo, BlueZ development
In-Reply-To: <20140125231309.GB16167@x220.p-661hnu-f1>

Hi Johan,

On Sat, Jan 25, 2014 at 7:13 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
>> What about the suggestion to make l2cap-tester check if LE CoC is
>> enabled on the kernel and skip the the tests that depend on it? Right
>> now, the tests simply fail which is misleading (at first I thought it
>> was a regression).
>>
>> Another option is to change the test name to mention that they require
>> enabling LE CoC.
>
> This has never bothered me much since the assumption is that mainly
> developers would be running these tools and therefore know the
> implications and requirements. I have a feeling that adding this kind of
> checks might be a bit overkill, especially since this debugfs entry will
> disappear as soon as we do one more test run at the UPF next week. After
> that LE CoC support will always be there if you've got a new enough
> kernel.

If the are plans to have this option removed real soon, no problem for me then.

Best Regards,
-- 
Anderson Lizardo
INdT - Manaus - Brazil

^ permalink raw reply

* [PATCH BlueZ 1/2] unit/test-ringbuf: Fix indentation
From: Anderson Lizardo @ 2014-01-26  1:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo

---
 unit/test-ringbuf.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/unit/test-ringbuf.c b/unit/test-ringbuf.c
index a19216f..e63321c 100644
--- a/unit/test-ringbuf.c
+++ b/unit/test-ringbuf.c
@@ -41,7 +41,8 @@ static unsigned int nlpo2(unsigned int x)
 	x |= (x >> 4);
 	x |= (x >> 8);
 	x |= (x >> 16);
-        return x + 1;
+
+	return x + 1;
 }
 
 static unsigned int align_power2(unsigned int u)
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH BlueZ 2/2] shared: Fix undefined behavior when calculating next power of two
From: Anderson Lizardo @ 2014-01-26  1:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1390700061-18666-1-git-send-email-anderson.lizardo@openbossa.org>

According to GCC documentation, __builtin_clz() is undefined if argument
is zero. The following problem was detected when compiling with -O0:

ERROR:unit/test-ringbuf.c:70:test_power2: assertion failed: (size1 ==
size2)

Also refactor align_power2() so the internal "find last set bit"
operation is in its own fls() function (similar to how kernel does).
fls() checks if argument is zero before calling __builtin_clz().
---
 src/shared/ringbuf.c | 9 ++++++++-
 unit/test-ringbuf.c  | 7 ++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/shared/ringbuf.c b/src/shared/ringbuf.c
index 3e5c7d3..f9c4376 100644
--- a/src/shared/ringbuf.c
+++ b/src/shared/ringbuf.c
@@ -48,9 +48,16 @@ struct ringbuf {
 
 #define RINGBUF_RESET 0
 
+/* Find last (most siginificant) set bit */
+static inline unsigned int fls(unsigned int x)
+{
+	return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
+}
+
+/* Round up to nearest power of two */
 static inline unsigned int align_power2(unsigned int u)
 {
-	return 1 << ((sizeof(u) * 8) - __builtin_clz(u - 1));
+	return 1 << fls(u - 1);
 }
 
 struct ringbuf *ringbuf_new(size_t size)
diff --git a/unit/test-ringbuf.c b/unit/test-ringbuf.c
index e63321c..75be3a3 100644
--- a/unit/test-ringbuf.c
+++ b/unit/test-ringbuf.c
@@ -45,9 +45,14 @@ static unsigned int nlpo2(unsigned int x)
 	return x + 1;
 }
 
+static unsigned int fls(unsigned int x)
+{
+	return x ? sizeof(x) * 8 - __builtin_clz(x) : 0;
+}
+
 static unsigned int align_power2(unsigned int u)
 {
-	return 1 << ((sizeof(u) * 8) - __builtin_clz(u - 1));
+	return 1 << fls(u - 1);
 }
 
 static void test_power2(void)
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH BlueZ v2 0/4] android: Minor fixes
From: Anderson Lizardo @ 2014-01-26  1:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1390512281-26541-1-git-send-email-anderson.lizardo@openbossa.org>

Hi,

Changes since v1:

* Rebased against current master
* Fixed typo in commit message

This patch set contains 2 patches fixing problems found while trying to run
android-tester on a system with some features disabled on the kernel. Two other
patches are simple cleanups.

Best Regards
Anderson Lizardo

Anderson Lizardo (4):
  android/tester: Fix crash on failure inside setup()
  android: Remove useless extra parenthesis
  android: Trivial replacement of tabs where spaces are expected
  emulator: Fix crash if socket(AF_ALG) is not supported by the kernel

 android/android-tester.c | 91 ++++++++++++++++++++++++++----------------------
 android/bluetooth.c      |  2 +-
 android/hidhost.c        |  2 +-
 android/ipc-tester.c     |  2 +-
 emulator/bthost.c        |  6 ++--
 5 files changed, 56 insertions(+), 47 deletions(-)

-- 
1.8.3.2


^ permalink raw reply

* [PATCH BlueZ 1/4] android/tester: Fix crash on failure inside setup()
From: Anderson Lizardo @ 2014-01-26  1:43 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1390700642-10482-1-git-send-email-anderson.lizardo@openbossa.org>

The various setup_* functions were still continuing even though setup()
failed and did not initialize data->if_bluetooth properly.

Also do a little refactoring by moving tester_setup_failed() calls to
the setup() callers, so they stay close to the other failure points and
not hidden deep into a helper function.

Crash detected by Valgrind:

==4959== Invalid read of size 4
==4959==    at 0x805967A: setup_base (android-tester.c:2029)
==4959==    by 0x8055541: setup_callback (tester.c:373)
==4959==    by 0x408348F: g_idle_dispatch (gmain.c:5250)
==4959==    by 0x4086A75: g_main_context_dispatch (gmain.c:3065)
==4959==    by 0x4086E14: g_main_context_iterate.isra.23 (gmain.c:3712)
==4959==    by 0x40872FA: g_main_loop_run (gmain.c:3906)
==4959==    by 0x41744D2: (below main) (libc-start.c:226)
==4959==  Address 0x4 is not stack'd, malloc'd or (recently) free'd
---
 android/android-tester.c | 85 ++++++++++++++++++++++++++----------------------
 1 file changed, 46 insertions(+), 39 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index aa953bf..e4f95ce 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -1951,8 +1951,7 @@ static bt_callbacks_t bt_callbacks = {
 	.le_test_mode_cb = NULL
 };
 
-
-static void setup(struct test_data *data)
+static bool setup(struct test_data *data)
 {
 	const hw_module_t *module;
 	hw_device_t *device;
@@ -1962,18 +1961,15 @@ static void setup(struct test_data *data)
 	int len;
 	int err;
 
-	if (pipe(signal_fd)) {
-		tester_setup_failed();
-		return;
-	}
+	if (pipe(signal_fd))
+		return false;
 
 	pid = fork();
 
 	if (pid < 0) {
 		close(signal_fd[0]);
 		close(signal_fd[1]);
-		tester_setup_failed();
-		return;
+		return false;
 	}
 
 	if (pid == 0) {
@@ -1991,32 +1987,27 @@ static void setup(struct test_data *data)
 	len = read(signal_fd[0], buf, sizeof(buf));
 	if (len <= 0 || (strcmp(buf, EMULATOR_SIGNAL))) {
 		close(signal_fd[0]);
-		tester_setup_failed();
-		return;
+		return false;
 	}
 
 	close(signal_fd[0]);
 
 	err = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
-	if (err) {
-		tester_setup_failed();
-		return;
-	}
+	if (err)
+		return false;
 
 	err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
-	if (err) {
-		tester_setup_failed();
-		return;
-	}
+	if (err)
+		return false;
 
 	data->device = device;
 
 	data->if_bluetooth = ((bluetooth_device_t *)
 					device)->get_bluetooth_interface();
-	if (!data->if_bluetooth) {
-		tester_setup_failed();
-		return;
-	}
+	if (!data->if_bluetooth)
+		return false;
+
+	return true;
 }
 
 static void setup_base(const void *test_data)
@@ -2024,7 +2015,10 @@ static void setup_base(const void *test_data)
 	struct test_data *data = tester_get_data();
 	bt_status_t status;
 
-	setup(data);
+	if (!setup(data)) {
+		tester_setup_failed();
+		return;
+	}
 
 	status = data->if_bluetooth->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
@@ -2040,7 +2034,10 @@ static void setup_enabled_adapter(const void *test_data)
 	struct test_data *data = tester_get_data();
 	bt_status_t status;
 
-	setup(data);
+	if (!setup(data)) {
+		tester_setup_failed();
+		return;
+	}
 
 	status = data->if_bluetooth->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
@@ -2786,7 +2783,10 @@ static void setup_socket_interface(const void *test_data)
 	bt_status_t status;
 	const void *sock;
 
-	setup(data);
+	if (!setup(data)) {
+		tester_setup_failed();
+		return;
+	}
 
 	status = data->if_bluetooth->init(&bt_socket_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
@@ -2812,7 +2812,10 @@ static void setup_socket_interface_enabled(const void *test_data)
 	bt_status_t status;
 	const void *sock;
 
-	setup(data);
+	if (!setup(data)) {
+		tester_setup_failed();
+		return;
+	}
 
 	status = data->if_bluetooth->init(&bt_socket_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
@@ -3158,41 +3161,42 @@ static bthh_callbacks_t bthh_callbacks = {
 	.virtual_unplug_cb = hidhost_virual_unplug_cb
 };
 
-static void setup_hidhost(const void *test_data)
+static bool setup_hidhost(const void *test_data)
 {
 	struct test_data *data = tester_get_data();
 	bt_status_t status;
 	const void *hid;
 
-	setup(data);
+	if (!setup(data))
+		return false;
 
 	status = data->if_bluetooth->init(&bt_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
 		data->if_bluetooth = NULL;
-		tester_setup_failed();
-		return;
+		return false;
 	}
 
 	hid = data->if_bluetooth->get_profile_interface(BT_PROFILE_HIDHOST_ID);
-	if (!hid) {
-		tester_setup_failed();
-		return;
-	}
+	if (!hid)
+		return false;
 
 	data->if_hid = hid;
 
 	status = data->if_hid->init(&bthh_callbacks);
 	if (status != BT_STATUS_SUCCESS) {
 		data->if_hid = NULL;
-		tester_setup_failed();
-		return;
+		return false;
 	}
+
+	return true;
 }
 
 static void setup_hidhost_interface(const void *test_data)
 {
-	setup_hidhost(test_data);
-	tester_setup_complete();
+	if (setup_hidhost(test_data))
+		tester_setup_complete();
+	else
+		tester_setup_failed();
 }
 
 #define HID_GET_REPORT_PROTOCOL		0x60
@@ -3437,7 +3441,10 @@ static void setup_hidhost_connect(const void *test_data)
 	struct test_data *data = tester_get_data();
 	struct bthost *bthost;
 
-	setup_hidhost(test_data);
+	if (!setup_hidhost(test_data)) {
+		tester_setup_failed();
+		return;
+	}
 
 	bthost = hciemu_client_get_host(data->hciemu);
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH BlueZ 2/4] android: Remove useless extra parenthesis
From: Anderson Lizardo @ 2014-01-26  1:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1390700642-10482-1-git-send-email-anderson.lizardo@openbossa.org>

---
 android/android-tester.c | 4 ++--
 android/bluetooth.c      | 2 +-
 android/ipc-tester.c     | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index e4f95ce..ba9137a 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -518,7 +518,7 @@ static void emulator(int pipe, int hci_index)
 	memset(buf, 0, sizeof(buf));
 
 	len = read(fd, buf, sizeof(buf));
-	if (len <= 0 || (strcmp(buf, "bluetooth.start=daemon")))
+	if (len <= 0 || strcmp(buf, "bluetooth.start=daemon"))
 		goto failed;
 
 	close(pipe);
@@ -1985,7 +1985,7 @@ static bool setup(struct test_data *data)
 	data->bluetoothd_pid = pid;
 
 	len = read(signal_fd[0], buf, sizeof(buf));
-	if (len <= 0 || (strcmp(buf, EMULATOR_SIGNAL))) {
+	if (len <= 0 || strcmp(buf, EMULATOR_SIGNAL)) {
 		close(signal_fd[0]);
 		return false;
 	}
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 339fd77..cb1b87a 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -74,7 +74,7 @@
 #define DEVICES_CACHE_MAX 300
 
 #define BASELEN_PROP_CHANGED (sizeof(struct hal_ev_adapter_props_changed) \
-					+ (sizeof(struct hal_property)))
+					+ sizeof(struct hal_property))
 
 #define BASELEN_REMOTE_DEV_PROP (sizeof(struct hal_ev_remote_device_props) \
 					+ sizeof(struct hal_property))
diff --git a/android/ipc-tester.c b/android/ipc-tester.c
index e1aeb2e..ec8d3ff 100644
--- a/android/ipc-tester.c
+++ b/android/ipc-tester.c
@@ -264,7 +264,7 @@ static void emulator(int pipe, int hci_index)
 	memset(buf, 0, sizeof(buf));
 
 	len = read(fd, buf, sizeof(buf));
-	if (len <= 0 || (strcmp(buf, "ctl.start=bluetoothd")))
+	if (len <= 0 || strcmp(buf, "ctl.start=bluetoothd"))
 		goto failed;
 
 	close(pipe);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH BlueZ 3/4] android: Trivial replacement of tabs where spaces are expected
From: Anderson Lizardo @ 2014-01-26  1:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1390700642-10482-1-git-send-email-anderson.lizardo@openbossa.org>

---
 android/android-tester.c | 2 +-
 android/hidhost.c        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/android/android-tester.c b/android/android-tester.c
index ba9137a..870ad8d 100644
--- a/android/android-tester.c
+++ b/android/android-tester.c
@@ -3459,7 +3459,7 @@ static void setup_hidhost_connect(const void *test_data)
 	bthost_write_scan_enable(bthost, 0x03);
 }
 
-static void hid_discon_cb(bt_bdaddr_t *bd_addr,	bthh_connection_state_t state)
+static void hid_discon_cb(bt_bdaddr_t *bd_addr, bthh_connection_state_t state)
 {
 	if (state == BTHH_CONN_STATE_DISCONNECTED)
 		tester_test_passed();
diff --git a/android/hidhost.c b/android/hidhost.c
index 37b28a6..6d1088a 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -375,7 +375,7 @@ static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf,
 
 	if (!((buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_INPUT)) ||
 			(buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_OUTPUT)) ||
-			(buf[0]	== (HID_MSG_DATA | HID_DATA_TYPE_FEATURE)))) {
+			(buf[0] == (HID_MSG_DATA | HID_DATA_TYPE_FEATURE)))) {
 		ev = g_malloc0(ev_len);
 		ev->status = buf[0];
 		bdaddr2android(&dev->dst, ev->bdaddr);
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH BlueZ 4/4] emulator: Fix crash if socket(AF_ALG) is not supported by the kernel
From: Anderson Lizardo @ 2014-01-26  1:44 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1390700642-10482-1-git-send-email-anderson.lizardo@openbossa.org>

In this situation, smp_stop() was being called with NULL pointer.

Crash detected by valgrind:

==7925== Invalid read of size 4
==7925==    at 0x8052F18: smp_stop (smp.c:480)
==7925==    by 0x8052542: bthost_stop (bthost.c:2073)
==7925==    by 0x805521D: hciemu_unref (hciemu.c:372)
==7925==    by 0x8058C65: test_post_teardown (android-tester.c:464)
==7925==    by 0x8055DE7: tester_teardown_complete (tester.c:533)
==7925==    by 0x8055501: teardown_callback (tester.c:312)
==7925==    by 0x408348F: g_idle_dispatch (gmain.c:5250)
==7925==    by 0x4086A75: g_main_context_dispatch (gmain.c:3065)
==7925==    by 0x4086E14: g_main_context_iterate.isra.23 (gmain.c:3712)
==7925==    by 0x40872FA: g_main_loop_run (gmain.c:3906)
==7925==    by 0x41744D2: (below main) (libc-start.c:226)
==7925==  Address 0x8 is not stack'd, malloc'd or (recently) free'd
---
 emulator/bthost.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index c4603ae..3ff2a36 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -2070,6 +2070,8 @@ bool bthost_connect_rfcomm(struct bthost *bthost, uint16_t handle,
 
 void bthost_stop(struct bthost *bthost)
 {
-	smp_stop(bthost->smp_data);
-	bthost->smp_data = NULL;
+	if (bthost->smp_data) {
+		smp_stop(bthost->smp_data);
+		bthost->smp_data = NULL;
+	}
 }
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH 2/3] android/avdtp: Retry send on EAGAIN as well
From: Luiz Augusto von Dentz @ 2014-01-26  4:29 UTC (permalink / raw)
  To: Szymon Janc; +Cc: Andrei Emeltchenko, linux-bluetooth@vger.kernel.org
In-Reply-To: <3119819.bMHWn5I4f0@athlon>

Hi Szymon,

On Sat, Jan 25, 2014 at 12:16 AM, Szymon Janc <szymon.janc@gmail.com> wrote:
> Hi Andrei,
>
> On Friday 24 January 2014 16:56:42 Andrei Emeltchenko wrote:
>> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>>
>> ---
>>  android/avdtp.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/android/avdtp.c b/android/avdtp.c
>> index 5da1206..1055bc1 100644
>> --- a/android/avdtp.c
>> +++ b/android/avdtp.c
>> @@ -444,7 +444,7 @@ static gboolean try_send(int sk, void *data, size_t len)
>>
>>       do {
>>               err = send(sk, data, len, 0);
>> -     } while (err < 0 && errno == EINTR);
>> +     } while (err < 0 && (errno == EINTR || errno == EAGAIN));
>>
>
> This makes try_send() blocking, if this is ok then at least some explanation
> in commit message would be welcome.

And if we want to block we should not set the socket as non-blocking
in first place, Im not even sure this is easy to currently reproduce
any case that would block since the command are quite small we would
have to schedule several in a sequence but normally we can only have
one command outstanding.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* 3.14-mw regression:  circular locking dependency (&tty->legacy_mutex){+.+.+.}, at: [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
From: Sander Eikelenboom @ 2014-01-26 10:47 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Marcel Holtmann
  Cc: linux-wireless, linux-bluetooth, linux-serial

Hi,

I have got a regression with a 3.14-mw kernel (last commit is 4ba9920e5e9c0e16b5ed24292d45322907bb9035)
when a script is started that reads from serial over bluetooth, that wasn't in the 3.13 release kernel:


Jan 26 11:36:10 serveerstertje kernel: [   72.892926]
Jan 26 11:36:10 serveerstertje kernel: [   72.900249] ======================================================
Jan 26 11:36:10 serveerstertje kernel: [   72.907697] [ INFO: possible circular locking dependency detected ]
Jan 26 11:36:10 serveerstertje kernel: [   72.915214] 3.13.0-20140125-mw-pcireset+ #1 Not tainted
Jan 26 11:36:10 serveerstertje kernel: [   72.922307] -------------------------------------------------------
Jan 26 11:36:10 serveerstertje kernel: [   72.928315] zabbix_slimmeme/5909 is trying to acquire lock:
Jan 26 11:36:10 serveerstertje kernel: [   72.934323]  (&tty->legacy_mutex){+.+.+.}, at: [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
Jan 26 11:36:10 serveerstertje kernel: [   72.940434] 
Jan 26 11:36:10 serveerstertje kernel: [   72.940434] but task is already holding lock:
Jan 26 11:36:10 serveerstertje kernel: [   72.952263]  (&port->mutex){+.+.+.}, at: [<ffffffff81518aa7>] tty_port_open+0x67/0xe0
Jan 26 11:36:10 serveerstertje kernel: [   72.958292] 
Jan 26 11:36:10 serveerstertje kernel: [   72.958292] which lock already depends on the new lock.
Jan 26 11:36:10 serveerstertje kernel: [   72.958292] 
Jan 26 11:36:10 serveerstertje kernel: [   72.976267] 
Jan 26 11:36:10 serveerstertje kernel: [   72.976267] the existing dependency chain (in reverse order) is:
Jan 26 11:36:10 serveerstertje kernel: [   72.988276] 
Jan 26 11:36:10 serveerstertje kernel: [   72.988276] -> #1 (&port->mutex){+.+.+.}:
Jan 26 11:36:10 serveerstertje kernel: [   73.000386]        [<ffffffff81102dfd>] lock_acquire+0xcd/0x110
Jan 26 11:36:10 serveerstertje kernel: [   73.006526]        [<ffffffff81ad3f97>] mutex_lock_nested+0x47/0x560
Jan 26 11:36:10 serveerstertje kernel: [   73.012612]        [<ffffffff81518aa7>] tty_port_open+0x67/0xe0
Jan 26 11:36:10 serveerstertje kernel: [   73.018637]        [<ffffffff81aa4356>] rfcomm_tty_open+0x26/0xe0
Jan 26 11:36:10 serveerstertje kernel: [   73.024674]        [<ffffffff8150fcea>] tty_open+0x16a/0x5c0
Jan 26 11:36:10 serveerstertje kernel: [   73.030748]        [<ffffffff811b4013>] chrdev_open+0xa3/0x1c0
Jan 26 11:36:10 serveerstertje kernel: [   73.036833]        [<ffffffff811ad686>] do_dentry_open.isra.16+0x246/0x2f0
Jan 26 11:36:10 serveerstertje kernel: [   73.043001]        [<ffffffff811ad81d>] finish_open+0x1d/0x30
Jan 26 11:36:10 serveerstertje kernel: [   73.049106]        [<ffffffff811befae>] do_last+0x7ce/0xdf0
Jan 26 11:36:10 serveerstertje kernel: [   73.055191]        [<ffffffff811bf68d>] path_openat+0xbd/0x6b0
Jan 26 11:36:10 serveerstertje kernel: [   73.061211]        [<ffffffff811c004e>] do_filp_open+0x3e/0xa0
Jan 26 11:36:10 serveerstertje kernel: [   73.067177]        [<ffffffff811aeaec>] do_sys_open+0x13c/0x230
Jan 26 11:36:10 serveerstertje kernel: [   73.073141]        [<ffffffff811aebfd>] SyS_open+0x1d/0x20
Jan 26 11:36:10 serveerstertje kernel: [   73.079047]        [<ffffffff81ad6f39>] system_call_fastpath+0x16/0x1b
Jan 26 11:36:10 serveerstertje kernel: [   73.084962] 
Jan 26 11:36:10 serveerstertje kernel: [   73.084962] -> #0 (&tty->legacy_mutex){+.+.+.}:
Jan 26 11:36:10 serveerstertje kernel: [   73.096600]        [<ffffffff8110230b>] __lock_acquire+0x1d4b/0x2220
Jan 26 11:36:10 serveerstertje kernel: [   73.102559]        [<ffffffff81102dfd>] lock_acquire+0xcd/0x110
Jan 26 11:36:10 serveerstertje kernel: [   73.108475]        [<ffffffff81ad3f97>] mutex_lock_nested+0x47/0x560
Jan 26 11:36:10 serveerstertje kernel: [   73.114419]        [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
Jan 26 11:36:10 serveerstertje kernel: [   73.120354]        [<ffffffff81ad63ab>] tty_lock+0xb/0x10
Jan 26 11:36:10 serveerstertje kernel: [   73.126258]        [<ffffffff81aa4677>] rfcomm_dev_activate+0xb7/0x250
Jan 26 11:36:10 serveerstertje kernel: [   73.132222]        [<ffffffff81518ad7>] tty_port_open+0x97/0xe0
Jan 26 11:36:10 serveerstertje kernel: [   73.138195]        [<ffffffff81aa4356>] rfcomm_tty_open+0x26/0xe0
Jan 26 11:36:10 serveerstertje kernel: [   73.144207]        [<ffffffff8150fcea>] tty_open+0x16a/0x5c0
Jan 26 11:36:10 serveerstertje kernel: [   73.150164]        [<ffffffff811b4013>] chrdev_open+0xa3/0x1c0
Jan 26 11:36:10 serveerstertje kernel: [   73.156127]        [<ffffffff811ad686>] do_dentry_open.isra.16+0x246/0x2f0
Jan 26 11:36:10 serveerstertje kernel: [   73.162070]        [<ffffffff811ad81d>] finish_open+0x1d/0x30
Jan 26 11:36:10 serveerstertje kernel: [   73.167933]        [<ffffffff811befae>] do_last+0x7ce/0xdf0
Jan 26 11:36:10 serveerstertje kernel: [   73.173787]        [<ffffffff811bf68d>] path_openat+0xbd/0x6b0
Jan 26 11:36:10 serveerstertje kernel: [   73.179600]        [<ffffffff811c004e>] do_filp_open+0x3e/0xa0
Jan 26 11:36:10 serveerstertje kernel: [   73.185302]        [<ffffffff811aeaec>] do_sys_open+0x13c/0x230
Jan 26 11:36:10 serveerstertje kernel: [   73.190880]        [<ffffffff811aebfd>] SyS_open+0x1d/0x20
Jan 26 11:36:10 serveerstertje kernel: [   73.196247]        [<ffffffff81ad6f39>] system_call_fastpath+0x16/0x1b
Jan 26 11:36:10 serveerstertje kernel: [   73.201486] 
Jan 26 11:36:10 serveerstertje kernel: [   73.201486] other info that might help us debug this:
Jan 26 11:36:10 serveerstertje kernel: [   73.201486] 
Jan 26 11:36:10 serveerstertje kernel: [   73.216718]  Possible unsafe locking scenario:
Jan 26 11:36:10 serveerstertje kernel: [   73.216718] 
Jan 26 11:36:10 serveerstertje kernel: [   73.226933]        CPU0                    CPU1
Jan 26 11:36:10 serveerstertje kernel: [   73.231978]        ----                    ----
Jan 26 11:36:10 serveerstertje kernel: [   73.237001]   lock(&port->mutex);
Jan 26 11:36:10 serveerstertje kernel: [   73.241994]                                lock(&tty->legacy_mutex);
Jan 26 11:36:10 serveerstertje kernel: [   73.247043]                                lock(&port->mutex);
Jan 26 11:36:10 serveerstertje kernel: [   73.251999]   lock(&tty->legacy_mutex);
Jan 26 11:36:10 serveerstertje kernel: [   73.256902] 
Jan 26 11:36:10 serveerstertje kernel: [   73.256902]  *** DEADLOCK ***
Jan 26 11:36:10 serveerstertje kernel: [   73.256902] 
Jan 26 11:36:10 serveerstertje kernel: [   73.270890] 1 lock held by zabbix_slimmeme/5909:
Jan 26 11:36:10 serveerstertje kernel: [   73.275398]  #0:  (&port->mutex){+.+.+.}, at: [<ffffffff81518aa7>] tty_port_open+0x67/0xe0
Jan 26 11:36:10 serveerstertje kernel: [   73.280124] 
Jan 26 11:36:10 serveerstertje kernel: [   73.280124] stack backtrace:
Jan 26 11:36:10 serveerstertje kernel: [   73.289130] CPU: 5 PID: 5909 Comm: zabbix_slimmeme Not tainted 3.13.0-20140125-mw-pcireset+ #1
Jan 26 11:36:10 serveerstertje kernel: [   73.293860] Hardware name: MSI MS-7640/890FXA-GD70 (MS-7640)  , BIOS V1.8B1 09/13/2010
Jan 26 11:36:10 serveerstertje kernel: [   73.298625]  ffffffff826e2b70 ffff88005858f818 ffffffff81acbcfa ffff880057c72300
Jan 26 11:36:10 serveerstertje kernel: [   73.303571]  ffffffff826e2b70 ffff88005858f868 ffffffff81ac7011 ffff880057c72300
Jan 26 11:36:10 serveerstertje kernel: [   73.308511]  ffff880057c72300 ffff88005858f868 ffff880057c72ac0 0000000000000000
Jan 26 11:36:10 serveerstertje kernel: [   73.313325] Call Trace:
Jan 26 11:36:10 serveerstertje kernel: [   73.318092]  [<ffffffff81acbcfa>] dump_stack+0x46/0x58
Jan 26 11:36:10 serveerstertje kernel: [   73.322900]  [<ffffffff81ac7011>] print_circular_bug+0x2f6/0x32a
Jan 26 11:36:10 serveerstertje kernel: [   73.327723]  [<ffffffff8110230b>] __lock_acquire+0x1d4b/0x2220
Jan 26 11:36:10 serveerstertje kernel: [   73.332545]  [<ffffffff810fedbd>] ? trace_hardirqs_on+0xd/0x10
Jan 26 11:36:10 serveerstertje kernel: [   73.337414]  [<ffffffff810e6141>] ? finish_task_switch+0x41/0xf0
Jan 26 11:36:10 serveerstertje kernel: [   73.342279]  [<ffffffff81ad0244>] ? sleep_on_timeout+0x4/0x20
Jan 26 11:36:10 serveerstertje kernel: [   73.347128]  [<ffffffff81102dfd>] lock_acquire+0xcd/0x110
Jan 26 11:36:10 serveerstertje kernel: [   73.351950]  [<ffffffff81ad6344>] ? tty_lock_nested+0x44/0xa0
Jan 26 11:36:10 serveerstertje kernel: [   73.356792]  [<ffffffff81ad3f97>] mutex_lock_nested+0x47/0x560
Jan 26 11:36:10 serveerstertje kernel: [   73.361599]  [<ffffffff81ad6344>] ? tty_lock_nested+0x44/0xa0
Jan 26 11:36:10 serveerstertje kernel: [   73.366363]  [<ffffffff810fec6b>] ? trace_hardirqs_on_caller+0xfb/0x240
Jan 26 11:36:10 serveerstertje kernel: [   73.371200]  [<ffffffff810fedbd>] ? trace_hardirqs_on+0xd/0x10
Jan 26 11:36:10 serveerstertje kernel: [   73.376030]  [<ffffffff81ad6344>] tty_lock_nested+0x44/0xa0
Jan 26 11:36:10 serveerstertje kernel: [   73.380842]  [<ffffffff81ad63ab>] tty_lock+0xb/0x10
Jan 26 11:36:10 serveerstertje kernel: [   73.385616]  [<ffffffff81aa4677>] rfcomm_dev_activate+0xb7/0x250
Jan 26 11:36:10 serveerstertje kernel: [   73.390398]  [<ffffffff81ad4287>] ? mutex_lock_nested+0x337/0x560
Jan 26 11:36:10 serveerstertje kernel: [   73.395154]  [<ffffffff810f90f0>] ? __init_waitqueue_head+0x60/0x60
Jan 26 11:36:10 serveerstertje kernel: [   73.399861]  [<ffffffff81518ad7>] tty_port_open+0x97/0xe0
Jan 26 11:36:10 serveerstertje kernel: [   73.404552]  [<ffffffff81aa4356>] rfcomm_tty_open+0x26/0xe0
Jan 26 11:36:10 serveerstertje kernel: [   73.409263]  [<ffffffff8150fcea>] tty_open+0x16a/0x5c0
Jan 26 11:36:10 serveerstertje kernel: [   73.413954]  [<ffffffff811b4013>] chrdev_open+0xa3/0x1c0
Jan 26 11:36:10 serveerstertje kernel: [   73.418657]  [<ffffffff81457bfd>] ? lockref_get+0x1d/0x30
Jan 26 11:36:10 serveerstertje kernel: [   73.423379]  [<ffffffff811b3f70>] ? cdev_put+0x30/0x30
Jan 26 11:36:10 serveerstertje kernel: [   73.428056]  [<ffffffff811ad686>] do_dentry_open.isra.16+0x246/0x2f0
Jan 26 11:36:10 serveerstertje kernel: [   73.432768]  [<ffffffff811ad81d>] finish_open+0x1d/0x30
Jan 26 11:36:10 serveerstertje kernel: [   73.437464]  [<ffffffff811befae>] do_last+0x7ce/0xdf0
Jan 26 11:36:10 serveerstertje kernel: [   73.442166]  [<ffffffff811baff3>] ? inode_permission+0x13/0x50
Jan 26 11:36:10 serveerstertje kernel: [   73.446861]  [<ffffffff811bb5ce>] ? link_path_walk+0x21e/0x880
Jan 26 11:36:10 serveerstertje kernel: [   73.451533]  [<ffffffff810fec6b>] ? trace_hardirqs_on_caller+0xfb/0x240
Jan 26 11:36:10 serveerstertje kernel: [   73.456280]  [<ffffffff811bf68d>] path_openat+0xbd/0x6b0
Jan 26 11:36:10 serveerstertje kernel: [   73.461029]  [<ffffffff8104cb03>] ? __do_page_fault+0x103/0x4e0
Jan 26 11:36:10 serveerstertje kernel: [   73.465782]  [<ffffffff81102e1d>] ? lock_acquire+0xed/0x110
Jan 26 11:36:10 serveerstertje kernel: [   73.470553]  [<ffffffff811c004e>] do_filp_open+0x3e/0xa0
Jan 26 11:36:10 serveerstertje kernel: [   73.475321]  [<ffffffff811cda31>] ? __alloc_fd+0xd1/0x120
Jan 26 11:36:10 serveerstertje kernel: [   73.480064]  [<ffffffff811aeaec>] do_sys_open+0x13c/0x230
Jan 26 11:36:10 serveerstertje kernel: [   73.484743]  [<ffffffff810fec6b>] ? trace_hardirqs_on_caller+0xfb/0x240
Jan 26 11:36:10 serveerstertje kernel: [   73.489470]  [<ffffffff811aebfd>] SyS_open+0x1d/0x20
Jan 26 11:36:10 serveerstertje kernel: [   73.494191]  [<ffffffff81ad6f39>] system_call_fastpath+0x16/0x1b

^ permalink raw reply

* Re: Discovering LE advertisements programatically
From: Adam Warski @ 2014-01-26 11:03 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: BlueZ development
In-Reply-To: <CAJdJm_PFAWLvBQFXOntGu+sA7-vGuVRx5956OL3CD8QjmqZiEA@mail.gmail.com>


>> I’m trying to find a good way to discover and retrieve LE advertisements programatically.
>> 
>> My first shot was to try to use DBus. I was trying to extend what the test/test-discovery script is doing, but it seems using DBus I can only get notified of new devices being discovered. Is there a way to get the actual LE advertisement via DBus? The device properties seem not to contain the info from the advertisement PDU.
>> 
>> If that’s not possible using DBus, is the way to go just using C?
>> 
>> I also tried using command line, a combination of “hcitool lescan” and “hcidump”/“hcidump -R" gives what I need more or less (plain hcidump gives me the RSSI, hcidump -R gives me the raw packet that I need). Still, I guess there must be a better way.
> 
> My suggestion would be to take a look at "hcitool lescan" for how it
> is done using C sockets. Or you can modify hcitool lescan to dump the
> full advertising report instead of just the name.

Indeed by modifying the source of the hcitool, lescan method (print_advertising_devices), I am able to get the advertisement content. However, I’d also like to get the RSSI - is it possible from that method? I have access to the open device (dd), and the evt_le_meta_event and le_advertising_info structures - but that doesn’t seem to be enough. There is a hci_read_rssi in lib/hci.c, but it requires a “handle” - I think it’s only useable if a conneciton is open.

An alternative route that I see is to extract some part of hcidump, where I can get access to the raw packet and the RSSI, having the whole frame at my disposal. But that seems a bit “hackish” :)

Thanks,
Adam

-- 
Adam Warski

http://twitter.com/#!/adamwarski
http://www.softwaremill.com
http://www.warski.org


^ permalink raw reply

* Re: Discovering LE advertisements programatically
From: Adam Warski @ 2014-01-26 11:20 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: BlueZ development
In-Reply-To: <C4A59DF3-F4DF-445A-AA86-6BB9A81A2910@warski.org>


>>> I’m trying to find a good way to discover and retrieve LE advertisements programatically.
>>> 
>>> My first shot was to try to use DBus. I was trying to extend what the test/test-discovery script is doing, but it seems using DBus I can only get notified of new devices being discovered. Is there a way to get the actual LE advertisement via DBus? The device properties seem not to contain the info from the advertisement PDU.
>>> 
>>> If that’s not possible using DBus, is the way to go just using C?
>>> 
>>> I also tried using command line, a combination of “hcitool lescan” and “hcidump”/“hcidump -R" gives what I need more or less (plain hcidump gives me the RSSI, hcidump -R gives me the raw packet that I need). Still, I guess there must be a better way.
>> 
>> My suggestion would be to take a look at "hcitool lescan" for how it
>> is done using C sockets. Or you can modify hcitool lescan to dump the
>> full advertising report instead of just the name.
> 
> Indeed by modifying the source of the hcitool, lescan method (print_advertising_devices), I am able to get the advertisement content. However, I’d also like to get the RSSI - is it possible from that method? I have access to the open device (dd), and the evt_le_meta_event and le_advertising_info structures - but that doesn’t seem to be enough. There is a hci_read_rssi in lib/hci.c, but it requires a “handle” - I think it’s only useable if a conneciton is open.

Actually, looking at the whole data received from the socket, I think the last byte - and the only byte remaining after the advertisement packet - is the RSSI.

So I guess writing to the group worked as a rubber duck :)

Adam

-- 
Adam Warski

http://twitter.com/#!/adamwarski
http://www.softwaremill.com
http://www.warski.org


^ permalink raw reply

* [PATCH BlueZ v3 1/8] android: Add copy of current AVCTP implemention
From: Luiz Augusto von Dentz @ 2014-01-26 23:55 UTC (permalink / raw)
  To: linux-bluetooth

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

These files are not added to any makefile on purpose because they still
have external dependencies.
---
v2: Fix issues with dependencies in Android, adds proper reject for messages
that cannot be handled, fix avctp_new not initializing the handlers properly
and finally fixes using 0 instead of NULL in various places.
v3: Rebase

 {profiles/audio => android}/avctp.c | 0
 {profiles/audio => android}/avctp.h | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 copy {profiles/audio => android}/avctp.c (100%)
 copy {profiles/audio => android}/avctp.h (100%)

diff --git a/profiles/audio/avctp.c b/android/avctp.c
similarity index 100%
copy from profiles/audio/avctp.c
copy to android/avctp.c
diff --git a/profiles/audio/avctp.h b/android/avctp.h
similarity index 100%
copy from profiles/audio/avctp.h
copy to android/avctp.h
-- 
1.8.4.2


^ permalink raw reply

* [PATCH BlueZ v3 2/8] android/AVCTP: Strip dependencies
From: Luiz Augusto von Dentz @ 2014-01-26 23:55 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1390780546-18402-1-git-send-email-luiz.dentz@gmail.com>

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

This strips AVCTP code of any dependency of core and btio to make it
transport agnostic.
---
 android/Android.mk  |   1 +
 android/Makefile.am |   1 +
 android/avctp.c     | 794 ++++++++--------------------------------------------
 android/avctp.h     |  40 +--
 4 files changed, 134 insertions(+), 702 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index 32e9e98..5f2c1d4 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -29,6 +29,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/audio-ipc.c \
 	bluez/android/avdtp.c \
 	bluez/android/a2dp.c \
+	bluez/android/avctp.c \
 	bluez/android/pan.c \
 	bluez/src/log.c \
 	bluez/src/shared/mgmt.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index f85de20..88fe667 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -33,6 +33,7 @@ android_bluetoothd_SOURCES = android/main.c \
 				android/audio-ipc.h android/audio-ipc.c \
 				android/avdtp.h android/avdtp.c \
 				android/a2dp.h android/a2dp.c \
+				android/avctp.h android/avctp.c \
 				android/socket.h android/socket.c \
 				android/pan.h android/pan.c \
 				btio/btio.h btio/btio.c \
diff --git a/android/avctp.c b/android/avctp.c
index 6fd1454..d7f047a 100644
--- a/android/avctp.c
+++ b/android/avctp.c
@@ -34,28 +34,20 @@
 #include <unistd.h>
 #include <assert.h>
 #include <signal.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <netinet/in.h>
 
-#include <bluetooth/bluetooth.h>
 #include <bluetooth/sdp.h>
-#include <bluetooth/l2cap.h>
 
 #include <glib.h>
 
-#include "btio/btio.h"
-#include "lib/uuid.h"
-#include "src/adapter.h"
-#include "src/device.h"
-
 #include "src/log.h"
-#include "src/error.h"
 #include "src/uinput.h"
 
 #include "avctp.h"
-#include "avrcp.h"
 
 /* AV/C Panel 1.23, page 76:
  * command with the pressed value is valid for two seconds
@@ -116,20 +108,6 @@ struct avc_header {
 #error "Unknown byte order"
 #endif
 
-struct avctp_state_callback {
-	avctp_state_cb cb;
-	struct btd_device *dev;
-	unsigned int id;
-	void *user_data;
-};
-
-struct avctp_server {
-	struct btd_adapter *adapter;
-	GIOChannel *control_io;
-	GIOChannel *browsing_io;
-	GSList *sessions;
-};
-
 struct avctp_control_req {
 	struct avctp_pending_req *p;
 	uint8_t code;
@@ -158,7 +136,7 @@ struct avctp_pending_req {
 	int err;
 	avctp_process_cb process;
 	void *data;
-	GDestroyNotify destroy;
+	avctp_destroy_cb_t destroy;
 };
 
 struct avctp_channel {
@@ -174,7 +152,7 @@ struct avctp_channel {
 	GQueue *queue;
 	GSList *processed;
 	guint process_id;
-	GDestroyNotify destroy;
+	avctp_destroy_cb_t destroy;
 };
 
 struct key_pressed {
@@ -183,14 +161,8 @@ struct key_pressed {
 };
 
 struct avctp {
-	struct avctp_server *server;
-	struct btd_device *device;
-
-	avctp_state_t state;
-
 	int uinput;
 
-	guint auth_id;
 	unsigned int passthrough_id;
 	unsigned int unit_id;
 	unsigned int subunit_id;
@@ -202,7 +174,7 @@ struct avctp {
 
 	uint8_t key_quirks[256];
 	struct key_pressed key;
-	bool initiator;
+	uint16_t version;
 };
 
 struct avctp_passthrough_handler {
@@ -222,7 +194,7 @@ struct avctp_browsing_pdu_handler {
 	avctp_browsing_pdu_cb cb;
 	void *user_data;
 	unsigned int id;
-	GDestroyNotify destroy;
+	avctp_destroy_cb_t destroy;
 };
 
 static struct {
@@ -260,10 +232,6 @@ static struct {
 	{ NULL }
 };
 
-static GSList *callbacks = NULL;
-static GSList *servers = NULL;
-
-static void auth_cb(DBusError *derr, void *user_data);
 static gboolean process_queue(gpointer user_data);
 static gboolean avctp_passthrough_rsp(struct avctp *session, uint8_t code,
 					uint8_t subunit, uint8_t *operands,
@@ -489,83 +457,6 @@ static void avctp_channel_destroy(struct avctp_channel *chan)
 	g_free(chan);
 }
 
-static void avctp_disconnected(struct avctp *session)
-{
-	struct avctp_server *server;
-
-	if (!session)
-		return;
-
-	if (session->browsing)
-		avctp_channel_destroy(session->browsing);
-
-	if (session->control)
-		avctp_channel_destroy(session->control);
-
-	if (session->auth_id != 0) {
-		btd_cancel_authorization(session->auth_id);
-		session->auth_id = 0;
-	}
-
-	if (session->key.timer > 0)
-		g_source_remove(session->key.timer);
-
-	if (session->uinput >= 0) {
-		char address[18];
-
-		ba2str(device_get_address(session->device), address);
-		DBG("AVCTP: closing uinput for %s", address);
-
-		ioctl(session->uinput, UI_DEV_DESTROY);
-		close(session->uinput);
-		session->uinput = -1;
-	}
-
-	server = session->server;
-	server->sessions = g_slist_remove(server->sessions, session);
-	btd_device_unref(session->device);
-	g_free(session);
-}
-
-static void avctp_set_state(struct avctp *session, avctp_state_t new_state)
-{
-	GSList *l;
-	avctp_state_t old_state = session->state;
-
-	session->state = new_state;
-
-	for (l = callbacks; l != NULL; l = l->next) {
-		struct avctp_state_callback *cb = l->data;
-
-		if (cb->dev && cb->dev != session->device)
-			continue;
-
-		cb->cb(session->device, old_state, new_state, cb->user_data);
-	}
-
-	switch (new_state) {
-	case AVCTP_STATE_DISCONNECTED:
-		DBG("AVCTP Disconnected");
-		avctp_disconnected(session);
-		break;
-	case AVCTP_STATE_CONNECTING:
-		DBG("AVCTP Connecting");
-		break;
-	case AVCTP_STATE_CONNECTED:
-		DBG("AVCTP Connected");
-		break;
-	case AVCTP_STATE_BROWSING_CONNECTING:
-		DBG("AVCTP Browsing Connecting");
-		break;
-	case AVCTP_STATE_BROWSING_CONNECTED:
-		DBG("AVCTP Browsing Connected");
-		break;
-	default:
-		error("Invalid AVCTP state %d", new_state);
-		return;
-	}
-}
-
 static int avctp_send(struct avctp_channel *control, uint8_t transaction,
 				uint8_t cr, uint8_t code,
 				uint8_t subunit, uint8_t opcode,
@@ -875,7 +766,8 @@ static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond,
 	handler = g_slist_nth_data(browsing->handlers, 0);
 	if (handler == NULL) {
 		DBG("handler not found");
-		packet_size += avrcp_browsing_general_reject(operands);
+		/* FIXME: Add general reject */
+		/* packet_size += avrcp_browsing_general_reject(operands); */
 		goto send;
 	}
 
@@ -894,7 +786,6 @@ send:
 
 failed:
 	DBG("AVCTP Browsing: disconnected");
-	avctp_set_state(session, AVCTP_STATE_CONNECTED);
 
 	if (session->browsing) {
 		avctp_channel_destroy(session->browsing);
@@ -967,7 +858,9 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
 	handler = find_handler(control->handlers, avc->opcode);
 	if (!handler) {
 		DBG("handler not found for 0x%02x", avc->opcode);
-		packet_size += avrcp_handle_vendor_reject(&code, operands);
+		/* FIXME:
+		 * packet_size += avrcp_handle_vendor_reject(&code, operands);
+		 */
 		avc->code = code;
 		goto done;
 	}
@@ -991,11 +884,11 @@ done:
 
 failed:
 	DBG("AVCTP session %p got disconnected", session);
-	avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
+	avctp_shutdown(session);
 	return FALSE;
 }
 
-static int uinput_create(char *name)
+static int uinput_create(const char *name)
 {
 	struct uinput_dev dev;
 	int fd, err, i;
@@ -1050,11 +943,9 @@ static int uinput_create(char *name)
 	return fd;
 }
 
-static void init_uinput(struct avctp *session)
+int avctp_init_uinput(struct avctp *session, const char *name,
+							const char *address)
 {
-	char address[18], name[248 + 1];
-
-	device_get_name(session->device, name, sizeof(name));
 	if (g_str_equal(name, "Nokia CK-20W")) {
 		session->key_quirks[AVC_FORWARD] |= QUIRK_NO_RELEASE;
 		session->key_quirks[AVC_BACKWARD] |= QUIRK_NO_RELEASE;
@@ -1062,24 +953,28 @@ static void init_uinput(struct avctp *session)
 		session->key_quirks[AVC_PAUSE] |= QUIRK_NO_RELEASE;
 	}
 
-	ba2str(device_get_address(session->device), address);
 	session->uinput = uinput_create(address);
-	if (session->uinput < 0)
-		error("AVRCP: failed to init uinput for %s", address);
-	else
-		DBG("AVRCP: uinput initialized for %s", address);
+	if (session->uinput < 0) {
+		error("AVCTP: failed to init uinput for %s", address);
+		return session->uinput;
+	}
+
+	return 0;
 }
 
-static struct avctp_channel *avctp_channel_create(struct avctp *session,
-							GIOChannel *io,
-							GDestroyNotify destroy)
+static struct avctp_channel *avctp_channel_create(struct avctp *session, int fd,
+						size_t imtu, size_t omtu,
+						avctp_destroy_cb_t destroy)
 {
 	struct avctp_channel *chan;
 
 	chan = g_new0(struct avctp_channel, 1);
 	chan->session = session;
-	chan->io = g_io_channel_ref(io);
+	chan->io = g_io_channel_unix_new(fd);
 	chan->queue = g_queue_new();
+	chan->imtu = imtu;
+	chan->omtu = omtu;
+	chan->buffer = g_malloc0(MAX(imtu, omtu));
 	chan->destroy = destroy;
 
 	return chan;
@@ -1104,381 +999,10 @@ static void avctp_destroy_browsing(void *data)
 	chan->handlers = NULL;
 }
 
-static void avctp_connect_browsing_cb(GIOChannel *chan, GError *err,
-							gpointer data)
-{
-	struct avctp *session = data;
-	struct avctp_channel *browsing = session->browsing;
-	char address[18];
-	uint16_t imtu, omtu;
-	GError *gerr = NULL;
-
-	if (err) {
-		error("Browsing: %s", err->message);
-		goto fail;
-	}
-
-	bt_io_get(chan, &gerr,
-			BT_IO_OPT_DEST, &address,
-			BT_IO_OPT_IMTU, &imtu,
-			BT_IO_OPT_OMTU, &omtu,
-			BT_IO_OPT_INVALID);
-	if (gerr) {
-		error("%s", gerr->message);
-		g_io_channel_shutdown(chan, TRUE, NULL);
-		g_io_channel_unref(chan);
-		g_error_free(gerr);
-		goto fail;
-	}
-
-	DBG("AVCTP Browsing: connected to %s", address);
-
-	if (browsing == NULL) {
-		browsing = avctp_channel_create(session, chan,
-						avctp_destroy_browsing);
-		session->browsing = browsing;
-	}
-
-	browsing->imtu = imtu;
-	browsing->omtu = omtu;
-	browsing->buffer = g_malloc0(MAX(imtu, omtu));
-	browsing->watch = g_io_add_watch(session->browsing->io,
-				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-				(GIOFunc) session_browsing_cb, session);
-
-	avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTED);
-
-	/* Process any request that was pending the connection to complete */
-	if (browsing->process_id == 0 && !g_queue_is_empty(browsing->queue))
-		browsing->process_id = g_idle_add(process_queue, browsing);
-
-	return;
-
-fail:
-	avctp_set_state(session, AVCTP_STATE_CONNECTED);
-
-	if (session->browsing) {
-		avctp_channel_destroy(session->browsing);
-		session->browsing = NULL;
-	}
-}
-
-static void avctp_connect_cb(GIOChannel *chan, GError *err, gpointer data)
-{
-	struct avctp *session = data;
-	char address[18];
-	uint16_t imtu, omtu;
-	GError *gerr = NULL;
-
-	if (err) {
-		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-		error("%s", err->message);
-		return;
-	}
-
-	bt_io_get(chan, &gerr,
-			BT_IO_OPT_DEST, &address,
-			BT_IO_OPT_IMTU, &imtu,
-			BT_IO_OPT_IMTU, &omtu,
-			BT_IO_OPT_INVALID);
-	if (gerr) {
-		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-		error("%s", gerr->message);
-		g_error_free(gerr);
-		return;
-	}
-
-	DBG("AVCTP: connected to %s", address);
-
-	if (session->control == NULL)
-		session->control = avctp_channel_create(session, chan, NULL);
-
-	session->control->imtu = imtu;
-	session->control->omtu = omtu;
-	session->control->buffer = g_malloc0(MAX(imtu, omtu));
-	session->control->watch = g_io_add_watch(session->control->io,
-				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-				(GIOFunc) session_cb, session);
-
-	session->passthrough_id = avctp_register_pdu_handler(session,
-						AVC_OP_PASSTHROUGH,
-						handle_panel_passthrough,
-						NULL);
-	session->unit_id = avctp_register_pdu_handler(session,
-						AVC_OP_UNITINFO,
-						handle_unit_info,
-						NULL);
-	session->subunit_id = avctp_register_pdu_handler(session,
-						AVC_OP_SUBUNITINFO,
-						handle_subunit_info,
-						NULL);
-
-	init_uinput(session);
-
-	avctp_set_state(session, AVCTP_STATE_CONNECTED);
-}
-
-static void auth_cb(DBusError *derr, void *user_data)
-{
-	struct avctp *session = user_data;
-	GError *err = NULL;
-
-	session->auth_id = 0;
-
-	if (session->control->watch > 0) {
-		g_source_remove(session->control->watch);
-		session->control->watch = 0;
-	}
-
-	if (derr && dbus_error_is_set(derr)) {
-		error("Access denied: %s", derr->message);
-		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-		return;
-	}
-
-	if (!bt_io_accept(session->control->io, avctp_connect_cb, session,
-								NULL, &err)) {
-		error("bt_io_accept: %s", err->message);
-		g_error_free(err);
-		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-	}
-}
-
-static struct avctp_server *find_server(GSList *list, struct btd_adapter *a)
-{
-	for (; list; list = list->next) {
-		struct avctp_server *server = list->data;
-
-		if (server->adapter == a)
-			return server;
-	}
-
-	return NULL;
-}
-
-static struct avctp *find_session(GSList *list, struct btd_device *device)
-{
-	for (; list != NULL; list = g_slist_next(list)) {
-		struct avctp *s = list->data;
-
-		if (s->device == device)
-			return s;
-	}
-
-	return NULL;
-}
-
-static struct avctp *avctp_get_internal(struct btd_device *device)
-{
-	struct avctp_server *server;
-	struct avctp *session;
-
-	server = find_server(servers, device_get_adapter(device));
-	if (server == NULL)
-		return NULL;
-
-	session = find_session(server->sessions, device);
-	if (session)
-		return session;
-
-	session = g_new0(struct avctp, 1);
-
-	session->server = server;
-	session->device = btd_device_ref(device);
-	session->state = AVCTP_STATE_DISCONNECTED;
-	session->uinput = -1;
-
-	server->sessions = g_slist_append(server->sessions, session);
-
-	return session;
-}
-
-static void avctp_control_confirm(struct avctp *session, GIOChannel *chan,
-						struct btd_device *dev)
-{
-	const bdaddr_t *src;
-	const bdaddr_t *dst;
-
-	if (session->control != NULL) {
-		error("Control: Refusing unexpected connect");
-		g_io_channel_shutdown(chan, TRUE, NULL);
-		return;
-	}
-
-	avctp_set_state(session, AVCTP_STATE_CONNECTING);
-	session->control = avctp_channel_create(session, chan, NULL);
-
-	src = btd_adapter_get_address(device_get_adapter(dev));
-	dst = device_get_address(dev);
-
-	session->auth_id = btd_request_authorization(src, dst,
-							AVRCP_REMOTE_UUID,
-							auth_cb, session);
-	if (session->auth_id == 0)
-		goto drop;
-
-	session->control->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP |
-						G_IO_NVAL, session_cb, session);
-	return;
-
-drop:
-	avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-}
-
-static void avctp_browsing_confirm(struct avctp *session, GIOChannel *chan,
-						struct btd_device *dev)
-{
-	GError *err = NULL;
-
-	if (session->control == NULL || session->browsing != NULL) {
-		error("Browsing: Refusing unexpected connect");
-		g_io_channel_shutdown(chan, TRUE, NULL);
-		return;
-	}
-
-	if (bt_io_accept(chan, avctp_connect_browsing_cb, session, NULL,
-								&err)) {
-		avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING);
-		return;
-	}
-
-	error("Browsing: %s", err->message);
-	g_error_free(err);
-
-	return;
-}
-
-static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
-{
-	struct avctp *session;
-	char address[18];
-	bdaddr_t src, dst;
-	GError *err = NULL;
-	uint16_t psm;
-	struct btd_device *device;
-
-	bt_io_get(chan, &err,
-			BT_IO_OPT_SOURCE_BDADDR, &src,
-			BT_IO_OPT_DEST_BDADDR, &dst,
-			BT_IO_OPT_DEST, address,
-			BT_IO_OPT_PSM, &psm,
-			BT_IO_OPT_INVALID);
-	if (err) {
-		error("%s", err->message);
-		g_error_free(err);
-		g_io_channel_shutdown(chan, TRUE, NULL);
-		return;
-	}
-
-	DBG("AVCTP: incoming connect from %s", address);
-
-	device = btd_adapter_find_device(adapter_find(&src), &dst);
-	if (!device)
-		return;
-
-	session = avctp_get_internal(device);
-	if (session == NULL)
-		return;
-
-	if (btd_device_get_service(device, AVRCP_REMOTE_UUID) == NULL)
-		btd_device_add_uuid(device, AVRCP_REMOTE_UUID);
-
-	if (btd_device_get_service(device, AVRCP_TARGET_UUID) == NULL)
-		btd_device_add_uuid(device, AVRCP_TARGET_UUID);
-
-	switch (psm) {
-	case AVCTP_CONTROL_PSM:
-		avctp_control_confirm(session, chan, device);
-		break;
-	case AVCTP_BROWSING_PSM:
-		avctp_browsing_confirm(session, chan, device);
-		break;
-	}
-
-	return;
-}
-
-static GIOChannel *avctp_server_socket(const bdaddr_t *src, gboolean master,
-						uint8_t mode, uint16_t psm)
-{
-	GError *err = NULL;
-	GIOChannel *io;
-
-	io = bt_io_listen(NULL, avctp_confirm_cb, NULL,
-				NULL, &err,
-				BT_IO_OPT_SOURCE_BDADDR, src,
-				BT_IO_OPT_PSM, psm,
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-				BT_IO_OPT_MASTER, master,
-				BT_IO_OPT_MODE, mode,
-				BT_IO_OPT_INVALID);
-	if (!io) {
-		error("%s", err->message);
-		g_error_free(err);
-	}
-
-	return io;
-}
-
-int avctp_register(struct btd_adapter *adapter, gboolean master)
-{
-	struct avctp_server *server;
-	const bdaddr_t *src = btd_adapter_get_address(adapter);
-
-	server = g_new0(struct avctp_server, 1);
-
-	server->control_io = avctp_server_socket(src, master, L2CAP_MODE_BASIC,
-							AVCTP_CONTROL_PSM);
-	if (!server->control_io) {
-		g_free(server);
-		return -1;
-	}
-	server->browsing_io = avctp_server_socket(src, master, L2CAP_MODE_ERTM,
-							AVCTP_BROWSING_PSM);
-	if (!server->browsing_io) {
-		if (server->control_io) {
-			g_io_channel_shutdown(server->control_io, TRUE, NULL);
-			g_io_channel_unref(server->control_io);
-			server->control_io = NULL;
-		}
-		g_free(server);
-		return -1;
-	}
-
-	server->adapter = btd_adapter_ref(adapter);
-
-	servers = g_slist_append(servers, server);
-
-	return 0;
-}
-
-void avctp_unregister(struct btd_adapter *adapter)
-{
-	struct avctp_server *server;
-
-	server = find_server(servers, adapter);
-	if (!server)
-		return;
-
-	while (server->sessions)
-		avctp_disconnected(server->sessions->data);
-
-	servers = g_slist_remove(servers, server);
-
-	g_io_channel_shutdown(server->browsing_io, TRUE, NULL);
-	g_io_channel_unref(server->browsing_io);
-	server->browsing_io = NULL;
-
-	g_io_channel_shutdown(server->control_io, TRUE, NULL);
-	g_io_channel_unref(server->control_io);
-	btd_adapter_unref(server->adapter);
-	g_free(server);
-}
-
 static struct avctp_pending_req *pending_create(struct avctp_channel *chan,
 						avctp_process_cb process,
 						void *data,
-						GDestroyNotify destroy)
+						avctp_destroy_cb_t destroy)
 {
 	struct avctp_pending_req *p;
 	GSList *l, *tmp;
@@ -1733,39 +1257,6 @@ int avctp_send_vendordep_req(struct avctp *session, uint8_t code,
 						func, user_data);
 }
 
-unsigned int avctp_add_state_cb(struct btd_device *dev, avctp_state_cb cb,
-							void *user_data)
-{
-	struct avctp_state_callback *state_cb;
-	static unsigned int id = 0;
-
-	state_cb = g_new(struct avctp_state_callback, 1);
-	state_cb->cb = cb;
-	state_cb->dev = dev;
-	state_cb->id = ++id;
-	state_cb->user_data = user_data;
-
-	callbacks = g_slist_append(callbacks, state_cb);
-
-	return state_cb->id;
-}
-
-gboolean avctp_remove_state_cb(unsigned int id)
-{
-	GSList *l;
-
-	for (l = callbacks; l != NULL; l = l->next) {
-		struct avctp_state_callback *cb = l->data;
-		if (cb && cb->id == id) {
-			callbacks = g_slist_remove(callbacks, cb);
-			g_free(cb);
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
 unsigned int avctp_register_passthrough_handler(struct avctp *session,
 						avctp_passthrough_cb cb,
 						void *user_data)
@@ -1787,29 +1278,18 @@ unsigned int avctp_register_passthrough_handler(struct avctp *session,
 	return handler->id;
 }
 
-bool avctp_unregister_passthrough_handler(unsigned int id)
+bool avctp_unregister_passthrough_handler(struct avctp *session,
+							unsigned int id)
 {
-	GSList *l;
-
-	for (l = servers; l; l = l->next) {
-		struct avctp_server *server = l->data;
-		GSList *s;
+	if (session->handler == NULL)
+		return false;
 
-		for (s = server->sessions; s; s = s->next) {
-			struct avctp *session = s->data;
-
-			if (session->handler == NULL)
-				continue;
-
-			if (session->handler->id == id) {
-				g_free(session->handler);
-				session->handler = NULL;
-				return true;
-			}
-		}
-	}
+	if (session->handler->id != id)
+		return false;
 
-	return false;
+	g_free(session->handler);
+	session->handler = NULL;
+	return true;
 }
 
 unsigned int avctp_register_pdu_handler(struct avctp *session, uint8_t opcode,
@@ -1841,7 +1321,7 @@ unsigned int avctp_register_pdu_handler(struct avctp *session, uint8_t opcode,
 unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
 						avctp_browsing_pdu_cb cb,
 						void *user_data,
-						GDestroyNotify destroy)
+						avctp_destroy_cb_t destroy)
 {
 	struct avctp_channel *browsing = session->browsing;
 	struct avctp_browsing_pdu_handler *handler;
@@ -1864,165 +1344,129 @@ unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
 	return handler->id;
 }
 
-gboolean avctp_unregister_pdu_handler(unsigned int id)
+bool avctp_unregister_pdu_handler(struct avctp *session, unsigned int id)
 {
+	struct avctp_channel *control = session->control;
 	GSList *l;
 
-	for (l = servers; l; l = l->next) {
-		struct avctp_server *server = l->data;
-		GSList *s;
-
-		for (s = server->sessions; s; s = s->next) {
-			struct avctp *session = s->data;
-			struct avctp_channel *control = session->control;
-			GSList *h;
+	if (!control)
+		return false;
 
-			if (control == NULL)
-				continue;
+	for (l = control->handlers; l; l = g_slist_next(l)) {
+		struct avctp_pdu_handler *handler = l->data;
 
-			for (h = control->handlers; h; h = h->next) {
-				struct avctp_pdu_handler *handler = h->data;
-
-				if (handler->id != id)
-					continue;
+		if (handler->id != id)
+			continue;
 
-				control->handlers = g_slist_remove(
-							control->handlers,
-							handler);
-				g_free(handler);
-				return TRUE;
-			}
-		}
+		control->handlers = g_slist_remove(control->handlers, handler);
+		g_free(handler);
+		return true;
 	}
 
-	return FALSE;
+	return false;
 }
 
-gboolean avctp_unregister_browsing_pdu_handler(unsigned int id)
+bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
+							unsigned int id)
 {
+	struct avctp_channel *browsing = session->browsing;
 	GSList *l;
 
-	for (l = servers; l; l = l->next) {
-		struct avctp_server *server = l->data;
-		GSList *s;
-
-		for (s = server->sessions; s; s = s->next) {
-			struct avctp *session = s->data;
-			struct avctp_channel *browsing = session->browsing;
-			GSList *h;
-
-			if (browsing == NULL)
-				continue;
+	if (browsing == NULL)
+		return false;
 
-			for (h = browsing->handlers; h; h = h->next) {
-				struct avctp_browsing_pdu_handler *handler =
-								h->data;
+	for (l = browsing->handlers; l; l = g_slist_next(l)) {
+		struct avctp_browsing_pdu_handler *handler = l->data;
 
-				if (handler->id != id)
-					continue;
+		if (handler->id != id)
+			continue;
 
-				browsing->handlers = g_slist_remove(
-							browsing->handlers,
-							handler);
-				g_free(handler);
-				return TRUE;
-			}
-		}
+		browsing->handlers = g_slist_remove(browsing->handlers,
+								handler);
+		g_free(handler);
+		return true;
 	}
 
-	return FALSE;
+	return false;
 }
 
-struct avctp *avctp_connect(struct btd_device *device)
+struct avctp *avctp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
 {
 	struct avctp *session;
-	GError *err = NULL;
-	GIOChannel *io;
-	const bdaddr_t *src;
-
-	session = avctp_get_internal(device);
-	if (!session)
-		return NULL;
-
-	if (session->state > AVCTP_STATE_DISCONNECTED)
-		return session;
-
-	avctp_set_state(session, AVCTP_STATE_CONNECTING);
+	struct avctp_channel *control;
+	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
-	src = btd_adapter_get_address(session->server->adapter);
+	session = g_new0(struct avctp, 1);
+	session->version = version;
 
-	io = bt_io_connect(avctp_connect_cb, session, NULL, &err,
-				BT_IO_OPT_SOURCE_BDADDR, src,
-				BT_IO_OPT_DEST_BDADDR,
-				device_get_address(session->device),
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-				BT_IO_OPT_PSM, AVCTP_CONTROL_PSM,
-				BT_IO_OPT_INVALID);
-	if (err) {
-		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-		error("%s", err->message);
-		g_error_free(err);
+	control = avctp_channel_create(session, fd, imtu, omtu, NULL);
+	if (!control) {
+		g_free(session);
 		return NULL;
 	}
 
-	session->control = avctp_channel_create(session, io, NULL);
-	session->initiator = true;
-	g_io_channel_unref(io);
+	session->control = control;
+	session->passthrough_id = avctp_register_pdu_handler(session,
+						AVC_OP_PASSTHROUGH,
+						handle_panel_passthrough,
+						NULL);
+	session->unit_id = avctp_register_pdu_handler(session,
+						AVC_OP_UNITINFO,
+						handle_unit_info,
+						NULL);
+	session->subunit_id = avctp_register_pdu_handler(session,
+						AVC_OP_SUBUNITINFO,
+						handle_subunit_info,
+						NULL);
+
+	control->watch = g_io_add_watch(session->control->io, cond,
+						(GIOFunc) session_cb, session);
 
 	return session;
 }
 
-int avctp_connect_browsing(struct avctp *session)
+int avctp_connect_browsing(struct avctp *session, int fd, size_t imtu,
+								size_t omtu)
 {
-	const bdaddr_t *src;
-	GError *err = NULL;
-	GIOChannel *io;
-
-	if (session->state != AVCTP_STATE_CONNECTED)
-		return -ENOTCONN;
-
-	if (session->browsing != NULL)
-		return 0;
+	struct avctp_channel *browsing;
+	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
 
-	avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING);
-
-	src = btd_adapter_get_address(session->server->adapter);
-
-	io = bt_io_connect(avctp_connect_browsing_cb, session, NULL, &err,
-				BT_IO_OPT_SOURCE_BDADDR, src,
-				BT_IO_OPT_DEST_BDADDR,
-				device_get_address(session->device),
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
-				BT_IO_OPT_PSM, AVCTP_BROWSING_PSM,
-				BT_IO_OPT_MODE, L2CAP_MODE_ERTM,
-				BT_IO_OPT_INVALID);
-	if (err) {
-		error("%s", err->message);
-		g_error_free(err);
-		return -EIO;
-	}
+	if (session->browsing)
+		return -EISCONN;
 
-	session->browsing = avctp_channel_create(session, io,
+	browsing = avctp_channel_create(session, fd, imtu, omtu,
 						avctp_destroy_browsing);
-	g_io_channel_unref(io);
+	if (!browsing)
+		return -EINVAL;
+
+	session->browsing = browsing;
+	browsing->watch = g_io_add_watch(session->browsing->io, cond,
+					(GIOFunc) session_browsing_cb, session);
 
 	return 0;
 }
 
-void avctp_disconnect(struct avctp *session)
+void avctp_shutdown(struct avctp *session)
 {
-	if (session->state == AVCTP_STATE_DISCONNECTED)
+	if (!session)
 		return;
 
-	avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
-}
+	if (session->browsing)
+		avctp_channel_destroy(session->browsing);
 
-struct avctp *avctp_get(struct btd_device *device)
-{
-	return avctp_get_internal(device);
-}
+	if (session->control)
+		avctp_channel_destroy(session->control);
 
-bool avctp_is_initiator(struct avctp *session)
-{
-	return session->initiator;
+	if (session->key.timer > 0)
+		g_source_remove(session->key.timer);
+
+	if (session->uinput >= 0) {
+		DBG("AVCTP: closing uinput");
+
+		ioctl(session->uinput, UI_DEV_DESTROY);
+		close(session->uinput);
+		session->uinput = -1;
+	}
+
+	g_free(session);
 }
diff --git a/android/avctp.h b/android/avctp.h
index f9c665e..99aaf95 100644
--- a/android/avctp.h
+++ b/android/avctp.h
@@ -82,19 +82,6 @@
 
 struct avctp;
 
-typedef enum {
-	AVCTP_STATE_DISCONNECTED = 0,
-	AVCTP_STATE_CONNECTING,
-	AVCTP_STATE_CONNECTED,
-	AVCTP_STATE_BROWSING_CONNECTING,
-	AVCTP_STATE_BROWSING_CONNECTED
-} avctp_state_t;
-
-typedef void (*avctp_state_cb) (struct btd_device *dev,
-				avctp_state_t old_state,
-				avctp_state_t new_state,
-				void *user_data);
-
 typedef bool (*avctp_passthrough_cb) (struct avctp *session,
 					uint8_t op, bool pressed,
 					void *user_data);
@@ -113,34 +100,33 @@ typedef size_t (*avctp_browsing_pdu_cb) (struct avctp *session,
 					uint8_t *operands, size_t operand_count,
 					void *user_data);
 
-unsigned int avctp_add_state_cb(struct btd_device *dev, avctp_state_cb cb,
-							void *user_data);
-gboolean avctp_remove_state_cb(unsigned int id);
+typedef void (*avctp_destroy_cb_t) (void *user_data);
 
-int avctp_register(struct btd_adapter *adapter, gboolean master);
-void avctp_unregister(struct btd_adapter *adapter);
+struct avctp *avctp_new(int fd, size_t imtu, size_t omtu, uint16_t version);
+int avctp_init_uinput(struct avctp *session, const char *name,
+							const char *address);
+int avctp_connect_browsing(struct avctp *session, int fd, size_t imtu,
+								size_t omtu);
 
-struct avctp *avctp_connect(struct btd_device *device);
-struct avctp *avctp_get(struct btd_device *device);
-bool avctp_is_initiator(struct avctp *session);
-int avctp_connect_browsing(struct avctp *session);
-void avctp_disconnect(struct avctp *session);
+void avctp_shutdown(struct avctp *session);
 
 unsigned int avctp_register_passthrough_handler(struct avctp *session,
 						avctp_passthrough_cb cb,
 						void *user_data);
-bool avctp_unregister_passthrough_handler(unsigned int id);
+bool avctp_unregister_passthrough_handler(struct avctp *session,
+							unsigned int id);
 
 unsigned int avctp_register_pdu_handler(struct avctp *session, uint8_t opcode,
 						avctp_control_pdu_cb cb,
 						void *user_data);
-gboolean avctp_unregister_pdu_handler(unsigned int id);
+bool avctp_unregister_pdu_handler(struct avctp *session, unsigned int id);
 
 unsigned int avctp_register_browsing_pdu_handler(struct avctp *session,
 						avctp_browsing_pdu_cb cb,
 						void *user_data,
-						GDestroyNotify destroy);
-gboolean avctp_unregister_browsing_pdu_handler(unsigned int id);
+						avctp_destroy_cb_t destroy);
+bool avctp_unregister_browsing_pdu_handler(struct avctp *session,
+							unsigned int id);
 
 int avctp_send_passthrough(struct avctp *session, uint8_t op);
 int avctp_send_vendordep(struct avctp *session, uint8_t transaction,
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH BlueZ v3 3/8] android: Add initial skeleton for AVRCP in the daemon
From: Luiz Augusto von Dentz @ 2014-01-26 23:55 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1390780546-18402-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/Android.mk                          |  1 +
 android/Makefile.am                         |  1 +
 plugins/external-dummy.c => android/avrcp.c | 32 ++++++++++++++++++++++-------
 android/{hidhost.h => avrcp.h}              |  6 +++---
 android/main.c                              | 11 ++++++++++
 5 files changed, 41 insertions(+), 10 deletions(-)
 copy plugins/external-dummy.c => android/avrcp.c (62%)
 copy android/{hidhost.h => avrcp.h} (84%)

diff --git a/android/Android.mk b/android/Android.mk
index 5f2c1d4..169eba8 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.c \
 	bluez/android/pan.c \
 	bluez/src/log.c \
 	bluez/src/shared/mgmt.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index 88fe667..d4a76bb 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.h android/avrcp.c \
 				android/socket.h android/socket.c \
 				android/pan.h android/pan.c \
 				btio/btio.h btio/btio.c \
diff --git a/plugins/external-dummy.c b/android/avrcp.c
similarity index 62%
copy from plugins/external-dummy.c
copy to android/avrcp.c
index 536ad06..a6fb5f5 100644
--- a/plugins/external-dummy.c
+++ b/android/avrcp.c
@@ -2,6 +2,9 @@
  *
  *  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
@@ -22,20 +25,35 @@
 #include <config.h>
 #endif
 
-#include "src/plugin.h"
+#include <stdbool.h>
+#include <glib.h>
+
+#include "lib/bluetooth.h"
 #include "src/log.h"
+#include "avrcp.h"
+#include "hal-msg.h"
+#include "ipc.h"
+
+static bdaddr_t adapter_addr;
+
+static const struct ipc_handler cmd_handlers[] = {
+};
 
-static int dummy_init(void)
+bool bt_avrcp_register(const bdaddr_t *addr)
 {
 	DBG("");
 
-	return 0;
+	bacpy(&adapter_addr, addr);
+
+	ipc_register(HAL_SERVICE_ID_AVRCP, cmd_handlers,
+						G_N_ELEMENTS(cmd_handlers));
+
+	return true;
 }
 
-static void dummy_exit(void)
+void bt_avrcp_unregister(void)
 {
 	DBG("");
-}
 
-BLUETOOTH_PLUGIN_DEFINE(external_dummy, VERSION,
-		BLUETOOTH_PLUGIN_PRIORITY_LOW, dummy_init, dummy_exit)
+	ipc_unregister(HAL_SERVICE_ID_AVRCP);
+}
diff --git a/android/hidhost.h b/android/avrcp.h
similarity index 84%
copy from android/hidhost.h
copy to android/avrcp.h
index ea14446..6fe7fbf 100644
--- a/android/hidhost.h
+++ b/android/avrcp.h
@@ -2,7 +2,7 @@
  *
  *  BlueZ - Bluetooth protocol stack for Linux
  *
- *  Copyright (C) 2013  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2014  Intel Corporation. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -21,5 +21,5 @@
  *
  */
 
-bool bt_hid_register(const bdaddr_t *addr);
-void bt_hid_unregister(void);
+bool bt_avrcp_register(const bdaddr_t *addr);
+void bt_avrcp_unregister(void);
diff --git a/android/main.c b/android/main.c
index cdeb420..c6ada62 100644
--- a/android/main.c
+++ b/android/main.c
@@ -55,6 +55,7 @@
 #include "ipc.h"
 #include "a2dp.h"
 #include "pan.h"
+#include "avrcp.h"
 
 #define STARTUP_GRACE_SECONDS 5
 #define SHUTDOWN_GRACE_SECONDS 10
@@ -107,6 +108,13 @@ static void service_register(const void *buf, uint16_t len)
 		}
 
 		break;
+	case HAL_SERVICE_ID_AVRCP:
+		if (!bt_avrcp_register(&adapter_bdaddr)) {
+			status = HAL_STATUS_FAILED;
+			goto failed;
+		}
+
+		break;
 	default:
 		DBG("service %u not supported", m->service_id);
 		status = HAL_STATUS_FAILED;
@@ -149,6 +157,9 @@ static void service_unregister(const void *buf, uint16_t len)
 	case HAL_SERVICE_ID_PAN:
 		bt_pan_unregister();
 		break;
+	case HAL_SERVICE_ID_AVRCP:
+		bt_avrcp_unregister();
+		break;
 	default:
 		/* This would indicate bug in HAL, as unregister should not be
 		 * called in init failed */
-- 
1.8.4.2


^ permalink raw reply related

* [PATCH BlueZ v3 4/8]  android: Add initial skeleton for AVRCP in the HAL
From: Luiz Augusto von Dentz @ 2014-01-26 23:55 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1390780546-18402-1-git-send-email-luiz.dentz@gmail.com>

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

---
 android/Android.mk      |  1 +
 android/Makefile.am     |  1 +
 android/hal-avrcp.c     | 87 +++++++++++++++++++++++++++++++++++++++++++++++++
 android/hal-bluetooth.c |  3 ++
 android/hal.h           |  2 ++
 5 files changed, 94 insertions(+)
 create mode 100644 android/hal-avrcp.c

diff --git a/android/Android.mk b/android/Android.mk
index 169eba8..0bd8b91 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -98,6 +98,7 @@ LOCAL_SRC_FILES := \
 	bluez/android/hal-hidhost.c \
 	bluez/android/hal-pan.c \
 	bluez/android/hal-a2dp.c \
+	bluez/android/hal-avrcp.c \
 	bluez/android/hal-utils.c \
 
 LOCAL_C_INCLUDES += \
diff --git a/android/Makefile.am b/android/Makefile.am
index d4a76bb..664524f 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -50,6 +50,7 @@ android_bluetooth_default_la_SOURCES = android/hal.h android/hal-bluetooth.c \
 					android/hal-hidhost.c \
 					android/hal-pan.c \
 					android/hal-a2dp.c \
+					android/hal-avrcp.c \
 					android/hardware/bluetooth.h \
 					android/hardware/bt_av.h \
 					android/hardware/bt_gatt.h \
diff --git a/android/hal-avrcp.c b/android/hal-avrcp.c
new file mode 100644
index 0000000..01d233b
--- /dev/null
+++ b/android/hal-avrcp.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "hal-log.h"
+#include "hal.h"
+#include "hal-msg.h"
+#include "hal-ipc.h"
+
+static const btrc_callbacks_t *cbs = NULL;
+
+static bool interface_ready(void)
+{
+	return cbs != NULL;
+}
+
+static bt_status_t init(btrc_callbacks_t *callbacks)
+{
+	struct hal_cmd_register_module cmd;
+	int ret;
+
+	DBG("");
+
+	if (interface_ready())
+		return BT_STATUS_DONE;
+
+	cbs = callbacks;
+
+	cmd.service_id = HAL_SERVICE_ID_AVRCP;
+
+	ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
+
+	if (ret != BT_STATUS_SUCCESS) {
+		cbs = NULL;
+		hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
+	}
+
+	return ret;
+}
+
+static void cleanup()
+{
+	struct hal_cmd_unregister_module cmd;
+
+	DBG("");
+
+	if (!interface_ready())
+		return;
+
+	cbs = NULL;
+
+	cmd.service_id = HAL_SERVICE_ID_AVRCP;
+
+	hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
+					sizeof(cmd), &cmd, 0, NULL, NULL);
+
+	hal_ipc_unregister(HAL_SERVICE_ID_AVRCP);
+}
+
+static btrc_interface_t iface = {
+	.size = sizeof(iface),
+	.init = init,
+	.cleanup = cleanup
+};
+
+btrc_interface_t *bt_get_avrcp_interface()
+{
+	return &iface;
+}
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 4f0e7b7..0dac158 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -762,6 +762,9 @@ static const void *get_profile_interface(const char *profile_id)
 	if (!strcmp(profile_id, BT_PROFILE_ADVANCED_AUDIO_ID))
 		return bt_get_a2dp_interface();
 
+	if (!strcmp(profile_id, BT_PROFILE_AV_RC_ID))
+		return bt_get_avrcp_interface();
+
 	return NULL;
 }
 
diff --git a/android/hal.h b/android/hal.h
index b475411..1ff4fbd 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -20,11 +20,13 @@
 #include <hardware/bt_hh.h>
 #include <hardware/bt_pan.h>
 #include <hardware/bt_av.h>
+#include <hardware/bt_rc.h>
 
 btsock_interface_t *bt_get_sock_interface(void);
 bthh_interface_t *bt_get_hidhost_interface(void);
 btpan_interface_t *bt_get_pan_interface(void);
 btav_interface_t *bt_get_a2dp_interface(void);
+btrc_interface_t *bt_get_avrcp_interface(void);
 
 void bt_thread_associate(void);
 void bt_thread_disassociate(void);
-- 
1.8.4.2


^ permalink raw reply related


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