Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / mgmt.c
index 190668367e422b7ace0e04946ae59c35d34ba6c6..b8554d429d889f97bd735cc62aaafce1e85bae5c 100644 (file)
@@ -44,7 +44,7 @@ static const u16 mgmt_commands[] = {
        MGMT_OP_SET_DISCOVERABLE,
        MGMT_OP_SET_CONNECTABLE,
        MGMT_OP_SET_FAST_CONNECTABLE,
-       MGMT_OP_SET_PAIRABLE,
+       MGMT_OP_SET_BONDABLE,
        MGMT_OP_SET_LINK_SECURITY,
        MGMT_OP_SET_SSP,
        MGMT_OP_SET_HS,
@@ -553,7 +553,7 @@ static u32 get_supported_settings(struct hci_dev *hdev)
        u32 settings = 0;
 
        settings |= MGMT_SETTING_POWERED;
-       settings |= MGMT_SETTING_PAIRABLE;
+       settings |= MGMT_SETTING_BONDABLE;
        settings |= MGMT_SETTING_DEBUG_KEYS;
        settings |= MGMT_SETTING_CONNECTABLE;
        settings |= MGMT_SETTING_DISCOVERABLE;
@@ -603,8 +603,8 @@ static u32 get_current_settings(struct hci_dev *hdev)
        if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
                settings |= MGMT_SETTING_DISCOVERABLE;
 
-       if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
-               settings |= MGMT_SETTING_PAIRABLE;
+       if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
+               settings |= MGMT_SETTING_BONDABLE;
 
        if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
                settings |= MGMT_SETTING_BREDR;
@@ -1086,8 +1086,8 @@ static void enable_advertising(struct hci_request *req)
                return;
 
        memset(&cp, 0, sizeof(cp));
-       cp.min_interval = cpu_to_le16(0x0800);
-       cp.max_interval = cpu_to_le16(0x0800);
+       cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
+       cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
        cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
        cp.own_address_type = own_addr_type;
        cp.channel_map = hdev->le_adv_channel_map;
@@ -1152,7 +1152,7 @@ static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
         * for mgmt we require user-space to explicitly enable
         * it
         */
-       clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
+       clear_bit(HCI_BONDABLE, &hdev->dev_flags);
 }
 
 static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
@@ -1881,7 +1881,18 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
                if (cp->val) {
                        scan = SCAN_PAGE;
                } else {
-                       scan = 0;
+                       /* If we don't have any whitelist entries just
+                        * disable all scanning. If there are entries
+                        * and we had both page and inquiry scanning
+                        * enabled then fall back to only page scanning.
+                        * Otherwise no changes are needed.
+                        */
+                       if (list_empty(&hdev->whitelist))
+                               scan = SCAN_DISABLED;
+                       else if (test_bit(HCI_ISCAN, &hdev->flags))
+                               scan = SCAN_PAGE;
+                       else
+                               goto no_scan_update;
 
                        if (test_bit(HCI_ISCAN, &hdev->flags) &&
                            hdev->discov_timeout > 0)
@@ -1891,6 +1902,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
                hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
        }
 
+no_scan_update:
        /* If we're going from non-connectable to connectable or
         * vice-versa when fast connectable is enabled ensure that fast
         * connectable gets disabled. write_fast_connectable won't do
@@ -1918,7 +1930,7 @@ failed:
        return err;
 }
 
-static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
+static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
                        u16 len)
 {
        struct mgmt_mode *cp = data;
@@ -1928,17 +1940,17 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
        BT_DBG("request for %s", hdev->name);
 
        if (cp->val != 0x00 && cp->val != 0x01)
-               return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
+               return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
                                  MGMT_STATUS_INVALID_PARAMS);
 
        hci_dev_lock(hdev);
 
        if (cp->val)
-               changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
+               changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
        else
-               changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
+               changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
 
-       err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
+       err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
        if (err < 0)
                goto unlock;
 
@@ -2264,7 +2276,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
 
        if (val) {
                hci_cp.le = val;
-               hci_cp.simul = lmp_le_br_capable(hdev);
+               hci_cp.simul = 0x00;
        } else {
                if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
                        disable_advertising(&req);
@@ -3201,7 +3213,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
        conn->io_capability = cp->io_cap;
        cmd->user_data = conn;
 
-       if (conn->state == BT_CONNECTED &&
+       if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
            hci_conn_security(conn, sec_level, auth_type, true))
                pairing_complete(cmd, 0);
 
@@ -5271,7 +5283,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
                                    MGMT_STATUS_INVALID_PARAMS,
                                    &cp->addr, sizeof(cp->addr));
 
-       if (cp->action != 0x00 && cp->action != 0x01)
+       if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
                return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
                                    MGMT_STATUS_INVALID_PARAMS,
                                    &cp->addr, sizeof(cp->addr));
@@ -5281,7 +5293,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
        if (cp->addr.type == BDADDR_BREDR) {
                bool update_scan;
 
-               /* Only "connect" action supported for now */
+               /* Only incoming connections action is supported for now */
                if (cp->action != 0x01) {
                        err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
                                           MGMT_STATUS_INVALID_PARAMS,
@@ -5307,8 +5319,10 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
        else
                addr_type = ADDR_LE_DEV_RANDOM;
 
-       if (cp->action)
+       if (cp->action == 0x02)
                auto_conn = HCI_AUTO_CONN_ALWAYS;
+       else if (cp->action == 0x01)
+               auto_conn = HCI_AUTO_CONN_DIRECT;
        else
                auto_conn = HCI_AUTO_CONN_REPORT;
 
@@ -5665,7 +5679,7 @@ static const struct mgmt_handler {
        { set_discoverable,       false, MGMT_SET_DISCOVERABLE_SIZE },
        { set_connectable,        false, MGMT_SETTING_SIZE },
        { set_fast_connectable,   false, MGMT_SETTING_SIZE },
-       { set_pairable,           false, MGMT_SETTING_SIZE },
+       { set_bondable,           false, MGMT_SETTING_SIZE },
        { set_link_security,      false, MGMT_SETTING_SIZE },
        { set_ssp,                false, MGMT_SETTING_SIZE },
        { set_hs,                 false, MGMT_SETTING_SIZE },
@@ -5870,6 +5884,7 @@ static void restart_le_actions(struct hci_dev *hdev)
                list_del_init(&p->action);
 
                switch (p->auto_connect) {
+               case HCI_AUTO_CONN_DIRECT:
                case HCI_AUTO_CONN_ALWAYS:
                        list_add(&p->action, &hdev->pend_le_conns);
                        break;
@@ -5922,8 +5937,8 @@ static int powered_update_hci(struct hci_dev *hdev)
            lmp_bredr_capable(hdev)) {
                struct hci_cp_write_le_host_supported cp;
 
-               cp.le = 1;
-               cp.simul = lmp_le_br_capable(hdev);
+               cp.le = 0x01;
+               cp.simul = 0x00;
 
                /* Check first if we already have the right
                 * host state (host features set)