Skip to content

Commit fcd89c0

Browse files
Ville TervoGustavo F. Padovan
Ville Tervo
authored and
Gustavo F. Padovan
committed
Bluetooth: Add LE connect support
Bluetooth V4.0 adds support for Low Energy (LE) connections. Specification introduces new set of hci commands to control LE connection. This patch adds logic to create, cancel and disconnect LE connections. Signed-off-by: Ville Tervo <[email protected]> Acked-by: Marcel Holtmann <[email protected]> Signed-off-by: Gustavo F. Padovan <[email protected]>
1 parent 63185f6 commit fcd89c0

File tree

4 files changed

+164
-7
lines changed

4 files changed

+164
-7
lines changed

include/net/bluetooth/hci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ enum {
168168
#define SCO_LINK 0x00
169169
#define ACL_LINK 0x01
170170
#define ESCO_LINK 0x02
171+
/* Low Energy links do not have defined link type. Use invented one */
172+
#define LE_LINK 0x80
171173

172174
/* LMP features */
173175
#define LMP_3SLOT 0x01

include/net/bluetooth/hci_core.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct hci_conn_hash {
6060
spinlock_t lock;
6161
unsigned int acl_num;
6262
unsigned int sco_num;
63+
unsigned int le_num;
6364
};
6465

6566
struct bdaddr_list {
@@ -309,20 +310,36 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
309310
{
310311
struct hci_conn_hash *h = &hdev->conn_hash;
311312
list_add(&c->list, &h->list);
312-
if (c->type == ACL_LINK)
313+
switch (c->type) {
314+
case ACL_LINK:
313315
h->acl_num++;
314-
else
316+
break;
317+
case LE_LINK:
318+
h->le_num++;
319+
break;
320+
case SCO_LINK:
321+
case ESCO_LINK:
315322
h->sco_num++;
323+
break;
324+
}
316325
}
317326

318327
static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
319328
{
320329
struct hci_conn_hash *h = &hdev->conn_hash;
321330
list_del(&c->list);
322-
if (c->type == ACL_LINK)
331+
switch (c->type) {
332+
case ACL_LINK:
323333
h->acl_num--;
324-
else
334+
break;
335+
case LE_LINK:
336+
h->le_num--;
337+
break;
338+
case SCO_LINK:
339+
case ESCO_LINK:
325340
h->sco_num--;
341+
break;
342+
}
326343
}
327344

328345
static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,

net/bluetooth/hci_conn.c

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,32 @@
4545
#include <net/bluetooth/bluetooth.h>
4646
#include <net/bluetooth/hci_core.h>
4747

48+
static void hci_le_connect(struct hci_conn *conn)
49+
{
50+
struct hci_dev *hdev = conn->hdev;
51+
struct hci_cp_le_create_conn cp;
52+
53+
conn->state = BT_CONNECT;
54+
conn->out = 1;
55+
56+
memset(&cp, 0, sizeof(cp));
57+
cp.scan_interval = cpu_to_le16(0x0004);
58+
cp.scan_window = cpu_to_le16(0x0004);
59+
bacpy(&cp.peer_addr, &conn->dst);
60+
cp.conn_interval_min = cpu_to_le16(0x0008);
61+
cp.conn_interval_max = cpu_to_le16(0x0100);
62+
cp.supervision_timeout = cpu_to_le16(0x0064);
63+
cp.min_ce_len = cpu_to_le16(0x0001);
64+
cp.max_ce_len = cpu_to_le16(0x0001);
65+
66+
hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
67+
}
68+
69+
static void hci_le_connect_cancel(struct hci_conn *conn)
70+
{
71+
hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
72+
}
73+
4874
void hci_acl_connect(struct hci_conn *conn)
4975
{
5076
struct hci_dev *hdev = conn->hdev;
@@ -193,8 +219,12 @@ static void hci_conn_timeout(unsigned long arg)
193219
switch (conn->state) {
194220
case BT_CONNECT:
195221
case BT_CONNECT2:
196-
if (conn->type == ACL_LINK && conn->out)
197-
hci_acl_connect_cancel(conn);
222+
if (conn->out) {
223+
if (conn->type == ACL_LINK)
224+
hci_acl_connect_cancel(conn);
225+
else if (conn->type == LE_LINK)
226+
hci_le_connect_cancel(conn);
227+
}
198228
break;
199229
case BT_CONFIG:
200230
case BT_CONNECTED:
@@ -361,15 +391,30 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
361391
}
362392
EXPORT_SYMBOL(hci_get_route);
363393

364-
/* Create SCO or ACL connection.
394+
/* Create SCO, ACL or LE connection.
365395
* Device _must_ be locked */
366396
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
367397
{
368398
struct hci_conn *acl;
369399
struct hci_conn *sco;
400+
struct hci_conn *le;
370401

371402
BT_DBG("%s dst %s", hdev->name, batostr(dst));
372403

404+
if (type == LE_LINK) {
405+
le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
406+
if (!le)
407+
le = hci_conn_add(hdev, LE_LINK, dst);
408+
if (!le)
409+
return NULL;
410+
if (le->state == BT_OPEN)
411+
hci_le_connect(le);
412+
413+
hci_conn_hold(le);
414+
415+
return le;
416+
}
417+
373418
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
374419
if (!acl) {
375420
acl = hci_conn_add(hdev, ACL_LINK, dst);

net/bluetooth/hci_event.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,43 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
11071107
hci_dev_unlock(hdev);
11081108
}
11091109

1110+
static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1111+
{
1112+
struct hci_cp_le_create_conn *cp;
1113+
struct hci_conn *conn;
1114+
1115+
BT_DBG("%s status 0x%x", hdev->name, status);
1116+
1117+
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
1118+
if (!cp)
1119+
return;
1120+
1121+
hci_dev_lock(hdev);
1122+
1123+
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
1124+
1125+
BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
1126+
conn);
1127+
1128+
if (status) {
1129+
if (conn && conn->state == BT_CONNECT) {
1130+
conn->state = BT_CLOSED;
1131+
hci_proto_connect_cfm(conn, status);
1132+
hci_conn_del(conn);
1133+
}
1134+
} else {
1135+
if (!conn) {
1136+
conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
1137+
if (conn)
1138+
conn->out = 1;
1139+
else
1140+
BT_ERR("No memory for new connection");
1141+
}
1142+
}
1143+
1144+
hci_dev_unlock(hdev);
1145+
}
1146+
11101147
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
11111148
{
11121149
__u8 status = *((__u8 *) skb->data);
@@ -1738,6 +1775,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
17381775
mgmt_disconnect_failed(hdev->id);
17391776
break;
17401777

1778+
case HCI_OP_LE_CREATE_CONN:
1779+
hci_cs_le_create_conn(hdev, ev->status);
1780+
break;
1781+
17411782
default:
17421783
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
17431784
break;
@@ -2321,6 +2362,54 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
23212362
hci_dev_unlock(hdev);
23222363
}
23232364

2365+
static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2366+
{
2367+
struct hci_ev_le_conn_complete *ev = (void *) skb->data;
2368+
struct hci_conn *conn;
2369+
2370+
BT_DBG("%s status %d", hdev->name, ev->status);
2371+
2372+
hci_dev_lock(hdev);
2373+
2374+
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
2375+
if (!conn)
2376+
goto unlock;
2377+
2378+
if (ev->status) {
2379+
hci_proto_connect_cfm(conn, ev->status);
2380+
conn->state = BT_CLOSED;
2381+
hci_conn_del(conn);
2382+
goto unlock;
2383+
}
2384+
2385+
conn->handle = __le16_to_cpu(ev->handle);
2386+
conn->state = BT_CONNECTED;
2387+
2388+
hci_conn_hold_device(conn);
2389+
hci_conn_add_sysfs(conn);
2390+
2391+
hci_proto_connect_cfm(conn, ev->status);
2392+
2393+
unlock:
2394+
hci_dev_unlock(hdev);
2395+
}
2396+
2397+
static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2398+
{
2399+
struct hci_ev_le_meta *le_ev = (void *) skb->data;
2400+
2401+
skb_pull(skb, sizeof(*le_ev));
2402+
2403+
switch (le_ev->subevent) {
2404+
case HCI_EV_LE_CONN_COMPLETE:
2405+
hci_le_conn_complete_evt(hdev, skb);
2406+
break;
2407+
2408+
default:
2409+
break;
2410+
}
2411+
}
2412+
23242413
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
23252414
{
23262415
struct hci_event_hdr *hdr = (void *) skb->data;
@@ -2461,6 +2550,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
24612550
hci_remote_host_features_evt(hdev, skb);
24622551
break;
24632552

2553+
case HCI_EV_LE_META:
2554+
hci_le_meta_evt(hdev, skb);
2555+
break;
2556+
24642557
default:
24652558
BT_DBG("%s event 0x%x", hdev->name, event);
24662559
break;

0 commit comments

Comments
 (0)