Bluetooth: Use same LE min/max connection event length during update
[pandora-kernel.git] / net / bluetooth / hci_conn.c
index ba5366c..bd66c52 100644 (file)
@@ -225,8 +225,8 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
        cp.conn_interval_max    = cpu_to_le16(max);
        cp.conn_latency         = cpu_to_le16(latency);
        cp.supervision_timeout  = cpu_to_le16(to_multiplier);
-       cp.min_ce_len           = __constant_cpu_to_le16(0x0001);
-       cp.max_ce_len           = __constant_cpu_to_le16(0x0001);
+       cp.min_ce_len           = __constant_cpu_to_le16(0x0000);
+       cp.max_ce_len           = __constant_cpu_to_le16(0x0000);
 
        hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
 }
@@ -514,6 +514,21 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
 }
 EXPORT_SYMBOL(hci_get_route);
 
+/* This function requires the caller holds hdev->lock */
+static void le_conn_failed(struct hci_conn *conn, u8 status)
+{
+       struct hci_dev *hdev = conn->hdev;
+
+       conn->state = BT_CLOSED;
+
+       mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type,
+                           status);
+
+       hci_proto_connect_cfm(conn, status);
+
+       hci_conn_del(conn);
+}
+
 static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
 {
        struct hci_conn *conn;
@@ -530,14 +545,7 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
        if (!conn)
                goto done;
 
-       conn->state = BT_CLOSED;
-
-       mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type,
-                           status);
-
-       hci_proto_connect_cfm(conn, status);
-
-       hci_conn_del(conn);
+       le_conn_failed(conn, status);
 
 done:
        hci_dev_unlock(hdev);
@@ -558,8 +566,8 @@ static int hci_create_le_conn(struct hci_conn *conn)
        bacpy(&cp.peer_addr, &conn->dst);
        cp.peer_addr_type = conn->dst_type;
        cp.own_address_type = conn->src_type;
-       cp.conn_interval_min = cpu_to_le16(hdev->le_conn_min_interval);
-       cp.conn_interval_max = cpu_to_le16(hdev->le_conn_max_interval);
+       cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval);
+       cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval);
        cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
        cp.min_ce_len = __constant_cpu_to_le16(0x0000);
        cp.max_ce_len = __constant_cpu_to_le16(0x0000);
@@ -578,7 +586,9 @@ static int hci_create_le_conn(struct hci_conn *conn)
 static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
                                    u8 dst_type, u8 sec_level, u8 auth_type)
 {
+       struct hci_conn_params *params;
        struct hci_conn *conn;
+       struct smp_irk *irk;
        int err;
 
        if (test_bit(HCI_ADVERTISING, &hdev->flags))
@@ -607,15 +617,36 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
        if (conn)
                return ERR_PTR(-EBUSY);
 
+       /* Convert from L2CAP channel address type to HCI address type */
+       if (dst_type == BDADDR_LE_PUBLIC)
+               dst_type = ADDR_LE_DEV_PUBLIC;
+       else
+               dst_type = ADDR_LE_DEV_RANDOM;
+
+       /* When given an identity address with existing identity
+        * resolving key, the connection needs to be established
+        * to a resolvable random address.
+        *
+        * This uses the cached random resolvable address from
+        * a previous scan. When no cached address is available,
+        * try connecting to the identity address instead.
+        *
+        * Storing the resolvable random address is required here
+        * to handle connection failures. The address will later
+        * be resolved back into the original identity address
+        * from the connect request.
+        */
+       irk = hci_find_irk_by_addr(hdev, dst, dst_type);
+       if (irk && bacmp(&irk->rpa, BDADDR_ANY)) {
+               dst = &irk->rpa;
+               dst_type = ADDR_LE_DEV_RANDOM;
+       }
+
        conn = hci_conn_add(hdev, LE_LINK, dst);
        if (!conn)
                return ERR_PTR(-ENOMEM);
 
-       if (dst_type == BDADDR_LE_PUBLIC)
-               conn->dst_type = ADDR_LE_DEV_PUBLIC;
-       else
-               conn->dst_type = ADDR_LE_DEV_RANDOM;
-
+       conn->dst_type = dst_type;
        conn->src_type = hdev->own_addr_type;
 
        conn->state = BT_CONNECT;
@@ -625,6 +656,15 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
        conn->pending_sec_level = sec_level;
        conn->auth_type = auth_type;
 
+       params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
+       if (params) {
+               conn->le_conn_min_interval = params->conn_min_interval;
+               conn->le_conn_max_interval = params->conn_max_interval;
+       } else {
+               conn->le_conn_min_interval = hdev->le_conn_min_interval;
+               conn->le_conn_max_interval = hdev->le_conn_max_interval;
+       }
+
        err = hci_create_le_conn(conn);
        if (err)
                return ERR_PTR(err);
@@ -800,14 +840,23 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
        if (!(conn->link_mode & HCI_LM_AUTH))
                goto auth;
 
-       /* An authenticated combination key has sufficient security for any
-          security level. */
-       if (conn->key_type == HCI_LK_AUTH_COMBINATION)
+       /* An authenticated FIPS approved combination key has sufficient
+        * security for security level 4. */
+       if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 &&
+           sec_level == BT_SECURITY_FIPS)
+               goto encrypt;
+
+       /* An authenticated combination key has sufficient security for
+          security level 3. */
+       if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 ||
+            conn->key_type == HCI_LK_AUTH_COMBINATION_P256) &&
+           sec_level == BT_SECURITY_HIGH)
                goto encrypt;
 
        /* An unauthenticated combination key has sufficient security for
           security level 1 and 2. */
-       if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
+       if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 ||
+            conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) &&
            (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW))
                goto encrypt;
 
@@ -816,7 +865,8 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
           is generated using maximum PIN code length (16).
           For pre 2.1 units. */
        if (conn->key_type == HCI_LK_COMBINATION &&
-           (sec_level != BT_SECURITY_HIGH || conn->pin_length == 16))
+           (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW ||
+            conn->pin_length == 16))
                goto encrypt;
 
 auth:
@@ -840,13 +890,17 @@ int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
 {
        BT_DBG("hcon %p", conn);
 
-       if (sec_level != BT_SECURITY_HIGH)
-               return 1; /* Accept if non-secure is required */
+       /* Accept if non-secure or higher security level is required */
+       if (sec_level != BT_SECURITY_HIGH && sec_level != BT_SECURITY_FIPS)
+               return 1;
 
-       if (conn->sec_level == BT_SECURITY_HIGH)
+       /* Accept if secure or higher security level is already present */
+       if (conn->sec_level == BT_SECURITY_HIGH ||
+           conn->sec_level == BT_SECURITY_FIPS)
                return 1;
 
-       return 0; /* Reject not secure link */
+       /* Reject not secure link */
+       return 0;
 }
 EXPORT_SYMBOL(hci_conn_check_secure);