Linux bluetooth development
 help / color / mirror / Atom feed
* [RFC 12/16] Bluetooth: Use abstract chan->data in comparison
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-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>
---
 net/bluetooth/l2cap_core.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 934ac1b..92936db 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -2682,12 +2682,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.7.11.7


^ permalink raw reply related

* [RFC 11/16] Bluetooth: remove parent socket usage from l2cap_core.c
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

Since we do not touch the parent sock in l2cap_core.c anymore we don't
need to lock it there anymore. That lock was replaced by the
l2cap_chan_lock and inside the new_connection() call for l2cap_sock.c the
parent lock is locked, so the operations that uses it can be performed
safely.

The l2cap_chan_lock give us the needed protection to handle the incoming
connections.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 net/bluetooth/l2cap_core.c | 16 ++++------------
 net/bluetooth/l2cap_sock.c |  4 ++++
 2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a69976b..934ac1b 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1315,7 +1315,6 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
 
 static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 {
-	struct sock *parent;
 	struct l2cap_chan *chan, *pchan;
 
 	BT_DBG("");
@@ -1326,9 +1325,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 	if (!pchan)
 		return;
 
-	parent = pchan->sk;
-
-	lock_sock(parent);
+	l2cap_chan_lock(pchan);
 
 	chan = pchan->ops->new_connection(pchan);
 	if (!chan)
@@ -1345,7 +1342,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 	l2cap_chan_ready(chan);
 
 clean:
-	release_sock(parent);
+	l2cap_chan_unlock(pchan);
 }
 
 static void l2cap_conn_ready(struct l2cap_conn *conn)
@@ -3567,7 +3564,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
 	struct l2cap_conn_rsp rsp;
 	struct l2cap_chan *chan = NULL, *pchan;
-	struct sock *parent, *sk = NULL;
 	int result, status = L2CAP_CS_NO_INFO;
 
 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
@@ -3582,10 +3578,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 		goto sendresp;
 	}
 
-	parent = pchan->sk;
-
 	mutex_lock(&conn->chan_lock);
-	lock_sock(parent);
+	l2cap_chan_lock(pchan);
 
 	/* Check if the ACL is secure enough (if not SDP) */
 	if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
@@ -3605,8 +3599,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 	if (!chan)
 		goto response;
 
-	sk = chan->sk;
-
 	hci_conn_hold(conn->hcon);
 
 	bacpy(&chan->src, conn->src);
@@ -3656,7 +3648,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 	}
 
 response:
-	release_sock(parent);
+	l2cap_chan_unlock(pchan);
 	mutex_unlock(&conn->chan_lock);
 
 sendresp:
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 4ab3adc..e4fcbde 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -943,6 +943,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
 {
 	struct sock *sk, *parent = chan->data;
 
+	lock_sock(parent);
+
 	/* Check for backlog size */
 	if (sk_acceptq_is_full(parent)) {
 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
@@ -960,6 +962,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
 
 	bt_accept_enqueue(parent, sk);
 
+	release_sock(parent);
+
 	return l2cap_pi(sk)->chan;
 }
 
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 10/16] Bluetooth: Remove socket lock from state_change() in l2cap_core
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

This simplifies a lot the state change handling inside l2cap_core.c,
we got rid of __l2cap_state_change() and l2cap_state_change() doesn't lock
the socket anymore, instead the socket is locked inside the ops user code
in l2cap_sock.c.

In some places we were not using the locked version, and now we are using
it. There is no side effect in locking the socket in these places.

Handle the operation of lock the socket to ops user benefit A2MP, since
there is no socket lock there it doesn't need any special function in
l2cap work without touching socket locks.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 net/bluetooth/l2cap_core.c | 32 +++++++-------------------------
 net/bluetooth/l2cap_sock.c |  4 ++++
 2 files changed, 11 insertions(+), 25 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3d96c3b..a69976b 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -210,7 +210,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 	return 0;
 }
 
-static void __l2cap_state_change(struct l2cap_chan *chan, int state)
+static void l2cap_state_change(struct l2cap_chan *chan, int state)
 {
 	BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
 	       state_to_string(state));
@@ -219,33 +219,16 @@ static void __l2cap_state_change(struct l2cap_chan *chan, int state)
 	chan->ops->state_change(chan, state, 0);
 }
 
-static void l2cap_state_change(struct l2cap_chan *chan, int state)
-{
-	struct sock *sk = chan->sk;
-
-	lock_sock(sk);
-	__l2cap_state_change(chan, state);
-	release_sock(sk);
-}
-
 static void l2cap_state_change_and_error(struct l2cap_chan *chan, int state,
 					 int err)
 {
-	struct sock *sk = chan->sk;
-
-	lock_sock(sk);
 	chan->state = state;
 	chan->ops->state_change(chan, state, err);
-	release_sock(sk);
 }
 
 static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
 {
-	struct sock *sk = chan->sk;
-
-	lock_sock(sk);
 	chan->ops->state_change(chan, chan->state, 0);
-	release_sock(sk);
 }
 
 static void __set_retrans_timer(struct l2cap_chan *chan)
@@ -1219,7 +1202,6 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 	mutex_lock(&conn->chan_lock);
 
 	list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
-		struct sock *sk = chan->sk;
 
 		l2cap_chan_lock(chan);
 
@@ -3644,7 +3626,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
 		if (l2cap_chan_check_security(chan)) {
 			if (test_bit(CONN_DEFER_SETUP, &chan->conn_state)) {
-				__l2cap_state_change(chan, BT_CONNECT2);
+				l2cap_state_change(chan, BT_CONNECT2);
 				result = L2CAP_CR_PEND;
 				status = L2CAP_CS_AUTHOR_PEND;
 				chan->ops->defer(chan);
@@ -3654,21 +3636,21 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 				 * physical link is up.
 				 */
 				if (amp_id) {
-					__l2cap_state_change(chan, BT_CONNECT2);
+					l2cap_state_change(chan, BT_CONNECT2);
 					result = L2CAP_CR_PEND;
 				} else {
-					__l2cap_state_change(chan, BT_CONFIG);
+					l2cap_state_change(chan, BT_CONFIG);
 					result = L2CAP_CR_SUCCESS;
 				}
 				status = L2CAP_CS_NO_INFO;
 			}
 		} else {
-			__l2cap_state_change(chan, BT_CONNECT2);
+			l2cap_state_change(chan, BT_CONNECT2);
 			result = L2CAP_CR_PEND;
 			status = L2CAP_CS_AUTHEN_PEND;
 		}
 	} else {
-		__l2cap_state_change(chan, BT_CONNECT2);
+		l2cap_state_change(chan, BT_CONNECT2);
 		result = L2CAP_CR_PEND;
 		status = L2CAP_CS_NO_INFO;
 	}
@@ -4547,7 +4529,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,
 			       sizeof(rsp), &rsp);
 
 		if (result == L2CAP_CR_SUCCESS) {
-			__l2cap_state_change(chan, BT_CONFIG);
+			l2cap_state_change(chan, BT_CONFIG);
 			set_bit(CONF_REQ_SENT, &chan->conf_state);
 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
 				       L2CAP_CONF_REQ,
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index c8bbe4e..4ab3adc 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1051,10 +1051,14 @@ static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state, int e
 {
 	struct sock *sk = chan->data;
 
+	lock_sock(sk);
+
 	sk->sk_state = state;
 
 	if (err)
 		sk->sk_err = err;
+
+	release_sock(sk);
 }
 
 static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 09/16] Bluetooth: lock socket in defer_cb call
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

Since we removed the lock around the ops->defer() call inside
l2cap_core.c we need now to protect the defer_cb call.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 net/bluetooth/l2cap_sock.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index a6ecf58..c8bbe4e 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1095,11 +1095,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
 
 static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
 {
-	struct sock *sk = chan->data;
-	struct sock *parent = bt_sk(sk)->parent;
+	struct sock *parent, *sk = chan->data;
+
+	lock_sock(sk);
 
+	parent = bt_sk(sk)->parent;
 	if (parent)
 		parent->sk_data_ready(parent, 0);
+
+	release_sock(sk);
 }
 
 static struct l2cap_ops l2cap_chan_ops = {
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 08/16] Bluetooth: Improving locking in l2cap_conn_start()
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

Since we don't read bt_sk(sk) in here anymore we can remove the lock from
the block and only use it when calling l2cap_state_change().

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 net/bluetooth/l2cap_core.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index aacf202..3d96c3b 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1252,7 +1252,6 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 			rsp.dcid = cpu_to_le16(chan->scid);
 
 			if (l2cap_chan_check_security(chan)) {
-				lock_sock(sk);
 				if (test_bit(CONN_DEFER_SETUP,
 					     &chan->conn_state)) {
 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
@@ -1260,11 +1259,10 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 					chan->ops->defer(chan);
 
 				} else {
-					__l2cap_state_change(chan, BT_CONFIG);
+					l2cap_state_change(chan, BT_CONFIG);
 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
 				}
-				release_sock(sk);
 			} else {
 				rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
 				rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
@@ -6398,12 +6396,9 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
 			}
 		} else if (chan->state == BT_CONNECT2) {
-			struct sock *sk = chan->sk;
 			struct l2cap_conn_rsp rsp;
 			__u16 res, stat;
 
-			lock_sock(sk);
-
 			if (!status) {
 				if (test_bit(CONN_DEFER_SETUP,
 					     &chan->conn_state)) {
@@ -6411,19 +6406,17 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 					stat = L2CAP_CS_AUTHOR_PEND;
 					chan->ops->defer(chan);
 				} else {
-					__l2cap_state_change(chan, BT_CONFIG);
+					l2cap_state_change(chan, BT_CONFIG);
 					res = L2CAP_CR_SUCCESS;
 					stat = L2CAP_CS_NO_INFO;
 				}
 			} else {
-				__l2cap_state_change(chan, BT_DISCONN);
+				l2cap_state_change(chan, BT_DISCONN);
 				__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
 				res = L2CAP_CR_SEC_BLOCK;
 				stat = L2CAP_CS_NO_INFO;
 			}
 
-			release_sock(sk);
-
 			rsp.scid   = cpu_to_le16(chan->dcid);
 			rsp.dcid   = cpu_to_le16(chan->scid);
 			rsp.result = cpu_to_le16(res);
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 07/16] Bluetooth: duplicate DEFER_SETUP flag on l2cap_chan
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

Now l2cap_chan also has the DEFER_SETUP flag, so we don't need to access
the bt_sk(sk) to read this flag inside l2cap_core.c. We need to kep it
duplicate since it is used in Bluetooth socket code as well.

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

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index c361c47..b1cc286 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -636,6 +636,7 @@ enum {
 	CONN_REJ_ACT,
 	CONN_SEND_FBIT,
 	CONN_RNR_SENT,
+	CONN_DEFER_SETUP,
 };
 
 /* Definitions for flags in l2cap_chan */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d3af9ddd..aacf202 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -620,10 +620,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 {
 	struct l2cap_conn *conn = chan->conn;
-	struct sock *sk = chan->sk;
 
-	BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state),
-	       sk);
+	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
 
 	switch (chan->state) {
 	case BT_LISTEN:
@@ -646,7 +644,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 			struct l2cap_conn_rsp rsp;
 			__u16 result;
 
-			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
+			if (test_bit(CONN_DEFER_SETUP, &chan->conn_state))
 				result = L2CAP_CR_SEC_BLOCK;
 			else
 				result = L2CAP_CR_BAD_PSM;
@@ -1255,8 +1253,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 
 			if (l2cap_chan_check_security(chan)) {
 				lock_sock(sk);
-				if (test_bit(BT_SK_DEFER_SETUP,
-					     &bt_sk(sk)->flags)) {
+				if (test_bit(CONN_DEFER_SETUP,
+					     &chan->conn_state)) {
 					rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
 					rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
 					chan->ops->defer(chan);
@@ -3647,7 +3645,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 
 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
 		if (l2cap_chan_check_security(chan)) {
-			if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+			if (test_bit(CONN_DEFER_SETUP, &chan->conn_state)) {
 				__l2cap_state_change(chan, BT_CONNECT2);
 				result = L2CAP_CR_PEND;
 				status = L2CAP_CS_AUTHOR_PEND;
@@ -6407,8 +6405,8 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 			lock_sock(sk);
 
 			if (!status) {
-				if (test_bit(BT_SK_DEFER_SETUP,
-					     &bt_sk(sk)->flags)) {
+				if (test_bit(CONN_DEFER_SETUP,
+					     &chan->conn_state)) {
 					res = L2CAP_CR_PEND;
 					stat = L2CAP_CS_AUTHOR_PEND;
 					chan->ops->defer(chan);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 61c10bc..a6ecf58 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -659,10 +659,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
 			break;
 		}
 
-		if (opt)
+		if (opt) {
 			set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
-		else
+			set_bit(CONN_DEFER_SETUP, &chan->conn_state);
+		} else {
 			clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+			clear_bit(CONN_DEFER_SETUP, &chan->conn_state);
+		}
 		break;
 
 	case BT_FLUSHABLE:
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 06/16] Bluetooth: use l2cap_chan_ready() instead of duplicate code
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

l2cap_chan_ready() does exactly what we want here avoiding duplicate code.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 net/bluetooth/l2cap_core.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a035f7a..d3af9ddd 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1399,12 +1399,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 				l2cap_chan_ready(chan);
 
 		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
-			struct sock *sk = chan->sk;
-			__clear_chan_timer(chan);
-			lock_sock(sk);
-			__l2cap_state_change(chan, BT_CONNECTED);
-			sk->sk_state_change(sk);
-			release_sock(sk);
+			l2cap_chan_ready(chan);
 
 		} else if (chan->state == BT_CONNECT) {
 			l2cap_do_start(chan);
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 05/16] Bluetooth: Add missing braces to an "else if"
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

Trivial change in the coding style.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 net/bluetooth/l2cap_core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 91e12b6..a035f7a 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1406,8 +1406,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
 			sk->sk_state_change(sk);
 			release_sock(sk);
 
-		} else if (chan->state == BT_CONNECT)
+		} else if (chan->state == BT_CONNECT) {
 			l2cap_do_start(chan);
+		}
 
 		l2cap_chan_unlock(chan);
 	}
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 04/16] Bluetooth: add l2cap_state_change_and_error()
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

Add helper to set both state and error at the same time.

Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
 net/bluetooth/l2cap_core.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index e0aabe8..91e12b6 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -228,9 +228,15 @@ static void l2cap_state_change(struct l2cap_chan *chan, int state)
 	release_sock(sk);
 }
 
-static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
+static void l2cap_state_change_and_error(struct l2cap_chan *chan, int state,
+					 int err)
 {
-	chan->ops->state_change(chan, chan->state, 0);
+	struct sock *sk = chan->sk;
+
+	lock_sock(sk);
+	chan->state = state;
+	chan->ops->state_change(chan, state, err);
+	release_sock(sk);
 }
 
 static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
@@ -238,7 +244,7 @@ static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
 	struct sock *sk = chan->sk;
 
 	lock_sock(sk);
-	__l2cap_chan_set_err(chan, err);
+	chan->ops->state_change(chan, chan->state, 0);
 	release_sock(sk);
 }
 
@@ -1180,7 +1186,6 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
 
 static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
 {
-	struct sock *sk = chan->sk;
 	struct l2cap_conn *conn = chan->conn;
 	struct l2cap_disconn_req req;
 
@@ -1203,10 +1208,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
 		       sizeof(req), &req);
 
-	lock_sock(sk);
-	__l2cap_state_change(chan, BT_DISCONN);
-	__l2cap_chan_set_err(chan, err);
-	release_sock(sk);
+	l2cap_state_change_and_error(chan, BT_DISCONN, err);
 }
 
 /* ---- L2CAP connections ---- */
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 03/16] Bluetooth: extend state_change() call to report errors too
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

Now l2cap_core doesn't need to touch sk_err element anymore, it just tell
l2cap_sock via this call which error it wants to set.

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

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 0aee196..c361c47 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -551,7 +551,7 @@ struct l2cap_ops {
 	void			(*teardown) (struct l2cap_chan *chan, int err);
 	void			(*close) (struct l2cap_chan *chan);
 	void			(*state_change) (struct l2cap_chan *chan,
-						 int state);
+						 int state, int err);
 	void			(*ready) (struct l2cap_chan *chan);
 	void			(*defer) (struct l2cap_chan *chan);
 	struct sk_buff		*(*alloc_skb) (struct l2cap_chan *chan,
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 2f67d5e..2b6faae 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -663,7 +663,7 @@ static void a2mp_chan_close_cb(struct l2cap_chan *chan)
 	l2cap_chan_put(chan);
 }
 
-static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state)
+static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state, int err)
 {
 	struct amp_mgr *mgr = chan->data;
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 1fbaf63..e0aabe8 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -216,7 +216,7 @@ static void __l2cap_state_change(struct l2cap_chan *chan, int state)
 	       state_to_string(state));
 
 	chan->state = state;
-	chan->ops->state_change(chan, state);
+	chan->ops->state_change(chan, state, 0);
 }
 
 static void l2cap_state_change(struct l2cap_chan *chan, int state)
@@ -230,9 +230,7 @@ static void l2cap_state_change(struct l2cap_chan *chan, int state)
 
 static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
 {
-	struct sock *sk = chan->sk;
-
-	sk->sk_err = err;
+	chan->ops->state_change(chan, chan->state, 0);
 }
 
 static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 221aef9..61c10bc 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1044,11 +1044,14 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err)
 	release_sock(sk);
 }
 
-static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state)
+static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state, int err)
 {
 	struct sock *sk = chan->data;
 
 	sk->sk_state = state;
+
+	if (err)
+		sk->sk_err = err;
 }
 
 static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 02/16] Bluetooth: Remove sk_sndtimeo from l2cap_core.c
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

We now have a new struct member in l2cap_chan to store this value for
access inside l2cap_core.c

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

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 445b71e..0aee196 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -480,6 +480,7 @@ struct l2cap_chan {
 	__u8		tx_state;
 	__u8		rx_state;
 
+	unsigned long	sndtimeo;
 	unsigned long	conf_state;
 	unsigned long	conn_state;
 	unsigned long	flags;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 4a06959..1fbaf63 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -630,7 +630,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 	case BT_CONFIG:
 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
 		    conn->hcon->type == ACL_LINK) {
-			__set_chan_timer(chan, sk->sk_sndtimeo);
+			__set_chan_timer(chan, chan->sndtimeo);
 			l2cap_send_disconn_req(chan, reason);
 		} else
 			l2cap_chan_del(chan, reason);
@@ -1607,7 +1607,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
 int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 		       bdaddr_t *dst, u8 dst_type)
 {
-	struct sock *sk = chan->sk;
 	bdaddr_t *src = &chan->src;
 	struct l2cap_conn *conn;
 	struct hci_conn *hcon;
@@ -1721,7 +1720,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 	l2cap_chan_lock(chan);
 
 	l2cap_state_change(chan, BT_CONNECT);
-	__set_chan_timer(chan, sk->sk_sndtimeo);
+	__set_chan_timer(chan, chan->sndtimeo);
 
 	if (hcon->state == BT_CONNECTED) {
 		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
@@ -3646,7 +3645,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 
 	dcid = chan->scid;
 
-	__set_chan_timer(chan, sk->sk_sndtimeo);
+	__set_chan_timer(chan, chan->sndtimeo);
 
 	chan->ident = cmd->ident;
 
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 0977966..221aef9 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1178,6 +1178,7 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
 
 	/* Default config options */
 	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+	chan->sndtimeo = sk->sk_sndtimeo;
 
 	chan->data = sk;
 	chan->ops = &l2cap_chan_ops;
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 01/16] Bluetooth: Add src and dst info to struct l2cap_chan
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan
In-Reply-To: <1355285624-25811-1-git-send-email-gustavo@padovan.org>

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

Adding these two info to l2cap_chan makes the l2cap_core.c a little more
independent of the struct sock.

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

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7588ef4..445b71e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -435,6 +435,9 @@ struct l2cap_seq_list {
 struct l2cap_chan {
 	struct sock *sk;
 
+	bdaddr_t	src;
+	bdaddr_t	dst;
+
 	struct l2cap_conn	*conn;
 	struct hci_conn		*hs_hcon;
 	struct hci_chan		*hs_hchan;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2c78208..4a06959 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -148,7 +148,7 @@ static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
 	struct l2cap_chan *c;
 
 	list_for_each_entry(c, &chan_list, global_l) {
-		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
+		if (c->sport == psm && !bacmp(&c->src, src))
 			return c;
 	}
 	return NULL;
@@ -1305,7 +1305,6 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
 	read_lock(&chan_list_lock);
 
 	list_for_each_entry(c, &chan_list, global_l) {
-		struct sock *sk = c->sk;
 
 		if (state && c->state != state)
 			continue;
@@ -1315,16 +1314,16 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
 			int src_any, dst_any;
 
 			/* Exact match. */
-			src_match = !bacmp(&bt_sk(sk)->src, src);
-			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
+			src_match = !bacmp(&c->src, src);
+			dst_match = !bacmp(&c->dst, dst);
 			if (src_match && dst_match) {
 				read_unlock(&chan_list_lock);
 				return c;
 			}
 
 			/* Closest match */
-			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
-			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
+			src_any = !bacmp(&c->src, BDADDR_ANY);
+			dst_any = !bacmp(&c->dst, BDADDR_ANY);
 			if ((src_match && dst_any) || (src_any && dst_match) ||
 			    (src_any && dst_any))
 				c1 = c;
@@ -1338,7 +1337,7 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
 
 static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 {
-	struct sock *parent, *sk;
+	struct sock *parent;
 	struct l2cap_chan *chan, *pchan;
 
 	BT_DBG("");
@@ -1357,13 +1356,11 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 	if (!chan)
 		goto clean;
 
-	sk = chan->sk;
-
 	hci_conn_hold(conn->hcon);
 	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
 
-	bacpy(&bt_sk(sk)->src, conn->src);
-	bacpy(&bt_sk(sk)->dst, conn->dst);
+	bacpy(&chan->src, conn->src);
+	bacpy(&chan->dst, conn->dst);
 
 	l2cap_chan_add(conn, chan);
 
@@ -1577,7 +1574,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
 	read_lock(&chan_list_lock);
 
 	list_for_each_entry(c, &chan_list, global_l) {
-		struct sock *sk = c->sk;
 
 		if (state && c->state != state)
 			continue;
@@ -1587,16 +1583,16 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
 			int src_any, dst_any;
 
 			/* Exact match. */
-			src_match = !bacmp(&bt_sk(sk)->src, src);
-			dst_match = !bacmp(&bt_sk(sk)->dst, dst);
+			src_match = !bacmp(&c->src, src);
+			dst_match = !bacmp(&c->dst, dst);
 			if (src_match && dst_match) {
 				read_unlock(&chan_list_lock);
 				return c;
 			}
 
 			/* Closest match */
-			src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY);
-			dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY);
+			src_any = !bacmp(&c->src, BDADDR_ANY);
+			dst_any = !bacmp(&c->dst, BDADDR_ANY);
 			if ((src_match && dst_any) || (src_any && dst_match) ||
 			    (src_any && dst_any))
 				c1 = c;
@@ -1612,7 +1608,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 		       bdaddr_t *dst, u8 dst_type)
 {
 	struct sock *sk = chan->sk;
-	bdaddr_t *src = &bt_sk(sk)->src;
+	bdaddr_t *src = &chan->src;
 	struct l2cap_conn *conn;
 	struct hci_conn *hcon;
 	struct hci_dev *hdev;
@@ -1679,9 +1675,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 	}
 
 	/* Set destination address and psm */
-	lock_sock(sk);
-	bacpy(&bt_sk(sk)->dst, dst);
-	release_sock(sk);
+	bacpy(&chan->dst, dst);
 
 	chan->psm = psm;
 	chan->dcid = cid;
@@ -3642,8 +3636,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 
 	hci_conn_hold(conn->hcon);
 
-	bacpy(&bt_sk(sk)->src, conn->src);
-	bacpy(&bt_sk(sk)->dst, conn->dst);
+	bacpy(&chan->src, conn->src);
+	bacpy(&chan->dst, conn->dst);
 	chan->psm  = psm;
 	chan->dcid = scid;
 	chan->local_amp_id = amp_id;
@@ -6279,17 +6273,16 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
 	/* Find listening sockets and check their link_mode */
 	read_lock(&chan_list_lock);
 	list_for_each_entry(c, &chan_list, global_l) {
-		struct sock *sk = c->sk;
 
 		if (c->state != BT_LISTEN)
 			continue;
 
-		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
+		if (!bacmp(&c->src, &hdev->bdaddr)) {
 			lm1 |= HCI_LM_ACCEPT;
 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
 				lm1 |= HCI_LM_MASTER;
 			exact++;
-		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
+		} else if (!bacmp(&c->src, BDADDR_ANY)) {
 			lm2 |= HCI_LM_ACCEPT;
 			if (test_bit(FLAG_ROLE_SWITCH, &c->flags))
 				lm2 |= HCI_LM_MASTER;
@@ -6573,10 +6566,9 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
 	read_lock(&chan_list_lock);
 
 	list_for_each_entry(c, &chan_list, global_l) {
-		struct sock *sk = c->sk;
 
 		seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
-			   &bt_sk(sk)->src, &bt_sk(sk)->dst,
+			   &c->src, &c->dst,
 			   c->state, __le16_to_cpu(c->psm),
 			   c->scid, c->dcid, c->imtu, c->omtu,
 			   c->sec_level, c->mode);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 1bcfb84..0977966 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -97,7 +97,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 	    __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM)
 		chan->sec_level = BT_SECURITY_SDP;
 
-	bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
+	bacpy(&chan->src, &la.l2_bdaddr);
 
 	chan->state = BT_BOUND;
 	sk->sk_state = BT_BOUND;
@@ -259,11 +259,11 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
 
 	if (peer) {
 		la->l2_psm = chan->psm;
-		bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
+		bacpy(&la->l2_bdaddr, &chan->dst);
 		la->l2_cid = cpu_to_le16(chan->dcid);
 	} else {
 		la->l2_psm = chan->sport;
-		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
+		bacpy(&la->l2_bdaddr, &chan->src);
 		la->l2_cid = cpu_to_le16(chan->scid);
 	}
 
-- 
1.7.11.7


^ permalink raw reply related

* [RFC 00/16] Completely remove socket dependency from l2cap_core.c
From: Gustavo Padovan @ 2012-12-12  4:13 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Gustavo Padovan

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

This is the last series of patches to completely remove the l2cap socket usage
in the l2cap_core.c file. We now have a C API to access L2CAP and as a next
step we should convert RFCOMM to use this API.

Gustavo Padovan (16):
  Bluetooth: Add src and dst info to struct l2cap_chan
  Bluetooth: Remove sk_sndtimeo from l2cap_core.c
  Bluetooth: extend state_change() call to report errors too
  Bluetooth: add l2cap_state_change_and_error()
  Bluetooth: Add missing braces to an "else if"
  Bluetooth: use l2cap_chan_ready() instead of duplicate code
  Bluetooth: duplicate DEFER_SETUP flag on l2cap_chan
  Bluetooth: Improving locking in l2cap_conn_start()
  Bluetooth: lock socket in defer_cb call
  Bluetooth: Remove socket lock from state_change() in l2cap_core
  Bluetooth: remove parent socket usage from l2cap_core.c
  Bluetooth: Use abstract chan->data in comparison
  Bluetooth: Move l2cap_wait_ack() to l2cap_sock.c
  Bluetooth: Create l2cap->ops->resume()
  Bluetooth: Create l2cap->ops->set_shutdown()
  Bluetooth: Remove sk member from struct l2cap_chan

 include/net/bluetooth/l2cap.h |  20 ++++-
 net/bluetooth/a2mp.c          |   4 +-
 net/bluetooth/l2cap_core.c    | 200 ++++++++++++------------------------------
 net/bluetooth/l2cap_sock.c    |  95 +++++++++++++++++---
 4 files changed, 159 insertions(+), 160 deletions(-)

-- 
1.7.11.7


^ permalink raw reply

* [BLE] org.bluez.Device1.Connect() returns org.bluez.Error.NotAvailable
From: Ting Chou @ 2012-12-12  3:57 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org

Hello,

The Problem
-----------

I am trying to connect to a BLE device (thermometer) by the D-Bus API with
following steps:

  1. Call org.bluez.Device1.Connect(), got org.bluez.Error.NotAvailable. But
     from the log of hcidump, the device is connected.
  2. Invoke org.bluez.Device1.Disconnect(), hcidump shows it is disconnected.
  3. Connect again, org.bluez.Device1.Connect() still throws
     org.bluez.Error.NotAvailable, but this time, there's nothing from hcidump,
     i.e., the device is not connected.

I'm not sure is this expected or it is a bug. If this is a bug, and you don't
have time to fix it, I'd love to help, but I may need a mentor.

Reproduce Steps
---------------

1. ting@user-OptiPlex-755:~/w/bluez$ sudo test/test-discovery -i hci0
   [ 00:07:80:4C:5F:17 ]
       Name = DKBLE112 thermometer
       Paired = 0
       Adapter = /org/bluez/hci0
       LegacyPairing = 0
       Alias = DKBLE112 thermometer
       Connected = 0
       Address = 00:07:80:4C:5F:17
       RSSI = -66
       Trusted = 0
       Blocked = 0
   ting@user-OptiPlex-755:~/w/bluez$ sudo test/test-device connect 00:07:80:4C:5F:17
   Traceback (most recent call last):
     File "test/test-device", line 104, in <module>
       device.ConnectProfile(args[2])
     File "/usr/lib/python2.7/dist-packages/dbus/proxies.py", line 70, in __call__
       return self._proxy_method(*args, **keywords)
     File "/usr/lib/python2.7/dist-packages/dbus/proxies.py", line 145, in __call__
       **keywords)
     File "/usr/lib/python2.7/dist-packages/dbus/connection.py", line 651, in call_blocking
       message, timeout)
   dbus.exceptions.DBusException: org.bluez.Error.NotAvailable: Operation currently not available

2. ting@user-OptiPlex-755:~/w/bluez$ sudo test/test-device disconnect 00:1C:4D:00:09:02

3. ting@user-OptiPlex-755:~/w/bluez$ sudo test/test-device connect 00:07:80:4C:5F:17
   Traceback (most recent call last):
     File "test/test-device", line 104, in <module>
       device.ConnectProfile(args[2])
     File "/usr/lib/python2.7/dist-packages/dbus/proxies.py", line 70, in __call__
       return self._proxy_method(*args, **keywords)
     File "/usr/lib/python2.7/dist-packages/dbus/proxies.py", line 145, in __call__
       **keywords)
     File "/usr/lib/python2.7/dist-packages/dbus/connection.py", line 651, in call_blocking
       message, timeout)
   dbus.exceptions.DBusException: org.bluez.Error.NotAvailable: Operation currently not available

I Found
-------

- I checked /var/log/syslog and src/device.c, and found connect_profiles() is
  called twice at the first time calling org.bluez.Device.Connect():

  - 1st time
    dev->svc_resolved==FALSE, device_resolve_svc() is invoked.

  - 2nd time
    dev->svc_resolved==TRUE
    In the for loop of iterating device profiles, there're two profiles:

      a) p->auto_connect==FALSE, p->name==deviceinfo, p->local_uuid==NULL
      b) p->auto_connect==FALSE, p->name==Health Thermometer GATT driver, p->local_uuid==NULL

    Since none of them have auto_connect TRUE, dev->pending==NULL, and
    btd_error_not_available() is called.

- I tried org.bluez.Device1.ConnectProfile() as well, but since all the profiles
  have local_uuid NULL, find_connectable_profile() return NULL and
  btd_error_invalid_args() is called.

Regards,
Ting

^ permalink raw reply

* Re: [PATCH ] Bluetooth: Remove unnecessary include l2cap.h.
From: Gustavo Padovan @ 2012-12-11 22:26 UTC (permalink / raw)
  To: Rami Rosen; +Cc: linux-bluetooth, marcel, johan.hedberg
In-Reply-To: <1354943305-7069-1-git-send-email-ramirose@gmail.com>

Hi Rami,

* Rami Rosen <ramirose@gmail.com> [2012-12-08 07:08:25 +0200]:

> This patch removes unnecessary include of <net/bluetooth/l2cap.h>
> in bluetooth/bnep/core.c.
> 
> Signed-off-by: Rami Rosen <ramirose@gmail.com>
> ---
>  net/bluetooth/bnep/core.c | 1 -
>  1 file changed, 1 deletion(-)

Patch has been applied to bluetooth-next. Thanks.

	Gustavo

^ permalink raw reply

* Re: [PATCH] Bluetooth: Fix sending HCI commands after reset
From: Gustavo Padovan @ 2012-12-11 22:24 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth, stable
In-Reply-To: <1355212279-2069-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

* Szymon Janc <szymon.janc@tieto.com> [2012-12-11 08:51:19 +0100]:

> After sending reset command wait for its command complete event before
> sending next command. Some chips sends CC event for command received
> before reset if reset was send before chip replied with CC.
> 
> This is also required by specification that host shall not send
> additional HCI commands before receiving CC for reset.
> 
> < HCI Command: Reset (0x03|0x0003) plen 0                              [hci0] 18.404612
> > HCI Event: Command Complete (0x0e) plen 4                            [hci0] 18.405850
>       Write Extended Inquiry Response (0x03|0x0052) ncmd 1
>         Status: Success (0x00)
> < HCI Command: Read Local Supported Features (0x04|0x0003) plen 0      [hci0] 18.406079
> > HCI Event: Command Complete (0x0e) plen 4                            [hci0] 18.407864
>       Reset (0x03|0x0003) ncmd 1
>         Status: Success (0x00)
> < HCI Command: Read Local Supported Features (0x04|0x0003) plen 0      [hci0] 18.408062
> > HCI Event: Command Complete (0x0e) plen 12                           [hci0] 18.408835
> 
> Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
> Cc: stable@vger.kernel.org
> Acked-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
>  net/bluetooth/hci_event.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Patch has been applied to bluetooth.git. Thanks.

	Gustavo

^ permalink raw reply

* Problem on setting up l2cap connection on different version of Bluez
From: XIAN PAN @ 2012-12-11 22:20 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

My question is about the Bluetooth HID device simulation, for example,
let a computer working as a faked Bluetooth HID device. I study the
l2test.c file. My simulation program first finish hid service record
registration, and then calls l2cap_listen function (similar to the
do_listen function in l2test.c) to wait a connection request. If there
is a connection requirement, the simulation program calls the
l2cap_accept function to set up a connection.

My problem is: the simulation program only can work on Ubuntu 8.04
(kernel 2.6.24.29 and bluez 2.25). I try it on other OS such as Ubuntu
10.04, Fedora 13, Opensuse 11.1 (kernel 2.6x and bluez 4.8), none of
them can work. It looks like no l2cap requirement coming that my
program always wait for accepting l2cap requirement. That seems I miss
something in the program that it cannot work with the latest Bluez. In
fact, I search a lot on Internet and read other similar programs, such
as hidclient program
(http://anselm.hoffmeister.be/computer/hidclient/index.html.en) and
xkbdbthid (http://www.mulliner.org/bluetooth/xkbdbthid.php).
Unfortunately, those programs have the same problem as I meet: Only
can work on old Bluez. I really have not clue for this problem.

The simulation program first finish HID Mouse Service Record
registration, and then calls l2cap_listen function to wait a
connection. If there is a connection requirement, the simulation
program calls the l2cap_accept function. Those functions are taken
from bluez and bluez-utils. (for convenience, the simulation program
is in the attachment). If the simulation program runs on Ubuntu 10.04
or Fedora 13, it will wait there forever, even if another computer
already sends a connection requirement. It looks like that the
simulation program stops on l2cap_listen and never wakes up to call
the l2cap_accept function. What I miss in this process???

Thanks for your kind help.

Sincerely,
Xian

^ permalink raw reply

* Re: [PATCH 2/3 v1] Bluetooth: Move discovery state check inside hci_dev_lock()
From: Gustavo Padovan @ 2012-12-11 22:17 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth
In-Reply-To: <1354791958-28334-3-git-send-email-jaganath.k@samsung.com>

Hi Jaganath,

* Jaganath Kanakkassery <jaganath.k@samsung.com> [2012-12-06 16:35:57 +0530]:

> Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
> ---
>  net/bluetooth/hci_event.c |    9 ++++-----
>  net/bluetooth/mgmt.c      |    4 ----
>  2 files changed, 4 insertions(+), 9 deletions(-)

Please add a proper commit message. We do not allow empty commit messages,
even if the commit is trivial.

	Gustavo

^ permalink raw reply

* Re: [PATCH 3/3 v1] Bluetooth: Fix stop discovery while in STARTING state
From: Gustavo Padovan @ 2012-12-11 22:15 UTC (permalink / raw)
  To: Jaganath Kanakkassery; +Cc: linux-bluetooth
In-Reply-To: <1354791958-28334-4-git-send-email-jaganath.k@samsung.com>

Hi Jaganath,

* Jaganath Kanakkassery <jaganath.k@samsung.com> [2012-12-06 16:35:58 +0530]:

> If stop_discovery() is called when discovery state is STARTING, it
> will be failed currently. This patch fixes this.
> 
> Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
> ---
>  include/net/bluetooth/hci_core.h |    1 +
>  net/bluetooth/hci_core.c         |    9 ++++++++-
>  net/bluetooth/hci_event.c        |   15 +++++++++++++--
>  net/bluetooth/mgmt.c             |    9 +++++++++
>  4 files changed, 31 insertions(+), 3 deletions(-)
> 
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index bd63a9f..d09777a 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -64,6 +64,7 @@ struct discovery_state {
>  		DISCOVERY_RESOLVING,
>  		DISCOVERY_STOPPING,
>  	} state;
> +	int prev_state;
>  	struct list_head	all;	/* All devices found during inquiry */
>  	struct list_head	unknown;	/* Name state not known */
>  	struct list_head	resolve;	/* Name needs to be resolved */
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index c6c67b2..93d0261 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -391,7 +391,13 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
>  
>  	switch (state) {
>  	case DISCOVERY_STOPPED:
> -		if (hdev->discovery.state != DISCOVERY_STARTING)
> +		if (hdev->discovery.state == DISCOVERY_STARTING)
> +			break;
> +
> +		if (hdev->discovery.state == DISCOVERY_STOPPING &&
> +		    hdev->discovery.prev_state == DISCOVERY_STARTING)
> +			mgmt_stop_discovery_complete(hdev, 0);
> +		else
>  			mgmt_discovering(hdev, 0);

I don't think we need to be this complicated here, I don't think that add
discovery.prev_state is a good a idea. I would prefer if you add
discovery.discovering that will tell if we are discovering or not, then check
inside mgmt_discovering() if the value is the same and return right away.
You would just need to add the mgmt_stop_discovery_complete() in case state is
DISCOVERY_STOPPING.

>  		break;
>  	case DISCOVERY_STARTING:
> @@ -405,6 +411,7 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state)
>  		break;
>  	}
>  
> +	hdev->discovery.prev_state = hdev->discovery.state;
>  	hdev->discovery.state = state;
>  }
>  
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index 1fadba5..3f9f317 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1085,6 +1085,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
>  		if (status) {
>  			hci_dev_lock(hdev);
>  			mgmt_start_discovery_failed(hdev, status);
> +			if (hdev->discovery.state == DISCOVERY_STOPPING)
> +				mgmt_stop_discovery_complete(hdev, status);

I think this case will be handled by hci_discovery_set_state(), and you could
just remove this from here. And why you return the set_scan_enable status
error to the stop discovery command?

>  			hci_dev_unlock(hdev);
>  			return;
>  		}
> @@ -1092,7 +1094,10 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
>  		set_bit(HCI_LE_SCAN, &hdev->dev_flags);
>  
>  		hci_dev_lock(hdev);
> -		hci_discovery_set_state(hdev, DISCOVERY_FINDING);
> +		if (hdev->discovery.state == DISCOVERY_STOPPING)
> +			hci_cancel_le_scan(hdev);
> +		else
> +			hci_discovery_set_state(hdev, DISCOVERY_FINDING);
>  		hci_dev_unlock(hdev);
>  		break;
>  
> @@ -1180,8 +1185,11 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
>  		hci_req_complete(hdev, HCI_OP_INQUIRY, status);
>  		hci_conn_check_pending(hdev);
>  		hci_dev_lock(hdev);
> -		if (test_bit(HCI_MGMT, &hdev->dev_flags))
> +		if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
>  			mgmt_start_discovery_failed(hdev, status);
> +			if (hdev->discovery.state == DISCOVERY_STOPPING)
> +				mgmt_stop_discovery_complete(hdev, status);
> +		}

Saome thing as the previous comment, you don't need this.
mgmt_start_discovery_failed() calls hci_discovery_set_state().

>  		hci_dev_unlock(hdev);
>  		return;
>  	}
> @@ -1189,6 +1197,9 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
>  	set_bit(HCI_INQUIRY, &hdev->flags);
>  
>  	hci_dev_lock(hdev);
> +	if (hdev->discovery.state == DISCOVERY_STOPPING)
> +		hci_cancel_inquiry(hdev);
> +	else
>  	hci_discovery_set_state(hdev, DISCOVERY_FINDING);

Wrong indentation level inside the else.

>  	hci_dev_unlock(hdev);
>  }
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 332152b..a645494 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -2387,6 +2387,11 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
>  
>  	hci_dev_lock(hdev);
>  
> +	if (hdev->discovery.state == DISCOVERY_STARTING) {
> +		err = 0;
> +		goto proceed;
> +	}
> +
>  	if (!hci_discovery_active(hdev)) {

I would do something like this instead:

        if (hdev->discovery.state != DISCOVERY_STARTING &&
	            !hci_discovery_active(hdev)) {


And remove the label jump from here...

>  		err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
>  				   MGMT_STATUS_REJECTED, &mgmt_cp->type,
> @@ -2401,6 +2406,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
>  		goto unlock;
>  	}
>  
> +proceed:
>  	cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
>  	if (!cmd) {
>  		err = -ENOMEM;
> @@ -2435,6 +2441,9 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
>  
>  		break;
>  
> +	case DISCOVERY_STARTING:

and add err = 0 here.

	Gustavo

^ permalink raw reply

* Problem on setting up l2cap connection on different version of Bluez
From: XIAN PAN @ 2012-12-11 21:56 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Marcel Holtmann
In-Reply-To: <CAEoLCeYkpmXysL5M-2RW=MYaGcAt3Maqa-qbhzumtczNmPqewg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1923 bytes --]

Hi,

My question is about the Bluetooth HID device simulation, for example, let
a computer working as a faked Bluetooth HID device. I study the l2test.c
file. My simulation program first finish hid service record registration,
and then calls l2cap_listen function (similar to the do_listen function in
l2test.c) to wait a connection request. If there is a connection
requirement, the simulation program calls the l2cap_accept function to set
up a connection.

My problem is: the simulation program only can work on Ubuntu 8.04 (kernel
2.6.24.29 and bluez 2.25). I try it on other OS such as Ubuntu 10.04,
Fedora 13, Opensuse 11.1 (kernel 2.6x and bluez 4.8), none of them can
work. It looks like no l2cap requirement coming that my program always wait
for accepting l2cap requirement. That seems I miss something in the program
that it cannot work with the latest Bluez. In fact, I search a lot on
Internet and read other similar programs, such as hidclient program (
http://anselm.hoffmeister.be/computer/hidclient/index.html.en) and
xkbdbthid (http://www.mulliner.org/bluetooth/xkbdbthid.php). Unfortunately,
those programs have the same problem as I meet: Only can work on old Bluez.
I really have not clue for this problem.

The simulation program first finish HID Mouse Service Record registration,
and then calls l2cap_listen function to wait a connection. If there is a
connection requirement, the simulation program calls the l2cap_accept
function. Those functions are taken from bluez and bluez-utils. (for
convenience, the simulation program is in the attachment). If the
simulation program runs on Ubuntu 10.04 or Fedora 13, it will wait there
forever, even if another computer already sends a connection requirement.
It looks like that the simulation program stops on l2cap_listen and never
wakes up to call the l2cap_accept function. What I miss in this process???

Thanks for your kind help.

Sincerely,
Xian

[-- Attachment #2: Type: text/html, Size: 2262 bytes --]

^ permalink raw reply

* Re: hidp bug concerning ctrl_sk sock
From: Karl Relton @ 2012-12-11 20:05 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354828992.3394.7.camel@dellpc>

On Thu, 2012-12-06 at 21:23 +0000, Karl Relton wrote:
> With reference to bug https://bugzilla.kernel.org/show_bug.cgi?id=50541
> it seems to me that the hidp driver has a problem in the hidp_session()
> function.
> 
> The sock structure pointed to by ctrl_sk is being freed from under the
> functions feet (as far as I can see), causing this function to crash.
> Shouldn't a lock_sock or sock_hold be necessary to keep the sock
> structure around until hidp_session has finished with it?
> 
> 
A bit more testing, and a bit more accurate diagnosis to report. The
ctrl_sk is being orphaned in the l2cap bluetooth driver code. The
orphaning sets the sk_wq to null, leading to the OOPS in the
wait_event_timeout() call in hidp_session.

Is there some way of marking the sock as in use so that l2cap doesn't
orphan it straight away?




^ permalink raw reply

* [RFC v2 5/5] Bluetooth: Fallback transparent SCO from T2 to T1
From: Frédéric Dalleau @ 2012-12-11 16:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1355244832-2729-1-git-send-email-frederic.dalleau@linux.intel.com>

When initiating an eSCO connection, force use of T2 settings at first try.
T2 is the recommended settings from HFP 1.6 WideBand Speech so we only do that
on an transparent eSCO request. Upon connection failure, try T1 settings.
To know which of T2 or T1 should be used, we use the connection attempt index.
T2 failure is detected if Synchronous Connection Complete Event fails with
error 0x0d. This error code has been found experimentally by sending a T2
request to a T1 only SCO listener. It means "Connection Rejected due to
Limited resource".
---
 include/net/bluetooth/hci_core.h |    2 +-
 net/bluetooth/hci_conn.c         |   13 +++++++++++--
 net/bluetooth/hci_event.c        |    1 +
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 7b9902a..9ef7fe0 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -438,7 +438,7 @@ enum {
 	HCI_CONN_SSP_ENABLED,
 	HCI_CONN_POWER_SAVE,
 	HCI_CONN_REMOTE_OOB,
-	HCI_CONN_SCO_T2_SETTINGS,
+	HCI_CONN_SCO_TRANSPARENT,
 };
 
 static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 4bba2fb..87c2fa4 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -181,10 +181,19 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
 	cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
 	cp.voice_setting  = cpu_to_le16(hdev->voice_setting);
 
-	if (test_and_clear_bit(HCI_CONN_SCO_T2_SETTINGS, &conn->flags)) {
+	if (conn->attempt == 1 &&
+	    test_bit(HCI_CONN_SCO_TRANSPARENT, &conn->flags)) {
+		cp.pkt_type       = cpu_to_le16(EDR_ESCO_MASK & ~ESCO_2EV3);
 		cp.voice_setting |= 3;
 		cp.max_latency    = __constant_cpu_to_le16(0x000d);
 		cp.retrans_effort = 0x02;
+	} else if (conn->attempt == 2 &&
+		   test_bit(HCI_CONN_SCO_TRANSPARENT, &conn->flags)) {
+		cp.pkt_type       = cpu_to_le16(ESCO_EV3 | EDR_ESCO_MASK);
+		cp.voice_setting |= 3;
+		cp.max_latency    = __constant_cpu_to_le16(0x0007);
+		cp.retrans_effort = 0x02;
+		clear_bit(HCI_CONN_SCO_TRANSPARENT, &conn->flags);
 	} else {
 		cp.max_latency    = __constant_cpu_to_le16(0xffff);
 		cp.retrans_effort = 0xff;
@@ -584,7 +593,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
 	hci_conn_hold(sco);
 
 	if (codec)
-		set_bit(HCI_CONN_SCO_T2_SETTINGS, &sco->flags);
+		set_bit(HCI_CONN_SCO_TRANSPARENT, &sco->flags);
 
 	if (acl->state == BT_CONNECTED &&
 	    (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 175d23d..762ec1d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3319,6 +3319,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
 		hci_conn_add_sysfs(conn);
 		break;
 
+	case 0x0d:	/* No resource available */
 	case 0x11:	/* Unsupported Feature or Parameter Value */
 	case 0x1c:	/* SCO interval rejected */
 	case 0x1a:	/* Unsupported Remote Feature */
-- 
1.7.9.5


^ permalink raw reply related

* [RFC v2 4/5] Bluetooth: Set parameters for outgoing connections
From: Frédéric Dalleau @ 2012-12-11 16:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1355244832-2729-1-git-send-email-frederic.dalleau@linux.intel.com>

In order to establish the connection, the outgoing connection must also
request the codec. Here we need to set a bit in ACL connection flag to set up
the desired parameters if ACL is not up yet.
---
 include/net/bluetooth/hci_core.h |    3 +++
 net/bluetooth/hci_conn.c         |   21 ++++++++++++++++-----
 net/bluetooth/sco.c              |    4 ++--
 3 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index cb5d131..7b9902a 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -438,6 +438,7 @@ enum {
 	HCI_CONN_SSP_ENABLED,
 	HCI_CONN_POWER_SAVE,
 	HCI_CONN_REMOTE_OOB,
+	HCI_CONN_SCO_T2_SETTINGS,
 };
 
 static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -586,6 +587,8 @@ struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
 
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
 			     __u8 dst_type, __u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
+				 u8 sec_level, u8 auth_type, u8 codec);
 int hci_conn_check_link_mode(struct hci_conn *conn);
 int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
 int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 25bfce0..4bba2fb 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -179,9 +179,16 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
 
 	cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
 	cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
-	cp.max_latency    = __constant_cpu_to_le16(0xffff);
 	cp.voice_setting  = cpu_to_le16(hdev->voice_setting);
-	cp.retrans_effort = 0xff;
+
+	if (test_and_clear_bit(HCI_CONN_SCO_T2_SETTINGS, &conn->flags)) {
+		cp.voice_setting |= 3;
+		cp.max_latency    = __constant_cpu_to_le16(0x000d);
+		cp.retrans_effort = 0x02;
+	} else {
+		cp.max_latency    = __constant_cpu_to_le16(0xffff);
+		cp.retrans_effort = 0xff;
+	}
 
 	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
 }
@@ -551,8 +558,9 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
 	return acl;
 }
 
-static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
-				bdaddr_t *dst, u8 sec_level, u8 auth_type)
+struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
+					bdaddr_t *dst, u8 sec_level,
+					u8 auth_type, u8 codec)
 {
 	struct hci_conn *acl;
 	struct hci_conn *sco;
@@ -575,6 +583,9 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
 
 	hci_conn_hold(sco);
 
+	if (codec)
+		set_bit(HCI_CONN_SCO_T2_SETTINGS, &sco->flags);
+
 	if (acl->state == BT_CONNECTED &&
 	    (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
 		set_bit(HCI_CONN_POWER_SAVE, &acl->flags);
@@ -605,7 +616,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
 		return hci_connect_acl(hdev, dst, sec_level, auth_type);
 	case SCO_LINK:
 	case ESCO_LINK:
-		return hci_connect_sco(hdev, type, dst, sec_level, auth_type);
+		return hci_connect_sco(hdev, type, dst, sec_level, auth_type, 0);
 	}
 
 	return ERR_PTR(-EINVAL);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 6a957a3..bee0b5c 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -176,8 +176,8 @@ static int sco_connect(struct sock *sk)
 	else
 		type = SCO_LINK;
 
-	hcon = hci_connect(hdev, type, dst, BDADDR_BREDR, BT_SECURITY_LOW,
-			   HCI_AT_NO_BONDING);
+	hcon = hci_connect_sco(hdev, type, dst, BT_SECURITY_LOW,
+			       HCI_AT_NO_BONDING, sco_pi(sk)->mode);
 	if (IS_ERR(hcon)) {
 		err = PTR_ERR(hcon);
 		goto done;
-- 
1.7.9.5


^ permalink raw reply related

* [RFC v2 3/5] Bluetooth: Use codec to create SCO connection
From: Frédéric Dalleau @ 2012-12-11 16:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1355244832-2729-1-git-send-email-frederic.dalleau@linux.intel.com>

When an incoming SCO connection is requested, check the selected codec, and
reply appropriately. Codec should have been negotiated previously.
Note that this patch only changes replies for defered setup.
---
 include/net/bluetooth/hci_core.h |    2 +-
 net/bluetooth/hci_event.c        |   21 +++++++++++++++++----
 net/bluetooth/sco.c              |    2 +-
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 014a2ea..cb5d131 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -577,7 +577,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
 int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
-void hci_conn_accept(struct hci_conn *conn, int mask);
+void hci_conn_accept(struct hci_conn *conn, int mask, int mode);
 
 struct hci_chan *hci_chan_create(struct hci_conn *conn);
 void hci_chan_del(struct hci_chan *chan);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 705078a..175d23d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2047,7 +2047,7 @@ unlock:
 	hci_conn_check_pending(hdev);
 }
 
-void hci_conn_accept(struct hci_conn *conn, int mask)
+void hci_conn_accept(struct hci_conn *conn, int mask, int mode)
 {
 	struct hci_dev *hdev = conn->hdev;
 
@@ -2070,13 +2070,26 @@ void hci_conn_accept(struct hci_conn *conn, int mask)
 		struct hci_cp_accept_sync_conn_req cp;
 
 		bacpy(&cp.bdaddr, &conn->dst);
-		cp.pkt_type = cpu_to_le16(conn->pkt_type);
 
+		cp.pkt_type       = cpu_to_le16(conn->pkt_type);
 		cp.tx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
 		cp.rx_bandwidth   = __constant_cpu_to_le32(0x00001f40);
-		cp.max_latency    = __constant_cpu_to_le16(0xffff);
 		cp.content_format = cpu_to_le16(hdev->voice_setting);
-		cp.retrans_effort = 0xff;
+
+		switch (mode) {
+		case 0:
+			cp.max_latency    = __constant_cpu_to_le16(0xffff);
+			cp.retrans_effort = 0xff;
+			break;
+		case 1:
+			cp.content_format |= cpu_to_le16(3);
+			if (conn->pkt_type & ESCO_2EV3)
+				cp.max_latency = __constant_cpu_to_le16(0x0008);
+			else
+				cp.max_latency = __constant_cpu_to_le16(0x000D);
+			cp.retrans_effort = 0x02;
+			break;
+		}
 
 		hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ,
 			     sizeof(cp), &cp);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 22ad5fa..6a957a3 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -666,7 +666,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 
 	if (sk->sk_state == BT_CONNECT2 &&
 	    test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
-		hci_conn_accept(pi->conn->hcon, 0);
+		hci_conn_accept(pi->conn->hcon, 0, pi->mode);
 		sk->sk_state = BT_CONFIG;
 
 		release_sock(sk);
-- 
1.7.9.5


^ permalink raw reply related

* [RFC v2 2/5] Bluetooth: Add setsockopt for SCO socket mode
From: Frédéric Dalleau @ 2012-12-11 16:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1355244832-2729-1-git-send-email-frederic.dalleau@linux.intel.com>

This patch implements setsockopt().
---
 net/bluetooth/sco.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index bdb21b2..22ad5fa 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -678,6 +678,47 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
 }
 
+static int sco_sock_setsockopt_old(struct socket *sock, int optname,
+				   char __user *optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct sco_options opts;
+	int len, err = 0;
+
+	BT_DBG("sk %p", sk);
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case SCO_OPTIONS:
+		if (sk->sk_state != BT_OPEN &&
+		    sk->sk_state != BT_BOUND &&
+		    sk->sk_state != BT_CONNECT2) {
+			err = -EINVAL;
+			break;
+		}
+
+		opts.mode = SCO_MODE_CVSD;
+
+		len = min_t(unsigned int, sizeof(opts), optlen);
+		if (copy_from_user((char *) &opts, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+
+		sco_pi(sk)->mode = opts.mode;
+		BT_DBG("mode %d", opts.mode);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
 static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
 {
 	struct sock *sk = sock->sk;
@@ -686,6 +727,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
 
 	BT_DBG("sk %p", sk);
 
+	if (level == SOL_SCO)
+		return sco_sock_setsockopt_old(sock, optname, optval, optlen);
+
 	lock_sock(sk);
 
 	switch (optname) {
-- 
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