Linux bluetooth development
 help / color / mirror / Atom feed
* [RFC -v2 12/16] Bluetooth: Use abstract chan->data in comparison
From: Gustavo Padovan @ 2012-12-21 18:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1356113459-7932-1-git-send-email-gustavo@padovan.org>

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

If the L2CAP user is l2cap_sock.c chan->data is a pointer to the l2cap
socket so chan->sk and chan->data are the same thing. Then we can just
compare with chan->data instead.

Non-socket users will have skb->sk = NULL, thus this change does not
interfere in other users.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 include/net/bluetooth/l2cap.h | 2 +-
 net/bluetooth/l2cap_core.c    | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0c76c55..6986140 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -536,7 +536,7 @@ struct l2cap_chan {
 	struct list_head	list;
 	struct list_head	global_l;
 
-	void			*data;
+	void			*data; /* l2cap user data. eg: sk for sockets */
 	struct l2cap_ops	*ops;
 	struct mutex		lock;
 };
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6d62bfb..935534c 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -2677,12 +2677,11 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
 	mutex_lock(&conn->chan_lock);
 
 	list_for_each_entry(chan, &conn->chan_l, list) {
-		struct sock *sk = chan->sk;
 		if (chan->chan_type != L2CAP_CHAN_RAW)
 			continue;
 
 		/* Don't send frame to the socket it came from */
-		if (skb->sk == sk)
+		if (skb->sk && skb->sk == chan->data)
 			continue;
 		nskb = skb_clone(skb, GFP_KERNEL);
 		if (!nskb)
-- 
1.8.0.2


^ permalink raw reply related

* [RFC -v2 13/16] Bluetooth: Move l2cap_wait_ack() to l2cap_sock.c
From: Gustavo Padovan @ 2012-12-21 18:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1356113459-7932-1-git-send-email-gustavo@padovan.org>

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

The wait_ack code has a heavy dependency on the socket data structures
and, as of now, it won't be worthless change it to use non-socket
structures as the only user of such feature is a socket.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 include/net/bluetooth/l2cap.h |  3 ++-
 net/bluetooth/l2cap_core.c    | 32 --------------------------------
 net/bluetooth/l2cap_sock.c    | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 6986140..574b3ae 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -757,6 +757,8 @@ static inline bool l2cap_clear_timer(struct l2cap_chan *chan,
 		msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
 #define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
 
+#define __missing_ack(c) (c->unacked_frames > 0 && c->conn)
+
 static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2)
 {
 	if (seq1 >= seq2)
@@ -793,7 +795,6 @@ int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
 
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
-int __l2cap_wait_ack(struct sock *sk);
 
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 935534c..f151775 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1706,38 +1706,6 @@ done:
 	return err;
 }
 
-int __l2cap_wait_ack(struct sock *sk)
-{
-	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-	DECLARE_WAITQUEUE(wait, current);
-	int err = 0;
-	int timeo = HZ/5;
-
-	add_wait_queue(sk_sleep(sk), &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	while (chan->unacked_frames > 0 && chan->conn) {
-		if (!timeo)
-			timeo = HZ/5;
-
-		if (signal_pending(current)) {
-			err = sock_intr_errno(timeo);
-			break;
-		}
-
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		err = sock_error(sk);
-		if (err)
-			break;
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
-	return err;
-}
-
 static void l2cap_monitor_timeout(struct work_struct *work)
 {
 	struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 3d76de8..58b4a5d 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -853,6 +853,38 @@ static void l2cap_sock_kill(struct sock *sk)
 	sock_put(sk);
 }
 
+static int __l2cap_wait_ack(struct sock *sk)
+{
+	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	DECLARE_WAITQUEUE(wait, current);
+	int err = 0;
+	int timeo = HZ/5;
+
+	add_wait_queue(sk_sleep(sk), &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (__missing_ack(chan)) {
+		if (!timeo)
+			timeo = HZ/5;
+
+		if (signal_pending(current)) {
+			err = sock_intr_errno(timeo);
+			break;
+		}
+
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		err = sock_error(sk);
+		if (err)
+			break;
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk_sleep(sk), &wait);
+	return err;
+}
+
 static int l2cap_sock_shutdown(struct socket *sock, int how)
 {
 	struct sock *sk = sock->sk;
-- 
1.8.0.2


^ permalink raw reply related

* [RFC -v2 14/16] Bluetooth: Create l2cap->ops->resume()
From: Gustavo Padovan @ 2012-12-21 18:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1356113459-7932-1-git-send-email-gustavo@padovan.org>

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

resume() will isolate the code the code to get a socket back from the
suspended state when a security elevation happens.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 include/net/bluetooth/l2cap.h |  5 +++++
 net/bluetooth/a2mp.c          |  1 +
 net/bluetooth/l2cap_core.c    |  6 +-----
 net/bluetooth/l2cap_sock.c    | 13 +++++++++++++
 4 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 574b3ae..cab7773 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -555,6 +555,7 @@ struct l2cap_ops {
 	void			(*defer) (struct l2cap_chan *chan);
 	struct sk_buff		*(*alloc_skb) (struct l2cap_chan *chan,
 					       unsigned long len, int nb);
+	void			(*resume) (struct l2cap_chan *chan);
 };
 
 struct l2cap_conn {
@@ -789,6 +790,10 @@ static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
 {
 }
 
+static inline void l2cap_chan_no_resume(struct l2cap_chan *chan)
+{
+}
+
 extern bool disable_ertm;
 
 int l2cap_init_sockets(void);
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index ad6e42f..4a542b3 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -708,6 +708,7 @@ static struct l2cap_ops a2mp_chan_ops = {
 	.teardown = l2cap_chan_no_teardown,
 	.ready = l2cap_chan_no_ready,
 	.defer = l2cap_chan_no_defer,
+	.resume = l2cap_chan_no_resume,
 };
 
 static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index f151775..72dd394 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6315,11 +6315,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 
 		if (!status && (chan->state == BT_CONNECTED ||
 				chan->state == BT_CONFIG)) {
-			struct sock *sk = chan->sk;
-
-			clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
-			sk->sk_state_change(sk);
-
+			chan->ops->resume(chan);
 			l2cap_check_encryption(chan, encrypt);
 			l2cap_chan_unlock(chan);
 			continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 58b4a5d..e7b3291 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1147,6 +1147,18 @@ static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
 	release_sock(sk);
 }
 
+static void l2cap_sock_resume_cb(struct l2cap_chan *chan)
+{
+	struct sock *sk = chan->data;
+
+	lock_sock(sk);
+
+	clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags);
+	sk->sk_state_change(sk);
+
+	release_sock(sk);
+}
+
 static struct l2cap_ops l2cap_chan_ops = {
 	.name		= "L2CAP Socket Interface",
 	.new_connection	= l2cap_sock_new_connection_cb,
@@ -1157,6 +1169,7 @@ static struct l2cap_ops l2cap_chan_ops = {
 	.ready		= l2cap_sock_ready_cb,
 	.defer		= l2cap_sock_defer_cb,
 	.alloc_skb	= l2cap_sock_alloc_skb_cb,
+	.resume		= l2cap_sock_resume_cb,
 };
 
 static void l2cap_sock_destruct(struct sock *sk)
-- 
1.8.0.2


^ permalink raw reply related

* [RFC -v2 15/16] Bluetooth: Create l2cap->ops->set_shutdown()
From: Gustavo Padovan @ 2012-12-21 18:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1356113459-7932-1-git-send-email-gustavo@padovan.org>

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Isolates the code that sets the socket shutdown mask. This is the last
commit to remove the socket usage from l2cap_core.c

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 include/net/bluetooth/l2cap.h |  5 +++++
 net/bluetooth/a2mp.c          |  1 +
 net/bluetooth/l2cap_core.c    |  7 +------
 net/bluetooth/l2cap_sock.c    | 10 ++++++++++
 4 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index cab7773..d3c8f57 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -556,6 +556,7 @@ struct l2cap_ops {
 	struct sk_buff		*(*alloc_skb) (struct l2cap_chan *chan,
 					       unsigned long len, int nb);
 	void			(*resume) (struct l2cap_chan *chan);
+	void			(*set_shutdown) (struct l2cap_chan *chan);
 };
 
 struct l2cap_conn {
@@ -794,6 +795,10 @@ static inline void l2cap_chan_no_resume(struct l2cap_chan *chan)
 {
 }
 
+static inline void l2cap_chan_no_set_shutdown(struct l2cap_chan *chan)
+{
+}
+
 extern bool disable_ertm;
 
 int l2cap_init_sockets(void);
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 4a542b3..0a2ec84 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -709,6 +709,7 @@ static struct l2cap_ops a2mp_chan_ops = {
 	.ready = l2cap_chan_no_ready,
 	.defer = l2cap_chan_no_defer,
 	.resume = l2cap_chan_no_resume,
+	.set_shutdown = l2cap_chan_no_set_shutdown,
 };
 
 static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 72dd394..5104a88 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3973,7 +3973,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
 	struct l2cap_disconn_rsp rsp;
 	u16 dcid, scid;
 	struct l2cap_chan *chan;
-	struct sock *sk;
 
 	scid = __le16_to_cpu(req->scid);
 	dcid = __le16_to_cpu(req->dcid);
@@ -3990,15 +3989,11 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
 
 	l2cap_chan_lock(chan);
 
-	sk = chan->sk;
-
 	rsp.dcid = cpu_to_le16(chan->scid);
 	rsp.scid = cpu_to_le16(chan->dcid);
 	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
 
-	lock_sock(sk);
-	sk->sk_shutdown = SHUTDOWN_MASK;
-	release_sock(sk);
+	chan->ops->set_shutdown(chan);
 
 	l2cap_chan_hold(chan);
 	l2cap_chan_del(chan, ECONNRESET);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index e7b3291..07ef90c 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1159,6 +1159,15 @@ static void l2cap_sock_resume_cb(struct l2cap_chan *chan)
 	release_sock(sk);
 }
 
+static void l2cap_sock_set_shutdown_cb(struct l2cap_chan *chan)
+{
+	struct sock *sk = chan->data;
+
+	lock_sock(sk);
+	sk->sk_shutdown = SHUTDOWN_MASK;
+	release_sock(sk);
+}
+
 static struct l2cap_ops l2cap_chan_ops = {
 	.name		= "L2CAP Socket Interface",
 	.new_connection	= l2cap_sock_new_connection_cb,
@@ -1170,6 +1179,7 @@ static struct l2cap_ops l2cap_chan_ops = {
 	.defer		= l2cap_sock_defer_cb,
 	.alloc_skb	= l2cap_sock_alloc_skb_cb,
 	.resume		= l2cap_sock_resume_cb,
+	.set_shutdown	= l2cap_sock_set_shutdown_cb,
 };
 
 static void l2cap_sock_destruct(struct sock *sk)
-- 
1.8.0.2


^ permalink raw reply related

* [RFC -v2 16/16] Bluetooth: Remove sk member from struct l2cap_chan
From: Gustavo Padovan @ 2012-12-21 18:10 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1356113459-7932-1-git-send-email-gustavo@padovan.org>

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

Now that the removal of socket usage from l2cap_core.c is done we can
remove sk from struct l2cap_chan since we do not use it anywhere anymore.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 include/net/bluetooth/l2cap.h | 2 --
 net/bluetooth/l2cap_sock.c    | 5 ++---
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index d3c8f57..e444d55 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -433,8 +433,6 @@ struct l2cap_seq_list {
 #define L2CAP_SEQ_LIST_TAIL	0x8000
 
 struct l2cap_chan {
-	struct sock *sk;
-
 	bdaddr_t	src;
 	bdaddr_t	dst;
 
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 07ef90c..910c9d7 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1101,11 +1101,12 @@ static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state,
 static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
 					       unsigned long len, int nb)
 {
+	struct sock *sk = chan->data;
 	struct sk_buff *skb;
 	int err;
 
 	l2cap_chan_unlock(chan);
-	skb = bt_skb_send_alloc(chan->sk, len, nb, &err);
+	skb = bt_skb_send_alloc(sk, len, nb, &err);
 	l2cap_chan_lock(chan);
 
 	if (!skb)
@@ -1293,8 +1294,6 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 
 	l2cap_chan_hold(chan);
 
-	chan->sk = sk;
-
 	l2cap_pi(sk)->chan = chan;
 
 	return sk;
-- 
1.8.0.2


^ permalink raw reply related

* Re: [PATCH 2/2] Bluetooth: mgmt: Avoid using magic number in status code
From: Gustavo Padovan @ 2012-12-21 19:10 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1355407881-22110-2-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

* Szymon Janc <szymon.janc@tieto.com> [2012-12-13 15:11:21 +0100]:

> Use MGMT_STATUS_SUCCESS for success return code.
> 
> Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
> ---
>  net/bluetooth/mgmt.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)

Both patches have been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply

* Re: [PATCH 1/2] Bluetooth: Fix to update EIR for uuid16 properly
From: Johan Hedberg @ 2012-12-21 19:31 UTC (permalink / raw)
  To: Syam Sidhardhan; +Cc: linux-bluetooth
In-Reply-To: <1356097469-24073-1-git-send-email-s.syam@samsung.com>

Hi Syam,

On Fri, Dec 21, 2012, Syam Sidhardhan wrote:
> If we register a uuid other than uuid16, especially custom 128 bit uuid
> then nothing is updated in the EIR and it was broken.
> 
> After registering a 16 bit uuid. ex: "sdptool add SP", we can see the
> uuid in the EIR as below.
> < 0000: 01 52 0c f1 00 08 09 52  65 64 77 6f 6f 64 15 03  .R.....Redwood..
>   0010: 01 11 32 11 2f 11 06 11  05 11 0a 11 0e 11 0c 11  ..2./...........
>   0020: 1f 11 12 11 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0030: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0040: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0050: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0060: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0070: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0080: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0090: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00a0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00b0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00c0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00d0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00e0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00f0: 00 00 00 00 00                                    .....
> > 0000: 04 0e 04 01 52 0c 00                              ....R..
> 
> But after register a user defined 128 bit uuid, nothing is
> updated in the EIR.
> 
> < 0000: 01 52 0c f1 00 08 09 52  65 64 77 6f 6f 64 00 00  .R.....Redwood..
>   0010: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0020: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0030: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0040: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0050: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0060: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0070: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0080: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   0090: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00a0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00b0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00c0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00d0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00e0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
>   00f0: 00 00 00 00 00                                    .....
> > 0000: 04 0e 04 01 52 0c 00                              ....R..
> 
> With this fix, we can see the EIR is updated properly.
> 
> Signed-off-by: Syam Sidhardhan <s.syam@samsung.com>
> ---
>  net/bluetooth/mgmt.c |    2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index f559b96..512a3f5 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -514,8 +514,6 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
>  		u16 uuid16;
>  
>  		uuid16 = get_uuid16(uuid->uuid);
> -		if (uuid16 == 0)
> -			return;
>  
>  		if (uuid16 < 0x1100)
>  			continue;

Nak. The bug is real and should be fixed but your fix is wrong. The
right fix it to convert this return statement into a continue statement
since we do still want to check for a 0 return value from get_uuid16.

Along with this patch please prepare another one to increment the mgmt
revision. These two should go together to upstream trees so that we can
introduce a check in user space to know whether it's safe to pass
non-16bit UUIDs to the kernel or not.

Johan

^ permalink raw reply

* [PATCH BlueZ 00/25] Broadcaster/Observer implementation
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira

Main changes from RFC series:
- Add version to Observer interface (org.bluez.Observer1)
- Merge some patches to decrease series size.

This series contains the implementation for Broadcaster/Observer roles. It has
changes for adapter API, userspace implementation for MGMT API and new commands
in btmgmt tool.

The kernel patches for new MGMT commands were sent one week ago by Jefferson
Delfes: http://article.gmane.org/gmane.linux.bluez.kernel/32703

For now, only Service Data and Manufacturer Specific Data can be
broadcasted/observed. All other data types defined by BT SIG are not
appropriate for general application use, and should be managed by BlueZ itself.

For Observer role, we have:
* Two methods to register watchers: RegisterServiceObserver() and
  RegisterManufacturerObserver().
* Respective methods to unregister watchers: UnregisterServiceObserver() and
  UnregisterManufacturerObserver()
* The data received are sent to application through ServiceReceived() and/or
  ManufacturerReceived().

An application can register only a observer watcher for each type: one for
Service Data and one for Manufacturer Specific Data. Both types can be enabled
for the same watcher.

For Broadcaster role, we have:
* Two methods to set data in controller: SetServiceData() and
  SetManufacturerData().
* One method for releasing any previously set Advertising data:
  ClearBroadcastData().

The same application can set a new Service Data and a new Manufacturer Specific
Data. To update any data set previously, the application should use
SetServiceData() or SetManufacturerData() using same Service UUID or Company
Identifier Code, respectively. Using ClearBroadcastData() will clean all data
set by application.

For MGMT API, new functions were implemented for Set Observer, Set Broadcaster,
Set Controller Data and Unset Controller Data (see doc/mgmt-api.txt for
details).

Anderson Lizardo (1):
  mgmt-api: Broadcaster/Observer management API

Bruna Moreira (13):
  lib: Add set broadcaster/observer operations
  btmgmt: Add set controller data support
  btmgmt: Add unset controller data support
  doc: Add Broadcaster/Observer D-Bus API documentation
  observer: Add Register/UnregisterManufacturerObserver() D-Bus method
  observer: Add watchers and filters for observers
  observer: Add Service/ManufacturerReceived() D-Bus method
  observer: Add python test script
  lib: Maximum value to advertising and scan response
  broadcaster: Build and send ADV/EIR data blob to kernel
  broadcaster: Add ClearBroadcastData() D-Bus method
  broadcaster: Update some data of already broadcast value
  broadcaster: Add python test script

Jefferson Delfes (11):
  lib: Add set/uset controller data operations
  btmgmt: Add set broadcaster and set observer support
  mgmt: Add set observer and set broadcaster command
  mgmt: Add set controller data command
  mgmt: Add unset controller data command
  adapter: Add D-Bus API for Observer GAP Role
  observer: Add Register/UnregisterServiceObserver() D-Bus method
  eir: Add manufacturer and service data fields
  adapter: Add D-Bus API for Broadcaster GAP Role
  broadcaster: Add SetService/ManufacturerData() D-Bus method
  broadcaster: Add list of broadcaster sessions

 doc/adapter-api.txt   |  117 +++++++
 doc/mgmt-api.txt      |   64 ++++
 lib/hci.h             |    6 +-
 lib/mgmt.h            |   26 ++
 src/adapter.c         |  811 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/adapter.h         |    3 +
 src/bluetooth.conf    |    1 +
 src/eir.c             |   42 +++
 src/eir.h             |   19 ++
 src/mgmt.c            |  119 ++++++++
 src/mgmt.h            |    6 +
 test/test-broadcaster |   61 ++++
 test/test-observer    |   75 +++++
 tools/btmgmt.c        |  139 +++++++++
 14 files changed, 1486 insertions(+), 3 deletions(-)
 create mode 100755 test/test-broadcaster
 create mode 100755 test/test-observer

-- 
1.7.9.5


^ permalink raw reply

* [PATCH BlueZ 01/25] mgmt-api: Broadcaster/Observer management API
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Anderson Lizardo <anderson.lizardo@openbossa.org>

Add new management commands for enabling or disabling broadcasting and
observation modes, as defined by the Observer and Broadcaster GAP roles
on the Core specification 4.0.

The commands can also be used for adding information to EIR on BR/EDR
controllers. For a list of all available AD/EIR types, see the Core
Specification Supplement (CSS) document.

Note that some AD/EIR types are managed internally by the kernel and are
not available through these new commands.
---
 doc/mgmt-api.txt |   64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 60f4da4..fe052af 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -141,6 +141,8 @@ Read Controller Information Command
 		8	Basic Rate/Enhanced Data Rate
 		9	High Speed
 		10	Low Energy
+		11	Broadcaster
+		12	Observer
 
 	This command generates a Command Complete event on success or
 	a Command Status event on failure.
@@ -845,6 +847,68 @@ Set Device ID Command
 	a Command Status event on failure.
 
 
+Set Controller Data Command
+===========================
+
+	Command Code:		0x0029
+	Controller Index:	<controller id>
+	Command Parameters:	Flags (1 Octet)
+				Type (1 Octet)
+				Length (1 Octet)
+				Data (0-255 Octets)
+	Return Parameters:
+
+	This command can be used to set AD for LE capable controllers or EIR
+	for BR/EDR controllers. Multiple AD/EIR types can be configured by
+	calling this command multiple times. If the controller is BR/EDR/LE
+	capable (also known as "dual mode"), only the LE advertising is set.
+
+	The Flags parameter is currently unused, but it will contain bitwise
+	flags to fine tune how and when the data will set on the controller.
+
+	This command generates a Command Complete event on success or
+	a Command Status event on failure.
+
+
+Unset Controller Data Command
+=============================
+
+	Command Code:		0x002A
+	Controller Index:	<controller id>
+	Command Parameters:	Type (1 Octet)
+	Return Parameters:
+
+	Remove the AD/EIR information identified by Type, so it will not be
+	broadcasted anymore.
+
+	This command generates a Command Complete event on success or
+	on failure.
+
+
+Set Broadcaster Command
+=======================
+
+	Command Code:		0x002B
+	Controller Index:	<controller id>
+	Command Parameters:	Broadcaster (1 Octet)
+	Return Parameters:	Current_Settings (4 Octets)
+
+	This command generates a Command Complete event on success or
+	a Command Status event on failure.
+
+
+Set Observer Command
+====================
+
+	Command Code:		0x002C
+	Controller Index:	<controller id>
+	Command Parameters:	Observer (1 Octet)
+	Return Parameters:	Current_Settings (4 Octets)
+
+	This command generates a Command Complete event on success or
+	a Command Status event on failure.
+
+
 Command Complete Event
 ======================
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 02/25] lib: Add set/uset controller data operations
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

Add structure for new commands: Set Controller Data and Unset Controller
Data. Add new defines for flags that will be used in Set/Unset
Controller Data operation.
---
 lib/mgmt.h |   18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/lib/mgmt.h b/lib/mgmt.h
index 6c7e44a..fffb0aa 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -318,6 +318,22 @@ struct mgmt_cp_set_device_id {
 	uint16_t version;
 } __packed;
 
+#define MGMT_DATA_NORMAL_PRIORITY	0x00
+#define MGMT_DATA_HIGH_PRIORITY		0x01
+
+#define MGMT_OP_SET_CONTROLLER_DATA	0x0029
+struct mgmt_cp_set_controller_data {
+	uint8_t flags;
+	uint8_t type;
+	uint8_t length;
+	uint8_t data[0];
+} __packed;
+
+#define MGMT_OP_UNSET_CONTROLLER_DATA	0x002A
+struct mgmt_cp_unset_controller_data {
+	uint8_t type;
+} __packed;
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	uint16_t opcode;
@@ -496,6 +512,8 @@ static const char *mgmt_op[] = {
 	"Block Device",
 	"Unblock Device",
 	"Set Device ID",
+	"Set Controller Data",
+	"Unset Controller Data",
 };
 
 static const char *mgmt_ev[] = {
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 03/25] lib: Add set broadcaster/observer operations
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

Add opcodes for new Set Broadcaster and Set Observer commands.
---
 lib/mgmt.h |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lib/mgmt.h b/lib/mgmt.h
index fffb0aa..44c4405 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -92,6 +92,8 @@ struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_BREDR		0x00000080
 #define MGMT_SETTING_HS			0x00000100
 #define MGMT_SETTING_LE			0x00000200
+#define MGMT_SETTING_BROADCASTER	0x00000400
+#define MGMT_SETTING_OBSERVER		0x00000800
 
 #define MGMT_OP_READ_INFO		0x0004
 struct mgmt_rp_read_info {
@@ -334,6 +336,10 @@ struct mgmt_cp_unset_controller_data {
 	uint8_t type;
 } __packed;
 
+#define MGMT_OP_SET_BROADCASTER		0x002B
+
+#define MGMT_OP_SET_OBSERVER		0x002C
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	uint16_t opcode;
@@ -514,6 +520,8 @@ static const char *mgmt_op[] = {
 	"Set Device ID",
 	"Set Controller Data",
 	"Unset Controller Data",
+	"Set Broadcaster",
+	"Set Observer",
 };
 
 static const char *mgmt_ev[] = {
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 04/25] btmgmt: Add set broadcaster and set observer support
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

Add new broadcaster command for running the Set Broadcaster operation
from MGMT API. Also, add new observer command for running the Set
Observer operation from MGMT API.
---
 tools/btmgmt.c |   14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index b89bcac..4d9eab6 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -235,6 +235,8 @@ static const char *settings_str[] = {
 				"br/edr",
 				"hs",
 				"le" ,
+				"broadcaster",
+				"observer",
 };
 
 static void print_settings(uint32_t settings)
@@ -1111,6 +1113,16 @@ static void cmd_le(int mgmt_sk, uint16_t index, int argc, char **argv)
 	cmd_setting(mgmt_sk, index, MGMT_OP_SET_LE, argc, argv);
 }
 
+static void cmd_broadcaster(int mgmt_sk, uint16_t index, int argc, char **argv)
+{
+	cmd_setting(mgmt_sk, index, MGMT_OP_SET_BROADCASTER, argc, argv);
+}
+
+static void cmd_observer(int mgmt_sk, uint16_t index, int argc, char **argv)
+{
+	cmd_setting(mgmt_sk, index, MGMT_OP_SET_OBSERVER, argc, argv);
+}
+
 static void class_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
 				void *rsp, uint16_t len, void *user_data)
 {
@@ -1848,6 +1860,8 @@ static struct {
 	{ "rm-uuid",	cmd_remove_uuid, "Remove UUID"			},
 	{ "clr-uuids",	cmd_clr_uuids,	"Clear UUIDs",			},
 	{ "did",	cmd_did,	"Set Device ID",		},
+	{ "broadcaster",cmd_broadcaster,"Toggle Broadcaster Mode",	},
+	{ "observer",	cmd_observer,	"Toggle Observer Mode",		},
 	{ NULL, NULL, 0 }
 };
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 05/25] btmgmt: Add set controller data support
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

Add new command set-data for running the Set Controller Data operation
from MGMT API.
---
 tools/btmgmt.c |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 4d9eab6..3ae0ecb 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -1829,6 +1829,90 @@ done:
 	}
 }
 
+static void set_data_rsp(int mgmt_sk, uint16_t op, uint16_t id, uint8_t status,
+				void *rsp, uint16_t len, void *user_data)
+{
+	if (status != 0) {
+		fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
+				mgmt_opstr(op), status, mgmt_errstr(status));
+		exit(EXIT_FAILURE);
+	}
+
+	exit(EXIT_SUCCESS);
+}
+
+static void set_data_usage(void)
+{
+	printf("Usage: btmgmt set_data [-p] <data type> <byte array>\n");
+	printf("\nexample: btmgmt set_data -p 0xff 11 11 aa bb cc\n");
+	printf("\nparameters:\n");
+	printf("\tp: controller data priority.\n");
+	printf("\t<data type>: 0x16 (service data) or 0xff (manufacturer\n"
+		"\t specific data). Values different from that will return\n"
+		"\t error from kernel.\n");
+	printf("\t<byte array>: two bytes (service uuid or company identifier\n"
+		"\t code) following by hex encoded bytes (data).\n");
+}
+
+static struct option set_data_options[] = {
+	{ "help",	0, 0, 'h' },
+	{ "priority",	1, 0, 'p' },
+	{ 0, 0, 0, 0 }
+};
+
+static void cmd_set_data(int mgmt_sk, uint16_t index, int argc, char **argv)
+{
+	struct mgmt_cp_set_controller_data *cp;
+	uint8_t data_len, flags = 0;
+	unsigned int i;
+	int opt;
+
+	while ((opt = getopt_long(argc, argv, "+ph", set_data_options,
+								NULL)) != -1) {
+		switch (opt) {
+		case 'p':
+			flags = MGMT_DATA_HIGH_PRIORITY;
+			break;
+		case 'h':
+		default:
+			set_data_usage();
+			exit(EXIT_SUCCESS);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+	optind = 0;
+
+	if (argc < 1) {
+		set_data_usage();
+		exit(EXIT_FAILURE);
+	}
+
+	data_len = argc - 1;
+	cp = malloc(sizeof(*cp) + data_len);
+	cp->flags = flags;
+	sscanf(argv[0], "%hhx", &cp->type);
+
+	for (i = 0; i < data_len; i++)
+		sscanf(argv[i + 1], "%hhx", &cp->data[i]);
+
+	cp->length = data_len;
+
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_SET_CONTROLLER_DATA, index,
+						cp, sizeof(*cp) + data_len,
+						set_data_rsp, NULL) < 0) {
+		free(cp);
+		fprintf(stderr, "Unable to send set controller data cmd\n");
+		exit(EXIT_FAILURE);
+	}
+
+	free(cp);
+}
+
 static struct {
 	char *cmd;
 	void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
@@ -1862,6 +1946,7 @@ static struct {
 	{ "did",	cmd_did,	"Set Device ID",		},
 	{ "broadcaster",cmd_broadcaster,"Toggle Broadcaster Mode",	},
 	{ "observer",	cmd_observer,	"Toggle Observer Mode",		},
+	{ "set-data",	cmd_set_data,	"Set Controller Data",		},
 	{ NULL, NULL, 0 }
 };
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 06/25] btmgmt: Add unset controller data support
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

Add new command unset-data for running the Unset Controller Data
operation from MGMT API.
---
 tools/btmgmt.c |   40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 3ae0ecb..99f5562 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -1913,6 +1913,45 @@ static void cmd_set_data(int mgmt_sk, uint16_t index, int argc, char **argv)
 	free(cp);
 }
 
+static void unset_data_rsp(int mgmt_sk, uint16_t op, uint16_t id,
+		uint8_t status, void *rsp, uint16_t len, void *user_data)
+{
+	if (status != 0) {
+		fprintf(stderr, "%s failed, status 0x%02x (%s)\n",
+				mgmt_opstr(op), status, mgmt_errstr(status));
+		exit(EXIT_FAILURE);
+	}
+
+	exit(EXIT_SUCCESS);
+}
+
+static void cmd_unset_data(int mgmt_sk, uint16_t index, int argc, char **argv)
+{
+	struct mgmt_cp_unset_controller_data cp;
+
+	if (argc < 2) {
+		printf("Usage: btmgmt %s <data type>\n", argv[0]);
+		printf("\nexample: btmgmt %s 0xff\n", argv[0]);
+		printf("\nparameters:\n");
+		printf("\t<data type>: 0x16 (service data) or 0xff\n"
+				"\t(manufacturer specific data).\n");
+
+		exit(EXIT_FAILURE);
+	}
+
+	memset(&cp, 0, sizeof(cp));
+	sscanf(argv[1], "%hhx", &cp.type);
+
+	if (index == MGMT_INDEX_NONE)
+		index = 0;
+
+	if (mgmt_send_cmd(mgmt_sk, MGMT_OP_UNSET_CONTROLLER_DATA, index,
+				&cp, sizeof(cp), unset_data_rsp, NULL) < 0) {
+		fprintf(stderr, "Unable to send unset controller data cmd\n");
+		exit(EXIT_FAILURE);
+	}
+}
+
 static struct {
 	char *cmd;
 	void (*func)(int mgmt_sk, uint16_t index, int argc, char **argv);
@@ -1947,6 +1986,7 @@ static struct {
 	{ "broadcaster",cmd_broadcaster,"Toggle Broadcaster Mode",	},
 	{ "observer",	cmd_observer,	"Toggle Observer Mode",		},
 	{ "set-data",	cmd_set_data,	"Set Controller Data",		},
+	{ "unset-data",	cmd_unset_data,	"Unset Controller Data",	},
 	{ NULL, NULL, 0 }
 };
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 07/25] mgmt: Add set observer and set broadcaster command
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

Implement Set Observer and Set Broadcaster support in MGMT API.

For observer, setting TRUE will make the adapter start LE discovery,
otherwise, setting FALSE will make the adapter stop LE discovery.

For broadcaster, setting TRUE will make the new data sent by Set
Controller Data command to be set in adapter and the advertising will
start. Setting FALSE will stop advertising.
---
 src/mgmt.c |   16 ++++++++++++++++
 src/mgmt.h |    2 ++
 2 files changed, 18 insertions(+)

diff --git a/src/mgmt.c b/src/mgmt.c
index 03ec049..0f212b2 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -1651,6 +1651,12 @@ static void mgmt_cmd_complete(int sk, uint16_t index, void *buf, size_t len)
 	case MGMT_OP_SET_DEVICE_ID:
 		DBG("set_did complete");
 		break;
+	case MGMT_OP_SET_BROADCASTER:
+		DBG("set_broadcaster complete");
+		break;
+	case MGMT_OP_SET_OBSERVER:
+		DBG("set_observer complete");
+		break;
 	default:
 		error("Unknown command complete for opcode %u", opcode);
 		break;
@@ -2358,6 +2364,16 @@ int mgmt_set_fast_connectable(int index, gboolean enable)
 	return 0;
 }
 
+int mgmt_set_broadcaster(int index, gboolean enable)
+{
+	return mgmt_set_mode(index, MGMT_OP_SET_BROADCASTER, enable);
+}
+
+int mgmt_set_observer(int index, gboolean enable)
+{
+	return mgmt_set_mode(index, MGMT_OP_SET_OBSERVER, enable);
+}
+
 int mgmt_read_clock(int index, const bdaddr_t *bdaddr, int which, int timeout,
 					uint32_t *clock, uint16_t *accuracy)
 {
diff --git a/src/mgmt.h b/src/mgmt.h
index 1ea8488..1607a95 100644
--- a/src/mgmt.h
+++ b/src/mgmt.h
@@ -32,6 +32,8 @@ int mgmt_set_pairable(int index, gboolean pairable);
 int mgmt_set_name(int index, const char *name);
 int mgmt_set_dev_class(int index, uint8_t major, uint8_t minor);
 int mgmt_set_fast_connectable(int index, gboolean enable);
+int mgmt_set_broadcaster(int index, gboolean enable);
+int mgmt_set_observer(int index, gboolean enable);
 
 int mgmt_start_discovery(int index);
 int mgmt_start_le_scanning(int index);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 08/25] mgmt: Add set controller data command
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

Implement new Set Controller Data command in MGMT API. The maximum size
for new data is 27 bytes. The data sent using this command will be
stored in internal list and it will be set in adapter after receiving a
Set Broadcaster with TRUE.
---
 src/adapter.c |    8 ++++++
 src/adapter.h |    3 +++
 src/mgmt.c    |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/mgmt.h    |    3 +++
 4 files changed, 92 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 6ff20e1..d741ae1 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -563,6 +563,10 @@ void adapter_name_changed(struct btd_adapter *adapter, const char *name)
 				(const uint8_t *) name, strlen(name));
 }
 
+void adapter_set_controller_data_complete(struct btd_adapter *adapter)
+{
+}
+
 int adapter_set_name(struct btd_adapter *adapter, const char *name)
 {
 	char maxname[MAX_NAME_LENGTH + 1];
@@ -1150,6 +1154,10 @@ static DBusMessage *remove_device(DBusConnection *conn, DBusMessage *msg,
 	return NULL;
 }
 
+void adapter_set_controller_data_failed(struct btd_adapter *adapter)
+{
+}
+
 static const GDBusMethodTable adapter_methods[] = {
 	{ GDBUS_METHOD("StartDiscovery", NULL, NULL,
 			adapter_start_discovery) },
diff --git a/src/adapter.h b/src/adapter.h
index d35b8db..ad79ae1 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -236,3 +236,6 @@ void adapter_store_cached_name(const bdaddr_t *local, const bdaddr_t *peer,
 void btd_adapter_for_each_device(struct btd_adapter *adapter,
 			void (*cb)(struct btd_device *device, void *data),
 			void *data);
+
+void adapter_set_controller_data_complete(struct btd_adapter *adapter);
+void adapter_set_controller_data_failed(struct btd_adapter *adapter);
diff --git a/src/mgmt.c b/src/mgmt.c
index 0f212b2..d1b5043 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -1426,6 +1426,28 @@ static void start_discovery_complete(int sk, uint16_t index, uint8_t status,
 		adapter_set_discovering(adapter, FALSE);
 }
 
+static void set_controller_data_complete(int sk, uint16_t index, void *buf,
+								size_t len)
+{
+	struct btd_adapter *adapter;
+
+	DBG("hci%d", index);
+
+	if (index > max_index) {
+		error("Unexpected index %u in set_controller data complete",
+									index);
+		return;
+	}
+
+	adapter = manager_find_adapter_by_id(index);
+	if (adapter == NULL) {
+		DBG("Adapter not found");
+		return;
+	}
+
+	adapter_set_controller_data_complete(adapter);
+}
+
 static void read_local_oob_data_failed(int sk, uint16_t index)
 {
 	struct btd_adapter *adapter;
@@ -1443,6 +1465,23 @@ static void read_local_oob_data_failed(int sk, uint16_t index)
 		adapter_read_local_oob_data_complete(adapter, NULL, NULL);
 }
 
+static void set_controller_data_failed(int sk, uint16_t index)
+{
+	struct btd_adapter *adapter;
+
+	if (index > max_index) {
+		error("Unexpected index %u in set_controller_data_failed",
+								index);
+		return;
+	}
+
+	DBG("hci%u", index);
+
+	adapter = manager_find_adapter_by_id(index);
+	if (adapter)
+		adapter_set_controller_data_failed(adapter);
+}
+
 static void handle_pending_uuids(uint16_t index)
 {
 	struct controller_info *info;
@@ -1651,6 +1690,10 @@ static void mgmt_cmd_complete(int sk, uint16_t index, void *buf, size_t len)
 	case MGMT_OP_SET_DEVICE_ID:
 		DBG("set_did complete");
 		break;
+	case MGMT_OP_SET_CONTROLLER_DATA:
+		DBG("set_controller_data complete");
+		set_controller_data_complete(sk, index, ev->data, len);
+		break;
 	case MGMT_OP_SET_BROADCASTER:
 		DBG("set_broadcaster complete");
 		break;
@@ -1701,6 +1744,9 @@ static void mgmt_cmd_status(int sk, uint16_t index, void *buf, size_t len)
 			return;
 		}
 		break;
+	case MGMT_OP_SET_CONTROLLER_DATA:
+		set_controller_data_failed(sk, index);
+		break;
 	}
 
 	error("hci%u: %s (0x%04x) failed: %s (0x%02x)", index,
@@ -2821,3 +2867,35 @@ int mgmt_ssp_enabled(int index)
 
 	return mgmt_ssp(info->current_settings);
 }
+
+int mgmt_set_controller_data(int index, uint8_t flags, uint8_t data_type,
+					uint8_t *data, uint8_t data_length)
+{
+	char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_set_controller_data) +
+							HCI_MAX_EIR_LENGTH];
+	struct mgmt_hdr *hdr = (void *) buf;
+	struct mgmt_cp_set_controller_data *cp = (void *) &buf[sizeof(*hdr)];
+	uint16_t cp_size;
+	int err = 0;
+
+	DBG("hci%d flags %d data_type 0x%hhx data_length %d", index, flags,
+							data_type, data_length);
+
+	memset(buf, 0, sizeof(buf));
+
+	cp_size = sizeof(*cp) + data_length;
+
+	hdr->opcode = htobs(MGMT_OP_SET_CONTROLLER_DATA);
+	hdr->index = htobs(index);
+	hdr->len = htobs(cp_size);
+
+	cp->flags = flags;
+	cp->type = data_type;
+	cp->length = data_length;
+	memcpy(cp->data, data, data_length);
+
+	if (write(mgmt_sock, buf, sizeof(*hdr) + cp_size) < 0)
+		err = -errno;
+
+	return err;
+}
diff --git a/src/mgmt.h b/src/mgmt.h
index 1607a95..92b4757 100644
--- a/src/mgmt.h
+++ b/src/mgmt.h
@@ -84,3 +84,6 @@ int mgmt_confirm_name(int index, const bdaddr_t *bdaddr, uint8_t bdaddr_type,
 							gboolean name_known);
 
 int mgmt_ssp_enabled(int index);
+
+int mgmt_set_controller_data(int index, uint8_t flags, uint8_t data_type,
+					uint8_t *data, uint8_t data_length);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 09/25] mgmt: Add unset controller data command
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

Implement Unset Controller Data command in MGMT API.  This operation
will remove all data from specific type that was set previously with Set
Controller Data operation.
---
 src/mgmt.c |   25 +++++++++++++++++++++++++
 src/mgmt.h |    1 +
 2 files changed, 26 insertions(+)

diff --git a/src/mgmt.c b/src/mgmt.c
index d1b5043..9a6affc 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -1694,6 +1694,9 @@ static void mgmt_cmd_complete(int sk, uint16_t index, void *buf, size_t len)
 		DBG("set_controller_data complete");
 		set_controller_data_complete(sk, index, ev->data, len);
 		break;
+	case MGMT_OP_UNSET_CONTROLLER_DATA:
+		DBG("unset_controller_data complete");
+		break;
 	case MGMT_OP_SET_BROADCASTER:
 		DBG("set_broadcaster complete");
 		break;
@@ -2899,3 +2902,25 @@ int mgmt_set_controller_data(int index, uint8_t flags, uint8_t data_type,
 
 	return err;
 }
+
+int mgmt_unset_controller_data(int index, uint8_t data_type)
+{
+	char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_unset_controller_data)];
+	struct mgmt_hdr *hdr = (void *) buf;
+	struct mgmt_cp_unset_controller_data *cp = (void *) &buf[sizeof(*hdr)];
+
+	DBG("hci%d data_type 0x%hhx", index, data_type);
+
+	memset(buf, 0, sizeof(buf));
+
+	hdr->opcode = htobs(MGMT_OP_UNSET_CONTROLLER_DATA);
+	hdr->index = htobs(index);
+	hdr->len = htobs(sizeof(*cp));
+
+	cp->type = data_type;
+
+	if (write(mgmt_sock, buf, sizeof(buf)) < 0)
+		return -errno;
+
+	return 0;
+}
diff --git a/src/mgmt.h b/src/mgmt.h
index 92b4757..187c971 100644
--- a/src/mgmt.h
+++ b/src/mgmt.h
@@ -87,3 +87,4 @@ int mgmt_ssp_enabled(int index);
 
 int mgmt_set_controller_data(int index, uint8_t flags, uint8_t data_type,
 					uint8_t *data, uint8_t data_length);
+int mgmt_unset_controller_data(int index, uint8_t data_type);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 10/25] doc: Add Broadcaster/Observer D-Bus API documentation
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

---
 doc/adapter-api.txt |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt
index 62c7a27..e8ca305 100644
--- a/doc/adapter-api.txt
+++ b/doc/adapter-api.txt
@@ -43,6 +43,102 @@ Methods		void StartDiscovery()
 			Possible errors: org.bluez.Error.InvalidArguments
 					 org.bluez.Error.Failed
 
+		void RegisterServiceObserver(object observer,
+							uint16 match_value)
+
+			Registers an observer agent to monitor Service Data
+			broadcasts. This agent will be notified whenever a
+			broadcast is received that matches that filter. It is
+			possible use same object path for two observers:
+			Service Data and Manufacturer Specific Data.
+
+			The match_value parameter must be the 16-bit UUID for
+			the service whose data is to be monitored.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+
+		void RegisterManufacturerObserver(object observer,
+							uint16 match_value)
+
+			Registers an observer agent to monitor Manufacturer
+			Specific Data broadcasts. This agent will be notified
+			whenever a broadcast is received that matches that
+			filter. It is possible use same object path for two
+			observers: Service Data and Manufacturer Specific Data.
+
+			The match_value parameter must be the 16-bit Company
+			Identifier Code for the manufacturer whose data is to
+			be monitored.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.AlreadyExists
+
+		void UnregisterServiceObserver(object observer)
+
+			Unregisters a Service Data observer. Broadcasts will
+			not be notified to this agent anymore. The observer
+			will be destroyed only if no Manufacturer Specific Data
+			was registered with the same object path.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.DoesNotExist
+
+		void UnregisterManufacturerObserver(object observer)
+
+			Unregisters a Manufacturer Specific Data observer.
+			Broadcasts will not be notified to this agent anymore.
+			The observer will be destroyed only if no Service Data
+			was registered with the same object path.
+
+			Possible errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.DoesNotExist
+
+		void SetServiceData(uint16 uuid, array{byte} data)
+
+			Set Service Data for broadcast. Different applications
+			can register different Adv. data types, and they are
+			all concatenated to form the Adv. data. Broadcasting is
+			enabled as soon as the first SetServiceData() call is
+			made.
+
+			This method can be used to update service data already
+			being broadcasted.
+
+			Use ClearBroadcastData() to release any Adv. data for
+			the application. Advertising data is also released when
+			application exits, and once the last Broadcaster exits,
+			advertising is disabled.
+
+			Possible Errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.Failed
+
+		void SetManufacturerData(uint16 cid, array{byte} data)
+
+			Set Manufacturer Specific Data for broadcast. Different
+			applications can register different Adv. data types,
+			and they are all concatenated to form the Adv. data.
+			Broadcasting is enabled as soon as the first
+			SetManufacturerData() call is made.
+
+			This method can be used to update manufacturer data
+			already being broadcasted.
+
+			Use ClearBroadcastData() to release any Adv. data for
+			the application. Advertising data is also released when
+			application exits, and once the last Broadcaster exits,
+			advertising is disabled.
+
+			Possible Errors: org.bluez.Error.InvalidArguments
+					 org.bluez.Error.Failed
+
+		void ClearBroadcastData()
+
+			This method will release any previously set Advertising
+			data.
+
+			Possible errors: org.bluez.Error.Failed
+
 Properties	string Address [readonly]
 
 			The Bluetooth device address.
@@ -118,3 +214,24 @@ Properties	string Address [readonly]
 
 			List of 128-bit UUIDs that represents the available
 			local services.
+
+Observer hierarchy
+==================
+
+Service		unique name
+Interface	org.bluez.Observer1
+Object path	freely definable
+
+Methods		void ServiceReceived(string address, uint16 uuid,
+							array{byte} data)
+
+			This callback gets called when a broadcast data has
+			arrived that matches filter used in
+			RegisterServiceObserver.
+
+		void ManufacturerReceived(string address, uint16 cid,
+							array{byte} data)
+
+			This callback gets called when a broadcast data has
+			arrived that matches filter used in
+			RegisterManufacturerObserver.
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 11/25] adapter: Add D-Bus API for Observer GAP Role
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

Implement dummy calls for register or unregister Observer Agents.
---
 src/adapter.c      |   38 ++++++++++++++++++++++++++++++++++++++
 src/bluetooth.conf |    1 +
 2 files changed, 39 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index d741ae1..34dad6e 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1154,6 +1154,30 @@ static DBusMessage *remove_device(DBusConnection *conn, DBusMessage *msg,
 	return NULL;
 }
 
+static DBusMessage *register_service_observer(DBusConnection *conn,
+						DBusMessage *msg, void *data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_service_observer(DBusConnection *conn,
+						DBusMessage *msg, void *data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *register_manuf_observer(DBusConnection *conn,
+						DBusMessage *msg, void *data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_manuf_observer(DBusConnection *conn,
+						DBusMessage *msg, void *data)
+{
+	return dbus_message_new_method_return(msg);
+}
+
 void adapter_set_controller_data_failed(struct btd_adapter *adapter)
 {
 }
@@ -1166,6 +1190,20 @@ static const GDBusMethodTable adapter_methods[] = {
 	{ GDBUS_ASYNC_METHOD("RemoveDevice",
 			GDBUS_ARGS({ "device", "o" }), NULL,
 			remove_device) },
+	{ GDBUS_METHOD("RegisterServiceObserver",
+			GDBUS_ARGS({ "observer", "o" }, { "match_value", "q" }),
+			NULL,
+			register_service_observer) },
+	{ GDBUS_METHOD("UnregisterServiceObserver",
+			GDBUS_ARGS({ "observer", "o" }), NULL,
+			unregister_service_observer) },
+	{ GDBUS_METHOD("RegisterManufacturerObserver",
+			GDBUS_ARGS({ "observer", "o" }, { "match_value", "q" }),
+			NULL,
+			register_manuf_observer) },
+	{ GDBUS_METHOD("UnregisterManufacturerObserver",
+			GDBUS_ARGS({ "observer", "o" }), NULL,
+			unregister_manuf_observer) },
 	{ }
 };
 
diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 0495200..e8176ed 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -15,6 +15,7 @@
     <allow send_interface="org.bluez.MediaPlayer1"/>
     <allow send_interface="org.bluez.ThermometerWatcher1"/>
     <allow send_interface="org.bluez.AlertAgent1"/>
+    <allow send_interface="org.bluez.Observer1"/>
     <allow send_interface="org.bluez.Profile1"/>
     <allow send_interface="org.bluez.HeartRateWatcher1"/>
     <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 12/25] observer: Add Register/UnregisterServiceObserver() D-Bus method
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

An observer for Service Data must be registered using
RegisterServiceObserver() D-Bus method so it can receive any advertising
which matches with the filter used. Use UnregisterServiceObserver()
D-Bus method for unregistering an observer and stop sending broadcasts
to the agent.
---
 src/adapter.c |   35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 34dad6e..a5c23da 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1157,12 +1157,47 @@ static DBusMessage *remove_device(DBusConnection *conn, DBusMessage *msg,
 static DBusMessage *register_service_observer(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
+	struct btd_adapter *adapter = data;
+	const char *path, *sender = dbus_message_get_sender(msg);
+	unsigned int uuid;
+	int err;
+
+	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+					DBUS_TYPE_UINT16, &uuid,
+					DBUS_TYPE_INVALID) == FALSE)
+		return btd_error_invalid_args(msg);
+
+	err = mgmt_set_observer(adapter->dev_id, TRUE);
+	if (err < 0) {
+		error("Failed to set Observer: %s (%d)", strerror(-err), -err);
+
+		return btd_error_failed(msg, strerror(-err));
+	}
+
+	DBG("Service Data Observer registered for hci%d at %s:%s",
+						adapter->dev_id, sender, path);
+
 	return dbus_message_new_method_return(msg);
 }
 
 static DBusMessage *unregister_service_observer(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
+	const char *path, *sender = dbus_message_get_sender(msg);
+	struct btd_adapter *adapter = data;
+	int err;
+
+	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+						DBUS_TYPE_INVALID) == FALSE)
+		return btd_error_invalid_args(msg);
+
+	err = mgmt_set_observer(adapter->dev_id, FALSE);
+	if (err < 0)
+		return btd_error_failed(msg, strerror(-err));
+
+	DBG("Service Data Observer unregistered for hci%d at %s:%s",
+						adapter->dev_id, sender, path);
+
 	return dbus_message_new_method_return(msg);
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 13/25] observer: Add Register/UnregisterManufacturerObserver() D-Bus method
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

An observer for Manufacturer Specific Data must be registered using
RegisterManufacturerObserver() D-Bus method so it can receive any
advertising which matches with the filter used. Use
UnregisterManufacturerObserver() D-Bus method for unregistering an
observer avoid stop sending broadcasts to the agent.
---
 src/adapter.c |   35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index a5c23da..60dd54c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1204,12 +1204,47 @@ static DBusMessage *unregister_service_observer(DBusConnection *conn,
 static DBusMessage *register_manuf_observer(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
+	struct btd_adapter *adapter = data;
+	const char *path, *sender = dbus_message_get_sender(msg);
+	unsigned int company_id;
+	int err;
+
+	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+					DBUS_TYPE_UINT16, &company_id,
+					DBUS_TYPE_INVALID) == FALSE)
+		return btd_error_invalid_args(msg);
+
+	err = mgmt_set_observer(adapter->dev_id, TRUE);
+	if (err < 0) {
+		error("Failed to set Observer: %s (%d)", strerror(-err), -err);
+
+		return btd_error_failed(msg, strerror(-err));
+	}
+
+	DBG("Manufacturer Specific Data Observer registered for hci%d at %s:%s",
+						adapter->dev_id, sender, path);
+
 	return dbus_message_new_method_return(msg);
 }
 
 static DBusMessage *unregister_manuf_observer(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
+	const char *path, *sender = dbus_message_get_sender(msg);
+	struct btd_adapter *adapter = data;
+	int err;
+
+	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+						DBUS_TYPE_INVALID) == FALSE)
+		return btd_error_invalid_args(msg);
+
+	err = mgmt_set_observer(adapter->dev_id, FALSE);
+	if (err < 0)
+		return btd_error_failed(msg, strerror(-err));
+
+	DBG("Manuf. Specific Data Observer unregistered for hci%d at %s:%s",
+						adapter->dev_id, sender, path);
+
 	return dbus_message_new_method_return(msg);
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 14/25] observer: Add watchers and filters for observers
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

The adapter will keep a list of observers listening for advertising.
The new observer is added on the list when it is registered.

When an observer is registered, the filter must be stored to be used
after receiving a new advertising. The observer will only receive the
data from advertising if the filter matches.
---
 src/adapter.c |  187 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 179 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 60dd54c..316acb9 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -85,6 +85,11 @@
 #define REMOVE_TEMP_TIMEOUT (3 * 60)
 
 static const char *base_path = "/org/bluez";
+
+/* Filter Types (for Observer) */
+#define FILTER_SERVICE_UUID	0x01
+#define FILTER_COMPANY_IC	0x02
+
 static GSList *adapter_drivers = NULL;
 
 enum session_req_type {
@@ -116,6 +121,16 @@ struct discovery {
 	GSList *found;
 };
 
+struct observer_watcher {
+	struct btd_adapter *adapter;
+	guint id;			/* Listener id */
+	uint8_t filter_type;		/* Filer type: Service or Manufacturer
+					 * data */
+	void *filter_data;		/* Value of filter */
+	char *sender;			/* DBus sender */
+	char *path;			/* DBus path */
+};
+
 struct btd_adapter {
 	uint16_t dev_id;
 	gboolean powered;
@@ -136,6 +151,7 @@ struct btd_adapter {
 	GSList *disc_sessions;		/* Discovery sessions */
 	struct session_req *scanning_session;
 	GSList *connect_list;		/* Devices to connect when found */
+	GSList *observers;		/* Observer watchers */
 	guint discov_id;		/* Discovery timer */
 	struct discovery *discovery;	/* Discovery active */
 	gboolean connecting;		/* Connect active */
@@ -1154,10 +1170,85 @@ static DBusMessage *remove_device(DBusConnection *conn, DBusMessage *msg,
 	return NULL;
 }
 
+static void destroy_observer(gpointer user_data)
+{
+	struct observer_watcher *obs = user_data;
+
+	btd_adapter_unref(obs->adapter);
+
+	g_dbus_remove_watch(btd_get_dbus_connection(), obs->id);
+
+	g_free(obs->path);
+	g_free(obs->sender);
+	g_free(obs);
+}
+
+static gint cmp_observer(gconstpointer a, gconstpointer b)
+{
+	const struct observer_watcher *obs = a;
+	const struct observer_watcher *match = b;
+	int ret;
+
+	ret = g_strcmp0(obs->sender, match->sender);
+	if (ret != 0)
+		return ret;
+
+	ret = g_strcmp0(obs->path, match->path);
+	if (ret != 0)
+		return ret;
+
+	return obs->filter_type - match->filter_type;
+}
+
+static struct observer_watcher *find_observer(GSList *list, const char *sender,
+					const char *path, uint8_t filter)
+{
+	struct observer_watcher *match;
+	GSList *l;
+
+	match = g_new0(struct observer_watcher, 1);
+	match->sender = g_strdup(sender);
+	match->path = g_strdup(path);
+	match->filter_type = filter;
+
+	l = g_slist_find_custom(list, match, cmp_observer);
+	g_free(match->sender);
+	g_free(match->path);
+	g_free(match);
+
+	return l ? l->data : NULL;
+}
+
+static void observer_exit(DBusConnection *conn, void *user_data)
+{
+	struct observer_watcher *obs = user_data;
+	struct btd_adapter *adapter = obs->adapter;
+
+	if (obs->filter_type == FILTER_SERVICE_UUID)
+		DBG("Service Data Observer watcher %s disconnected", obs->path);
+	else
+		DBG("Manufacturer Data Observer watcher %s disconnected",
+								obs->path);
+
+	adapter->observers = g_slist_remove(adapter->observers, obs);
+
+	if (adapter->observers == NULL) {
+		int err;
+
+		err = mgmt_set_observer(adapter->dev_id, FALSE);
+		if (err < 0)
+			error("Failed to set Observer: %s (%d)",
+							strerror(-err), -err);
+	}
+
+	destroy_observer(obs);
+}
+
 static DBusMessage *register_service_observer(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
 	struct btd_adapter *adapter = data;
+	struct observer_watcher *obs;
 	const char *path, *sender = dbus_message_get_sender(msg);
 	unsigned int uuid;
 	int err;
@@ -1167,8 +1258,26 @@ static DBusMessage *register_service_observer(DBusConnection *conn,
 					DBUS_TYPE_INVALID) == FALSE)
 		return btd_error_invalid_args(msg);
 
+	obs = find_observer(adapter->observers, sender, path,
+							FILTER_SERVICE_UUID);
+	if (obs)
+		return btd_error_already_exists(msg);
+
+	obs = g_new0(struct observer_watcher, 1);
+	obs->filter_type = FILTER_SERVICE_UUID;
+	obs->filter_data = GUINT_TO_POINTER(uuid);
+	obs->sender = g_strdup(sender);
+	obs->path = g_strdup(path);
+	obs->adapter = btd_adapter_ref(adapter);
+	obs->id = g_dbus_add_disconnect_watch(conn, sender, observer_exit,
+								obs, NULL);
+
+	adapter->observers = g_slist_prepend(adapter->observers, obs);
+
 	err = mgmt_set_observer(adapter->dev_id, TRUE);
 	if (err < 0) {
+		adapter->observers = g_slist_remove(adapter->observers, obs);
+		destroy_observer(obs);
 		error("Failed to set Observer: %s (%d)", strerror(-err), -err);
 
 		return btd_error_failed(msg, strerror(-err));
@@ -1185,15 +1294,28 @@ static DBusMessage *unregister_service_observer(DBusConnection *conn,
 {
 	const char *path, *sender = dbus_message_get_sender(msg);
 	struct btd_adapter *adapter = data;
-	int err;
+	struct observer_watcher *obs;
 
 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
 						DBUS_TYPE_INVALID) == FALSE)
 		return btd_error_invalid_args(msg);
 
-	err = mgmt_set_observer(adapter->dev_id, FALSE);
-	if (err < 0)
-		return btd_error_failed(msg, strerror(-err));
+	obs = find_observer(adapter->observers, sender, path,
+							FILTER_SERVICE_UUID);
+	if (obs == NULL)
+		return btd_error_does_not_exist(msg);
+
+	adapter->observers = g_slist_remove(adapter->observers, obs);
+	g_dbus_remove_watch(btd_get_dbus_connection(), obs->id);
+	destroy_observer(obs);
+
+	if (adapter->observers == NULL) {
+		int err;
+
+		err = mgmt_set_observer(adapter->dev_id, FALSE);
+		if (err < 0)
+			return btd_error_failed(msg, strerror(-err));
+	}
 
 	DBG("Service Data Observer unregistered for hci%d at %s:%s",
 						adapter->dev_id, sender, path);
@@ -1205,6 +1327,7 @@ static DBusMessage *register_manuf_observer(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
 	struct btd_adapter *adapter = data;
+	struct observer_watcher *obs;
 	const char *path, *sender = dbus_message_get_sender(msg);
 	unsigned int company_id;
 	int err;
@@ -1214,8 +1337,26 @@ static DBusMessage *register_manuf_observer(DBusConnection *conn,
 					DBUS_TYPE_INVALID) == FALSE)
 		return btd_error_invalid_args(msg);
 
+	obs = find_observer(adapter->observers, sender, path,
+							FILTER_COMPANY_IC);
+	if (obs)
+		return btd_error_already_exists(msg);
+
+	obs = g_new0(struct observer_watcher, 1);
+	obs->filter_type = FILTER_COMPANY_IC;
+	obs->filter_data = GUINT_TO_POINTER(company_id);
+	obs->sender = g_strdup(sender);
+	obs->path = g_strdup(path);
+	obs->adapter = btd_adapter_ref(adapter);
+	obs->id = g_dbus_add_disconnect_watch(conn, sender, observer_exit,
+								obs, NULL);
+
+	adapter->observers = g_slist_prepend(adapter->observers, obs);
+
 	err = mgmt_set_observer(adapter->dev_id, TRUE);
 	if (err < 0) {
+		adapter->observers = g_slist_remove(adapter->observers, obs);
+		destroy_observer(obs);
 		error("Failed to set Observer: %s (%d)", strerror(-err), -err);
 
 		return btd_error_failed(msg, strerror(-err));
@@ -1232,15 +1373,28 @@ static DBusMessage *unregister_manuf_observer(DBusConnection *conn,
 {
 	const char *path, *sender = dbus_message_get_sender(msg);
 	struct btd_adapter *adapter = data;
-	int err;
+	struct observer_watcher *obs;
 
 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
 						DBUS_TYPE_INVALID) == FALSE)
 		return btd_error_invalid_args(msg);
 
-	err = mgmt_set_observer(adapter->dev_id, FALSE);
-	if (err < 0)
-		return btd_error_failed(msg, strerror(-err));
+	obs = find_observer(adapter->observers, sender, path,
+							FILTER_COMPANY_IC);
+	if (obs == NULL)
+		return btd_error_does_not_exist(msg);
+
+	adapter->observers = g_slist_remove(adapter->observers, obs);
+	g_dbus_remove_watch(btd_get_dbus_connection(), obs->id);
+	destroy_observer(obs);
+
+	if (adapter->observers == NULL) {
+		int err;
+
+		err = mgmt_set_observer(adapter->dev_id, FALSE);
+		if (err < 0)
+			return btd_error_failed(msg, strerror(-err));
+	}
 
 	DBG("Manuf. Specific Data Observer unregistered for hci%d at %s:%s",
 						adapter->dev_id, sender, path);
@@ -2830,6 +2984,21 @@ struct btd_adapter *adapter_create(int id)
 	return btd_adapter_ref(adapter);
 }
 
+static void release_all_obs(struct btd_adapter *adapter)
+{
+	int err;
+
+	if (!adapter->observers)
+		return;
+
+	err = mgmt_set_observer(adapter->dev_id, FALSE);
+	if (err < 0)
+		error("Failed to set Observer: %s (%d)",
+						strerror(-err), -err);
+
+	g_slist_free_full(adapter->observers, destroy_observer);
+}
+
 void adapter_remove(struct btd_adapter *adapter)
 {
 	GSList *l;
@@ -2852,6 +3021,8 @@ void adapter_remove(struct btd_adapter *adapter)
 
 	g_slist_free(adapter->pin_callbacks);
 
+	release_all_obs(adapter);
+
 	if (adapter->powered)
 		mgmt_set_powered(adapter->dev_id, FALSE);
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 15/25] eir: Add manufacturer and service data fields
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

From: Jefferson Delfes <jefferson.delfes@openbossa.org>

For advertising, there are another possible fields, Service Data and
Manufacturer Specific Data.
---
 src/eir.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 src/eir.h |   16 ++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/src/eir.c b/src/eir.c
index 1b6db8c..96adc5c 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -41,6 +41,22 @@
 
 #define EIR_OOB_MIN (2 + 6)
 
+static void svc_data_free(void *p)
+{
+	struct svc_data *sdata = p;
+
+	g_free(sdata->data);
+	g_free(sdata);
+}
+
+static void manuf_data_free(void *p)
+{
+	struct manuf_data *mdata = p;
+
+	g_free(mdata->data);
+	g_free(mdata);
+}
+
 void eir_data_free(struct eir_data *eir)
 {
 	g_slist_free_full(eir->services, g_free);
@@ -51,6 +67,10 @@ void eir_data_free(struct eir_data *eir)
 	eir->hash = NULL;
 	g_free(eir->randomizer);
 	eir->randomizer = NULL;
+	g_slist_free_full(eir->svcs_data, svc_data_free);
+	eir->svcs_data = NULL;
+	g_slist_free_full(eir->manufs_data, manuf_data_free);
+	eir->manufs_data = NULL;
 }
 
 static void eir_parse_uuid16(struct eir_data *eir, void *data, uint8_t len)
@@ -139,6 +159,8 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, uint8_t eir_len)
 	while (len < eir_len - 1) {
 		uint8_t field_len = eir_data[0];
 		uint8_t data_len, *data = &eir_data[2];
+		struct svc_data *sdata;
+		struct manuf_data *mdata;
 
 		/* Check for the end of EIR */
 		if (field_len == 0)
@@ -193,6 +215,16 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, uint8_t eir_len)
 							(data[2] << 16);
 			break;
 
+		case EIR_SVC_DATA:
+			if (data_len < 2)
+				break;
+			sdata = g_new(struct svc_data, 1);
+			sdata->uuid = bt_get_le16(data);
+			sdata->data_len = data_len - 2;
+			sdata->data = g_memdup(data + 2, data_len - 2);
+			eir->svcs_data = g_slist_append(eir->svcs_data, sdata);
+			break;
+
 		case EIR_GAP_APPEARANCE:
 			if (data_len < 2)
 				break;
@@ -209,6 +241,16 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, uint8_t eir_len)
 			if (data_len < 16)
 				break;
 			eir->randomizer = g_memdup(data, 16);
+
+		case EIR_MANUF_DATA:
+			if (data_len < 2)
+				break;
+			mdata = g_new(struct manuf_data, 1);
+			mdata->company_id = bt_get_le16(data);
+			mdata->data_len = data_len - 2;
+			mdata->data = g_memdup(data + 2, data_len - 2);
+			eir->manufs_data = g_slist_append(eir->manufs_data,
+									mdata);
 			break;
 		}
 
diff --git a/src/eir.h b/src/eir.h
index 91e045e..e410753 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -36,7 +36,21 @@
 #define EIR_SSP_HASH                0x0E  /* SSP Hash */
 #define EIR_SSP_RANDOMIZER          0x0F  /* SSP Randomizer */
 #define EIR_DEVICE_ID               0x10  /* device ID */
+#define EIR_SVC_DATA                0x16  /* service data */
 #define EIR_GAP_APPEARANCE          0x19  /* GAP appearance */
+#define EIR_MANUF_DATA              0xFF  /* manufacturer specific data */
+
+struct svc_data {
+	uint16_t uuid;
+	uint8_t data_len;
+	uint8_t *data;
+};
+
+struct manuf_data {
+	uint16_t company_id;
+	uint8_t data_len;
+	uint8_t *data;
+};
 
 struct eir_data {
 	GSList *services;
@@ -48,6 +62,8 @@ struct eir_data {
 	uint8_t *hash;
 	uint8_t *randomizer;
 	bdaddr_t addr;
+	GSList *svcs_data;
+	GSList *manufs_data;
 };
 
 void eir_data_free(struct eir_data *eir);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 16/25] observer: Add Service/ManufacturerReceived() D-Bus method
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

When an advertising matches with the filter registered in
RegisterServiceObserver() or RegisterManufacturerObserver(), the data is
sent to all observers registered using ServiceReceived() or
ManufacturerReceived(), respectively.
---
 src/adapter.c |  117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 116 insertions(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index 316acb9..4fc4fa9 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -86,6 +86,8 @@
 
 static const char *base_path = "/org/bluez";
 
+#define OBSERVER_INTERFACE "org.bluez.Observer1"
+
 /* Filter Types (for Observer) */
 #define FILTER_SERVICE_UUID	0x01
 #define FILTER_COMPANY_IC	0x02
@@ -180,6 +182,11 @@ struct btd_adapter {
 
 static gboolean process_auth_queue(gpointer user_data);
 
+struct broadcast_data {
+	struct eir_data *eir_data;
+	char peer_addr[18];
+};
+
 int btd_adapter_set_class(struct btd_adapter *adapter, uint8_t major,
 							uint8_t minor)
 {
@@ -3179,6 +3186,106 @@ static gboolean connect_pending_cb(gpointer user_data)
 	return FALSE;
 }
 
+static void service_received(struct observer_watcher *obs, char *peer_addr,
+							struct svc_data *sdata)
+{
+	const char *paddr = peer_addr;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(obs->sender, obs->path,
+							OBSERVER_INTERFACE,
+							"ServiceReceived");
+	if (msg == NULL) {
+		error("Unable to allocate new ServiceReceived method");
+		return;
+	}
+
+	dbus_message_append_args(msg, DBUS_TYPE_STRING, &paddr,
+						DBUS_TYPE_UINT16, &sdata->uuid,
+						DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+						&sdata->data, sdata->data_len,
+						DBUS_TYPE_INVALID);
+
+	dbus_message_set_no_reply(msg, TRUE);
+	g_dbus_send_message(btd_get_dbus_connection(), msg);
+}
+
+static void manufacturer_received(struct observer_watcher *obs,
+				char *peer_addr, struct manuf_data *mdata)
+{
+	const char *paddr = peer_addr;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(obs->sender, obs->path,
+							OBSERVER_INTERFACE,
+							"ManufacturerReceived");
+	if (msg == NULL) {
+		error("Unable to allocate new ManufacturerReceived method");
+		return;
+	}
+
+	dbus_message_append_args(msg, DBUS_TYPE_STRING, &paddr,
+					DBUS_TYPE_UINT16, &mdata->company_id,
+					DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+					&mdata->data, mdata->data_len,
+					DBUS_TYPE_INVALID);
+
+	dbus_message_set_no_reply(msg, TRUE);
+	g_dbus_send_message(btd_get_dbus_connection(), msg);
+}
+
+static void update_observer(gpointer data, gpointer user_data)
+{
+	struct observer_watcher *obs = data;
+	struct broadcast_data *bdata = user_data;
+	struct eir_data *eir = bdata->eir_data;
+	GSList *l;
+
+	if (obs->filter_type == FILTER_SERVICE_UUID) {
+		for (l = eir->svcs_data; l != NULL; l = g_slist_next(l)) {
+			struct svc_data *sdata = l->data;
+			uint16_t uuid = GPOINTER_TO_UINT(obs->filter_data);
+
+			if (uuid == sdata->uuid)
+				service_received(obs, bdata->peer_addr, sdata);
+		}
+	} else if (obs->filter_type == FILTER_COMPANY_IC) {
+		for (l = eir->manufs_data; l != NULL; l = g_slist_next(l)) {
+			struct manuf_data *mdata = l->data;
+			uint16_t company_id =
+					GPOINTER_TO_UINT(obs->filter_data);
+
+			if (company_id == mdata->company_id)
+				manufacturer_received(obs, bdata->peer_addr,
+									mdata);
+		}
+	}
+}
+
+static void adapter_broadcast_received(struct btd_adapter *adapter,
+			const bdaddr_t *bdaddr, struct eir_data *eir_data)
+{
+	struct broadcast_data *bdata;
+
+	/* No observers listening for advertising */
+	if (adapter->observers == NULL)
+		return;
+
+	/* No service/manufacturer data was sent */
+	if (eir_data->svcs_data == NULL && eir_data->manufs_data == NULL)
+		return;
+
+	bdata = g_new(struct broadcast_data, 1);
+	bdata->eir_data = eir_data;
+	ba2str(bdaddr, bdata->peer_addr);
+
+	DBG("Broadcast received from %s", bdata->peer_addr);
+
+	g_slist_foreach(adapter->observers, update_observer, bdata);
+
+	g_free(bdata);
+}
+
 void adapter_update_found_devices(struct btd_adapter *adapter,
 					const bdaddr_t *bdaddr,
 					uint8_t bdaddr_type, int8_t rssi,
@@ -3192,7 +3299,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
 	int err;
 	GSList *l;
 
-	if (!discovery) {
+	if (!discovery && !adapter->observers) {
 		error("Device found event while no discovery in progress");
 		return;
 	}
@@ -3204,6 +3311,14 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
 		return;
 	}
 
+	/* Send advertising to observers */
+	adapter_broadcast_received(adapter, bdaddr, &eir_data);
+
+	if (!discovery) {
+		eir_data_free(&eir_data);
+		return;
+	}
+
 	if (eir_data.name != NULL && eir_data.name_complete)
 		adapter_store_cached_name(&adapter->bdaddr, bdaddr,
 								eir_data.name);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ 17/25] observer: Add python test script
From: Bruna Moreira @ 2012-12-21 20:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1356121612-15172-1-git-send-email-bruna.moreira@openbossa.org>

---
 test/test-observer |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100755 test/test-observer

diff --git a/test/test-observer b/test/test-observer
new file mode 100755
index 0000000..04d3f05
--- /dev/null
+++ b/test/test-observer
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+
+'''Observer test script
+'''
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+from gi.repository import GObject
+
+import sys
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+from optparse import OptionParser, make_option
+import bluezutils
+
+def dbus_data(data):
+	return "".join(["%02x" % c for c in data])
+
+class Observer(dbus.service.Object):
+	@dbus.service.method("org.bluez.Observer1",
+					in_signature="sqay", out_signature="")
+	def ServiceReceived(self, address, uuid, value):
+		print("[ " + address + " ]")
+		print("    Service UUID = 0x%04x" % int(uuid))
+		print("    Data = %s" % dbus_data(value))
+		print()
+
+	@dbus.service.method("org.bluez.Observer1",
+					in_signature="sqay", out_signature="")
+	def ManufacturerReceived(self, address, cid, value):
+		print("[ " + address + " ]")
+		print("    Company ID = 0x%04x" % int(cid))
+		print("    Data = %s" % dbus_data(value))
+		print()
+
+if __name__ == "__main__":
+	dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+	bus = dbus.SystemBus()
+
+	manager = dbus.Interface(bus.get_object("org.bluez", "/"),
+					"org.bluez.Manager")
+
+	option_list = [
+		make_option("-i", "--adapter", action="store",
+			type="string", dest="adapter"),
+		make_option("-s", "--service", action="store",
+			type="int", dest="service_uuid",
+			help="Service UUID (e.g. \"0x0001\")"),
+		make_option("-c", "--company", action="store",
+			type="int", dest="company_id",
+			help="Company Identifier Code (e.g. \"0x0002\")"),
+		]
+
+	parser = OptionParser(option_list=option_list)
+
+	(options, args) = parser.parse_args()
+
+	if not options.service_uuid and not options.company_id:
+		parser.error("At least one option is required: -c or -s")
+
+	adapter = bluezutils.find_adapter(options.adapter)
+
+	path = "/test/observer"
+	observer = Observer(bus, path)
+
+	if options.service_uuid:
+		adapter.RegisterServiceObserver(path, dbus.UInt16(options.service_uuid))
+
+	if options.company_id:
+		adapter.RegisterManufacturerObserver(path, dbus.UInt16(options.company_id))
+
+	mainloop = GObject.MainLoop()
+	mainloop.run()
-- 
1.7.9.5


^ 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