]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/bluetooth/hci_event.c
Bluetooth: mgmt: Fix updating EIR when updating the name
[karo-tx-linux.git] / net / bluetooth / hci_event.c
index f6c13153a5e7b34ce1baa0224ccb0b9ecddfcf0c..e44e3fd68628faa16a8743d35e1d874f1e588fa1 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/interrupt.h>
-#include <linux/notifier.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -45,8 +44,6 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-static bool enable_le;
-
 /* Handle HCI Event packets */
 
 static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
@@ -195,8 +192,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 
        hci_req_complete(hdev, HCI_OP_RESET, status);
 
-       /* Reset all flags, except persistent ones */
-       hdev->dev_flags &= BIT(HCI_MGMT) | BIT(HCI_SETUP) | BIT(HCI_AUTO_OFF);
+       /* Reset all non-persistent flags */
+       hdev->dev_flags &= ~(BIT(HCI_LE_SCAN));
 }
 
 static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -212,12 +209,12 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
 
        hci_dev_lock(hdev);
 
-       if (test_bit(HCI_MGMT, &hdev->dev_flags))
-               mgmt_set_local_name_complete(hdev, sent, status);
-
        if (status == 0)
                memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
 
+       if (test_bit(HCI_MGMT, &hdev->dev_flags))
+               mgmt_set_local_name_complete(hdev, sent, status);
+
        hci_dev_unlock(hdev);
 }
 
@@ -253,6 +250,9 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
                        clear_bit(HCI_AUTH, &hdev->flags);
        }
 
+       if (test_bit(HCI_MGMT, &hdev->dev_flags))
+               mgmt_auth_enable_complete(hdev, status);
+
        hci_req_complete(hdev, HCI_OP_WRITE_AUTH_ENABLE, status);
 }
 
@@ -420,18 +420,6 @@ static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
        hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
 }
 
-static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
-{
-       struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
-
-       BT_DBG("%s status 0x%x", hdev->name, rp->status);
-
-       if (rp->status)
-               return;
-
-       hdev->ssp_mode = rp->mode;
-}
-
 static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -439,14 +427,18 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 
        BT_DBG("%s status 0x%x", hdev->name, status);
 
-       if (status)
-               return;
-
        sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
        if (!sent)
                return;
 
-       hdev->ssp_mode = *((__u8 *) sent);
+       if (test_bit(HCI_MGMT, &hdev->dev_flags))
+               mgmt_ssp_enable_complete(hdev, *((u8 *) sent), status);
+       else if (!status) {
+               if (*((u8 *) sent))
+                       set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
+               else
+                       clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
+       }
 }
 
 static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
@@ -547,7 +539,7 @@ static void hci_set_le_support(struct hci_dev *hdev)
 
        memset(&cp, 0, sizeof(cp));
 
-       if (enable_le) {
+       if (enable_le && test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
                cp.le = 1;
                cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
        }
@@ -566,8 +558,18 @@ static void hci_setup(struct hci_dev *hdev)
                hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
 
        if (hdev->features[6] & LMP_SIMPLE_PAIR) {
-               u8 mode = 0x01;
-               hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
+               if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+                       u8 mode = 0x01;
+                       hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE,
+                                                       sizeof(mode), &mode);
+               } else {
+                       struct hci_cp_write_eir cp;
+
+                       memset(hdev->eir, 0, sizeof(hdev->eir));
+                       memset(&cp, 0, sizeof(cp));
+
+                       hci_send_cmd(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
+               }
        }
 
        if (hdev->features[3] & LMP_RSSI_INQ)
@@ -584,6 +586,12 @@ static void hci_setup(struct hci_dev *hdev)
                                                        sizeof(cp), &cp);
        }
 
+       if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) {
+               u8 enable = 1;
+               hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE,
+                                               sizeof(enable), &enable);
+       }
+
        if (hdev->features[4] & LMP_LE)
                hci_set_le_support(hdev);
 }
@@ -953,8 +961,8 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
        hci_dev_lock(hdev);
 
        if (test_bit(HCI_MGMT, &hdev->dev_flags))
-               mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr,
-                                                               rp->status);
+               mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
+                                                               0, rp->status);
 
        hci_dev_unlock(hdev);
 }
@@ -970,6 +978,7 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
 
        if (test_bit(HCI_MGMT, &hdev->dev_flags))
                mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
+                                                               ACL_LINK, 0,
                                                                rp->status);
 
        hci_dev_unlock(hdev);
@@ -984,8 +993,8 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
        hci_dev_lock(hdev);
 
        if (test_bit(HCI_MGMT, &hdev->dev_flags))
-               mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
-                                                               rp->status);
+               mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
+                                                               0, rp->status);
 
        hci_dev_unlock(hdev);
 }
@@ -1001,6 +1010,7 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
 
        if (test_bit(HCI_MGMT, &hdev->dev_flags))
                mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
+                                                               ACL_LINK, 0,
                                                                rp->status);
 
        hci_dev_unlock(hdev);
@@ -1024,6 +1034,15 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb)
        __u8 status = *((__u8 *) skb->data);
 
        BT_DBG("%s status 0x%x", hdev->name, status);
+
+       hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_PARAM, status);
+
+       if (status) {
+               hci_dev_lock(hdev);
+               mgmt_start_discovery_failed(hdev, status);
+               hci_dev_unlock(hdev);
+               return;
+       }
 }
 
 static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
@@ -1034,28 +1053,47 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
 
        BT_DBG("%s status 0x%x", hdev->name, status);
 
-       if (status)
-               return;
-
        cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
        if (!cp)
                return;
 
        switch (cp->enable) {
        case LE_SCANNING_ENABLED:
+               hci_req_complete(hdev, HCI_OP_LE_SET_SCAN_ENABLE, status);
+
+               if (status) {
+                       hci_dev_lock(hdev);
+                       mgmt_start_discovery_failed(hdev, status);
+                       hci_dev_unlock(hdev);
+                       return;
+               }
+
                set_bit(HCI_LE_SCAN, &hdev->dev_flags);
 
                cancel_delayed_work_sync(&hdev->adv_work);
 
                hci_dev_lock(hdev);
                hci_adv_entries_clear(hdev);
+               hci_discovery_set_state(hdev, DISCOVERY_FINDING);
                hci_dev_unlock(hdev);
                break;
 
        case LE_SCANNING_DISABLED:
+               if (status)
+                       return;
+
                clear_bit(HCI_LE_SCAN, &hdev->dev_flags);
 
                schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT);
+
+               if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED) {
+                       mgmt_interleaved_discovery(hdev);
+               } else {
+                       hci_dev_lock(hdev);
+                       hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+                       hci_dev_unlock(hdev);
+               }
+
                break;
 
        default:
@@ -1092,10 +1130,15 @@ static inline void hci_cc_write_le_host_supported(struct hci_dev *hdev,
                                                        struct sk_buff *skb)
 {
        struct hci_cp_read_local_ext_features cp;
+       struct hci_cp_write_le_host_supported *sent;
        __u8 status = *((__u8 *) skb->data);
 
        BT_DBG("%s status 0x%x", hdev->name, status);
 
+       sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
+       if (sent && test_bit(HCI_MGMT, &hdev->dev_flags))
+               mgmt_le_enable_complete(hdev, sent->le, status);
+
        if (status)
                return;
 
@@ -1120,7 +1163,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
        set_bit(HCI_INQUIRY, &hdev->flags);
 
        hci_dev_lock(hdev);
-       hci_discovery_set_state(hdev, DISCOVERY_INQUIRY);
+       hci_discovery_set_state(hdev, DISCOVERY_FINDING);
        hci_dev_unlock(hdev);
 }
 
@@ -1264,7 +1307,7 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
 
        /* Only request authentication for SSP connections or non-SSP
         * devices with sec_level HIGH or if MITM protection is requested */
-       if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
+       if (!hci_conn_ssp_enabled(conn) &&
                                conn->pending_sec_level != BT_SECURITY_HIGH &&
                                !(conn->auth_type & 0x01))
                return 0;
@@ -1286,11 +1329,36 @@ static inline int hci_resolve_name(struct hci_dev *hdev, struct inquiry_entry *e
        return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
 }
 
-static void hci_resolve_next_name(struct hci_dev *hdev, bdaddr_t *bdaddr)
+static bool hci_resolve_next_name(struct hci_dev *hdev)
+{
+       struct discovery_state *discov = &hdev->discovery;
+       struct inquiry_entry *e;
+
+       if (list_empty(&discov->resolve))
+               return false;
+
+       e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
+       if (hci_resolve_name(hdev, e) == 0) {
+               e->name_state = NAME_PENDING;
+               return true;
+       }
+
+       return false;
+}
+
+static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
+                                       bdaddr_t *bdaddr, u8 *name, u8 name_len)
 {
        struct discovery_state *discov = &hdev->discovery;
        struct inquiry_entry *e;
 
+       if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+               mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00,
+                                       name, name_len, conn->dev_class);
+
+       if (discov->state == DISCOVERY_STOPPED)
+               return;
+
        if (discov->state == DISCOVERY_STOPPING)
                goto discov_complete;
 
@@ -1301,16 +1369,13 @@ static void hci_resolve_next_name(struct hci_dev *hdev, bdaddr_t *bdaddr)
        if (e) {
                e->name_state = NAME_KNOWN;
                list_del(&e->list);
+               if (name)
+                       mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00,
+                                       e->data.rssi, name, name_len);
        }
 
-       if (list_empty(&discov->resolve))
-               goto discov_complete;
-
-       e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
-       if (hci_resolve_name(hdev, e) == 0) {
-               e->name_state = NAME_PENDING;
+       if (hci_resolve_next_name(hdev))
                return;
-       }
 
 discov_complete:
        hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
@@ -1334,10 +1399,11 @@ 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 (test_bit(HCI_MGMT, &hdev->dev_flags))
-               hci_resolve_next_name(hdev, &cp->bdaddr);
+               hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
 
-       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
        if (!conn)
                goto unlock;
 
@@ -1497,6 +1563,28 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
        hci_dev_unlock(hdev);
 }
 
+static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
+{
+       struct hci_cp_disconnect *cp;
+       struct hci_conn *conn;
+
+       if (!status)
+               return;
+
+       cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
+       if (!cp)
+               return;
+
+       hci_dev_lock(hdev);
+
+       conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
+       if (conn)
+               mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
+                                               conn->dst_type, status);
+
+       hci_dev_unlock(hdev);
+}
+
 static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
 {
        struct hci_cp_le_create_conn *cp;
@@ -1561,7 +1649,7 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff
 
        hci_dev_lock(hdev);
 
-       if (discov->state != DISCOVERY_INQUIRY)
+       if (discov->state != DISCOVERY_FINDING)
                goto unlock;
 
        if (list_empty(&discov->resolve)) {
@@ -1643,8 +1731,6 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
                        conn->state = BT_CONFIG;
                        hci_conn_hold(conn);
                        conn->disc_timeout = HCI_DISCONN_TIMEOUT;
-                       mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
-                                                       conn->dst_type);
                } else
                        conn->state = BT_CONNECTED;
 
@@ -1785,9 +1871,11 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
        if (ev->status == 0)
                conn->state = BT_CLOSED;
 
-       if (conn->type == ACL_LINK || conn->type == LE_LINK) {
+       if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) &&
+                       (conn->type == ACL_LINK || conn->type == LE_LINK)) {
                if (ev->status != 0)
-                       mgmt_disconnect_failed(hdev, &conn->dst, ev->status);
+                       mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
+                                               conn->dst_type, ev->status);
                else
                        mgmt_device_disconnected(hdev, &conn->dst, conn->type,
                                                        conn->dst_type);
@@ -1816,22 +1904,23 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
                goto unlock;
 
        if (!ev->status) {
-               if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
-                               test_bit(HCI_CONN_REAUTH_PEND,  &conn->flags)) {
+               if (!hci_conn_ssp_enabled(conn) &&
+                               test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
                        BT_INFO("re-auth of legacy device is not possible.");
                } else {
                        conn->link_mode |= HCI_LM_AUTH;
                        conn->sec_level = conn->pending_sec_level;
                }
        } else {
-               mgmt_auth_failed(hdev, &conn->dst, ev->status);
+               mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
+                                                               ev->status);
        }
 
        clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
        clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
 
        if (conn->state == BT_CONFIG) {
-               if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
+               if (!ev->status && hci_conn_ssp_enabled(conn)) {
                        struct hci_cp_set_conn_encrypt cp;
                        cp.handle  = ev->handle;
                        cp.encrypt = 0x01;
@@ -1878,14 +1967,18 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
 
        hci_dev_lock(hdev);
 
-       if (test_bit(HCI_MGMT, &hdev->dev_flags)) {
-               if (ev->status == 0)
-                       mgmt_remote_name(hdev, &ev->bdaddr, ev->name);
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 
-               hci_resolve_next_name(hdev, &ev->bdaddr);
-       }
+       if (!test_bit(HCI_MGMT, &hdev->dev_flags))
+               goto check_auth;
 
-       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+       if (ev->status == 0)
+               hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
+                                       strnlen(ev->name, HCI_MAX_NAME_LENGTH));
+       else
+               hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
+
+check_auth:
        if (!conn)
                goto unlock;
 
@@ -1994,7 +2087,10 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
                bacpy(&cp.bdaddr, &conn->dst);
                cp.pscan_rep_mode = 0x02;
                hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
-       }
+       } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+               mgmt_device_connected(hdev, &conn->dst, conn->type,
+                                               conn->dst_type, NULL, 0,
+                                               conn->dev_class);
 
        if (!hci_outgoing_auth_needed(hdev, conn)) {
                conn->state = BT_CONNECTED;
@@ -2102,10 +2198,6 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
                hci_cc_host_buffer_size(hdev, skb);
                break;
 
-       case HCI_OP_READ_SSP_MODE:
-               hci_cc_read_ssp_mode(hdev, skb);
-               break;
-
        case HCI_OP_WRITE_SSP_MODE:
                hci_cc_write_ssp_mode(hdev, skb);
                break;
@@ -2291,8 +2383,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
                break;
 
        case HCI_OP_DISCONNECT:
-               if (ev->status != 0)
-                       mgmt_disconnect_failed(hdev, NULL, ev->status);
+               hci_cs_disconnect(hdev, ev->status);
                break;
 
        case HCI_OP_LE_CREATE_CONN:
@@ -2476,9 +2567,9 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
 
                if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
                        if (conn->mode == HCI_CM_ACTIVE)
-                               conn->power_save = 1;
+                               set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
                        else
-                               conn->power_save = 0;
+                               clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
                }
 
                if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
@@ -2751,7 +2842,8 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
                if (ie)
                        ie->data.ssp_mode = (ev->features[0] & 0x01);
 
-               conn->ssp_mode = (ev->features[0] & 0x01);
+               if (ev->features[0] & 0x01)
+                       set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
        }
 
        if (conn->state != BT_CONFIG)
@@ -2763,7 +2855,10 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
                bacpy(&cp.bdaddr, &conn->dst);
                cp.pscan_rep_mode = 0x02;
                hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
-       }
+       } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+               mgmt_device_connected(hdev, &conn->dst, conn->type,
+                                               conn->dst_type, NULL, 0,
+                                               conn->dev_class);
 
        if (!hci_outgoing_auth_needed(hdev, conn)) {
                conn->state = BT_CONNECTED;
@@ -2926,11 +3021,14 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
                struct hci_cp_io_capability_reply cp;
 
                bacpy(&cp.bdaddr, &ev->bdaddr);
-               cp.capability = conn->io_capability;
+               /* Change the IO capability from KeyboardDisplay
+                * to DisplayYesNo as it is not supported by BT spec. */
+               cp.capability = (conn->io_capability == 0x04) ?
+                                               0x01 : conn->io_capability;
                conn->auth_type = hci_get_auth_req(conn);
                cp.authentication = conn->auth_type;
 
-               if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
+               if ((conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) &&
                                hci_find_remote_oob_data(hdev, &conn->dst))
                        cp.oob_data = 0x01;
                else
@@ -2966,8 +3064,9 @@ static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *s
                goto unlock;
 
        conn->remote_cap = ev->capability;
-       conn->remote_oob = ev->oob_data;
        conn->remote_auth = ev->authentication;
+       if (ev->oob_data)
+               set_bit(HCI_CONN_REMOTE_OOB, &conn->flags);
 
 unlock:
        hci_dev_unlock(hdev);
@@ -3034,7 +3133,7 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
        }
 
 confirm:
-       mgmt_user_confirm_request(hdev, &ev->bdaddr, ev->passkey,
+       mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey,
                                                                confirm_hint);
 
 unlock:
@@ -3051,7 +3150,7 @@ static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
        hci_dev_lock(hdev);
 
        if (test_bit(HCI_MGMT, &hdev->dev_flags))
-               mgmt_user_passkey_request(hdev, &ev->bdaddr);
+               mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
 
        hci_dev_unlock(hdev);
 }
@@ -3075,7 +3174,8 @@ static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_
         * event gets always produced as initiator and is also mapped to
         * the mgmt_auth_failed event */
        if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0)
-               mgmt_auth_failed(hdev, &conn->dst, ev->status);
+               mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
+                                                               ev->status);
 
        hci_conn_put(conn);
 
@@ -3164,7 +3264,9 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
                goto unlock;
        }
 
-       mgmt_device_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type);
+       if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+               mgmt_device_connected(hdev, &ev->bdaddr, conn->type,
+                                               conn->dst_type, NULL, 0, 0);
 
        conn->sec_level = BT_SECURITY_LOW;
        conn->handle = __le16_to_cpu(ev->handle);
@@ -3210,7 +3312,7 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
        struct hci_cp_le_ltk_reply cp;
        struct hci_cp_le_ltk_neg_reply neg;
        struct hci_conn *conn;
-       struct link_key *ltk;
+       struct smp_ltk *ltk;
 
        BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
 
@@ -3226,10 +3328,17 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
 
        memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
        cp.handle = cpu_to_le16(conn->handle);
-       conn->pin_length = ltk->pin_len;
+
+       if (ltk->authenticated)
+               conn->sec_level = BT_SECURITY_HIGH;
 
        hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
 
+       if (ltk->type & HCI_SMP_STK) {
+               list_del(&ltk->list);
+               kfree(ltk);
+       }
+
        hci_dev_unlock(hdev);
 
        return;
@@ -3432,34 +3541,3 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
        kfree_skb(skb);
        hdev->stat.evt_rx++;
 }
-
-/* Generate internal stack event */
-void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
-{
-       struct hci_event_hdr *hdr;
-       struct hci_ev_stack_internal *ev;
-       struct sk_buff *skb;
-
-       skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);
-       if (!skb)
-               return;
-
-       hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);
-       hdr->evt  = HCI_EV_STACK_INTERNAL;
-       hdr->plen = sizeof(*ev) + dlen;
-
-       ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);
-       ev->type = type;
-       memcpy(ev->data, data, dlen);
-
-       bt_cb(skb)->incoming = 1;
-       __net_timestamp(skb);
-
-       bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
-       skb->dev = (void *) hdev;
-       hci_send_to_sock(hdev, skb, NULL);
-       kfree_skb(skb);
-}
-
-module_param(enable_le, bool, 0644);
-MODULE_PARM_DESC(enable_le, "Enable LE support");