From 3fb0b0ba884b0fb6db9e2a03e3cf86f3eebcaeec Mon Sep 17 00:00:00 2001 From: Brian Gix Date: Tue, 1 Nov 2011 16:27:25 -0700 Subject: [PATCH] Bluetooth: Add API to set LE Connection Parameters Include auto-setting connection parameters during Pairing for low latenecy, and default (high latency) settings for non-Pairing connections. Change-Id: Ie8e3f65da52213451dcc01fce38d95ae07d1b13b Signed-off-by: Brian Gix --- include/net/bluetooth/mgmt.h | 9 ++++++++ net/bluetooth/mgmt.c | 45 ++++++++++++++++++++++++++++++++++++ net/bluetooth/smp.c | 14 +++++++++++ 3 files changed, 68 insertions(+) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 127c7ca24b7..ce7ecf1a789 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -219,6 +219,15 @@ struct mgmt_cp_resolve_name { #define MGMT_OP_SET_LIMIT_DISCOVERABLE 0x001F +#define MGMT_OP_SET_CONNECTION_PARAMS 0x0020 +struct mgmt_cp_set_connection_params { + bdaddr_t bdaddr; + __le16 interval_min; + __le16 interval_max; + __le16 slave_latency; + __le16 timeout_multiplier; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 77845f21418..094bfdb71df 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1699,6 +1699,48 @@ failed: return err; } +static int set_connection_params(struct sock *sk, u16 index, + unsigned char *data, u16 len) +{ + struct mgmt_cp_set_connection_params *cp = (void *) data; + struct hci_dev *hdev; + struct hci_conn *conn; + int err; + + BT_DBG(""); + + if (len != sizeof(*cp)) + return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, + EINVAL); + + hdev = hci_dev_get(index); + if (!hdev) + return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, + ENODEV); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); + if (!conn) { + err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, + ENOTCONN); + goto failed; + } + + hci_le_conn_update(conn, le16_to_cpu(cp->interval_min), + le16_to_cpu(cp->interval_max), + le16_to_cpu(cp->slave_latency), + le16_to_cpu(cp->timeout_multiplier)); + + err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, 0); + +failed: + hci_dev_unlock(hdev); + hci_dev_put(hdev); + + return err; +} + static int set_local_name(struct sock *sk, u16 index, unsigned char *data, u16 len) { @@ -2262,6 +2304,9 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) case MGMT_OP_RESOLVE_NAME: err = resolve_name(sk, index, buf + sizeof(*hdr), len); break; + case MGMT_OP_SET_CONNECTION_PARAMS: + err = set_connection_params(sk, index, buf + sizeof(*hdr), len); + break; case MGMT_OP_READ_LOCAL_OOB_DATA: err = read_local_oob_data(sk, index); break; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index e7251480f16..a88f4a5406e 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -31,6 +31,11 @@ #define SMP_TIMEOUT 30000 /* 30 seconds */ +#define SMP_MIN_CONN_INTERVAL 40 /* 50ms (40 * 1.25ms) */ +#define SMP_MAX_CONN_INTERVAL 56 /* 70ms (56 * 1.25ms) */ +#define SMP_MAX_CONN_LATENCY 0 /* 0ms (0 * 1.25ms) */ +#define SMP_SUPERVISION_TIMEOUT 500 /* 5 seconds (500 * 10ms) */ + #ifndef FALSE #define FALSE 0 #define TRUE (!FALSE) @@ -696,6 +701,10 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) invalid_key: hcon->sec_req = FALSE; + /* Switch to Pairing Connection Parameters */ + hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL, SMP_MAX_CONN_INTERVAL, + SMP_MAX_CONN_LATENCY, SMP_SUPERVISION_TIMEOUT); + skb_pull(skb, sizeof(*rp)); memset(&cp, 0, sizeof(cp)); @@ -763,6 +772,11 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) if (hcon->link_mode & HCI_LM_MASTER) { struct smp_cmd_pairing cp; + /* Switch to Pairing Connection Parameters */ + hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL, + SMP_MAX_CONN_INTERVAL, SMP_MAX_CONN_LATENCY, + SMP_SUPERVISION_TIMEOUT); + build_pairing_cmd(conn, &cp, NULL, authreq); hcon->preq[0] = SMP_CMD_PAIRING_REQ; memcpy(&hcon->preq[1], &cp, sizeof(cp));