Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH] Bluetooth: Fix possible deadlock in SCO code
From: Chan-yeol Park @ 2012-11-28 14:35 UTC (permalink / raw)
  To: Gustavo Padovan; +Cc: linux-bluetooth
In-Reply-To: <1339738863-6407-1-git-send-email-gustavo@padovan.org>

Hi Gustavo

If we use the below patch, we face crash or circular locking dependency 
detected.
*It's very easily reproduced(about 100%)

I guess once sco_sock_shutdown() is called,"sk" would be destructed.
but due to response from remote side, sco_disconn_cfm(),sco_conn_del() 
would be called in order.
and finally in sco_conn_del() crash or circular locking dependency is 
happened.
because it access "sk" that is already destructed.

I think in sco_chan_del(), based on conn info, the relation between sk 
and conn should be cleaned
like the original code before you commit.

[  104.889622] Bluetooth: [sco_sock_shutdown] sock e8856000, sk eb695000
[  104.894666] Bluetooth: [sco_sock_clear_timer] sock eb695000 state 1
[  104.900869] Bluetooth: [__sco_sock_close] sk eb695000 state 1 socket 
e8856000
[  104.907976] Bluetooth: [sco_sock_set_timer] sock eb695000 state 8 
timeout 400
[  104.915106] Bluetooth: [sco_sock_release] sock e8856000, sk eb695000
[  104.921439] Bluetooth: [sco_sock_clear_timer] sock eb695000 state 8
[  104.927875] Bluetooth: [__sco_sock_close] sk eb695000 state 8 socket 
e8856000
[  104.938762] Bluetooth: [sco_chan_del] sk eb695000, conn ed38da60, err 104
[  104.956861] Bluetooth: [sco_sock_kill] sk eb695000 state 9
[  104.962321] Bluetooth: [sco_sock_destruct] sk eb695000
[  105.071125] Bluetooth: [sco_disconn_cfm] hcon ed376000 reason 22
[  105.075875] Bluetooth: [sco_conn_del] hcon ed376000 conn ed38da60, 
err 103
[  105.082848] Bluetooth: [sco_conn_del] before bh_lock_sock () sk eb695000

Could you give me your opinion?

regards
chanyeol

On 06/15/2012 02:41 PM, Gustavo Padovan wrote:
> From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
>
> sco_chan_del() only has conn != NULL when called from sco_conn_del() so
> just move the code from it that deal with conn to sco_conn_del().
>
> [  120.765529]
> [  120.765529] ======================================================
> [  120.766529] [ INFO: possible circular locking dependency detected ]
> [  120.766529] 3.5.0-rc1-10292-g3701f94-dirty #70 Tainted: G        W
> [  120.766529] -------------------------------------------------------
> [  120.766529] kworker/u:3/1497 is trying to acquire lock:
> [  120.766529]  (&(&conn->lock)->rlock#2){+.+...}, at:
> [<ffffffffa00b7ecc>] sco_chan_del+0x4c/0x170 [bluetooth]
> [  120.766529]
> [  120.766529] but task is already holding lock:
> [  120.766529]  (slock-AF_BLUETOOTH-BTPROTO_SCO){+.+...}, at:
> [<ffffffffa00b8401>] sco_conn_del+0x61/0xe0 [bluetooth]
> [  120.766529]
> [  120.766529] which lock already depends on the new lock.
> [  120.766529]
> [  120.766529]
> [  120.766529] the existing dependency chain (in reverse order) is:
> [  120.766529]
> [  120.766529] -> #1 (slock-AF_BLUETOOTH-BTPROTO_SCO){+.+...}:
> [  120.766529]        [<ffffffff8107980e>] lock_acquire+0x8e/0xb0
> [  120.766529]        [<ffffffff813c19e0>] _raw_spin_lock+0x40/0x80
> [  120.766529]        [<ffffffffa00b85e9>] sco_connect_cfm+0x79/0x300
> [bluetooth]
> [  120.766529]        [<ffffffffa0094b13>]
> hci_sync_conn_complete_evt.isra.90+0x343/0x400 [bluetooth]
> [  120.766529]        [<ffffffffa009d447>] hci_event_packet+0x317/0xfb0
> [bluetooth]
> [  120.766529]        [<ffffffffa008aa68>] hci_rx_work+0x2c8/0x890
> [bluetooth]
> [  120.766529]        [<ffffffff81047db7>] process_one_work+0x197/0x460
> [  120.766529]        [<ffffffff810489d6>] worker_thread+0x126/0x2d0
> [  120.766529]        [<ffffffff8104ee4d>] kthread+0x9d/0xb0
> [  120.766529]        [<ffffffff813c4294>] kernel_thread_helper+0x4/0x10
> [  120.766529]
> [  120.766529] -> #0 (&(&conn->lock)->rlock#2){+.+...}:
> [  120.766529]        [<ffffffff81078a8a>] __lock_acquire+0x154a/0x1d30
> [  120.766529]        [<ffffffff8107980e>] lock_acquire+0x8e/0xb0
> [  120.766529]        [<ffffffff813c19e0>] _raw_spin_lock+0x40/0x80
> [  120.766529]        [<ffffffffa00b7ecc>] sco_chan_del+0x4c/0x170
> [bluetooth]
> [  120.766529]        [<ffffffffa00b8414>] sco_conn_del+0x74/0xe0
> [bluetooth]
> [  120.766529]        [<ffffffffa00b88a2>] sco_disconn_cfm+0x32/0x60
> [bluetooth]
> [  120.766529]        [<ffffffffa0093a82>]
> hci_disconn_complete_evt.isra.53+0x242/0x390 [bluetooth]
> [  120.766529]        [<ffffffffa009d747>] hci_event_packet+0x617/0xfb0
> [bluetooth]
> [  120.766529]        [<ffffffffa008aa68>] hci_rx_work+0x2c8/0x890
> [bluetooth]
> [  120.766529]        [<ffffffff81047db7>] process_one_work+0x197/0x460
> [  120.766529]        [<ffffffff810489d6>] worker_thread+0x126/0x2d0
> [  120.766529]        [<ffffffff8104ee4d>] kthread+0x9d/0xb0
> [  120.766529]        [<ffffffff813c4294>] kernel_thread_helper+0x4/0x10
> [  120.766529]
> [  120.766529] other info that might help us debug this:
> [  120.766529]
> [  120.766529]  Possible unsafe locking scenario:
> [  120.766529]
> [  120.766529]        CPU0                    CPU1
> [  120.766529]        ----                    ----
> [  120.766529]   lock(slock-AF_BLUETOOTH-BTPROTO_SCO);
> [  120.766529]
> lock(&(&conn->lock)->rlock#2);
> [  120.766529]
> lock(slock-AF_BLUETOOTH-BTPROTO_SCO);
> [  120.766529]   lock(&(&conn->lock)->rlock#2);
> [  120.766529]
> [  120.766529]  *** DEADLOCK ***
>
> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> ---
>   net/bluetooth/sco.c |   19 +++++++++----------
>   1 file changed, 9 insertions(+), 10 deletions(-)
>
> diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
> index cbdd313..596fdc8 100644
> --- a/net/bluetooth/sco.c
> +++ b/net/bluetooth/sco.c
> @@ -149,6 +149,15 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
>   		sco_sock_clear_timer(sk);
>   		sco_chan_del(sk, err);
>   		bh_unlock_sock(sk);
> +
> +		sco_conn_lock(conn);
> +		conn->sk = NULL;
> +		sco_pi(sk)->conn = NULL;
> +		sco_conn_unlock(conn);
> +
> +		if (conn->hcon)
> +			hci_conn_put(conn->hcon);
> +
>   		sco_sock_kill(sk);
>   	}
>   
> @@ -838,16 +847,6 @@ static void sco_chan_del(struct sock *sk, int err)
>   
>   	BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
>   
> -	if (conn) {
> -		sco_conn_lock(conn);
> -		conn->sk = NULL;
> -		sco_pi(sk)->conn = NULL;
> -		sco_conn_unlock(conn);
> -
> -		if (conn->hcon)
> -			hci_conn_put(conn->hcon);
> -	}
> -
>   	sk->sk_state = BT_CLOSED;
>   	sk->sk_err   = err;
>   	sk->sk_state_change(sk);


^ permalink raw reply

* [PATCH] adapter: Fix memory leak in convert_config
From: Szymon Janc @ 2012-11-28 14:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

'converted' was not freed if config file was already converted.
---
 src/adapter.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/src/adapter.c b/src/adapter.c
index 163360f..b44eb36 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2698,6 +2698,7 @@ static void convert_config(struct btd_adapter *adapter, const char *filename,
 	if (converted) {
 		if (strcmp(converted, "yes") == 0) {
 			DBG("Legacy config file already converted");
+			g_free(converted);
 			return;
 		}
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 1/2] adapter: Fix memory leak in convert_config
From: Szymon Janc @ 2012-11-28 15:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

'converted' was not freed if config file was already converted.
---
 src/adapter.c |    1 +
 1 file changed, 1 insertion(+)

diff --git a/src/adapter.c b/src/adapter.c
index 163360f..d6f8a37 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2698,6 +2698,7 @@ static void convert_config(struct btd_adapter *adapter, const char *filename,
 	if (converted) {
 		if (strcmp(converted, "yes") == 0) {
 			DBG("Legacy config file already converted");
+			free(converted);
 			return;
 		}
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 2/2] adapter: Fix improper freeing with g_free in convert_config
From: Szymon Janc @ 2012-11-28 15:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1354115856-29301-1-git-send-email-szymon.janc@tieto.com>

Memory in textfile_get is allocated with malloc and it should be freed
with free not g_free.
---
 src/adapter.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index d6f8a37..f134dfe 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2702,7 +2702,7 @@ static void convert_config(struct btd_adapter *adapter, const char *filename,
 			return;
 		}
 
-		g_free(converted);
+		free(converted);
 	}
 
 	if (read_local_name(&adapter->bdaddr, str) == 0)
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 1/5] Bluetooth: AMP: Check that AMP is present and active
From: Andrei Emeltchenko @ 2012-11-28 15:59 UTC (permalink / raw)
  To: linux-bluetooth

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

Before starting quering remote AMP controllers make sure
that there is local active AMP controller.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/net/bluetooth/hci_core.h |   16 ++++++++++++++++
 net/bluetooth/l2cap_core.c       |    1 +
 2 files changed, 17 insertions(+)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2f2b743..014a2ea 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -779,6 +779,22 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_host_le_capable(dev)   !!((dev)->host_features[0] & LMP_HOST_LE)
 #define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR)
 
+/* returns true if at least one AMP active */
+static inline bool hci_amp_capable(void)
+{
+	struct hci_dev *hdev;
+	bool ret = false;
+
+	read_lock(&hci_dev_list_lock);
+	list_for_each_entry(hdev, &hci_dev_list, list)
+		if (hdev->amp_type == HCI_AMP &&
+		    test_bit(HCI_UP, &hdev->flags))
+			ret = true;
+	read_unlock(&hci_dev_list_lock);
+
+	return ret;
+}
+
 /* ----- HCI protocols ----- */
 #define HCI_PROTO_DEFER             0x01
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b52f66d..39e144f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1014,6 +1014,7 @@ static bool __amp_capable(struct l2cap_chan *chan)
 	struct l2cap_conn *conn = chan->conn;
 
 	if (enable_hs &&
+	    hci_amp_capable() &&
 	    chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED &&
 	    conn->fixed_chan_mask & L2CAP_FC_A2MP)
 		return true;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 2/5] Bluetooth: Refactor l2cap_send_disconn_req
From: Andrei Emeltchenko @ 2012-11-28 15:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354118382-25571-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

l2cap_send_disconn_req takes 3 parameters of which conn might be
derived from chan. Make this conversion inside l2cap_send_disconn_req.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |   56 ++++++++++++++++++++------------------------
 1 file changed, 26 insertions(+), 30 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 39e144f..d8cffdb 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -53,8 +53,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
 static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
 			   void *data);
 static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
-static void l2cap_send_disconn_req(struct l2cap_conn *conn,
-				   struct l2cap_chan *chan, int err);
+static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
 
 static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
 		     struct sk_buff_head *skbs, u8 event);
@@ -632,7 +631,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
 		if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
 		    conn->hcon->type == ACL_LINK) {
 			__set_chan_timer(chan, sk->sk_sndtimeo);
-			l2cap_send_disconn_req(conn, chan, reason);
+			l2cap_send_disconn_req(chan, reason);
 		} else
 			l2cap_chan_del(chan, reason);
 		break;
@@ -1181,10 +1180,10 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
 	}
 }
 
-static void l2cap_send_disconn_req(struct l2cap_conn *conn,
-				   struct l2cap_chan *chan, int err)
+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;
 
 	if (!conn)
@@ -1961,7 +1960,7 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan)
 		if (chan->max_tx != 0 &&
 		    bt_cb(skb)->control.retries > chan->max_tx) {
 			BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
-			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+			l2cap_send_disconn_req(chan, ECONNRESET);
 			l2cap_seq_list_clear(&chan->retrans_list);
 			break;
 		}
@@ -2667,7 +2666,7 @@ static void l2cap_tx_state_wait_f(struct l2cap_chan *chan,
 			__set_monitor_timer(chan);
 			chan->retry_count++;
 		} else {
-			l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
+			l2cap_send_disconn_req(chan, ECONNABORTED);
 		}
 		break;
 	default:
@@ -3878,7 +3877,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
 	/* Complete config. */
 	len = l2cap_parse_conf_req(chan, rsp);
 	if (len < 0) {
-		l2cap_send_disconn_req(conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		goto unlock;
 	}
 
@@ -3900,7 +3899,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
 			err = l2cap_ertm_init(chan);
 
 		if (err < 0)
-			l2cap_send_disconn_req(chan->conn, chan, -err);
+			l2cap_send_disconn_req(chan, -err);
 		else
 			l2cap_chan_ready(chan);
 
@@ -3968,7 +3967,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
 						   buf, &result);
 			if (len < 0) {
-				l2cap_send_disconn_req(conn, chan, ECONNRESET);
+				l2cap_send_disconn_req(chan, ECONNRESET);
 				goto done;
 			}
 
@@ -3989,7 +3988,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
 			char req[64];
 
 			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
-				l2cap_send_disconn_req(conn, chan, ECONNRESET);
+				l2cap_send_disconn_req(chan, ECONNRESET);
 				goto done;
 			}
 
@@ -3998,7 +3997,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
 						   req, &result);
 			if (len < 0) {
-				l2cap_send_disconn_req(conn, chan, ECONNRESET);
+				l2cap_send_disconn_req(chan, ECONNRESET);
 				goto done;
 			}
 
@@ -4014,7 +4013,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
 		l2cap_chan_set_err(chan, ECONNRESET);
 
 		__set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
-		l2cap_send_disconn_req(conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		goto done;
 	}
 
@@ -4031,7 +4030,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
 			err = l2cap_ertm_init(chan);
 
 		if (err < 0)
-			l2cap_send_disconn_req(chan->conn, chan, -err);
+			l2cap_send_disconn_req(chan, -err);
 		else
 			l2cap_chan_ready(chan);
 	}
@@ -4393,7 +4392,7 @@ static void l2cap_logical_fail(struct l2cap_chan *chan)
 	/* Logical link setup failed */
 	if (chan->state != BT_CONNECTED) {
 		/* Create channel failure, disconnect */
-		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		return;
 	}
 
@@ -4436,7 +4435,7 @@ static void l2cap_logical_finish_create(struct l2cap_chan *chan,
 
 		err = l2cap_ertm_init(chan);
 		if (err < 0)
-			l2cap_send_disconn_req(chan->conn, chan, -err);
+			l2cap_send_disconn_req(chan, -err);
 		else
 			l2cap_chan_ready(chan);
 	}
@@ -5401,7 +5400,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan,
 
 	if (control->reqseq == chan->next_tx_seq) {
 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
-		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		return;
 	}
 
@@ -5415,7 +5414,7 @@ static void l2cap_handle_srej(struct l2cap_chan *chan,
 
 	if (chan->max_tx != 0 && bt_cb(skb)->control.retries >= chan->max_tx) {
 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
-		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		return;
 	}
 
@@ -5459,7 +5458,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan,
 
 	if (control->reqseq == chan->next_tx_seq) {
 		BT_DBG("Invalid reqseq %d, disconnecting", control->reqseq);
-		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		return;
 	}
 
@@ -5468,7 +5467,7 @@ static void l2cap_handle_rej(struct l2cap_chan *chan,
 	if (chan->max_tx && skb &&
 	    bt_cb(skb)->control.retries >= chan->max_tx) {
 		BT_DBG("Retry limit exceeded (%d)", chan->max_tx);
-		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		return;
 	}
 
@@ -5652,8 +5651,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
 			break;
 		case L2CAP_TXSEQ_INVALID:
 		default:
-			l2cap_send_disconn_req(chan->conn, chan,
-					       ECONNRESET);
+			l2cap_send_disconn_req(chan, ECONNRESET);
 			break;
 		}
 		break;
@@ -5786,8 +5784,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
 			break;
 		case L2CAP_TXSEQ_INVALID:
 		default:
-			l2cap_send_disconn_req(chan->conn, chan,
-					       ECONNRESET);
+			l2cap_send_disconn_req(chan, ECONNRESET);
 			break;
 		}
 		break;
@@ -5982,7 +5979,7 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
 		BT_DBG("Invalid reqseq %d (next_tx_seq %d, expected_ack_seq %d",
 		       control->reqseq, chan->next_tx_seq,
 		       chan->expected_ack_seq);
-		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 	}
 
 	return err;
@@ -6051,7 +6048,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
 		len -= L2CAP_FCS_SIZE;
 
 	if (len > chan->mps) {
-		l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		goto drop;
 	}
 
@@ -6076,8 +6073,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
 		}
 
 		if (err)
-			l2cap_send_disconn_req(chan->conn, chan,
-					       ECONNRESET);
+			l2cap_send_disconn_req(chan, ECONNRESET);
 	} else {
 		const u8 rx_func_to_event[4] = {
 			L2CAP_EV_RECV_RR, L2CAP_EV_RECV_REJ,
@@ -6094,7 +6090,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
 
 		if (len != 0) {
 			BT_ERR("Trailing bytes: %d in sframe", len);
-			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+			l2cap_send_disconn_req(chan, ECONNRESET);
 			goto drop;
 		}
 
@@ -6105,7 +6101,7 @@ static int l2cap_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
 
 		event = rx_func_to_event[control->super];
 		if (l2cap_rx(chan, control, skb, event))
-			l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
+			l2cap_send_disconn_req(chan, ECONNRESET);
 	}
 
 	return 0;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 3/5] Bluetooth: Fix missing L2CAP EWS Conf parameter
From: Andrei Emeltchenko @ 2012-11-28 15:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354118382-25571-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

If L2CAP_FEAT_FCS is not supported we sould miss EWS option
configuration because of break. Make code more readable by
combining FCS configuration in the single block.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |   30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d8cffdb..f10e4be 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3106,18 +3106,16 @@ done:
 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
 			l2cap_add_opt_efs(&ptr, chan);
 
-		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
-			break;
-
-		if (chan->fcs == L2CAP_FCS_NONE ||
-		    test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
-			chan->fcs = L2CAP_FCS_NONE;
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
-		}
-
 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
 					   chan->tx_win);
+
+		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
+			if (chan->fcs == L2CAP_FCS_NONE ||
+			    test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
+				chan->fcs = L2CAP_FCS_NONE;
+				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
+			}
 		break;
 
 	case L2CAP_MODE_STREAMING:
@@ -3139,14 +3137,12 @@ done:
 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
 			l2cap_add_opt_efs(&ptr, chan);
 
-		if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
-			break;
-
-		if (chan->fcs == L2CAP_FCS_NONE ||
-		    test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
-			chan->fcs = L2CAP_FCS_NONE;
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
-		}
+		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
+			if (chan->fcs == L2CAP_FCS_NONE ||
+			    test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
+				chan->fcs = L2CAP_FCS_NONE;
+				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
+			}
 		break;
 	}
 
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 4/5] Bluetooth: Process receiving FCS_NONE in L2CAP Conf Rsp
From: Andrei Emeltchenko @ 2012-11-28 15:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354118382-25571-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Process L2CAP Config rsp Pending with FCS Option 0x00 (No FCS)
which is sent by Motorola Windows 7 Bluetooth stack. The trace
is shown below (all other options are skipped).

...
< ACL data: handle 1 flags 0x00 dlen 48
    L2CAP(s): Config req: dcid 0x0043 flags 0x00 clen 36
      ...
      FCS Option 0x00 (No FCS)
> ACL data: handle 1 flags 0x02 dlen 48
    L2CAP(s): Config req: dcid 0x0041 flags 0x00 clen 36
      ...
      FCS Option 0x01 (CRC16 Check)
< ACL data: handle 1 flags 0x00 dlen 47
    L2CAP(s): Config rsp: scid 0x0043 flags 0x00 result 4 clen 33
      Pending
      ...
> ACL data: handle 1 flags 0x02 dlen 50
    L2CAP(s): Config rsp: scid 0x0041 flags 0x00 result 4 clen 36
      Pending
      ...
      FCS Option 0x00 (No FCS)
< ACL data: handle 1 flags 0x00 dlen 14
    L2CAP(s): Config rsp: scid 0x0043 flags 0x00 result 0 clen 0
      Success
> ACL data: handle 1 flags 0x02 dlen 14
    L2CAP(s): Config rsp: scid 0x0041 flags 0x00 result 0 clen 0
      Success
...

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/l2cap_core.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index f10e4be..d30978b 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3429,6 +3429,12 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
 					   (unsigned long) &efs);
 			break;
+
+		case L2CAP_CONF_FCS:
+			if (*result == L2CAP_CONF_PENDING)
+				if (val == L2CAP_FCS_NONE)
+					set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
+			break;
 		}
 	}
 
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 5/5] Bluetooth: AMP: Mark controller radio powered down after HCIDEVDOWN
From: Andrei Emeltchenko @ 2012-11-28 15:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354118382-25571-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

After getting HCIDEVDOWN controller did not mark itself as 0x00 which
means: "The Controller radio is available but is currently physically
powered down". The result was even if the hdev was down we return
in controller list value 0x01 "status 0x01 (Bluetooth only)".

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/bluetooth/hci_core.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 69eb644..ec7d3a7 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -861,6 +861,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 	/* Clear flags */
 	hdev->flags = 0;
 
+	/* Controller radio is available but is currently powered down */
+	hdev->amp_status = 0;
+
 	memset(hdev->eir, 0, sizeof(hdev->eir));
 	memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
 
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH v2 1/2] adapter: Fix memory leak in convert_config
From: Johan Hedberg @ 2012-11-28 17:08 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1354115856-29301-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Wed, Nov 28, 2012, Szymon Janc wrote:
> 'converted' was not freed if config file was already converted.
> ---
>  src/adapter.c |    1 +
>  1 file changed, 1 insertion(+)

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH bluez] wiimote: add Wii-Remote-Plus ID and name detection
From: Peter Olson @ 2012-11-28 18:03 UTC (permalink / raw)
  To: David Herrmann; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CANq1E4Thu4XWHATv2BiA7m0Nppi92JdeGtLfCj35tr9g6RSw3A@mail.gmail.com>

Apologies, the testing as a whole is not yet complete as I have some
issues still. However, the bluez portion of the fixes David was making
so seem to work properly. Before the patch I would have to use blueman
to force a connection without a paring code, after the patch the
bluetooth recognizes the device automatically and prompts for
accepting the connection. My remaining issues lie with getting some
userspace tools to recognize the wiimote, not with the bluez.

Peter

On Wed, Nov 28, 2012 at 5:00 AM, David Herrmann
<dh.herrmann@googlemail.com> wrote:
> Hi Johan
>
> On Wed, Nov 28, 2012 at 1:50 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
>> Hi David,
>>
>> On Mon, Oct 22, 2012, David Herrmann wrote:
>>> The Nintendo Wii Remote Plus uses a new product ID and name. To detect
>>> them properly, we need to add them to the wiimote-module.
>>>
>>> To avoid an overlong "if" statement, this converts the match-function to
>>> walk over an array and check all VID/PID pairs and device-names. This
>>> makes adding new devices much easier.
>>> ---
>>> Hi Johan
>>>
>>> I am actually not sure why Nintendo changed the VID/PID for the new revisions of
>>> the WiimotePlus. I have a WiimotePlus which still uses the old numbers and works
>>> here quite well. However, I have now got multiple requests from people with the
>>> new device name and IDs. Unfortunately, I cannot test these so I'd like to have
>>> a "Tested-by" by Peter (CC'ed) before this is applied.
>>>
>>> Thanks
>>> David
>>>
>>>  plugins/wiimote.c | 35 ++++++++++++++++++++++++++++-------
>>>  1 file changed, 28 insertions(+), 7 deletions(-)
>>
>> Well, the Tested-by never came, but since the patch looks ok to me I
>> went ahead and applied it anyway (with a minor fix to use G_N_ELEMENTS()
>> instead of your custom array length calculation).
>
> Sorry for the long delay. But I don't have the device so it sometimes
> takes a bit longer. Anyway, it doesn't do any harm if we apply it so
> yes, thanks for not forgetting about it.
>
> Cheers
> David

^ permalink raw reply

* [PATCH 1/2] lib: Declare codec field in sco_options
From: Frédéric Dalleau @ 2012-11-28 18:06 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

---
 lib/sco.h |    1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/sco.h b/lib/sco.h
index 75336a5..70e2584 100644
--- a/lib/sco.h
+++ b/lib/sco.h
@@ -47,6 +47,7 @@ struct sockaddr_sco {
 #define SCO_OPTIONS	0x01
 struct sco_options {
 	uint16_t	mtu;
+	uint8_t		codec;
 };
 
 #define SCO_CONNINFO	0x02
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 2/2] scotest: Add option for SCO socket codec
From: Frédéric Dalleau @ 2012-11-28 18:06 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1354125970-15609-1-git-send-email-frederic.dalleau@linux.intel.com>

---
 test/scotest.c |   36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/test/scotest.c b/test/scotest.c
index a40e395..27df08d 100644
--- a/test/scotest.c
+++ b/test/scotest.c
@@ -58,6 +58,7 @@ static long data_size = 672;
 static bdaddr_t bdaddr;
 
 static int defer_setup = 0;
+static int codec = 0;
 
 static float tv2fl(struct timeval tv)
 {
@@ -68,6 +69,7 @@ static int do_connect(char *svr)
 {
 	struct sockaddr_sco addr;
 	struct sco_conninfo conn;
+	struct sco_options  opts;
 	socklen_t optlen;
 	int sk;
 
@@ -90,6 +92,15 @@ static int do_connect(char *svr)
 		goto error;
 	}
 
+	/* Add SCO options */
+	memset(&opts, 0, sizeof(opts));
+	opts.codec = codec;
+	if (setsockopt(sk, SOL_SCO, SCO_OPTIONS, &opts, sizeof(opts)) < 0) {
+		syslog(LOG_ERR, "Can't set socket options: %s (%d)",
+							strerror(errno), errno);
+		goto error;
+	}
+
 	/* Connect to remote device */
 	memset(&addr, 0, sizeof(addr));
 	addr.sco_family = AF_BLUETOOTH;
@@ -229,8 +240,16 @@ error:
 
 static void dump_mode(int sk)
 {
+	struct sco_options opts;
 	int len;
 
+	/* Add SCO options */
+	memset(&opts, 0, sizeof(opts));
+	opts.codec = codec;
+	if (setsockopt(sk, SOL_SCO, SCO_OPTIONS, &opts, sizeof(opts)) < 0)
+		syslog(LOG_ERR, "Can't set socket options: %s (%d)",
+							strerror(errno), errno);
+
 	if (defer_setup) {
 		len = read(sk, buf, sizeof(buf));
 		if (len < 0)
@@ -248,9 +267,17 @@ static void dump_mode(int sk)
 static void recv_mode(int sk)
 {
 	struct timeval tv_beg,tv_end,tv_diff;
+	struct sco_options opts;
 	long total;
 	int len;
 
+	/* Add SCO options */
+	memset(&opts, 0, sizeof(opts));
+	opts.codec = codec;
+	if (setsockopt(sk, SOL_SCO, SCO_OPTIONS, &opts, sizeof(opts)) < 0)
+		syslog(LOG_ERR, "Can't set socket options: %s (%d)",
+							strerror(errno), errno);
+
 	if (defer_setup) {
 		len = read(sk, buf, sizeof(buf));
 		if (len < 0)
@@ -381,7 +408,8 @@ static void usage(void)
 		"\t-n connect and be silent (client)\n"
 		"Options:\n"
 		"\t[-b bytes]\n"
-		"\t[-W seconds] enable deferred setup\n");
+		"\t[-W seconds] enable deferred setup\n"
+		"\t[-C codec] select codec (sco only: 0 cvsd, 1 msbc)\n");
 }
 
 int main(int argc ,char *argv[])
@@ -389,7 +417,7 @@ int main(int argc ,char *argv[])
 	struct sigaction sa;
 	int opt, sk, mode = RECV;
 
-	while ((opt = getopt(argc, argv, "rdscmnb:W:")) != EOF) {
+	while ((opt = getopt(argc, argv, "rdscmnb:W:C:")) != EOF) {
 		switch(opt) {
 		case 'r':
 			mode = RECV;
@@ -423,6 +451,10 @@ int main(int argc ,char *argv[])
 			defer_setup = atoi(optarg);
 			break;
 
+		case 'C':
+			codec = atoi(optarg);
+			break;
+
 		default:
 			usage();
 			exit(1);
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 0/4] sco: Another SCO socket option :)
From: Frédéric Dalleau @ 2012-11-28 18:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau

Hi,

This patch implements codec socket option on SCO sockets.
Currently it proposes T2 codec settins (see HFP 1.6 p.102)


How to test:
$ scotest -W 1 -C 1

on another machine with same patches run:
$ scotest -n $ADDR -C 1

Check result with btmon.

This took more time than I expected for I met the following issues :
* bluetooth-next branch crashed in apparmor after login.
* At some point, unplugging my usb dongle would also crash the kernel. It is
possible this one was a mix between different versions of kernel modules.
* if the connection request is not accepted, the initiator gets in timeout, and
there is a crash. I think this one will need be fixed.

Next step is to implement fallback between T2 and T1. I'm thinking about using
another bit in hconn->flags to store current settings selection.

Let me know what you think.
Best regards,
Frédéric


Frédéric Dalleau (4):
  Bluetooth: Add option for SCO socket codec
  Bluetooth: Add option for SCO socket socket
  Bluetooth: Use codec to create SCO connection
  Bluetooth: Set link parameters for outgoing connections

 include/net/bluetooth/hci_core.h |    6 +++--
 include/net/bluetooth/sco.h      |    2 ++
 net/bluetooth/hci_conn.c         |   24 ++++++++++++++----
 net/bluetooth/hci_event.c        |   23 ++++++++++++++---
 net/bluetooth/l2cap_core.c       |    4 +--
 net/bluetooth/mgmt.c             |    4 +--
 net/bluetooth/sco.c              |   51 ++++++++++++++++++++++++++++++++++++--
 7 files changed, 97 insertions(+), 17 deletions(-)

-- 
1.7.9.5


^ permalink raw reply

* [RFC 1/4] Bluetooth: Add option for SCO socket codec
From: Frédéric Dalleau @ 2012-11-28 18:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1354127316-17431-1-git-send-email-frederic.dalleau@linux.intel.com>

This patch extends the current SCO socket option to add a codec field. This
field is intended to choose between mSBC and CVSD codec at runtime. Incoming
connections will be setup during defered setup. Outgoing connections have to
be setup before connect(). The selected codec is stored in the sco socket info.
This patch declares needed members and implements getsockopt().
---
 include/net/bluetooth/sco.h |    2 ++
 net/bluetooth/sco.c         |    3 +++
 2 files changed, 5 insertions(+)

diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
index 1e35c43..c283de0 100644
--- a/include/net/bluetooth/sco.h
+++ b/include/net/bluetooth/sco.h
@@ -43,6 +43,7 @@ struct sockaddr_sco {
 #define SCO_OPTIONS	0x01
 struct sco_options {
 	__u16 mtu;
+	__u8 codec;
 };
 
 #define SCO_CONNINFO	0x02
@@ -73,6 +74,7 @@ struct sco_conn {
 struct sco_pinfo {
 	struct bt_sock	bt;
 	__u32		flags;
+	__u8		codec;
 	struct sco_conn	*conn;
 };
 
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index eea17cd..c2c0c13 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -427,6 +427,8 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int pro
 	sk->sk_protocol = proto;
 	sk->sk_state    = BT_OPEN;
 
+	sco_pi(sk)->codec = 0;
+
 	setup_timer(&sk->sk_timer, sco_sock_timeout, (unsigned long)sk);
 
 	bt_sock_link(&sco_sk_list, sk);
@@ -745,6 +747,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user
 		}
 
 		opts.mtu = sco_pi(sk)->conn->mtu;
+		opts.codec = sco_pi(sk)->codec;
 
 		BT_DBG("mtu %d", opts.mtu);
 
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 2/4] Bluetooth: Add option for SCO socket socket
From: Frédéric Dalleau @ 2012-11-28 18:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1354127316-17431-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 c2c0c13..b363712 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -687,6 +687,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.codec = 0;
+
+		len = min_t(unsigned int, sizeof(opts), optlen);
+		if (copy_from_user((char *) &opts, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+
+		sco_pi(sk)->codec = opts.codec;
+		BT_DBG("codec %d", opts.codec);
+		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;
@@ -695,6 +736,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

* [RFC 3/4] Bluetooth: Use codec to create SCO connection
From: Frédéric Dalleau @ 2012-11-28 18:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1354127316-17431-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 the reply for defered setup.
---
 include/net/bluetooth/hci_core.h |    2 +-
 net/bluetooth/hci_event.c        |   23 +++++++++++++++++++----
 net/bluetooth/sco.c              |    2 +-
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2f2b743..cb41552 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 codec);
 
 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..57ed7d3 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 codec)
 {
 	struct hci_dev *hdev = conn->hdev;
 
@@ -2070,13 +2070,28 @@ 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 (codec) {
+		case 0:
+			cp.max_latency    = __constant_cpu_to_le16(0xffff);
+			cp.retrans_effort = 0xff;
+			break;
+		case 1 /* mSBC */:
+			/* Transparent */
+			cp.content_format |= cpu_to_le16(3);
+			 /* 2EV3 unsupported */
+			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 b363712..be3e0b2 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -675,7 +675,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->codec);
 		sk->sk_state = BT_CONFIG;
 
 		release_sock(sk);
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 4/4] Bluetooth: Set link parameters for outgoing connections
From: Frédéric Dalleau @ 2012-11-28 18:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Frédéric Dalleau
In-Reply-To: <1354127316-17431-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 correct parameters if the ACL connection is not up yet.
---
 include/net/bluetooth/hci_core.h |    4 +++-
 net/bluetooth/hci_conn.c         |   24 +++++++++++++++++++-----
 net/bluetooth/l2cap_core.c       |    4 ++--
 net/bluetooth/mgmt.c             |    4 ++--
 net/bluetooth/sco.c              |    2 +-
 5 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index cb41552..e286196 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_TRANSP_DATA,
 };
 
 static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -585,7 +586,8 @@ void hci_chan_list_flush(struct hci_conn *conn);
 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);
+			     __u8 dst_type, __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..1636dd5 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_TRANSP_DATA, &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);
 }
@@ -552,7 +559,8 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
 }
 
 static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
-				bdaddr_t *dst, u8 sec_level, u8 auth_type)
+					bdaddr_t *dst, u8 sec_level,
+					u8 auth_type, u8 codec)
 {
 	struct hci_conn *acl;
 	struct hci_conn *sco;
@@ -575,6 +583,10 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
 
 	hci_conn_hold(sco);
 
+	if (codec)
+		set_bit(HCI_CONN_SCO_TRANSP_DATA, &sco->flags);
+
+
 	if (acl->state == BT_CONNECTED &&
 	    (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
 		set_bit(HCI_CONN_POWER_SAVE, &acl->flags);
@@ -594,7 +606,8 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
 
 /* Create SCO, ACL or LE connection. */
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
-			     __u8 dst_type, __u8 sec_level, __u8 auth_type)
+			     __u8 dst_type, __u8 sec_level, __u8 auth_type,
+			     __u8 codec)
 {
 	BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type);
 
@@ -605,7 +618,8 @@ 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,
+				       codec);
 	}
 
 	return ERR_PTR(-EINVAL);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b52f66d..2ca70a4 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1690,10 +1690,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
 
 	if (chan->dcid == L2CAP_CID_LE_DATA)
 		hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
-				   chan->sec_level, auth_type);
+				   chan->sec_level, auth_type, 0);
 	else
 		hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
-				   chan->sec_level, auth_type);
+				   chan->sec_level, auth_type, 0);
 
 	if (IS_ERR(hcon)) {
 		err = PTR_ERR(hcon);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 5d0ef75..d03405d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1917,10 +1917,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	if (cp->addr.type == BDADDR_BREDR)
 		conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr,
-				   cp->addr.type, sec_level, auth_type);
+				   cp->addr.type, sec_level, auth_type, 0);
 	else
 		conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr,
-				   cp->addr.type, sec_level, auth_type);
+				   cp->addr.type, sec_level, auth_type, 0);
 
 	memset(&rp, 0, sizeof(rp));
 	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index be3e0b2..e86ae29 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -186,7 +186,7 @@ static int sco_connect(struct sock *sk)
 		type = SCO_LINK;
 
 	hcon = hci_connect(hdev, type, dst, BDADDR_BREDR, BT_SECURITY_LOW,
-			   HCI_AT_NO_BONDING);
+			   HCI_AT_NO_BONDING, sco_pi(sk)->codec);
 	if (IS_ERR(hcon)) {
 		err = PTR_ERR(hcon);
 		goto done;
-- 
1.7.9.5


^ permalink raw reply related

* BLE : SMP pairing + LE_Start_encryption
From: Ajay @ 2012-11-28 21:27 UTC (permalink / raw)
  To: linux-bluetooth


Hi,
	how do i do smp pairing and ltk key distribution using l2cap socket 
connection?  does bluez provide any tools for LE pairing . my ultimate 
result should be enabling LE_start_encryption , which requires ltk key 
distribution (which is a part of LE_pairing).

	spec 4.0  says we can use l2cap cid 0x06 , defined for this purpose 
(smp pairing) . But when i used cid =0x06 , l2cap connect  creates an 
normal acl connection with cid = 40 , which doesnt trigger any smp 
modules at remote side.

	please look into this issue.
-- 
Thanks & regards

  AJAY KV
  GlobalEdge software Ltd
  8892753703

^ permalink raw reply

* Re: BLE : SMP pairing + LE_Start_encryption
From: Ajay @ 2012-11-29  0:35 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <CAJdJm_MCt+dep8XipFonUvRO5uoBiHNZeZm_80+LG7=E0DpTLg@mail.gmail.com>

On Friday 30 November 2012 05:38 PM, Anderson Lizardo wrote:
> Hi Ajay,
>
> On Wed, Nov 28, 2012 at 5:27 PM, Ajay <ajay.kv@globaledgesoft.com> wrote:
>>
>> Hi,
>>          how do i do smp pairing and ltk key distribution using l2cap socket
>> connection?  does bluez provide any tools for LE pairing . my ultimate
>> result should be enabling LE_start_encryption , which requires ltk key
>> distribution (which is a part of LE_pairing).
>
> Either using mgmt API to do pairing (see mgmt_create_bonding() in
> src/mgmt.c from bluez sources and doc/mgmt-api.txt for how to do this)
> or increase socket security level to at least medium using
> setsockopt() (see set_sec_level() in btio/btio.c for how to do this).
>
> In summary, you will need to use BlueZ code as reference if you want
> to do these things on your own. The easier route is to use BlueZ D-Bus
> API to do pairing.
>
> Regards,
>
  thanks  Anderson ,
   sorry if im confusing you .
	is it possible to create an l2cap connection with cid 0x06 and psm 0 ? 
  , so that i can make use of dedicated smp-l2cap channel for data 
transfer . I wanted to try how the remote device is handling on 
receiving an smp_pairing_request . i have seen in l2cap_core.c	 , it is 
getting handled inside a switch case (case cid == L2CAP_CID_SMP).

-- 
Thanks & regards

  AJAY KV
  GlobalEdge software Ltd
  8892753703

^ permalink raw reply

* Sco issue:iogear dongle
From: Deepthi @ 2012-11-29  5:54 UTC (permalink / raw)
  To: linux-bluetooth, bluefrog2012

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

Hi,
Thank you for the reply. Here I have attached  the hcidump logs from 
both sides (server & client side).

Please help,

-- 
Thanks & Regards,
Deepthi Elizabeth P V


[-- Attachment #2: sco_connreq_hcidump.txt --]
[-- Type: text/plain, Size: 3648 bytes --]


2012-11-29 11:05:11.821785 > ACL data: handle 12 flags 0x02 dlen 16
    L2CAP(s): Connect rsp: dcid 0x0040 scid 0x0040 result 0 status 0
      Connection successful
2012-11-29 11:05:11.821803 < ACL data: handle 12 flags 0x00 dlen 23
    L2CAP(s): Config req: dcid 0x0040 flags 0x00 clen 11
      RFC 0x00 (Basic) 
2012-11-29 11:05:11.825534 > ACL data: handle 12 flags 0x02 dlen 23
    L2CAP(s): Config req: dcid 0x0040 flags 0x00 clen 11
      RFC 0x00 (Basic) 
2012-11-29 11:05:11.825545 < ACL data: handle 12 flags 0x00 dlen 18
    L2CAP(s): Config rsp: scid 0x0040 flags 0x00 result 0 clen 4
      MTU 672 
2012-11-29 11:05:11.830534 > ACL data: handle 12 flags 0x02 dlen 18
    L2CAP(s): Config rsp: scid 0x0040 flags 0x00 result 0 clen 4
      MTU 672 
2012-11-29 11:05:11.831286 > HCI Event: Number of Completed Packets (0x13) plen 5
    handle 12 packets 2
2012-11-29 11:05:12.002285 > HCI Event: Number of Completed Packets (0x13) plen 5
    handle 12 packets 1
2012-11-29 11:05:12.100652 < HCI Command: Read RSSI (0x05|0x0005) plen 2
    handle 12
2012-11-29 11:05:12.102283 > HCI Event: Command Complete (0x0e) plen 7
    Read RSSI (0x05|0x0005) ncmd 1
    status 0x00 handle 12 rssi -15
2012-11-29 11:05:12.102317 < HCI Command: Read Link Quality (0x05|0x0003) plen 2
    handle 12
2012-11-29 11:05:12.103284 > HCI Event: Command Complete (0x0e) plen 7
    Read Link Quality (0x05|0x0003) ncmd 1
    status 0x00 handle 12 lq 255
2012-11-29 11:05:12.103314 < HCI Command: Read Transmit Power Level (0x03|0x002d) plen 3
    handle 12 type 0 (current)
2012-11-29 11:05:12.104285 > HCI Event: Command Complete (0x0e) plen 7
    Read Transmit Power Level (0x03|0x002d) ncmd 1
    status 0x00 handle 12 level 3
2012-11-29 11:05:12.830703 < ACL data: handle 12 flags 0x00 dlen 132
    L2CAP(d): cid 0x0040 len 128 [psm 4113]
      0000: 52 49 46 46 e2 0f 00 00  57 41 56 45 66 6d 74 20  RIFF....WAVEfmt 
      0010: 10 00 00 00 01 00 01 00  44 ac 00 00 88 58 01 00  ........D....X..
      0020: 02 00 10 00 64 61 74 61  b8 0f 00 00 00 00 00 00  ....data........
      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  ................
2012-11-29 11:05:12.850154 > ACL data: handle 12 flags 0x02 dlen 132
    L2CAP(d): cid 0x0040 len 128 [psm 4113]
      0000: 52 49 46 46 e2 0f 00 00  57 41 56 45 66 6d 74 20  RIFF....WAVEfmt 
      0010: 10 00 00 00 01 00 01 00  44 ac 00 00 88 58 01 00  ........D....X..
      0020: 02 00 10 00 64 61 74 61  b8 0f 00 00 00 00 00 00  ....data........
      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  ................
2012-11-29 11:05:12.850236 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17
    handle 12 voice setting 0x0060 ptype 0x0008
2012-11-29 11:05:12.851279 > HCI Event: Command Status (0x0f) plen 4
    Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1
2012-11-29 11:05:12.874279 > HCI Event: Synchronous Connect Complete (0x2c) plen 17
    status 0x00 handle 6 bdaddr 00:02:72:D6:AB:AD type eSCO
    Air mode: CVSD


[-- Attachment #3: sco_connaccept_hcidump.txt --]
[-- Type: text/plain, Size: 5071 bytes --]

1354166949.194632 > HCI Event: Number of Completed Packets (0x13) plen 5
  0000: 01 0b 00 02 00                                    .....
1354166949.194637 > ACL data: handle 11 flags 0x02 dlen 12
    L2CAP(s): Connect req: psm 4113 scid 0x0040
1354166949.194654 < ACL data: handle 11 flags 0x00 dlen 16
    0000: 0c 00 01 00 03 03 08 00  40 00 40 00 01 00 00 00  ........@.@.....
1354166949.194656 < ACL data: handle 11 flags 0x00 dlen 10
    0000: 06 00 01 00 0a 01 02 00  02 00                    ..........
1354166949.230631 > HCI Event: Number of Completed Packets (0x13) plen 5
  0000: 01 0b 00 02 00                                    .....
1354166949.231632 > ACL data: handle 11 flags 0x02 dlen 16
    L2CAP(s): Info rsp: type 2 result 0
      Extended feature mask 0x00b8
1354166949.231641 < ACL data: handle 11 flags 0x00 dlen 10
    0000: 06 00 01 00 0a 02 02 00  03 00                    ..........
1354166949.247632 > ACL data: handle 11 flags 0x02 dlen 20
    L2CAP(s): Info rsp: type 3 result 0
      Unknown (len 8)
1354166949.247642 < ACL data: handle 11 flags 0x00 dlen 16
    0000: 0c 00 01 00 03 03 08 00  40 00 40 00 00 00 00 00  ........@.@.....
1354166949.247645 < ACL data: handle 11 flags 0x00 dlen 23
    0000: 13 00 01 00 04 03 0f 00  40 00 00 00 04 09 00 00  ........@.......
    0010: 00 00 00 00 00 00 00                              .......
1354166949.298632 > HCI Event: Number of Completed Packets (0x13) plen 5
  0000: 01 0b 00 02 00                                    .....
1354166949.298636 > ACL data: handle 11 flags 0x02 dlen 23
    L2CAP(s): Config req: dcid 0x0040 flags 0x00 clen 11
      RFC 0x00 (Basic) 
1354166949.298647 < ACL data: handle 11 flags 0x00 dlen 18
    0000: 0e 00 01 00 05 04 0a 00  40 00 00 00 00 00 01 02  ........@.......
    0010: a0 02                                             ..
1354166949.306632 > ACL data: handle 11 flags 0x02 dlen 18
    L2CAP(s): Config rsp: scid 0x0040 flags 0x00 result 0 clen 4
      MTU 672 
1354166949.307631 > HCI Event: Number of Completed Packets (0x13) plen 5
  0000: 01 0b 00 02 00                                    .....
1354166949.566793 < HCI Command: Read RSSI (0x05|0x0005) plen 2
  0000: 0b 00                                             ..
1354166949.568632 > HCI Event: Command Complete (0x0e) plen 7
  0000: 01 05 14 00 0b 00 f0                              .......
1354166949.568729 < HCI Command: Read Link Quality (0x05|0x0003) plen 2
  0000: 0b 00                                             ..
1354166949.570631 > HCI Event: Command Complete (0x0e) plen 7
  0000: 01 03 14 00 0b 00 ff                              .......
1354166949.570661 < HCI Command: Read Transmit Power Level (0x03|0x002d) plen 3
  0000: 0b 00 00                                          ...
1354166949.572631 > HCI Event: Command Complete (0x0e) plen 7
  0000: 01 2d 0c 00 0b 00 03                              .-.....
1354166950.319635 > ACL data: handle 11 flags 0x02 dlen 132
    L2CAP(d): cid 0x0040 len 128 [psm 0]
      0000: 52 49 46 46 e2 0f 00 00  57 41 56 45 66 6d 74 20  RIFF....WAVEfmt 
      0010: 10 00 00 00 01 00 01 00  44 ac 00 00 88 58 01 00  ........D....X..
      0020: 02 00 10 00 64 61 74 61  b8 0f 00 00 00 00 00 00  ....data........
      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  ................
1354166950.319679 < ACL data: handle 11 flags 0x00 dlen 132
    0000: 80 00 40 00 52 49 46 46  e2 0f 00 00 57 41 56 45  ..@.RIFF....WAVE
    0010: 66 6d 74 20 10 00 00 00  01 00 01 00 44 ac 00 00  fmt ........D...
    0020: 88 58 01 00 02 00 10 00  64 61 74 61 b8 0f 00 00  .X......data....
    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                                       ....
1354166950.329632 > HCI Event: Connect Request (0x04) plen 10
  0000: 79 97 d6 72 02 00 00 01  18 02                    y..r......
1354166950.329660 < HCI Command: Accept Synchronous Connection (0x01|0x0029) plen 21
  0000: 79 97 d6 72 02 00 40 1f  00 00 40 1f 00 00 ff ff  y..r..@...@.....
  0010: 60 00 ff 08 00                                    `....
1354166950.331633 > HCI Event: Command Status (0x0f) plen 4
  0000: 00 01 29 04                                       ..).
1354166950.350635 > HCI Event: Synchronous Connect Complete (0x2c) plen 17
  0000: 00 06 00 79 97 d6 72 02  00 02 22 00 aa 00 aa 00  ...y..r...".....
  0010: 02                                                .


^ permalink raw reply

* Re: [RFC 0/4] sco: Another SCO socket option :)
From: Arnaud Mouiche @ 2012-11-29  8:41 UTC (permalink / raw)
  To: Frédéric Dalleau; +Cc: linux-bluetooth
In-Reply-To: <1354127316-17431-1-git-send-email-frederic.dalleau@linux.intel.com>

Hello Frédéric,

my natural feeling is to be generic as much as possible, and to not try 
to implement directly a particular profile in the kernel:
ex:
- I'm a hobbyist or academic and I want to use SCO socket for something 
else than standard profiles like an asymmetric synchronous connection (?)
- tomorrow, a new X or Y codec will be selected by the SIG and some new 
settings will be required (may be OPUS, now we have a high quality 
patent free, royalty-free and standardized codec available. 
http://opus-codec.org/)
- I've a BT module doesn't behave correctly when using exactly the 
parameters specified by the HFP specs (I think I have already seen one 
but don't remember which)

also, BT specs provided a generic API (HCI_Setup_Synchronous_Connection 
command & co). why try to remove the flexibility ?

Except this "codec only vs. every parameter" question, I like the 
implementation.

regards,
arnaud


On 11/28/2012 07:28 PM, Frédéric Dalleau wrote:
> Hi,
>
> This patch implements codec socket option on SCO sockets.
> Currently it proposes T2 codec settins (see HFP 1.6 p.102)
>
>
> How to test:
> $ scotest -W 1 -C 1
>
> on another machine with same patches run:
> $ scotest -n $ADDR -C 1
>
> Check result with btmon.
>
> This took more time than I expected for I met the following issues :
> * bluetooth-next branch crashed in apparmor after login.
> * At some point, unplugging my usb dongle would also crash the kernel. It is
> possible this one was a mix between different versions of kernel modules.
> * if the connection request is not accepted, the initiator gets in timeout, and
> there is a crash. I think this one will need be fixed.
>
> Next step is to implement fallback between T2 and T1. I'm thinking about using
> another bit in hconn->flags to store current settings selection.
>
> Let me know what you think.
> Best regards,
> Frédéric
>
>
> Frédéric Dalleau (4):
>    Bluetooth: Add option for SCO socket codec
>    Bluetooth: Add option for SCO socket socket
>    Bluetooth: Use codec to create SCO connection
>    Bluetooth: Set link parameters for outgoing connections
>
>   include/net/bluetooth/hci_core.h |    6 +++--
>   include/net/bluetooth/sco.h      |    2 ++
>   net/bluetooth/hci_conn.c         |   24 ++++++++++++++----
>   net/bluetooth/hci_event.c        |   23 ++++++++++++++---
>   net/bluetooth/l2cap_core.c       |    4 +--
>   net/bluetooth/mgmt.c             |    4 +--
>   net/bluetooth/sco.c              |   51 ++++++++++++++++++++++++++++++++++++--
>   7 files changed, 97 insertions(+), 17 deletions(-)
>


^ permalink raw reply

* Re: [PATCH BlueZ 1/6] gdbus: Add g_dbus_add_properties_watch function
From: Luiz Augusto von Dentz @ 2012-11-29  8:52 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org; +Cc: Lucas De Marchi, Marcel Holtmann
In-Reply-To: <1354020685-17028-1-git-send-email-luiz.dentz@gmail.com>

Hi Lucas, Marcel,

On Tue, Nov 27, 2012 at 2:51 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> Convenient function to create watches for D-Bus properties.
> ---
>  gdbus/gdbus.h |  5 +++++
>  gdbus/watch.c | 28 ++++++++++++++++++++++++++++
>  2 files changed, 33 insertions(+)
>
> diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
> index ba49621..8b6dfe5 100644
> --- a/gdbus/gdbus.h
> +++ b/gdbus/gdbus.h
> @@ -243,6 +243,11 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
>                                 const char *interface, const char *member,
>                                 GDBusSignalFunction function, void *user_data,
>                                 GDBusDestroyFunction destroy);
> +guint g_dbus_add_properties_watch(DBusConnection *connection,
> +                               const char *sender, const char *path,
> +                               const char *interface,
> +                               GDBusSignalFunction function, void *user_data,
> +                               GDBusDestroyFunction destroy);
>  gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
>  void g_dbus_remove_all_watches(DBusConnection *connection);
>
> diff --git a/gdbus/watch.c b/gdbus/watch.c
> index 1cd1211..9e4f994 100644
> --- a/gdbus/watch.c
> +++ b/gdbus/watch.c
> @@ -752,6 +752,34 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
>         return cb->id;
>  }
>
> +guint g_dbus_add_properties_watch(DBusConnection *connection,
> +                               const char *sender, const char *path,
> +                               const char *interface,
> +                               GDBusSignalFunction function, void *user_data,
> +                               GDBusDestroyFunction destroy)
> +{
> +       struct filter_data *data;
> +       struct filter_callback *cb;
> +
> +       data = filter_data_get(connection, signal_filter, sender, path,
> +                               DBUS_INTERFACE_PROPERTIES, "PropertiesChanged",
> +                               interface);
> +       if (data == NULL)
> +               return 0;
> +
> +       cb = filter_data_add_callback(data, NULL, NULL, function, destroy,
> +                                       user_data);
> +       if (cb == NULL)
> +               return 0;
> +
> +       if (data->name != NULL && data->name_watch == 0)
> +               data->name_watch = g_dbus_add_service_watch(connection,
> +                                                       data->name, NULL,
> +                                                       NULL, NULL, NULL);
> +
> +       return cb->id;
> +}
> +
>  gboolean g_dbus_remove_watch(DBusConnection *connection, guint id)
>  {
>         struct filter_data *data;
> --
> 1.7.11.7

Anything regarding this function? The point here is to be able to
listen to properties specific to one interface which is not possible
with g_dbus_add_signal_watch.


--
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCH BlueZ 1/3] media: Convert target MediaTransport interface to use D-Bus Properties
From: Luiz Augusto von Dentz @ 2012-11-29  9:06 UTC (permalink / raw)
  To: linux-bluetooth

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

---
 profiles/audio/media.c     |   3 +-
 profiles/audio/transport.c | 229 ++++++++++++++++++++-------------------------
 2 files changed, 102 insertions(+), 130 deletions(-)

diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index f2fba7b..2041d23 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -370,6 +370,7 @@ static gboolean set_configuration(struct media_endpoint *endpoint,
 					void *user_data,
 					GDestroyNotify destroy)
 {
+	DBusConnection *conn = btd_get_dbus_connection();
 	DBusMessage *msg;
 	const char *path;
 	DBusMessageIter iter;
@@ -401,7 +402,7 @@ static gboolean set_configuration(struct media_endpoint *endpoint,
 	path = media_transport_get_path(transport);
 	dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
 
-	transport_get_properties(transport, &iter);
+	g_dbus_get_properties(conn, path, "org.bluez.MediaTransport", &iter);
 
 	return media_endpoint_async_call(msg, endpoint, cb, user_data, destroy);
 }
diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index bd8b203..d8116fd 100644
--- a/profiles/audio/transport.c
+++ b/profiles/audio/transport.c
@@ -116,13 +116,6 @@ struct media_transport {
 					struct media_owner *owner);
 	void			(*cancel) (struct media_transport *transport,
 								guint id);
-	void			(*get_properties) (
-					struct media_transport *transport,
-					DBusMessageIter *dict);
-	int			(*set_property) (
-					struct media_transport *transport,
-					const char *property,
-					DBusMessageIter *value);
 	GDestroyNotify		destroy;
 	void			*data;
 };
@@ -200,9 +193,10 @@ static void transport_set_state(struct media_transport *transport,
 	str = state2str(state);
 
 	if (g_strcmp0(str, state2str(old_state)) != 0)
-		emit_property_changed(transport->path,
-					MEDIA_TRANSPORT_INTERFACE, "State",
-					DBUS_TYPE_STRING, &str);
+		g_dbus_emit_property_changed(btd_get_dbus_connection(),
+						transport->path,
+						MEDIA_TRANSPORT_INTERFACE,
+						"State");
 }
 
 void media_transport_destroy(struct media_transport *transport)
@@ -647,156 +641,133 @@ static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-static int set_property_a2dp(struct media_transport *transport,
-						const char *property,
-						DBusMessageIter *value)
+static gboolean get_device(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
 {
-	struct a2dp_transport *a2dp = transport->data;
+	struct media_transport *transport = data;
+	const char *path = device_get_path(transport->device->btd_dev);
 
-	if (g_strcmp0(property, "Delay") == 0) {
-		if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_UINT16)
-			return -EINVAL;
-		dbus_message_iter_get_basic(value, &a2dp->delay);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
 
-		/* FIXME: send new delay */
-		return 0;
-	} else if (g_strcmp0(property, "Volume") == 0) {
-		uint16_t volume;
+	return TRUE;
+}
 
-		if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_UINT16)
-			return -EINVAL;
+static gboolean get_uuid(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	const char *uuid = media_endpoint_get_uuid(transport->endpoint);
 
-		dbus_message_iter_get_basic(value, &volume);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
 
-		if (volume > 127)
-			return -EINVAL;
+	return TRUE;
+}
 
-		if (a2dp->volume == volume)
-			return 0;
+static gboolean get_codec(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	uint8_t codec = media_endpoint_get_codec(transport->endpoint);
 
-		return avrcp_set_volume(transport->device, volume);
-	}
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &codec);
 
-	return -EINVAL;
+	return TRUE;
 }
 
-static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
-								void *data)
+static gboolean get_configuration(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
 {
 	struct media_transport *transport = data;
-	DBusMessageIter iter;
-	DBusMessageIter value;
-	const char *property, *sender;
-	GSList *l;
-	int err;
-
-	if (!dbus_message_iter_init(msg, &iter))
-		return btd_error_invalid_args(msg);
+	DBusMessageIter array;
 
-	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-		return btd_error_invalid_args(msg);
-
-	dbus_message_iter_get_basic(&iter, &property);
-	dbus_message_iter_next(&iter);
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_BYTE_AS_STRING, &array);
 
-	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
-		return btd_error_invalid_args(msg);
-	dbus_message_iter_recurse(&iter, &value);
+	dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+						&transport->configuration,
+						transport->size);
 
-	sender = dbus_message_get_sender(msg);
-	err = -EINVAL;
+	dbus_message_iter_close_container(iter, &array);
 
-	/* Check if sender has acquired the transport */
-	for (l = transport->owners; l; l = l->next) {
-		struct media_owner *owner = l->data;
+	return TRUE;
+}
 
-		if (g_strcmp0(owner->name, sender) == 0) {
-			err = transport->set_property(transport, property,
-								&value);
-			break;
-		}
-	}
+static gboolean get_state(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	const char *state = state2str(transport->state);
 
-	if (err < 0) {
-		if (err == -EINVAL)
-			return btd_error_invalid_args(msg);
-		return btd_error_failed(msg, strerror(-err));
-	}
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &state);
 
-	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+	return TRUE;
 }
 
-static void get_properties_a2dp(struct media_transport *transport,
-						DBusMessageIter *dict)
+static gboolean delay_exists(const GDBusPropertyTable *property, void *data)
 {
+	struct media_transport *transport = data;
 	struct a2dp_transport *a2dp = transport->data;
 
-	dict_append_entry(dict, "Delay", DBUS_TYPE_UINT16, &a2dp->delay);
-
-	if (a2dp->volume <= 127)
-		dict_append_entry(dict, "Volume", DBUS_TYPE_UINT16,
-							&a2dp->volume);
+	return a2dp->delay != 0;
 }
 
-void transport_get_properties(struct media_transport *transport,
-							DBusMessageIter *iter)
+static gboolean get_delay(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
 {
-	DBusMessageIter dict;
-	const char *uuid;
-	uint8_t codec;
-	const char *state;
-	const char *path;
-
-	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
-			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
-			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
-			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+	struct media_transport *transport = data;
+	struct a2dp_transport *a2dp = transport->data;
 
-	/* Device */
-	path = device_get_path(transport->device->btd_dev);
-	dict_append_entry(&dict, "Device", DBUS_TYPE_OBJECT_PATH, &path);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &a2dp->delay);
 
-	uuid = media_endpoint_get_uuid(transport->endpoint);
-	dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &uuid);
+	return TRUE;
+}
 
-	codec = media_endpoint_get_codec(transport->endpoint);
-	dict_append_entry(&dict, "Codec", DBUS_TYPE_BYTE, &codec);
+static gboolean volume_exists(const GDBusPropertyTable *property, void *data)
+{
+	struct media_transport *transport = data;
+	struct a2dp_transport *a2dp = transport->data;
 
-	dict_append_array(&dict, "Configuration", DBUS_TYPE_BYTE,
-				&transport->configuration, transport->size);
+	return a2dp->volume <= 127;
+}
 
-	/* State */
-	state = state2str(transport->state);
-	dict_append_entry(&dict, "State", DBUS_TYPE_STRING, &state);
+static gboolean get_volume(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct a2dp_transport *a2dp = transport->data;
 
-	if (transport->get_properties)
-		transport->get_properties(transport, &dict);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &a2dp->volume);
 
-	dbus_message_iter_close_container(iter, &dict);
+	return TRUE;
 }
 
-static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg,
-					void *data)
+static void set_volume(const GDBusPropertyTable *property,
+			DBusMessageIter *iter, GDBusPendingPropertySet id,
+			void *data)
 {
 	struct media_transport *transport = data;
-	DBusMessage *reply;
-	DBusMessageIter iter;
+	struct a2dp_transport *a2dp = transport->data;
+	uint16_t volume;
 
-	reply = dbus_message_new_method_return(msg);
-	if (!reply)
-		return NULL;
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16)
+		return g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".InvalidArguments",
+					"Invalid arguments in method call");
+
+	dbus_message_iter_get_basic(iter, &volume);
 
-	dbus_message_iter_init_append(reply, &iter);
+	if (volume > 127)
+		return g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".InvalidArguments",
+					"Invalid arguments in method call");
 
-	transport_get_properties(transport, &iter);
+	if (a2dp->volume != volume)
+		avrcp_set_volume(transport->device, volume);
 
-	return reply;
+	g_dbus_pending_property_success(id);
 }
 
 static const GDBusMethodTable transport_methods[] = {
-	{ GDBUS_METHOD("GetProperties",
-			NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
-			get_properties) },
 	{ GDBUS_ASYNC_METHOD("Acquire",
 			GDBUS_ARGS({ "access_type", "s" }),
 			GDBUS_ARGS({ "fd", "h" }, { "mtu_r", "q" },
@@ -805,15 +776,17 @@ static const GDBusMethodTable transport_methods[] = {
 	{ GDBUS_ASYNC_METHOD("Release",
 			GDBUS_ARGS({ "access_type", "s" }), NULL,
 			release ) },
-	{ GDBUS_METHOD("SetProperty",
-			GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
-			NULL, set_property) },
 	{ },
 };
 
-static const GDBusSignalTable transport_signals[] = {
-	{ GDBUS_SIGNAL("PropertyChanged",
-			GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+static const GDBusPropertyTable transport_properties[] = {
+	{ "Device", "o", get_device },
+	{ "UUID", "s", get_uuid },
+	{ "Codec", "y", get_codec },
+	{ "Configuration", "ay", get_configuration },
+	{ "State", "s", get_state },
+	{ "Delay", "q", get_delay, NULL, delay_exists },
+	{ "Volume", "q", get_volume, set_volume, volume_exists },
 	{ }
 };
 
@@ -932,8 +905,6 @@ struct media_transport *media_transport_create(struct media_endpoint *endpoint,
 		transport->resume = resume_a2dp;
 		transport->suspend = suspend_a2dp;
 		transport->cancel = cancel_a2dp;
-		transport->get_properties = get_properties_a2dp;
-		transport->set_property = set_property_a2dp;
 		transport->data = a2dp;
 		transport->destroy = destroy_a2dp;
 
@@ -950,7 +921,7 @@ struct media_transport *media_transport_create(struct media_endpoint *endpoint,
 
 	if (g_dbus_register_interface(btd_get_dbus_connection(),
 				transport->path, MEDIA_TRANSPORT_INTERFACE,
-				transport_methods, transport_signals, NULL,
+				transport_methods, NULL, transport_properties,
 				transport, media_transport_free) == FALSE) {
 		error("Could not register transport %s", transport->path);
 		goto fail;
@@ -979,9 +950,9 @@ void media_transport_update_delay(struct media_transport *transport,
 
 	a2dp->delay = delay;
 
-	emit_property_changed(transport->path,
-				MEDIA_TRANSPORT_INTERFACE, "Delay",
-				DBUS_TYPE_UINT16, &a2dp->delay);
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+					transport->path,
+					MEDIA_TRANSPORT_INTERFACE, "Delay");
 }
 
 struct audio_device *media_transport_get_dev(struct media_transport *transport)
@@ -1000,7 +971,7 @@ void media_transport_update_volume(struct media_transport *transport,
 
 	a2dp->volume = volume;
 
-	emit_property_changed(transport->path,
-				MEDIA_TRANSPORT_INTERFACE, "Volume",
-				DBUS_TYPE_UINT16, &a2dp->volume);
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+					transport->path,
+					MEDIA_TRANSPORT_INTERFACE, "Volume");
 }
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH BlueZ 2/3] media-api: Update documentation of MediaTransport interface
From: Luiz Augusto von Dentz @ 2012-11-29  9:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1354179996-17019-1-git-send-email-luiz.dentz@gmail.com>

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

---
 doc/media-api.txt | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/doc/media-api.txt b/doc/media-api.txt
index a814b60..20aad19 100644
--- a/doc/media-api.txt
+++ b/doc/media-api.txt
@@ -261,12 +261,7 @@ Service		org.bluez
 Interface	org.bluez.MediaTransport
 Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/fdX
 
-Methods		dict GetProperties()
-
-			Returns all properties for the interface. See the
-			properties section for available properties.
-
-		fd, uint16, uint16 Acquire(string accesstype)
+Methods		fd, uint16, uint16 Acquire(string accesstype)
 
 			Acquire transport file descriptor and the MTU for read
 			and write respectively.
@@ -294,13 +289,6 @@ Methods		dict GetProperties()
 
 			Releases file descriptor.
 
-		void SetProperty(string name, variant value)
-
-			Changes the value of the specified property. Only
-			properties that are listed as read-write can be changed.
-
-			On success this will emit a PropertyChanged signal.
-
 Signals		void PropertyChanged(string name, variant value)
 
 			This signal indicates a changed value of the given
-- 
1.7.11.7


^ 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