Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kmanna/5825747 to your computer and use it in GitHub Desktop.
Save kmanna/5825747 to your computer and use it in GitHub Desktop.
From 9b55aebfea81ca8ac9f0731736fffee826537de8 Mon Sep 17 00:00:00 2001
From: Kyle Manna <kmanna@fanhattan.com>
Date: Wed, 19 Jun 2013 18:10:03 -0700
Subject: [PATCH 1/3] bluetooth: Add ability to pass connection params
* Useful for adding Bluetooth Low Energy Connection Parameters which
are currently hardcoded.
---
include/net/bluetooth/hci_core.h | 5 ++--
include/net/bluetooth/l2cap.h | 4 ++++
net/bluetooth/hci_conn.c | 47 +++++++++++++++++++++++---------------
net/bluetooth/l2cap_core.c | 7 ++++--
net/bluetooth/mgmt.c | 4 ++--
net/bluetooth/sco.c | 2 +-
6 files changed, 43 insertions(+), 26 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 014a2ea..d1ccc02 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -584,8 +584,9 @@ void hci_chan_del(struct hci_chan *chan);
void hci_chan_list_flush(struct hci_conn *conn);
struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
- __u8 dst_type, __u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, void *cp,
+ bdaddr_t *dst, __u8 dst_type,
+ __u8 sec_level, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7588ef4..6abfa91 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -438,6 +438,10 @@ struct l2cap_chan {
struct l2cap_conn *conn;
struct hci_conn *hs_hcon;
struct hci_chan *hs_hchan;
+
+ /* Optionally set by setsockopt */
+ struct hci_cp_le_create_conn *cp_le;
+
struct kref kref;
__u8 state;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 4925a02..1ecbbac 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -31,28 +31,34 @@
#include <net/bluetooth/a2mp.h>
#include <net/bluetooth/smp.h>
-static void hci_le_create_connection(struct hci_conn *conn)
+static void hci_le_create_connection(struct hci_conn *conn,
+ struct hci_cp_le_create_conn *cp)
{
struct hci_dev *hdev = conn->hdev;
- struct hci_cp_le_create_conn cp;
+ struct hci_cp_le_create_conn cp_stack;
conn->state = BT_CONNECT;
conn->out = true;
conn->link_mode |= HCI_LM_MASTER;
conn->sec_level = BT_SECURITY_LOW;
- 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;
- 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);
+ if (!cp) {
+ cp = &cp_stack;
+
+ memset(cp, 0, sizeof(*cp));
+ cp->scan_interval = __constant_cpu_to_le16(0x0060);
+ cp->scan_window = __constant_cpu_to_le16(0x0030);
+ 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);
+ }
+
+ bacpy(&cp->peer_addr, &conn->dst);
+ cp->peer_addr_type = conn->dst_type;
+
+ hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(*cp), cp);
}
static void hci_le_create_connection_cancel(struct hci_conn *conn)
@@ -498,7 +504,8 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
EXPORT_SYMBOL(hci_get_route);
static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
- u8 dst_type, u8 sec_level, u8 auth_type)
+ u8 dst_type, u8 sec_level, u8 auth_type,
+ struct hci_cp_le_create_conn *cp)
{
struct hci_conn *le;
@@ -516,7 +523,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
return ERR_PTR(-ENOMEM);
le->dst_type = bdaddr_to_le(dst_type);
- hci_le_create_connection(le);
+ hci_le_create_connection(le, cp);
}
le->pending_sec_level = sec_level;
@@ -593,14 +600,16 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type,
}
/* Create SCO, ACL or LE connection. */
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
- __u8 dst_type, __u8 sec_level, __u8 auth_type)
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, void *cp,
+ bdaddr_t *dst, __u8 dst_type,
+ __u8 sec_level, __u8 auth_type)
{
BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type);
switch (type) {
case LE_LINK:
- return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type);
+ return hci_connect_le(hdev, dst, dst_type, sec_level,
+ auth_type, cp);
case ACL_LINK:
return hci_connect_acl(hdev, dst, sec_level, auth_type);
case SCO_LINK:
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 22e6583..de086e5 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -461,6 +461,9 @@ static void l2cap_chan_destroy(struct kref *kref)
list_del(&chan->global_l);
write_unlock(&chan_list_lock);
+ if (chan->cp_le)
+ kfree(chan->cp_le);
+
kfree(chan);
}
@@ -1689,10 +1692,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
auth_type = l2cap_get_auth_type(chan);
if (chan->dcid == L2CAP_CID_LE_DATA)
- hcon = hci_connect(hdev, LE_LINK, dst, dst_type,
+ hcon = hci_connect(hdev, LE_LINK, chan->cp_le, dst, dst_type,
chan->sec_level, auth_type);
else
- hcon = hci_connect(hdev, ACL_LINK, dst, dst_type,
+ hcon = hci_connect(hdev, ACL_LINK, NULL, dst, dst_type,
chan->sec_level, auth_type);
if (IS_ERR(hcon)) {
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index f559b96..1ff28e0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1918,10 +1918,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
auth_type = HCI_AT_DEDICATED_BONDING_MITM;
if (cp->addr.type == BDADDR_BREDR)
- conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr,
+ conn = hci_connect(hdev, ACL_LINK, NULL, &cp->addr.bdaddr,
cp->addr.type, sec_level, auth_type);
else
- conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr,
+ conn = hci_connect(hdev, LE_LINK, NULL, &cp->addr.bdaddr,
cp->addr.type, sec_level, auth_type);
memset(&rp, 0, sizeof(rp));
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 299ef14..e2baf77 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -176,7 +176,7 @@ static int sco_connect(struct sock *sk)
else
type = SCO_LINK;
- hcon = hci_connect(hdev, type, dst, BDADDR_BREDR, BT_SECURITY_LOW,
+ hcon = hci_connect(hdev, type, NULL, dst, BDADDR_BREDR, BT_SECURITY_LOW,
HCI_AT_NO_BONDING);
if (IS_ERR(hcon)) {
err = PTR_ERR(hcon);
--
1.7.9.5
From 906472affdd070d240d078884610b13681d5939c Mon Sep 17 00:00:00 2001
From: Kyle Manna <kmanna@fanhattan.com>
Date: Thu, 20 Jun 2013 11:53:40 -0700
Subject: [PATCH 2/3] bluetooth: Add l2cap setsockopt for LE conn params
* Userspace can now specify connection parameters prior to connecting to the
device.
---
include/net/bluetooth/bluetooth.h | 2 ++
net/bluetooth/l2cap_sock.c | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 2554b3f..f2474fc 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -82,6 +82,8 @@ struct bt_power {
#define BT_CHANNEL_POLICY 10
+#define BT_LE_CONN_PARAM 11
+
/* BR/EDR only (default policy)
* AMP controllers cannot be used.
* Channel move requests from the remote device are denied.
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 97d47b9..3cc8fbe 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -748,6 +748,26 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
+ case BT_LE_CONN_PARAM:
+
+ if (sizeof(struct hci_cp_le_create_conn) != optlen) {
+ err = -EINVAL;
+ break;
+ }
+
+ chan->cp_le = kmalloc(optlen, GFP_KERNEL);
+ if (!chan->cp_le) {
+ err = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user((char *)chan->cp_le, optval, optlen)) {
+ err = -EFAULT;
+ break;
+ }
+
+ break;
+
default:
err = -ENOPROTOOPT;
break;
--
1.7.9.5
From 1e25dd4b891eb90fbc3c7116726066f6b9ec2c3d Mon Sep 17 00:00:00 2001
From: Kyle Manna <kmanna@fanhattan.com>
Date: Thu, 20 Jun 2013 12:13:23 -0700
Subject: [PATCH 3/3] WIP: bluetooth: Add debugging output
* Don't commit.
---
net/bluetooth/hci_conn.c | 3 +++
net/bluetooth/l2cap_sock.c | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 1ecbbac..0d5f9a1 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -42,7 +42,10 @@ static void hci_le_create_connection(struct hci_conn *conn,
conn->link_mode |= HCI_LM_MASTER;
conn->sec_level = BT_SECURITY_LOW;
+ pr_info("%s() cp = %p\n", __func__, cp);
+
if (!cp) {
+ pr_info("%s() using default cp!!\n", __func__);
cp = &cp_stack;
memset(cp, 0, sizeof(*cp));
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 3cc8fbe..9536557 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -591,6 +591,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
BT_DBG("sk %p", sk);
+ pr_info("%s(%p) optname = %d\n", __func__, sk, optname);
+
if (level == SOL_L2CAP)
return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
@@ -750,6 +752,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
case BT_LE_CONN_PARAM:
+ pr_info("%s(): attempting to copy connection parameters\n", __func__);
+
if (sizeof(struct hci_cp_le_create_conn) != optlen) {
err = -EINVAL;
break;
@@ -765,6 +769,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
err = -EFAULT;
break;
}
+
+ pr_info("%s(): connection parameters copied\n", __func__);
break;
--
1.7.9.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment