Bluetooth: Add LE/BR flag to Connect notification
When remote device is connected outside the control of BlueZ, it
needs to be informed of whether the new connection is LE or BR/EDR.
Signed-off-by: Brian Gix <bgix@codeaurora.org>
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 7ee9ff0..079538b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -630,8 +630,10 @@
struct adv_entry *entry;
le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
- if (le)
+ if (le) {
+ hci_conn_hold(le);
return le;
+ }
entry = hci_find_adv_entry(hdev, dst);
if (!entry)
@@ -783,11 +785,19 @@
(!conn->ssp_mode || !conn->hdev->ssp_mode))
return 1;
- if (conn->link_mode & HCI_LM_ENCRYPT)
- return hci_conn_auth(conn, sec_level, auth_type);
+ if (conn->type == LE_LINK) {
+ if (conn->pending_sec_level > sec_level)
+ sec_level = conn->pending_sec_level;
- if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+ if (sec_level > conn->sec_level)
+ conn->pending_sec_level = sec_level;
+ hci_proto_connect_cfm(conn, 0);
return 0;
+ } else if (conn->link_mode & HCI_LM_ENCRYPT) {
+ return hci_conn_auth(conn, sec_level, auth_type);
+ } else if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+ return 0;
+ }
if (hci_conn_auth(conn, sec_level, auth_type)) {
struct hci_cp_set_conn_encrypt cp;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 2891209..1e59cb3 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1572,11 +1572,11 @@
conn->state = BT_CONFIG;
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
- mgmt_connected(hdev->id, &ev->bdaddr);
+ mgmt_connected(hdev->id, &ev->bdaddr, 0);
} else if (conn->type == LE_LINK) {
conn->state = BT_CONNECTED;
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
- mgmt_connected(hdev->id, &ev->bdaddr);
+ mgmt_connected(hdev->id, &ev->bdaddr, 1);
} else
conn->state = BT_CONNECTED;
@@ -3030,7 +3030,7 @@
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
- mgmt_connected(hdev->id, &ev->bdaddr);
+ mgmt_connected(hdev->id, &ev->bdaddr, 1);
hci_conn_hold(conn);
hci_conn_hold_device(conn);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index ea81593..3bb58f9 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1004,8 +1004,13 @@
bh_lock_sock(sk);
if (conn->hcon->type == LE_LINK) {
- if (smp_conn_security(conn,
- l2cap_pi(sk)->sec_level))
+ u8 sec_level = l2cap_pi(sk)->sec_level;
+ u8 pending_sec = conn->hcon->pending_sec_level;
+
+ if (pending_sec > sec_level)
+ sec_level = pending_sec;
+
+ if (smp_conn_security(conn, sec_level))
l2cap_chan_ready(sk);
} else if (sk->sk_type != SOCK_SEQPACKET &&
@@ -1212,15 +1217,12 @@
conn = hcon->l2cap_data;
} else {
- if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA) {
+ if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
hcon = hci_connect(hdev, LE_LINK, 0, dst,
l2cap_pi(sk)->sec_level, auth_type);
- if (hcon->state == BT_CONNECTED)
- hci_conn_hold(hcon);
- } else {
+ else
hcon = hci_connect(hdev, ACL_LINK, 0, dst,
l2cap_pi(sk)->sec_level, auth_type);
- }
if (IS_ERR(hcon)) {
err = PTR_ERR(hcon);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4343184..79e0891 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2286,11 +2286,12 @@
return err;
}
-int mgmt_connected(u16 index, bdaddr_t *bdaddr)
+int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le)
{
struct mgmt_ev_connected ev;
bacpy(&ev.bdaddr, bdaddr);
+ ev.le = le;
return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
}