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 <bgix@codeaurora.org>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user