Bluetooth: Remove page timeout setting from HCI init sequence
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / bluetooth / hci_event.c
index 38100170d380a1f794c1ea75b7723f36312a7212..49b387cdcc3835bfe06da1583ec60ab295b809fa 100644 (file)
@@ -274,15 +274,24 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
        if (!status) {
                __u8 param = *((__u8 *) sent);
+               int old_pscan, old_iscan;
 
-               clear_bit(HCI_PSCAN, &hdev->flags);
-               clear_bit(HCI_ISCAN, &hdev->flags);
+               old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
+               old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
 
-               if (param & SCAN_INQUIRY)
+               if (param & SCAN_INQUIRY) {
                        set_bit(HCI_ISCAN, &hdev->flags);
+                       if (!old_iscan)
+                               mgmt_discoverable(hdev->id, 1);
+               } else if (old_iscan)
+                       mgmt_discoverable(hdev->id, 0);
 
-               if (param & SCAN_PAGE)
+               if (param & SCAN_PAGE) {
                        set_bit(HCI_PSCAN, &hdev->flags);
+                       if (!old_pscan)
+                               mgmt_connectable(hdev->id, 1);
+               } else if (old_pscan)
+                       mgmt_connectable(hdev->id, 0);
        }
 
        hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
@@ -548,6 +557,16 @@ static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
        hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, status);
 }
 
+static void hci_cc_delete_stored_link_key(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_DELETE_STORED_LINK_KEY, status);
+}
+
 static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
        BT_DBG("%s status 0x%x", hdev->name, status);
@@ -692,13 +711,13 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
        if (conn->state != BT_CONFIG || !conn->out)
                return 0;
 
-       if (conn->sec_level == BT_SECURITY_SDP)
+       if (conn->pending_sec_level == BT_SECURITY_SDP)
                return 0;
 
        /* Only request authentication for SSP connections or non-SSP
         * devices with sec_level HIGH */
        if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
-                                       conn->sec_level != BT_SECURITY_HIGH)
+                               conn->pending_sec_level != BT_SECURITY_HIGH)
                return 0;
 
        return 1;
@@ -1095,9 +1114,10 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 
        conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
        if (conn) {
-               if (!ev->status)
+               if (!ev->status) {
                        conn->link_mode |= HCI_LM_AUTH;
-               else
+                       conn->sec_level = conn->pending_sec_level;
+               } else
                        conn->sec_level = BT_SECURITY_LOW;
 
                clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
@@ -1392,6 +1412,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
                hci_cc_write_ca_timeout(hdev, skb);
                break;
 
+       case HCI_OP_DELETE_STORED_LINK_KEY:
+               hci_cc_delete_stored_link_key(hdev, skb);
+               break;
+
        default:
                BT_DBG("%s opcode 0x%x", hdev->name, opcode);
                break;
@@ -1585,6 +1609,10 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
                hci_conn_put(conn);
        }
 
+       if (!test_bit(HCI_PAIRABLE, &hdev->flags))
+               hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
+                                       sizeof(ev->bdaddr), &ev->bdaddr);
+
        hci_dev_unlock(hdev);
 }
 
@@ -1875,9 +1903,52 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
        hci_dev_lock(hdev);
 
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-       if (conn)
-               hci_conn_hold(conn);
+       if (!conn)
+               goto unlock;
+
+       hci_conn_hold(conn);
+
+       if (!test_bit(HCI_MGMT, &hdev->flags))
+               goto unlock;
+
+       if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
+                       (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
+               /* FIXME: Do IO capa response based on information
+                * provided through the management interface */
+       } else {
+               struct hci_cp_io_capability_neg_reply cp;
+
+               bacpy(&cp.bdaddr, &ev->bdaddr);
+               cp.reason = 0x16; /* Pairing not allowed */
+
+               hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
+                                                       sizeof(cp), &cp);
+       }
+
+unlock:
+       hci_dev_unlock(hdev);
+}
+
+static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct hci_ev_io_capa_reply *ev = (void *) skb->data;
+       struct hci_conn *conn;
+
+       BT_DBG("%s", hdev->name);
+
+       hci_dev_lock(hdev);
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+       if (!conn)
+               goto unlock;
+
+       hci_conn_hold(conn);
+
+       conn->remote_cap = ev->capability;
+       conn->remote_oob = ev->oob_data;
+       conn->remote_auth = ev->authentication;
 
+unlock:
        hci_dev_unlock(hdev);
 }
 
@@ -2041,6 +2112,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
                hci_io_capa_request_evt(hdev, skb);
                break;
 
+       case HCI_EV_IO_CAPA_REPLY:
+               hci_io_capa_reply_evt(hdev, skb);
+               break;
+
        case HCI_EV_SIMPLE_PAIR_COMPLETE:
                hci_simple_pair_complete_evt(hdev, skb);
                break;
@@ -2082,6 +2157,6 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
 
        bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
        skb->dev = (void *) hdev;
-       hci_send_to_sock(hdev, skb);
+       hci_send_to_sock(hdev, skb, NULL);
        kfree_skb(skb);
 }