aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_conn.c
diff options
context:
space:
mode:
authorVille Tervo <ville.tervo@nokia.com>2011-02-10 20:38:47 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-02-16 14:32:45 -0500
commitfcd89c09a59a054fb986861e0862aa2fff7d7c40 (patch)
tree115d525a9789e974b0a118d9cc22b792370f40f7 /net/bluetooth/hci_conn.c
parent63185f64ef06464706b32c9a301f71f68cd93e52 (diff)
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 <ville.tervo@nokia.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r--net/bluetooth/hci_conn.c51
1 files changed, 48 insertions, 3 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 42dc39f25b72..d0c470c18f9d 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -45,6 +45,32 @@
45#include <net/bluetooth/bluetooth.h> 45#include <net/bluetooth/bluetooth.h>
46#include <net/bluetooth/hci_core.h> 46#include <net/bluetooth/hci_core.h>
47 47
48static 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
69static 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
48void hci_acl_connect(struct hci_conn *conn) 74void hci_acl_connect(struct hci_conn *conn)
49{ 75{
50 struct hci_dev *hdev = conn->hdev; 76 struct hci_dev *hdev = conn->hdev;
@@ -193,8 +219,12 @@ static void hci_conn_timeout(unsigned long arg)
193 switch (conn->state) { 219 switch (conn->state) {
194 case BT_CONNECT: 220 case BT_CONNECT:
195 case BT_CONNECT2: 221 case BT_CONNECT2:
196 if (conn->type == ACL_LINK && conn->out) 222 if (conn->out) {
197 hci_acl_connect_cancel(conn); 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 }
198 break; 228 break;
199 case BT_CONFIG: 229 case BT_CONFIG:
200 case BT_CONNECTED: 230 case BT_CONNECTED:
@@ -361,15 +391,30 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
361} 391}
362EXPORT_SYMBOL(hci_get_route); 392EXPORT_SYMBOL(hci_get_route);
363 393
364/* Create SCO or ACL connection. 394/* Create SCO, ACL or LE connection.
365 * Device _must_ be locked */ 395 * Device _must_ be locked */
366struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type) 396struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
367{ 397{
368 struct hci_conn *acl; 398 struct hci_conn *acl;
369 struct hci_conn *sco; 399 struct hci_conn *sco;
400 struct hci_conn *le;
370 401
371 BT_DBG("%s dst %s", hdev->name, batostr(dst)); 402 BT_DBG("%s dst %s", hdev->name, batostr(dst));
372 403
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
373 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); 418 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
374 if (!acl) { 419 if (!acl) {
375 acl = hci_conn_add(hdev, ACL_LINK, dst); 420 acl = hci_conn_add(hdev, ACL_LINK, dst);