summaryrefslogtreecommitdiff
path: root/net/bluetooth
diff options
context:
space:
mode:
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-05-16 16:11:44 -0300
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2012-05-16 16:11:44 -0300
commit08e6d907fe606b751adddce54ad8f51e0950bc3f (patch)
tree1a987f519b1ea706a61cd23d7eeea038dfe81b7a /net/bluetooth
parentd34c34fb2592bd5231a153ad1676c3ded175410a (diff)
parent671267bf3aac3dae0555730b07ef29c042e325b2 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/af_bluetooth.c2
-rw-r--r--net/bluetooth/hci_core.c8
-rw-r--r--net/bluetooth/hci_event.c11
-rw-r--r--net/bluetooth/l2cap_core.c5
-rw-r--r--net/bluetooth/l2cap_sock.c12
5 files changed, 31 insertions, 7 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 72eb187a5f60..6fb68a9743af 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -450,7 +450,7 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wa
sk->sk_state == BT_CONFIG)
return mask;
- if (sock_writeable(sk))
+ if (!bt_sk(sk)->suspended && sock_writeable(sk))
mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
else
set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 83d3d3563bcc..a8962382f9c5 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2715,6 +2715,14 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
if (conn) {
hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
+ hci_dev_lock(hdev);
+ if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
+ !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+ mgmt_device_connected(hdev, &conn->dst, conn->type,
+ conn->dst_type, 0, NULL, 0,
+ conn->dev_class);
+ hci_dev_unlock(hdev);
+
/* Send to upper protocol */
l2cap_recv_acldata(conn, skb, flags);
return;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d81262aff263..4edbfd929f6e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2062,6 +2062,12 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
+ if (ev->status && conn->state == BT_CONNECTED) {
+ hci_acl_disconn(conn, 0x13);
+ hci_conn_put(conn);
+ goto unlock;
+ }
+
if (conn->state == BT_CONFIG) {
if (!ev->status)
conn->state = BT_CONNECTED;
@@ -2072,6 +2078,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
}
+unlock:
hci_dev_unlock(hdev);
}
@@ -2125,7 +2132,7 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
goto unlock;
}
- if (!ev->status) {
+ if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
struct hci_cp_remote_name_req cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
@@ -2901,7 +2908,7 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
if (conn->state != BT_CONFIG)
goto unlock;
- if (!ev->status) {
+ if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
struct hci_cp_remote_name_req cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7adfcecf7a5e..3714c9656459 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4916,6 +4916,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (!status && (chan->state == BT_CONNECTED ||
chan->state == BT_CONFIG)) {
+ struct sock *sk = chan->sk;
+
+ bt_sk(sk)->suspended = false;
+ sk->sk_state_change(sk);
+
l2cap_check_encryption(chan, encrypt);
l2cap_chan_unlock(chan);
continue;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 6bf8ff75d95f..b7bc7b981ee2 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -596,10 +596,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
sk->sk_state = BT_CONFIG;
chan->state = BT_CONFIG;
- /* or for ACL link, under defer_setup time */
- } else if (sk->sk_state == BT_CONNECT2 &&
- bt_sk(sk)->defer_setup) {
- err = l2cap_chan_check_security(chan);
+ /* or for ACL link */
+ } else if ((sk->sk_state == BT_CONNECT2 &&
+ bt_sk(sk)->defer_setup) ||
+ sk->sk_state == BT_CONNECTED) {
+ if (!l2cap_chan_check_security(chan))
+ bt_sk(sk)->suspended = true;
+ else
+ sk->sk_state_change(sk);
} else {
err = -EINVAL;
}