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:
Brian Gix
2011-11-01 16:27:25 -07:00
committed by Stephen Boyd
parent bad519927b
commit 3fb0b0ba88
3 changed files with 68 additions and 0 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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));