diff options
-rw-r--r-- | include/net/bluetooth/hci.h | 2 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 25 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 51 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 93 |
4 files changed, 164 insertions, 7 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 802d2505f138..e756f82a29e5 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -168,6 +168,8 @@ enum { | |||
168 | #define SCO_LINK 0x00 | 168 | #define SCO_LINK 0x00 |
169 | #define ACL_LINK 0x01 | 169 | #define ACL_LINK 0x01 |
170 | #define ESCO_LINK 0x02 | 170 | #define ESCO_LINK 0x02 |
171 | /* Low Energy links do not have defined link type. Use invented one */ | ||
172 | #define LE_LINK 0x80 | ||
171 | 173 | ||
172 | /* LMP features */ | 174 | /* LMP features */ |
173 | #define LMP_3SLOT 0x01 | 175 | #define LMP_3SLOT 0x01 |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 6163bff6fa91..f434e96ce020 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -60,6 +60,7 @@ struct hci_conn_hash { | |||
60 | spinlock_t lock; | 60 | spinlock_t lock; |
61 | unsigned int acl_num; | 61 | unsigned int acl_num; |
62 | unsigned int sco_num; | 62 | unsigned int sco_num; |
63 | unsigned int le_num; | ||
63 | }; | 64 | }; |
64 | 65 | ||
65 | struct bdaddr_list { | 66 | struct bdaddr_list { |
@@ -309,20 +310,36 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) | |||
309 | { | 310 | { |
310 | struct hci_conn_hash *h = &hdev->conn_hash; | 311 | struct hci_conn_hash *h = &hdev->conn_hash; |
311 | list_add(&c->list, &h->list); | 312 | list_add(&c->list, &h->list); |
312 | if (c->type == ACL_LINK) | 313 | switch (c->type) { |
314 | case ACL_LINK: | ||
313 | h->acl_num++; | 315 | 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: | ||
315 | h->sco_num++; | 322 | h->sco_num++; |
323 | break; | ||
324 | } | ||
316 | } | 325 | } |
317 | 326 | ||
318 | static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) | 327 | static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) |
319 | { | 328 | { |
320 | struct hci_conn_hash *h = &hdev->conn_hash; | 329 | struct hci_conn_hash *h = &hdev->conn_hash; |
321 | list_del(&c->list); | 330 | list_del(&c->list); |
322 | if (c->type == ACL_LINK) | 331 | switch (c->type) { |
332 | case ACL_LINK: | ||
323 | h->acl_num--; | 333 | 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: | ||
325 | h->sco_num--; | 340 | h->sco_num--; |
341 | break; | ||
342 | } | ||
326 | } | 343 | } |
327 | 344 | ||
328 | static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, | 345 | static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, |
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 | ||
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 | |||
48 | void hci_acl_connect(struct hci_conn *conn) | 74 | void 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 | } |
362 | EXPORT_SYMBOL(hci_get_route); | 392 | EXPORT_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 */ |
366 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type) | 396 | struct 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); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index cee46cbe7aeb..47c6e9316ce8 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1107,6 +1107,43 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) | |||
1107 | hci_dev_unlock(hdev); | 1107 | hci_dev_unlock(hdev); |
1108 | } | 1108 | } |
1109 | 1109 | ||
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 | |||
1110 | static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1147 | static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1111 | { | 1148 | { |
1112 | __u8 status = *((__u8 *) skb->data); | 1149 | __u8 status = *((__u8 *) skb->data); |
@@ -1738,6 +1775,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1738 | mgmt_disconnect_failed(hdev->id); | 1775 | mgmt_disconnect_failed(hdev->id); |
1739 | break; | 1776 | break; |
1740 | 1777 | ||
1778 | case HCI_OP_LE_CREATE_CONN: | ||
1779 | hci_cs_le_create_conn(hdev, ev->status); | ||
1780 | break; | ||
1781 | |||
1741 | default: | 1782 | default: |
1742 | BT_DBG("%s opcode 0x%x", hdev->name, opcode); | 1783 | BT_DBG("%s opcode 0x%x", hdev->name, opcode); |
1743 | break; | 1784 | break; |
@@ -2321,6 +2362,54 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ | |||
2321 | hci_dev_unlock(hdev); | 2362 | hci_dev_unlock(hdev); |
2322 | } | 2363 | } |
2323 | 2364 | ||
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 | |||
2324 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | 2413 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) |
2325 | { | 2414 | { |
2326 | struct hci_event_hdr *hdr = (void *) skb->data; | 2415 | struct hci_event_hdr *hdr = (void *) skb->data; |
@@ -2461,6 +2550,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
2461 | hci_remote_host_features_evt(hdev, skb); | 2550 | hci_remote_host_features_evt(hdev, skb); |
2462 | break; | 2551 | break; |
2463 | 2552 | ||
2553 | case HCI_EV_LE_META: | ||
2554 | hci_le_meta_evt(hdev, skb); | ||
2555 | break; | ||
2556 | |||
2464 | default: | 2557 | default: |
2465 | BT_DBG("%s event 0x%x", hdev->name, event); | 2558 | BT_DBG("%s event 0x%x", hdev->name, event); |
2466 | break; | 2559 | break; |