Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH -v2 2/3] Bluetooth: Handle psm == 0 case inside l2cap_add_psm()
From: Gustavo F. Padovan @ 2011-04-28  5:26 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303968420-12719-1-git-send-email-padovan@profusion.mobi>

When the user doesn't specify a psm we have the choose one for the
channel. Now we do this inside l2cap_add_psm().

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    1 -
 net/bluetooth/l2cap_core.c    |   32 ++++++++++++++++++++++++--------
 net/bluetooth/l2cap_sock.c    |   22 ----------------------
 3 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index f5f3c2c..fb3f90e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -458,7 +458,6 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
 void l2cap_streaming_send(struct l2cap_chan *chan);
 int l2cap_ertm_send(struct l2cap_chan *chan);
 
-struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src);
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 98ddd86..9e3f64f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -135,7 +135,7 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn
 	return c;
 }
 
-struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
+static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
 {
 	struct sock *sk;
 	struct hlist_node *node;
@@ -153,19 +153,35 @@ found:
 
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
 {
+	int err;
+
 	write_lock_bh(&l2cap_sk_list.lock);
 
-	if (__l2cap_get_sock_by_addr(psm, src)) {
-		write_unlock_bh(&l2cap_sk_list.lock);
-		return -EADDRINUSE;
+	if (psm && __l2cap_get_sock_by_addr(psm, src)) {
+		err = -EADDRINUSE;
+		goto done;
 	}
 
-	chan->psm = psm;
-	chan->sport = psm;
+	if (psm) {
+		chan->psm = psm;
+		chan->sport = psm;
+		err = 0;
+	} else {
+		u16 p;
 
-	write_unlock_bh(&l2cap_sk_list.lock);
+		err = -EINVAL;
+		for (p = 0x1001; p < 0x1100; p += 2)
+			if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) {
+				chan->psm   = cpu_to_le16(p);
+				chan->sport = cpu_to_le16(p);
+				err = 0;
+				break;
+			}
+	}
 
-	return 0;
+done:
+	write_unlock_bh(&l2cap_sk_list.lock);
+	return err;
 }
 
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 2156dce..aca99cd 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -256,28 +256,6 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 		goto done;
 	}
 
-	if (!chan->psm && !chan->scid) {
-		bdaddr_t *src = &bt_sk(sk)->src;
-		u16 psm;
-
-		err = -EINVAL;
-
-		write_lock_bh(&l2cap_sk_list.lock);
-
-		for (psm = 0x1001; psm < 0x1100; psm += 2)
-			if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
-				chan->psm   = cpu_to_le16(psm);
-				chan->sport = cpu_to_le16(psm);
-				err = 0;
-				break;
-			}
-
-		write_unlock_bh(&l2cap_sk_list.lock);
-
-		if (err < 0)
-			goto done;
-	}
-
 	sk->sk_max_ack_backlog = backlog;
 	sk->sk_ack_backlog = 0;
 	sk->sk_state = BT_LISTEN;
-- 
1.7.5.rc1


^ permalink raw reply related

* [PATCH -v2 1/3] Bluetooth: Add l2cap_add_psm() and l2cap_add_scid()
From: Gustavo F. Padovan @ 2011-04-28  5:26 UTC (permalink / raw)
  To: linux-bluetooth

The intention is to get rid of the l2cap_sk_list usage inside
l2cap_core.c. l2cap_sk_list will soon be replaced by a list that does not
depend on socket usage.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    4 +++
 net/bluetooth/l2cap_core.c    |   44 +++++++++++++++++++++++++++++++++++++++++
 net/bluetooth/l2cap_sock.c    |   44 ++++++++++------------------------------
 3 files changed, 59 insertions(+), 33 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index c34b1c1..f5f3c2c 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -458,6 +458,10 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
 void l2cap_streaming_send(struct l2cap_chan *chan);
 int l2cap_ertm_send(struct l2cap_chan *chan);
 
+struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src);
+int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
+int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
+
 void l2cap_sock_set_timer(struct sock *sk, long timeout);
 void l2cap_sock_clear_timer(struct sock *sk);
 void __l2cap_sock_close(struct sock *sk, int reason);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 338d8c3..98ddd86 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -135,6 +135,50 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn
 	return c;
 }
 
+struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
+{
+	struct sock *sk;
+	struct hlist_node *node;
+	sk_for_each(sk, node, &l2cap_sk_list.head) {
+		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+
+		if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+			goto found;
+	}
+
+	sk = NULL;
+found:
+	return sk;
+}
+
+int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
+{
+	write_lock_bh(&l2cap_sk_list.lock);
+
+	if (__l2cap_get_sock_by_addr(psm, src)) {
+		write_unlock_bh(&l2cap_sk_list.lock);
+		return -EADDRINUSE;
+	}
+
+	chan->psm = psm;
+	chan->sport = psm;
+
+	write_unlock_bh(&l2cap_sk_list.lock);
+
+	return 0;
+}
+
+int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
+{
+	write_lock_bh(&l2cap_sk_list.lock);
+
+	chan->scid = scid;
+
+	write_unlock_bh(&l2cap_sk_list.lock);
+
+	return 0;
+}
+
 static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 {
 	u16 cid = L2CAP_CID_DYN_START;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 09cc7a0..2156dce 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -78,22 +78,6 @@ void l2cap_sock_clear_timer(struct sock *sk)
 	sk_stop_timer(sk, &sk->sk_timer);
 }
 
-static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
-{
-	struct sock *sk;
-	struct hlist_node *node;
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-
-		if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src))
-			goto found;
-	}
-
-	sk = NULL;
-found:
-	return sk;
-}
-
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
 	struct sock *sk = sock->sk;
@@ -136,26 +120,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 		}
 	}
 
-	write_lock_bh(&l2cap_sk_list.lock);
+	if (la.l2_cid)
+		err = l2cap_add_scid(chan, la.l2_cid);
+	else
+		err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm);
 
-	if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
-		err = -EADDRINUSE;
-	} else {
-		/* Save source address */
-		bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
-		chan->psm   = la.l2_psm;
-		chan->sport = la.l2_psm;
-		sk->sk_state = BT_BOUND;
-
-		if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
-					__le16_to_cpu(la.l2_psm) == 0x0003)
-			chan->sec_level = BT_SECURITY_SDP;
-	}
+	if (err < 0)
+		goto done;
 
-	if (la.l2_cid)
-		chan->scid = la.l2_cid;
+	if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
+				__le16_to_cpu(la.l2_psm) == 0x0003)
+		chan->sec_level = BT_SECURITY_SDP;
 
-	write_unlock_bh(&l2cap_sk_list.lock);
+	bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
+	sk->sk_state = BT_BOUND;
 
 done:
 	release_sock(sk);
-- 
1.7.5.rc1


^ permalink raw reply related

* Re: [PATCH 3/3] Bluetooth: Remove l2cap_sk_list
From: Gustavo F. Padovan @ 2011-04-28  5:13 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <BANLkTimYW2ZweS5GSnVQ6nn_WTs9+b0RcA@mail.gmail.com>

* Anderson Lizardo <anderson.lizardo@openbossa.org> [2011-04-27 19:19:35 -0400]:

> Hi Gustavo,
> 
> On Wed, Apr 27, 2011 at 5:49 PM, Gustavo F. Padovan
> <padovan@profusion.mobi> wrote:
> > @@ -883,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch
> >  /* Find socket with psm and source bdaddr.
> >  * Returns closest match.
> >  */
> > -static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
> > +static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
> >  {
> > -       struct sock *sk = NULL, *sk1 = NULL;
> > -       struct hlist_node *node;
> > +       struct l2cap_chan *c, *c1 = NULL;
> >
> > -       read_lock(&l2cap_sk_list.lock);
> > +       read_lock(&chan_list_lock);
> >
> > -       sk_for_each(sk, node, &l2cap_sk_list.head) {
> > -               struct l2cap_chan *chan = l2cap_pi(sk)->chan;
> > +       list_for_each_entry(c, &chan_list, global_l) {
> > +               struct sock *sk = c->sk;
> >
> >                if (state && sk->sk_state != state)
> >                        continue;
> >
> > -               if (chan->psm == psm) {
> > +               if (c->psm == psm) {
> >                        /* Exact match. */
> > -                       if (!bacmp(&bt_sk(sk)->src, src))
> > -                               break;
> > +                       if (!bacmp(&bt_sk(sk)->src, src)) {
> > +                               read_unlock_bh(&chan_list_lock);
> > +                               return c;
> 
> What about this instead of the above:
> 
> c1 = c;
> break;
> 
> This avoids a duplicated read_unlock_bh() and keeps a single exit
> point for the function.

I still prefer my version. ;)

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* Re: btusb not working in 2.6.38.4
From: Gustavo F. Padovan @ 2011-04-28  5:11 UTC (permalink / raw)
  To: Andrej Podzimek; +Cc: linux-bluetooth, stable, greg
In-Reply-To: <4DB8A51A.8080608@podzimek.org>

Hi Andrej,

* Andrej Podzimek <andrej@podzimek.org> [2011-04-28 01:22:02 +0200]:

> Hello,
> 
> after a recent kernel update on Arch Linux (2.6.38.4), I can see the following problem in dmesg:
> 
> ------------[ cut here ]------------
> WARNING: at lib/kobject.c:595 kobject_put+0x40/0x50()
> Hardware name: To Be Filled By O.E.M.
> kobject: '(null)' (ffff88023f60d5a0): is not initialized, yet kobject_put() is being called.
> Modules linked in: btusb(+) bluetooth rfkill usbhid hid button i2c_i801 i2c_core r8169 mii iTCO_wdt iTCO_vendor_support psmouse sg serio_raw evdev pcspkr ip_tables ip6_tables x_tables tpm_tis tpm tpm_bios w83627ehf hwmon_vid coretemp ext4 mbcache jbd2 crc16 dm_mod usb_storage raid456 async_raid6_recov async_pq raid6_pq async_xor xor async_memcpy async_tx md_mod uhci_hcd xhci_hcd ehci_hcd usbcore sd_mod crc_t10dif ahci libahci libata scsi_mod cpufreq_ondemand acpi_cpufreq freq_table processor mperf i7core_edac edac_core
> Pid: 1820, comm: modprobe Not tainted 2.6.38-ARCH #1
> Call Trace:
>   [<ffffffff8103a86b>] ? warn_slowpath_common+0x7b/0xc0
>   [<ffffffff8103a965>] ? warn_slowpath_fmt+0x45/0x50
>   [<ffffffff81248d3f>] ? skb_dequeue+0x5f/0x80
>   [<ffffffff8116b6f0>] ? kobject_put+0x40/0x50
>   [<ffffffffa025f85c>] ? btusb_probe+0x57c/0x5e0 [btusb]
>   [<ffffffffa00b85d5>] ? usb_probe_interface+0xe5/0x1e0 [usbcore]
>   [<ffffffff81215aaf>] ? driver_probe_device+0x6f/0x190
>   [<ffffffff81215c63>] ? __driver_attach+0x93/0xa0
>   [<ffffffff81215bd0>] ? __driver_attach+0x0/0xa0
>   [<ffffffff81214b23>] ? bus_for_each_dev+0x53/0x80
>   [<ffffffff812153f8>] ? bus_add_driver+0x188/0x260
>   [<ffffffff81215e3a>] ? driver_register+0x6a/0x130
>   [<ffffffffa00b748a>] ? usb_register_driver+0x8a/0x180 [usbcore]
>   [<ffffffffa011c000>] ? btusb_init+0x0/0x1000 [btusb]
>   [<ffffffff810001dc>] ? do_one_initcall+0x3c/0x170
>   [<ffffffff8106db3a>] ? sys_init_module+0xda/0x230
>   [<ffffffff8100243b>] ? system_call_fastpath+0x16/0x1b
> ---[ end trace 9c4648061ddb0b67 ]---
> 
> Presumably, Bluetooth does not seem to work at all (i.e., hciconfig -a does not output anything).
> 
> The output from lsusb -v relevant to the specific device is attached.
> 
> The device worked 100% flawlessly with 2.6.38.3. I had an a2dp headset and a mouse paired with it, both of which worked perfectly fine in parallel.

The only Bluetooth change in 2.6.38.4 is: https://lkml.org/lkml/2011/4/19/406
However I don't think this patch is causing this issue. Do you care to patch -R it
and test?
If the problem is somewhere else we have to go with a bisect, there are only
70 patches, so it shouldn't take to long.

Greg, any idea on that? Are there similar reports of warnings for 2.6.38.4?

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* Re: [PATCH 7/7] Bluetooth: Fix link key persistent storage criteria
From: Anderson Lizardo @ 2011-04-28  0:00 UTC (permalink / raw)
  To: Anderson Lizardo, linux-bluetooth
In-Reply-To: <20110427235723.GA3378@jh-x301>

Hi Johan,

On Wed, Apr 27, 2011 at 7:57 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Lizardo,
>
> On Wed, Apr 27, 2011, Anderson Lizardo wrote:
>> > +       if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) {
>> > +               list_del(&key->list);
>> > +               kfree(key);
>> > +               return 0;
>>
>> Just to make sure, is this condition possible?
>>
>> * new_key parameter not zero
>> * old_key variable not NULL
>>
>> If so, "key" will point to an entry from hdev->link_keys , which will
>> be freed on the if() above without removing it from the list.
>
> Do you see the list_del call there? :)

Ok, I failed to see it :)

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* Re: [PATCH 7/7] Bluetooth: Fix link key persistent storage criteria
From: Johan Hedberg @ 2011-04-27 23:57 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <BANLkTikpQZ9MLvfnCH7oDMN2+_+M=M-QNQ@mail.gmail.com>

Hi Lizardo,

On Wed, Apr 27, 2011, Anderson Lizardo wrote:
> > +       if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) {
> > +               list_del(&key->list);
> > +               kfree(key);
> > +               return 0;
> 
> Just to make sure, is this condition possible?
> 
> * new_key parameter not zero
> * old_key variable not NULL
> 
> If so, "key" will point to an entry from hdev->link_keys , which will
> be freed on the if() above without removing it from the list.

Do you see the list_del call there? :)

Johan

^ permalink raw reply

* Re: [PATCH 7/7] Bluetooth: Fix link key persistent storage criteria
From: Anderson Lizardo @ 2011-04-27 23:47 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1303945480-25756-7-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

On Wed, Apr 27, 2011 at 7:04 PM,  <johan.hedberg@gmail.com> wrote:
> @@ -1042,6 +1078,20 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
>
>        BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
>
> +       /* Some buggy controller combinations generate a changed
> +        * combination key for legacy pairing even when there's no
> +        * previous key */
> +       if (type == HCI_LK_CHANGED_COMBINATION &&
> +                                       (!conn || conn->remote_auth == 0xff) &&
> +                                       old_key_type == 0xff)
> +               type = HCI_LK_COMBINATION;
> +
> +       if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) {
> +               list_del(&key->list);
> +               kfree(key);
> +               return 0;

Just to make sure, is this condition possible?

* new_key parameter not zero
* old_key variable not NULL

If so, "key" will point to an entry from hdev->link_keys , which will
be freed on the if() above without removing it from the list.

> +       }
> +
>        bacpy(&key->bdaddr, bdaddr);
>        memcpy(key->val, val, 16);
>        key->type = type;

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* Re: [PATCH 1/7] Bluetooth: Add automated SSP user confirmation responses
From: Johan Hedberg @ 2011-04-27 23:46 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <BANLkTinxDHjLjAPqMLys3nxsjkHNnM=x0A@mail.gmail.com>

Hi Lizardo,

On Wed, Apr 27, 2011, Anderson Lizardo wrote:
> On Wed, Apr 27, 2011 at 7:04 PM,  <johan.hedberg@gmail.com> wrote:
> > @@ -2447,14 +2447,47 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
> >                                                        struct sk_buff *skb)
> >  {
> >        struct hci_ev_user_confirm_req *ev = (void *) skb->data;
> > +       int loc_mitm, rem_mitm;
> > +       struct hci_conn *conn;
> >
> >        BT_DBG("%s", hdev->name);
> >
> >        hci_dev_lock(hdev);
> >
> > -       if (test_bit(HCI_MGMT, &hdev->flags))
> > -               mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
> > +       if (!test_bit(HCI_MGMT, &hdev->flags))
> > +               goto unlock;
> 
> You lock hdev for checking hdev->flags, but not for reading hdev->name
> on the BT_DBG() call. Is that ok?

I suppose hdev->name can be considered a read-only value as it never
changes after the HCI dev is created. There's also lots of other places
in hci_event.c that access it without locking, so I think this should be
fine.

Johan

^ permalink raw reply

* Re: [PATCH 1/7] Bluetooth: Add automated SSP user confirmation responses
From: Anderson Lizardo @ 2011-04-27 23:27 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1303945480-25756-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

On Wed, Apr 27, 2011 at 7:04 PM,  <johan.hedberg@gmail.com> wrote:
> @@ -2447,14 +2447,47 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
>                                                        struct sk_buff *skb)
>  {
>        struct hci_ev_user_confirm_req *ev = (void *) skb->data;
> +       int loc_mitm, rem_mitm;
> +       struct hci_conn *conn;
>
>        BT_DBG("%s", hdev->name);
>
>        hci_dev_lock(hdev);
>
> -       if (test_bit(HCI_MGMT, &hdev->flags))
> -               mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
> +       if (!test_bit(HCI_MGMT, &hdev->flags))
> +               goto unlock;

You lock hdev for checking hdev->flags, but not for reading hdev->name
on the BT_DBG() call. Is that ok?

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* Re: [PATCH] Use HCI_MAX_EIR_LENGTH instead of hard-coded value
From: Johan Hedberg @ 2011-04-27 23:25 UTC (permalink / raw)
  To: Bruna Moreira; +Cc: linux-bluetooth
In-Reply-To: <1303935663-31142-1-git-send-email-bruna.moreira@openbossa.org>

Hi Bruna,

On Wed, Apr 27, 2011, Bruna Moreira wrote:
> ---
> 
> NOTE: the constants EIR_DATA_LENGTH and HCI_MAX_EIR_LENGTH are duplicated.
> This will be fixed in next patches of discovery cleanup.
> 
>  lib/hci.c         |    4 ++--
>  plugins/hciops.c  |    2 +-
>  src/storage.c     |    4 ++--
>  test/hciemu.c     |    6 +++---
>  tools/hciconfig.c |   10 +++++-----
>  5 files changed, 13 insertions(+), 13 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] Change attrib server to use ATT CID & PSM defined in att.h
From: Johan Hedberg @ 2011-04-27 23:24 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1303909660-30690-1-git-send-email-claudio.takahasi@openbossa.org>

Hi Claudio,

On Wed, Apr 27, 2011, Claudio Takahasi wrote:
> ---
>  src/attrib-server.c |   11 ++++-------
>  1 files changed, 4 insertions(+), 7 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] Remove grouping by phone number in call-history results
From: Johan Hedberg @ 2011-04-27 23:23 UTC (permalink / raw)
  To: Radoslaw Jablonski; +Cc: linux-bluetooth
In-Reply-To: <1303901520-6508-1-git-send-email-ext-jablonski.radoslaw@nokia.com>

Hi Radek,

On Wed, Apr 27, 2011, Radoslaw Jablonski wrote:
> Now call history entries are distinguished also by call
> date (previously only contact-id was compared, so calls with
> different date were grouped into one entry in pull results).
> This change is needed for headsets with PBAP support that are
> confused when number of "new missed calls" is different than
> number of returned entries by pull call-history response (by
> example Nokia BH-903 hangs when this happens).
> ---
>  plugins/phonebook-tracker.c |   30 +++++++++++++++++++++++++++---
>  1 files changed, 27 insertions(+), 3 deletions(-)

Pushed upstream. Thanks.

Johan

^ permalink raw reply

* btusb not working in 2.6.38.4
From: Andrej Podzimek @ 2011-04-27 23:22 UTC (permalink / raw)
  To: linux-bluetooth


[-- Attachment #1.1: Type: text/plain, Size: 2298 bytes --]

Hello,

after a recent kernel update on Arch Linux (2.6.38.4), I can see the following problem in dmesg:

------------[ cut here ]------------
WARNING: at lib/kobject.c:595 kobject_put+0x40/0x50()
Hardware name: To Be Filled By O.E.M.
kobject: '(null)' (ffff88023f60d5a0): is not initialized, yet kobject_put() is being called.
Modules linked in: btusb(+) bluetooth rfkill usbhid hid button i2c_i801 i2c_core r8169 mii iTCO_wdt iTCO_vendor_support psmouse sg serio_raw evdev pcspkr ip_tables ip6_tables x_tables tpm_tis tpm tpm_bios w83627ehf hwmon_vid coretemp ext4 mbcache jbd2 crc16 dm_mod usb_storage raid456 async_raid6_recov async_pq raid6_pq async_xor xor async_memcpy async_tx md_mod uhci_hcd xhci_hcd ehci_hcd usbcore sd_mod crc_t10dif ahci libahci libata scsi_mod cpufreq_ondemand acpi_cpufreq freq_table processor mperf i7core_edac edac_core
Pid: 1820, comm: modprobe Not tainted 2.6.38-ARCH #1
Call Trace:
  [<ffffffff8103a86b>] ? warn_slowpath_common+0x7b/0xc0
  [<ffffffff8103a965>] ? warn_slowpath_fmt+0x45/0x50
  [<ffffffff81248d3f>] ? skb_dequeue+0x5f/0x80
  [<ffffffff8116b6f0>] ? kobject_put+0x40/0x50
  [<ffffffffa025f85c>] ? btusb_probe+0x57c/0x5e0 [btusb]
  [<ffffffffa00b85d5>] ? usb_probe_interface+0xe5/0x1e0 [usbcore]
  [<ffffffff81215aaf>] ? driver_probe_device+0x6f/0x190
  [<ffffffff81215c63>] ? __driver_attach+0x93/0xa0
  [<ffffffff81215bd0>] ? __driver_attach+0x0/0xa0
  [<ffffffff81214b23>] ? bus_for_each_dev+0x53/0x80
  [<ffffffff812153f8>] ? bus_add_driver+0x188/0x260
  [<ffffffff81215e3a>] ? driver_register+0x6a/0x130
  [<ffffffffa00b748a>] ? usb_register_driver+0x8a/0x180 [usbcore]
  [<ffffffffa011c000>] ? btusb_init+0x0/0x1000 [btusb]
  [<ffffffff810001dc>] ? do_one_initcall+0x3c/0x170
  [<ffffffff8106db3a>] ? sys_init_module+0xda/0x230
  [<ffffffff8100243b>] ? system_call_fastpath+0x16/0x1b
---[ end trace 9c4648061ddb0b67 ]---

Presumably, Bluetooth does not seem to work at all (i.e., hciconfig -a does not output anything).

The output from lsusb -v relevant to the specific device is attached.

The device worked 100% flawlessly with 2.6.38.3. I had an a2dp headset and a mouse paired with it, both of which worked perfectly fine in parallel.

If you need further debugging info, please let me know.

Andrej

[-- Attachment #1.2: lsusb-v --]
[-- Type: text/plain, Size: 10978 bytes --]

Bus 003 Device 006: ID 0a5c:2198 Broadcom Corp. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass          224 Wireless
  bDeviceSubClass         1 Radio Frequency
  bDeviceProtocol         1 Bluetooth
  bMaxPacketSize0        64
  idVendor           0x0a5c Broadcom Corp.
  idProduct          0x2198 
  bcdDevice            3.91
  iManufacturer           1 Broadcom Corp
  iProduct                2 Broadcom Bluetooth 3.0 Device
  iSerial                 3 000272AE4653
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          216
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      1 Bluetooth
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      1 Bluetooth
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0000  1x 0 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0000  1x 0 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      1 Bluetooth
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0009  1x 9 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0009  1x 9 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       2
      bNumEndpoints           2
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      1 Bluetooth
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0011  1x 17 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0011  1x 17 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       3
      bNumEndpoints           2
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      1 Bluetooth
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       4
      bNumEndpoints           2
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      1 Bluetooth
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       5
      bNumEndpoints           2
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      1 Bluetooth
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass    255 Vendor Specific Subclass
      bInterfaceProtocol    255 Vendor Specific Protocol
      iInterface              0 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       254 Application Specific Interface
      bInterfaceSubClass      1 Device Firmware Update
      bInterfaceProtocol      1 
      iInterface              0 
      Device Firmware Upgrade Interface Descriptor:
        bLength                             7
        bDescriptorType                    33
        bmAttributes                        7
          Will Not Detach
          Manifestation Tolerant
          Upload Supported
          Download Supported
        wDetachTimeout                   5000 milliseconds
        wTransferSize                      64 bytes
Device Status:     0x0000
  (Bus Powered)

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5804 bytes --]

^ permalink raw reply

* Re: [PATCH 3/3] Bluetooth: Remove l2cap_sk_list
From: Anderson Lizardo @ 2011-04-27 23:19 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth
In-Reply-To: <1303940957-22694-3-git-send-email-padovan@profusion.mobi>

Hi Gustavo,

On Wed, Apr 27, 2011 at 5:49 PM, Gustavo F. Padovan
<padovan@profusion.mobi> wrote:
> @@ -883,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch
>  /* Find socket with psm and source bdaddr.
>  * Returns closest match.
>  */
> -static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
> +static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
>  {
> -       struct sock *sk = NULL, *sk1 = NULL;
> -       struct hlist_node *node;
> +       struct l2cap_chan *c, *c1 = NULL;
>
> -       read_lock(&l2cap_sk_list.lock);
> +       read_lock(&chan_list_lock);
>
> -       sk_for_each(sk, node, &l2cap_sk_list.head) {
> -               struct l2cap_chan *chan = l2cap_pi(sk)->chan;
> +       list_for_each_entry(c, &chan_list, global_l) {
> +               struct sock *sk = c->sk;
>
>                if (state && sk->sk_state != state)
>                        continue;
>
> -               if (chan->psm == psm) {
> +               if (c->psm == psm) {
>                        /* Exact match. */
> -                       if (!bacmp(&bt_sk(sk)->src, src))
> -                               break;
> +                       if (!bacmp(&bt_sk(sk)->src, src)) {
> +                               read_unlock_bh(&chan_list_lock);
> +                               return c;

What about this instead of the above:

c1 = c;
break;

This avoids a duplicated read_unlock_bh() and keeps a single exit
point for the function.

> +                       }
>
>                        /* Closest match */
>                        if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
> -                               sk1 = sk;
> +                               c1 = c;
>                }
>        }
>
> -       read_unlock(&l2cap_sk_list.lock);
> +       read_unlock(&chan_list_lock);
>
> -       return node ? sk : sk1;
> +       return c1;
>  }
>
>  int l2cap_chan_connect(struct l2cap_chan *chan)

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* [PATCH] Bluetooth: Respect local MITM req in io_cap reply
From: johan.hedberg @ 2011-04-27 23:09 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303372461-11848-6-git-send-email-waldemar.rymarkiewicz@tieto.com>

From: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>

If host requires MITM protection notify that to controller in
io capabilities reply even if the remote device requires no bonding.

If it is not respected, host can get an unauthenticated link key while
it expects authenticated one.

Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 net/bluetooth/hci_event.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index cba0bdb..3c90736 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2369,7 +2369,7 @@ static inline u8 hci_get_auth_req(struct hci_conn *conn)
 
 	/* If remote requests no-bonding follow that lead */
 	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
-		return 0x00;
+		return conn->remote_auth | (conn->auth_type & 0x01);
 
 	return conn->auth_type;
 }
-- 
1.7.4.4


^ permalink raw reply related

* [PATCH 7/7] Bluetooth: Fix link key persistent storage criteria
From: johan.hedberg @ 2011-04-27 23:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303945480-25756-1-git-send-email-johan.hedberg@gmail.com>

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

Link keys should only be stored if very specific criteria of the
authentication process are fulfilled. This patch essentially copies the
criteria that user space has so far been using to the kernel side so
that the management interface works properly.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 include/net/bluetooth/hci_core.h |    4 +-
 net/bluetooth/hci_core.c         |   54 ++++++++++++++++++++++++++++++++++++-
 net/bluetooth/hci_event.c        |    2 +-
 net/bluetooth/mgmt.c             |    2 +-
 4 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 490b43b..5a794b7 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -515,8 +515,8 @@ int hci_uuids_clear(struct hci_dev *hdev);
 
 int hci_link_keys_clear(struct hci_dev *hdev);
 struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
-int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
-						u8 *key, u8 type, u8 pin_len);
+int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
+			bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
 int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 int hci_remote_oob_data_clear(struct hci_dev *hdev);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 07d0ba3..85fae57 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1022,8 +1022,44 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
 	return NULL;
 }
 
-int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
-						u8 *val, u8 type, u8 pin_len)
+int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
+						u8 key_type, u8 old_key_type)
+{
+	/* Legacy key */
+	if (key_type < 0x03)
+		return 1;
+
+	/* Debug keys are insecure so don't store them persistently */
+	if (key_type == HCI_LK_DEBUG_COMBINATION)
+		return 0;
+
+	/* Changed combination key and there's no previous one */
+	if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
+		return 0;
+
+	/* Security mode 3 case */
+	if (!conn)
+		return 1;
+
+	/* Neither local nor remote side had no-bonding as requirement */
+	if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
+		return 1;
+
+	/* Local side had dedicated bonding as requirement */
+	if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
+		return 1;
+
+	/* Remote side had dedicated bonding as requirement */
+	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
+		return 1;
+
+	/* If none of the above criteria match, then don't store the key
+	 * persistently */
+	return 0;
+}
+
+int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
+				bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
 {
 	struct link_key *key, *old_key;
 	u8 old_key_type;
@@ -1042,6 +1078,20 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
 
 	BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
 
+	/* Some buggy controller combinations generate a changed
+	 * combination key for legacy pairing even when there's no
+	 * previous key */
+	if (type == HCI_LK_CHANGED_COMBINATION &&
+					(!conn || conn->remote_auth == 0xff) &&
+					old_key_type == 0xff)
+		type = HCI_LK_COMBINATION;
+
+	if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) {
+		list_del(&key->list);
+		kfree(key);
+		return 0;
+	}
+
 	bacpy(&key->bdaddr, bdaddr);
 	memcpy(key->val, val, 16);
 	key->type = type;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index acb4e64..6982f41 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2112,7 +2112,7 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
 	}
 
 	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
-		hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
+		hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key,
 							ev->key_type, pin_len);
 
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 5ae581a..0262f79 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -945,7 +945,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
 	for (i = 0; i < key_count; i++) {
 		struct mgmt_key_info *key = &cp->keys[i];
 
-		hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type,
+		hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type,
 								key->pin_len);
 	}
 
-- 
1.7.4.4


^ permalink raw reply related

* [PATCH 6/7] Bluetooth: Fix logic in hci_pin_code_request_evt
From: johan.hedberg @ 2011-04-27 23:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303945480-25756-1-git-send-email-johan.hedberg@gmail.com>

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

The mgmt_ev_pin_code_request event should not be sent to user space if
the request gets rejected by the kernel due to the pairable flag not
being set.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 net/bluetooth/hci_event.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0e8ccda..acb4e64 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2019,8 +2019,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
 	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
 		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
 					sizeof(ev->bdaddr), &ev->bdaddr);
-
-	if (test_bit(HCI_MGMT, &hdev->flags))
+	else if (test_bit(HCI_MGMT, &hdev->flags))
 		mgmt_pin_code_request(hdev->id, &ev->bdaddr);
 
 	hci_dev_unlock(hdev);
-- 
1.7.4.4


^ permalink raw reply related

* [PATCH 5/7] Bluetooth: Fix reason code for pairing rejection
From: johan.hedberg @ 2011-04-27 23:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303945480-25756-1-git-send-email-johan.hedberg@gmail.com>

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

"Pairing not allowed" is 0x18 and not 0x16.

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

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 003d731..0e8ccda 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2426,7 +2426,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
 		struct hci_cp_io_capability_neg_reply cp;
 
 		bacpy(&cp.bdaddr, &ev->bdaddr);
-		cp.reason = 0x16; /* Pairing not allowed */
+		cp.reason = 0x18; /* Pairing not allowed */
 
 		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
 							sizeof(cp), &cp);
-- 
1.7.4.4


^ permalink raw reply related

* [PATCH 4/7] Bluetooth: Add confirm_hint parameter to user confirmation requests
From: johan.hedberg @ 2011-04-27 23:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303945480-25756-1-git-send-email-johan.hedberg@gmail.com>

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

When accepting a pairing request which fulfills the SSP auto-accept
criteria we need to push the request all the way to the user for
confirmation. This patch adds a new hint to the user_confirm_request
management event so user space can know when to show a numeric
comparison dialog and when to show a simple yes/no confirmation dialog.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 include/net/bluetooth/hci_core.h |    3 ++-
 include/net/bluetooth/mgmt.h     |    1 +
 net/bluetooth/hci_event.c        |   16 ++++++++++++++--
 net/bluetooth/mgmt.c             |    4 +++-
 4 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 09740c3..490b43b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -783,7 +783,8 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr);
 int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value);
+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value,
+							u8 confirm_hint);
 int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
 								u8 status);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 6b6ff92..8ea6b08 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -254,6 +254,7 @@ struct mgmt_ev_pin_code_request {
 #define MGMT_EV_USER_CONFIRM_REQUEST	0x000F
 struct mgmt_ev_user_confirm_request {
 	bdaddr_t bdaddr;
+	__u8 confirm_hint;
 	__le32 value;
 } __packed;
 
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 12a9bb9..003d731 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2461,7 +2461,7 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
 							struct sk_buff *skb)
 {
 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
-	int loc_mitm, rem_mitm;
+	int loc_mitm, rem_mitm, confirm_hint = 0;
 	struct hci_conn *conn;
 
 	BT_DBG("%s", hdev->name);
@@ -2493,6 +2493,16 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
 	/* If no side requires MITM protection; auto-accept */
 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
 				(!rem_mitm || conn->io_capability == 0x03)) {
+
+		/* If we're not the initiators request authorization to
+		 * proceed from user space (mgmt_user_confirm with
+		 * confirm_hint set to 1). */
+		if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
+			BT_DBG("Confirming auto-accept as acceptor");
+			confirm_hint = 1;
+			goto confirm;
+		}
+
 		BT_DBG("Auto-accept of user confirmation with %ums delay",
 						hdev->auto_accept_delay);
 
@@ -2507,7 +2517,9 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
 		goto unlock;
 	}
 
-	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
+confirm:
+	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey,
+								confirm_hint);
 
 unlock:
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index c304688..5ae581a 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1920,13 +1920,15 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
 	return err;
 }
 
-int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value)
+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value,
+							u8 confirm_hint)
 {
 	struct mgmt_ev_user_confirm_request ev;
 
 	BT_DBG("hci%u", index);
 
 	bacpy(&ev.bdaddr, bdaddr);
+	ev.confirm_hint = confirm_hint;
 	put_unaligned_le32(value, &ev.value);
 
 	return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
-- 
1.7.4.4


^ permalink raw reply related

* [PATCH 3/7] Bluetooth: Fix HCI_CONN_AUTH_PEND flag for all authentication requests
From: johan.hedberg @ 2011-04-27 23:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303945480-25756-1-git-send-email-johan.hedberg@gmail.com>

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

The HCI_CONN_AUTH_PEND flag should be set whenever requesting
authentication so that multiple pending requests can't occur.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 net/bluetooth/hci_event.c |   22 ++++++++++++++++++----
 1 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 4f1e695..12a9bb9 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1013,12 +1013,19 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
-	if (conn && hci_outgoing_auth_needed(hdev, conn)) {
+	if (!conn)
+		goto unlock;
+
+	if (!hci_outgoing_auth_needed(hdev, conn))
+		goto unlock;
+
+	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
 		struct hci_cp_auth_requested cp;
-		cp.handle = __cpu_to_le16(conn->handle);
+		cp.handle = cpu_to_le16(conn->handle);
 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
 	}
 
+unlock:
 	hci_dev_unlock(hdev);
 }
 
@@ -1500,12 +1507,19 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
 		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-	if (conn && hci_outgoing_auth_needed(hdev, conn)) {
+	if (!conn)
+		goto unlock;
+
+	if (!hci_outgoing_auth_needed(hdev, conn))
+		goto unlock;
+
+	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
 		struct hci_cp_auth_requested cp;
-		cp.handle = __cpu_to_le16(conn->handle);
+		cp.handle = cpu_to_le16(conn->handle);
 		hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
 	}
 
+unlock:
 	hci_dev_unlock(hdev);
 }
 
-- 
1.7.4.4


^ permalink raw reply related

* [PATCH 2/7] Bluetooth: Add variable SSP auto-accept delay support
From: johan.hedberg @ 2011-04-27 23:04 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303945480-25756-1-git-send-email-johan.hedberg@gmail.com>

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

Some test systems require an arbitrary delay to the auto-accept test
cases for Secure Simple Pairing in order for the tests to pass.
Previously when this was handled in user space it was worked around by
code modifications and recompilation, but now that it's on the kernel
side it's more convenient if there's a debugfs interface for it.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 include/net/bluetooth/hci_core.h |    3 +++
 net/bluetooth/hci_conn.c         |   17 +++++++++++++++++
 net/bluetooth/hci_event.c        |   10 +++++++++-
 net/bluetooth/hci_sysfs.c        |   31 +++++++++++++++++++++++++++++++
 4 files changed, 60 insertions(+), 1 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 02e7256..09740c3 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -126,6 +126,8 @@ struct hci_dev {
 	__u16		sniff_min_interval;
 	__u16		sniff_max_interval;
 
+	unsigned int	auto_accept_delay;
+
 	unsigned long	quirks;
 
 	atomic_t	cmd_cnt;
@@ -246,6 +248,7 @@ struct hci_conn {
 
 	struct timer_list disc_timer;
 	struct timer_list idle_timer;
+	struct timer_list auto_accept_timer;
 
 	struct work_struct work_add;
 	struct work_struct work_del;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 74cd755..7f5ad8a 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -269,6 +269,19 @@ static void hci_conn_idle(unsigned long arg)
 	hci_conn_enter_sniff_mode(conn);
 }
 
+static void hci_conn_auto_accept(unsigned long arg)
+{
+	struct hci_conn *conn = (void *) arg;
+	struct hci_dev *hdev = conn->hdev;
+
+	hci_dev_lock(hdev);
+
+	hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
+								&conn->dst);
+
+	hci_dev_unlock(hdev);
+}
+
 struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 {
 	struct hci_conn *conn;
@@ -312,6 +325,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 
 	setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
 	setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
+	setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
+							(unsigned long) conn);
 
 	atomic_set(&conn->refcnt, 0);
 
@@ -342,6 +357,8 @@ int hci_conn_del(struct hci_conn *conn)
 
 	del_timer(&conn->disc_timer);
 
+	del_timer(&conn->auto_accept_timer);
+
 	if (conn->type == ACL_LINK) {
 		struct hci_conn *sco = conn->link;
 		if (sco)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 038d70d..4f1e695 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2479,7 +2479,15 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
 	/* If no side requires MITM protection; auto-accept */
 	if ((!loc_mitm || conn->remote_cap == 0x03) &&
 				(!rem_mitm || conn->io_capability == 0x03)) {
-		BT_DBG("Auto-accept of user confirmation");
+		BT_DBG("Auto-accept of user confirmation with %ums delay",
+						hdev->auto_accept_delay);
+
+		if (hdev->auto_accept_delay > 0) {
+			int delay = msecs_to_jiffies(hdev->auto_accept_delay);
+			mod_timer(&conn->auto_accept_timer, jiffies + delay);
+			goto unlock;
+		}
+
 		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
 						sizeof(ev->bdaddr), &ev->bdaddr);
 		goto unlock;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 8775933..a6c3aa8 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -511,6 +511,35 @@ static const struct file_operations uuids_fops = {
 	.release	= single_release,
 };
 
+static int auto_accept_delay_set(void *data, u64 val)
+{
+	struct hci_dev *hdev = data;
+
+	hci_dev_lock_bh(hdev);
+
+	hdev->auto_accept_delay = val;
+
+	hci_dev_unlock_bh(hdev);
+
+	return 0;
+}
+
+static int auto_accept_delay_get(void *data, u64 *val)
+{
+	struct hci_dev *hdev = data;
+
+	hci_dev_lock_bh(hdev);
+
+	*val = hdev->auto_accept_delay;
+
+	hci_dev_unlock_bh(hdev);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
+					auto_accept_delay_set, "%llu\n");
+
 int hci_register_sysfs(struct hci_dev *hdev)
 {
 	struct device *dev = &hdev->dev;
@@ -545,6 +574,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
 
 	debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
 
+	debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev,
+						&auto_accept_delay_fops);
 	return 0;
 }
 
-- 
1.7.4.4


^ permalink raw reply related

* [PATCH 1/7] Bluetooth: Add automated SSP user confirmation responses
From: johan.hedberg @ 2011-04-27 23:04 UTC (permalink / raw)
  To: linux-bluetooth

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

This patch adds automated negative and positive (auto-accept) responses
for Secure Simple Pairing user confirmation requests. The responses are
only sent if the HCI_MGMT flag is set in order not to confuse older user
space versions (without management interface support).

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 net/bluetooth/hci_event.c |   37 +++++++++++++++++++++++++++++++++++--
 1 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3c90736..038d70d 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2447,14 +2447,47 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
 							struct sk_buff *skb)
 {
 	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
+	int loc_mitm, rem_mitm;
+	struct hci_conn *conn;
 
 	BT_DBG("%s", hdev->name);
 
 	hci_dev_lock(hdev);
 
-	if (test_bit(HCI_MGMT, &hdev->flags))
-		mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
+	if (!test_bit(HCI_MGMT, &hdev->flags))
+		goto unlock;
 
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+	if (!conn)
+		goto unlock;
+
+	loc_mitm = (conn->auth_type & 0x01);
+	rem_mitm = (conn->remote_auth & 0x01);
+
+	/* If we require MITM but the remote device can't provide that
+	 * (it has NoInputNoOutput) then reject the confirmation
+	 * request. The only exception is when we're dedicated bonding
+	 * initiators (connect_cfm_cb set) since then we always have the MITM
+	 * bit set. */
+	if (!conn->connect_cfm_cb && loc_mitm && conn->remote_cap == 0x03) {
+		BT_DBG("Rejecting request: remote device can't provide MITM");
+		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
+					sizeof(ev->bdaddr), &ev->bdaddr);
+		goto unlock;
+	}
+
+	/* If no side requires MITM protection; auto-accept */
+	if ((!loc_mitm || conn->remote_cap == 0x03) &&
+				(!rem_mitm || conn->io_capability == 0x03)) {
+		BT_DBG("Auto-accept of user confirmation");
+		hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
+						sizeof(ev->bdaddr), &ev->bdaddr);
+		goto unlock;
+	}
+
+	mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
+
+unlock:
 	hci_dev_unlock(hdev);
 }
 
-- 
1.7.4.4


^ permalink raw reply related

* Re: [PATCH 3/3] Bluetooth: Remove l2cap_sk_list
From: Vinicius Costa Gomes @ 2011-04-27 22:06 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth
In-Reply-To: <1303940957-22694-3-git-send-email-padovan@profusion.mobi>

Hi Gustavo,

On 18:49 Wed 27 Apr, Gustavo F. Padovan wrote:
> A new list was added to replace the socket based one. This new list
> doesn't depent on sock and then fits better inside l2cap_core.c code.
> 
> It also rename l2cap_chan_alloc() to l2cap_chan_create() and
> l2cap_chan_free() to l2cap_chan_destruct()

I think that l2cap_chan_destroy() would sound better. create/destroy sound
more related than create/destruct.

> 
> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
> ---
>  include/net/bluetooth/l2cap.h |    6 +-
>  net/bluetooth/l2cap_core.c    |  165 ++++++++++++++++++++++-------------------
>  net/bluetooth/l2cap_sock.c    |    6 +-
>  3 files changed, 95 insertions(+), 82 deletions(-)
> 


Cheers,
-- 
Vinicius

^ permalink raw reply

* Re: [PATCH v2 2/2] Bluetooth: Add discovering event to the Management interface
From: Gustavo F. Padovan @ 2011-04-27 21:54 UTC (permalink / raw)
  To: anderson.briglia; +Cc: linux-bluetooth, Johan Hedberg
In-Reply-To: <4db82875.624dec0a.70bd.226a@mx.google.com>

* anderson.briglia@openbossa.org <anderson.briglia@openbossa.org> [2011-04-27 10:29:57 -0400]:

> From: Johan Hedberg <johan.hedberg@nokia.com>
> 
> This patch adds a new event to the Management interface to track when
> local adapters are discovering remote devices. For now this only tracks
> BR/EDR discovery procedures.
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org>
> ---
>  include/net/bluetooth/hci_core.h |    1 +
>  include/net/bluetooth/mgmt.h     |    2 +
>  net/bluetooth/hci_event.c        |   40 ++++++++++++++++++++++++++++++++-----
>  net/bluetooth/mgmt.c             |    6 +++++
>  4 files changed, 43 insertions(+), 6 deletions(-)

Both applied, thanks.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* [PATCH 3/3] Bluetooth: Remove l2cap_sk_list
From: Gustavo F. Padovan @ 2011-04-27 21:49 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1303940957-22694-2-git-send-email-padovan@profusion.mobi>

A new list was added to replace the socket based one. This new list
doesn't depent on sock and then fits better inside l2cap_core.c code.

It also rename l2cap_chan_alloc() to l2cap_chan_create() and
l2cap_chan_free() to l2cap_chan_destruct()

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 include/net/bluetooth/l2cap.h |    6 +-
 net/bluetooth/l2cap_core.c    |  165 ++++++++++++++++++++++-------------------
 net/bluetooth/l2cap_sock.c    |    6 +-
 3 files changed, 95 insertions(+), 82 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index fb3f90e..2ba675c 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -350,6 +350,7 @@ struct l2cap_chan {
 	struct list_head	srej_l;
 
 	struct list_head list;
+	struct list_head global_l;
 };
 
 struct l2cap_conn {
@@ -441,7 +442,6 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 #define __is_sar_start(ctrl)	(((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
 
 extern int disable_ertm;
-extern struct bt_sock_list l2cap_sk_list;
 
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
@@ -469,9 +469,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
 struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 							int proto, gfp_t prio);
 void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
-struct l2cap_chan *l2cap_chan_alloc(struct sock *sk);
+struct l2cap_chan *l2cap_chan_create(struct sock *sk);
 void l2cap_chan_del(struct l2cap_chan *chan, int err);
-void l2cap_chan_free(struct l2cap_chan *chan);
+void l2cap_chan_destruct(struct l2cap_chan *chan);
 int l2cap_chan_connect(struct l2cap_chan *chan);
 
 #endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9e3f64f..c1d08f1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -62,9 +62,8 @@ static u8 l2cap_fixed_chan[8] = { 0x02, };
 
 static struct workqueue_struct *_busy_wq;
 
-struct bt_sock_list l2cap_sk_list = {
-	.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
-};
+LIST_HEAD(chan_list);
+DEFINE_RWLOCK(chan_list_lock);
 
 static void l2cap_busy_work(struct work_struct *work);
 
@@ -135,29 +134,27 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn
 	return c;
 }
 
-static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
+static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src)
 {
-	struct sock *sk;
-	struct hlist_node *node;
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	struct l2cap_chan *c;
 
-		if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+	list_for_each_entry(c, &chan_list, global_l) {
+		if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src))
 			goto found;
 	}
 
-	sk = NULL;
+	c = NULL;
 found:
-	return sk;
+	return c;
 }
 
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
 {
 	int err;
 
-	write_lock_bh(&l2cap_sk_list.lock);
+	write_lock_bh(&chan_list_lock);
 
-	if (psm && __l2cap_get_sock_by_addr(psm, src)) {
+	if (psm && __l2cap_global_chan_by_addr(psm, src)) {
 		err = -EADDRINUSE;
 		goto done;
 	}
@@ -171,7 +168,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
 
 		err = -EINVAL;
 		for (p = 0x1001; p < 0x1100; p += 2)
-			if (!__l2cap_get_sock_by_addr(cpu_to_le16(p), src)) {
+			if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) {
 				chan->psm   = cpu_to_le16(p);
 				chan->sport = cpu_to_le16(p);
 				err = 0;
@@ -180,17 +177,17 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm)
 	}
 
 done:
-	write_unlock_bh(&l2cap_sk_list.lock);
+	write_unlock_bh(&chan_list_lock);
 	return err;
 }
 
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid)
 {
-	write_lock_bh(&l2cap_sk_list.lock);
+	write_lock_bh(&chan_list_lock);
 
 	chan->scid = scid;
 
-	write_unlock_bh(&l2cap_sk_list.lock);
+	write_unlock_bh(&chan_list_lock);
 
 	return 0;
 }
@@ -207,7 +204,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
 	return 0;
 }
 
-struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
+struct l2cap_chan *l2cap_chan_create(struct sock *sk)
 {
 	struct l2cap_chan *chan;
 
@@ -217,11 +214,19 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
 
 	chan->sk = sk;
 
+	write_lock_bh(&chan_list_lock);
+	list_add(&chan->global_l, &chan_list);
+	write_unlock_bh(&chan_list_lock);
+
 	return chan;
 }
 
-void l2cap_chan_free(struct l2cap_chan *chan)
+void l2cap_chan_destruct(struct l2cap_chan *chan)
 {
+	write_lock_bh(&chan_list_lock);
+	list_del(&chan->global_l);
+	write_unlock_bh(&chan_list_lock);
+
 	kfree(chan);
 }
 
@@ -651,48 +656,51 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 /* Find socket with cid and source bdaddr.
  * Returns closest match, locked.
  */
-static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
+static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src)
 {
-	struct sock *sk = NULL, *sk1 = NULL;
-	struct hlist_node *node;
+	struct l2cap_chan *c, *c1 = NULL;
 
-	read_lock(&l2cap_sk_list.lock);
+	read_lock(&chan_list_lock);
 
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	list_for_each_entry(c, &chan_list, global_l) {
+		struct sock *sk = c->sk;
 
 		if (state && sk->sk_state != state)
 			continue;
 
-		if (chan->scid == cid) {
+		if (c->scid == cid) {
 			/* Exact match. */
-			if (!bacmp(&bt_sk(sk)->src, src))
-				break;
+			if (!bacmp(&bt_sk(sk)->src, src)) {
+				read_unlock(&chan_list_lock);
+				return c;
+			}
 
 			/* Closest match */
 			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
-				sk1 = sk;
+				c1 = c;
 		}
 	}
 
-	read_unlock(&l2cap_sk_list.lock);
+	read_unlock(&chan_list_lock);
 
-	return node ? sk : sk1;
+	return c1;
 }
 
 static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 {
 	struct sock *parent, *sk;
-	struct l2cap_chan *chan;
+	struct l2cap_chan *chan, *pchan;
 
 	BT_DBG("");
 
 	/* Check if we have socket listening on cid */
-	parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
+	pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
 							conn->src);
-	if (!parent)
+	if (!pchan)
 		return;
 
+	parent = pchan->sk;
+
 	bh_lock_sock(parent);
 
 	/* Check for backlog size */
@@ -705,7 +713,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 	if (!sk)
 		goto clean;
 
-	chan = l2cap_chan_alloc(sk);
+	chan = l2cap_chan_create(sk);
 	if (!chan) {
 		l2cap_sock_kill(sk);
 		goto clean;
@@ -883,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch
 /* Find socket with psm and source bdaddr.
  * Returns closest match.
  */
-static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
+static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src)
 {
-	struct sock *sk = NULL, *sk1 = NULL;
-	struct hlist_node *node;
+	struct l2cap_chan *c, *c1 = NULL;
 
-	read_lock(&l2cap_sk_list.lock);
+	read_lock(&chan_list_lock);
 
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	list_for_each_entry(c, &chan_list, global_l) {
+		struct sock *sk = c->sk;
 
 		if (state && sk->sk_state != state)
 			continue;
 
-		if (chan->psm == psm) {
+		if (c->psm == psm) {
 			/* Exact match. */
-			if (!bacmp(&bt_sk(sk)->src, src))
-				break;
+			if (!bacmp(&bt_sk(sk)->src, src)) {
+				read_unlock_bh(&chan_list_lock);
+				return c;
+			}
 
 			/* Closest match */
 			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
-				sk1 = sk;
+				c1 = c;
 		}
 	}
 
-	read_unlock(&l2cap_sk_list.lock);
+	read_unlock(&chan_list_lock);
 
-	return node ? sk : sk1;
+	return c1;
 }
 
 int l2cap_chan_connect(struct l2cap_chan *chan)
@@ -2079,22 +2088,26 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 {
 	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
 	struct l2cap_conn_rsp rsp;
-	struct l2cap_chan *chan = NULL;
+	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);
 	__le16 psm = req->psm;
 
-	BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
+	BT_ERR("psm 0x%2.2x scid 0x%4.4x", psm, scid);
 
 	/* Check if we have socket listening on psm */
-	parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
-	if (!parent) {
+	pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src);
+	if (!pchan) {
 		result = L2CAP_CR_BAD_PSM;
 		goto sendresp;
 	}
 
+	BT_ERR("%p 0x%2.2x", pchan, pchan->psm);
+
+	parent = pchan->sk;
+
 	bh_lock_sock(parent);
 
 	/* Check if the ACL is secure enough (if not SDP) */
@@ -2117,7 +2130,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 	if (!sk)
 		goto response;
 
-	chan = l2cap_chan_alloc(sk);
+	chan = l2cap_chan_create(sk);
 	if (!chan) {
 		l2cap_sock_kill(sk);
 		goto response;
@@ -3745,11 +3758,14 @@ done:
 static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
 {
 	struct sock *sk;
+	struct l2cap_chan *chan;
 
-	sk = l2cap_get_sock_by_psm(0, psm, conn->src);
-	if (!sk)
+	chan = l2cap_global_chan_by_psm(0, psm, conn->src);
+	if (!chan)
 		goto drop;
 
+	sk = chan->sk;
+
 	bh_lock_sock(sk);
 
 	BT_DBG("sk %p, len %d", sk, skb->len);
@@ -3775,11 +3791,14 @@ done:
 static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb)
 {
 	struct sock *sk;
+	struct l2cap_chan *chan;
 
-	sk = l2cap_get_sock_by_scid(0, cid, conn->src);
-	if (!sk)
+	chan = l2cap_global_chan_by_scid(0, cid, conn->src);
+	if (!chan)
 		goto drop;
 
+	sk = chan->sk;
+
 	bh_lock_sock(sk);
 
 	BT_DBG("sk %p, len %d", sk, skb->len);
@@ -3846,8 +3865,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 {
 	int exact = 0, lm1 = 0, lm2 = 0;
-	register struct sock *sk;
-	struct hlist_node *node;
+	struct l2cap_chan *c;
 
 	if (type != ACL_LINK)
 		return -EINVAL;
@@ -3855,25 +3873,25 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
 	/* Find listening sockets and check their link_mode */
-	read_lock(&l2cap_sk_list.lock);
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+	read_lock(&chan_list_lock);
+	list_for_each_entry(c, &chan_list, global_l) {
+		struct sock *sk = c->sk;
 
 		if (sk->sk_state != BT_LISTEN)
 			continue;
 
 		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
 			lm1 |= HCI_LM_ACCEPT;
-			if (chan->role_switch)
+			if (c->role_switch)
 				lm1 |= HCI_LM_MASTER;
 			exact++;
 		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
 			lm2 |= HCI_LM_ACCEPT;
-			if (chan->role_switch)
+			if (c->role_switch)
 				lm2 |= HCI_LM_MASTER;
 		}
 	}
-	read_unlock(&l2cap_sk_list.lock);
+	read_unlock(&chan_list_lock);
 
 	return exact ? lm1 : lm2;
 }
@@ -4126,25 +4144,22 @@ drop:
 
 static int l2cap_debugfs_show(struct seq_file *f, void *p)
 {
-	struct sock *sk;
-	struct hlist_node *node;
+	struct l2cap_chan *c;
 
-	read_lock_bh(&l2cap_sk_list.lock);
+	read_lock_bh(&chan_list_lock);
 
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_pinfo *pi = l2cap_pi(sk);
-		struct l2cap_chan *chan = pi->chan;
+	list_for_each_entry(c, &chan_list, global_l) {
+		struct sock *sk = c->sk;
 
 		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
 					batostr(&bt_sk(sk)->src),
 					batostr(&bt_sk(sk)->dst),
-					sk->sk_state, __le16_to_cpu(chan->psm),
-					chan->scid, chan->dcid,
-					chan->imtu, chan->omtu, chan->sec_level,
-					chan->mode);
+					sk->sk_state, __le16_to_cpu(c->psm),
+					c->scid, c->dcid, c->imtu, c->omtu,
+					c->sec_level, c->mode);
 	}
 
-	read_unlock_bh(&l2cap_sk_list.lock);
+	read_unlock_bh(&chan_list_lock);
 
 	return 0;
 }
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index aca99cd..3a78e46 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -808,8 +808,7 @@ void l2cap_sock_kill(struct sock *sk)
 
 	/* Kill poor orphan */
 
-	l2cap_chan_free(l2cap_pi(sk)->chan);
-	bt_sock_unlink(&l2cap_sk_list, sk);
+	l2cap_chan_destruct(l2cap_pi(sk)->chan);
 	sock_set_flag(sk, SOCK_DEAD);
 	sock_put(sk);
 }
@@ -1025,7 +1024,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g
 
 	setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
 
-	bt_sock_link(&l2cap_sk_list, sk);
 	return sk;
 }
 
@@ -1052,7 +1050,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 	if (!sk)
 		return -ENOMEM;
 
-	chan = l2cap_chan_alloc(sk);
+	chan = l2cap_chan_create(sk);
 	if (!chan) {
 		l2cap_sock_kill(sk);
 		return -ENOMEM;
-- 
1.7.5.rc1


^ 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