Bluetooth: Add 'Already Paired' error for Pair Device command
[cascardo/linux.git] / net / bluetooth / hci_core.c
index 3322d3f..a35d844 100644 (file)
@@ -51,7 +51,7 @@ DEFINE_RWLOCK(hci_dev_list_lock);
 
 /* HCI callback list */
 LIST_HEAD(hci_cb_list);
-DEFINE_RWLOCK(hci_cb_list_lock);
+DEFINE_MUTEX(hci_cb_list_lock);
 
 /* HCI ID Numbering */
 static DEFINE_IDA(hci_index_ida);
@@ -390,7 +390,7 @@ static void bredr_init(struct hci_request *req)
        hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL);
 }
 
-static void amp_init(struct hci_request *req)
+static void amp_init1(struct hci_request *req)
 {
        req->hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
 
@@ -400,9 +400,6 @@ static void amp_init(struct hci_request *req)
        /* Read Local Supported Commands */
        hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
 
-       /* Read Local Supported Features */
-       hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
-
        /* Read Local AMP Info */
        hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
 
@@ -416,6 +413,16 @@ static void amp_init(struct hci_request *req)
        hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL);
 }
 
+static void amp_init2(struct hci_request *req)
+{
+       /* Read Local Supported Features. Not all AMP controllers
+        * support this so it's placed conditionally in the second
+        * stage init.
+        */
+       if (req->hdev->commands[14] & 0x20)
+               hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
+}
+
 static void hci_init1_req(struct hci_request *req, unsigned long opt)
 {
        struct hci_dev *hdev = req->hdev;
@@ -432,7 +439,7 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt)
                break;
 
        case HCI_AMP:
-               amp_init(req);
+               amp_init1(req);
                break;
 
        default:
@@ -578,6 +585,9 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
 {
        struct hci_dev *hdev = req->hdev;
 
+       if (hdev->dev_type == HCI_AMP)
+               return amp_init2(req);
+
        if (lmp_bredr_capable(hdev))
                bredr_setup(req);
        else
@@ -896,17 +906,17 @@ static int __hci_init(struct hci_dev *hdev)
                                    &dut_mode_fops);
        }
 
+       err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT);
+       if (err < 0)
+               return err;
+
        /* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode
         * BR/EDR/LE type controllers. AMP controllers only need the
-        * first stage init.
+        * first two stages of init.
         */
        if (hdev->dev_type != HCI_BREDR)
                return 0;
 
-       err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT);
-       if (err < 0)
-               return err;
-
        err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT);
        if (err < 0)
                return err;
@@ -1591,6 +1601,12 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 {
        BT_DBG("%s %p", hdev->name, hdev);
 
+       if (!test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
+               /* Execute vendor specific shutdown routine */
+               if (hdev->shutdown)
+                       hdev->shutdown(hdev);
+       }
+
        cancel_delayed_work(&hdev->power_off);
 
        hci_req_cancel(hdev, ENODEV);
@@ -2500,6 +2516,33 @@ void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
        }
 }
 
+bool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
+{
+       struct smp_ltk *k;
+       u8 addr_type;
+
+       if (type == BDADDR_BREDR) {
+               if (hci_find_link_key(hdev, bdaddr))
+                       return true;
+               return false;
+       }
+
+       /* Convert to HCI addr type which struct smp_ltk uses */
+       if (type == BDADDR_LE_PUBLIC)
+               addr_type = ADDR_LE_DEV_PUBLIC;
+       else
+               addr_type = ADDR_LE_DEV_RANDOM;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
+               if (k->bdaddr_type == addr_type && !bacmp(bdaddr, &k->bdaddr))
+                       return true;
+       }
+       rcu_read_unlock();
+
+       return false;
+}
+
 /* HCI command timer function */
 static void hci_cmd_timeout(struct work_struct *work)
 {
@@ -3448,9 +3491,9 @@ int hci_register_cb(struct hci_cb *cb)
 {
        BT_DBG("%p name %s", cb, cb->name);
 
-       write_lock(&hci_cb_list_lock);
-       list_add(&cb->list, &hci_cb_list);
-       write_unlock(&hci_cb_list_lock);
+       mutex_lock(&hci_cb_list_lock);
+       list_add_tail(&cb->list, &hci_cb_list);
+       mutex_unlock(&hci_cb_list_lock);
 
        return 0;
 }
@@ -3460,9 +3503,9 @@ int hci_unregister_cb(struct hci_cb *cb)
 {
        BT_DBG("%p name %s", cb, cb->name);
 
-       write_lock(&hci_cb_list_lock);
+       mutex_lock(&hci_cb_list_lock);
        list_del(&cb->list);
-       write_unlock(&hci_cb_list_lock);
+       mutex_unlock(&hci_cb_list_lock);
 
        return 0;
 }
@@ -3517,7 +3560,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen,
        /* Stand-alone HCI commands must be flagged as
         * single-command requests.
         */
-       bt_cb(skb)->req.start = true;
+       bt_cb(skb)->req_start = 1;
 
        skb_queue_tail(&hdev->cmd_q, skb);
        queue_work(hdev->workqueue, &hdev->cmd_work);
@@ -4195,7 +4238,7 @@ static bool hci_req_is_complete(struct hci_dev *hdev)
        if (!skb)
                return true;
 
-       return bt_cb(skb)->req.start;
+       return bt_cb(skb)->req_start;
 }
 
 static void hci_resend_last(struct hci_dev *hdev)
@@ -4255,14 +4298,14 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
         * command queue (hdev->cmd_q).
         */
        if (hdev->sent_cmd) {
-               req_complete = bt_cb(hdev->sent_cmd)->req.complete;
+               req_complete = bt_cb(hdev->sent_cmd)->req_complete;
 
                if (req_complete) {
                        /* We must set the complete callback to NULL to
                         * avoid calling the callback more than once if
                         * this function gets called again.
                         */
-                       bt_cb(hdev->sent_cmd)->req.complete = NULL;
+                       bt_cb(hdev->sent_cmd)->req_complete = NULL;
 
                        goto call_complete;
                }
@@ -4271,12 +4314,12 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
        /* Remove all pending commands belonging to this request */
        spin_lock_irqsave(&hdev->cmd_q.lock, flags);
        while ((skb = __skb_dequeue(&hdev->cmd_q))) {
-               if (bt_cb(skb)->req.start) {
+               if (bt_cb(skb)->req_start) {
                        __skb_queue_head(&hdev->cmd_q, skb);
                        break;
                }
 
-               req_complete = bt_cb(skb)->req.complete;
+               req_complete = bt_cb(skb)->req_complete;
                kfree_skb(skb);
        }
        spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);