|
@@ -49,29 +49,6 @@ static const struct sco_param sco_param_wideband[] = {
|
|
|
{ EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */
|
|
|
};
|
|
|
|
|
|
-static void hci_le_create_connection(struct hci_conn *conn)
|
|
|
-{
|
|
|
- struct hci_dev *hdev = conn->hdev;
|
|
|
- struct hci_cp_le_create_conn cp;
|
|
|
-
|
|
|
- memset(&cp, 0, sizeof(cp));
|
|
|
- cp.scan_interval = __constant_cpu_to_le16(0x0060);
|
|
|
- cp.scan_window = __constant_cpu_to_le16(0x0030);
|
|
|
- bacpy(&cp.peer_addr, &conn->dst);
|
|
|
- cp.peer_addr_type = conn->dst_type;
|
|
|
- if (bacmp(&hdev->bdaddr, BDADDR_ANY))
|
|
|
- cp.own_address_type = ADDR_LE_DEV_PUBLIC;
|
|
|
- else
|
|
|
- cp.own_address_type = ADDR_LE_DEV_RANDOM;
|
|
|
- cp.conn_interval_min = __constant_cpu_to_le16(0x0028);
|
|
|
- cp.conn_interval_max = __constant_cpu_to_le16(0x0038);
|
|
|
- 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);
|
|
|
-
|
|
|
- hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
|
|
|
-}
|
|
|
-
|
|
|
static void hci_le_create_connection_cancel(struct hci_conn *conn)
|
|
|
{
|
|
|
hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
|
|
@@ -545,10 +522,74 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
|
|
|
}
|
|
|
EXPORT_SYMBOL(hci_get_route);
|
|
|
|
|
|
+static void create_le_conn_complete(struct hci_dev *hdev, u8 status)
|
|
|
+{
|
|
|
+ struct hci_conn *conn;
|
|
|
+
|
|
|
+ if (status == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ BT_ERR("HCI request failed to create LE connection: status 0x%2.2x",
|
|
|
+ status);
|
|
|
+
|
|
|
+ hci_dev_lock(hdev);
|
|
|
+
|
|
|
+ conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT);
|
|
|
+ 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);
|
|
|
+
|
|
|
+done:
|
|
|
+ hci_dev_unlock(hdev);
|
|
|
+}
|
|
|
+
|
|
|
+static int hci_create_le_conn(struct hci_conn *conn)
|
|
|
+{
|
|
|
+ struct hci_dev *hdev = conn->hdev;
|
|
|
+ struct hci_cp_le_create_conn cp;
|
|
|
+ struct hci_request req;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ hci_req_init(&req, hdev);
|
|
|
+
|
|
|
+ memset(&cp, 0, sizeof(cp));
|
|
|
+ cp.scan_interval = __constant_cpu_to_le16(0x0060);
|
|
|
+ cp.scan_window = __constant_cpu_to_le16(0x0030);
|
|
|
+ bacpy(&cp.peer_addr, &conn->dst);
|
|
|
+ cp.peer_addr_type = conn->dst_type;
|
|
|
+ if (bacmp(&hdev->bdaddr, BDADDR_ANY))
|
|
|
+ cp.own_address_type = ADDR_LE_DEV_PUBLIC;
|
|
|
+ else
|
|
|
+ cp.own_address_type = ADDR_LE_DEV_RANDOM;
|
|
|
+ cp.conn_interval_min = __constant_cpu_to_le16(0x0028);
|
|
|
+ cp.conn_interval_max = __constant_cpu_to_le16(0x0038);
|
|
|
+ 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);
|
|
|
+ hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
|
|
|
+
|
|
|
+ err = hci_req_run(&req, create_le_conn_complete);
|
|
|
+ if (err) {
|
|
|
+ hci_conn_del(conn);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
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 *conn;
|
|
|
+ int err;
|
|
|
|
|
|
if (test_bit(HCI_ADVERTISING, &hdev->flags))
|
|
|
return ERR_PTR(-ENOTSUPP);
|
|
@@ -569,7 +610,9 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
|
|
|
conn->link_mode |= HCI_LM_MASTER;
|
|
|
conn->sec_level = BT_SECURITY_LOW;
|
|
|
|
|
|
- hci_le_create_connection(conn);
|
|
|
+ err = hci_create_le_conn(conn);
|
|
|
+ if (err)
|
|
|
+ return ERR_PTR(err);
|
|
|
}
|
|
|
|
|
|
conn->pending_sec_level = sec_level;
|