blob: d0c470c18f9df8c8d60eff7cdab7b20ea63e8b7b [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI connection handling. */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28
29#include <linux/types.h>
30#include <linux/errno.h>
31#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/slab.h>
33#include <linux/poll.h>
34#include <linux/fcntl.h>
35#include <linux/init.h>
36#include <linux/skbuff.h>
37#include <linux/interrupt.h>
38#include <linux/notifier.h>
39#include <net/sock.h>
40
41#include <asm/system.h>
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020042#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <asm/unaligned.h>
44
45#include <net/bluetooth/bluetooth.h>
46#include <net/bluetooth/hci_core.h>
47
Ville Tervofcd89c02011-02-10 22:38:47 -030048static 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
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020074void hci_acl_connect(struct hci_conn *conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -070075{
76 struct hci_dev *hdev = conn->hdev;
77 struct inquiry_entry *ie;
78 struct hci_cp_create_conn cp;
79
80 BT_DBG("%p", conn);
81
82 conn->state = BT_CONNECT;
Marcel Holtmanna8746412008-07-14 20:13:46 +020083 conn->out = 1;
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 conn->link_mode = HCI_LM_MASTER;
86
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020087 conn->attempt++;
88
Marcel Holtmanne4e8e372008-07-14 20:13:47 +020089 conn->link_policy = hdev->link_policy;
90
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 memset(&cp, 0, sizeof(cp));
92 bacpy(&cp.bdaddr, &conn->dst);
93 cp.pscan_rep_mode = 0x02;
94
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020095 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
96 if (ie) {
Marcel Holtmann41a96212008-07-14 20:13:48 +020097 if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
98 cp.pscan_rep_mode = ie->data.pscan_rep_mode;
99 cp.pscan_mode = ie->data.pscan_mode;
100 cp.clock_offset = ie->data.clock_offset |
101 cpu_to_le16(0x8000);
102 }
103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104 memcpy(conn->dev_class, ie->data.dev_class, 3);
Marcel Holtmann41a96212008-07-14 20:13:48 +0200105 conn->ssp_mode = ie->data.ssp_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 }
107
Marcel Holtmanna8746412008-07-14 20:13:46 +0200108 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200110 cp.role_switch = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 else
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200112 cp.role_switch = 0x00;
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200113
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200114 hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
116
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200117static void hci_acl_connect_cancel(struct hci_conn *conn)
118{
119 struct hci_cp_create_conn_cancel cp;
120
121 BT_DBG("%p", conn);
122
123 if (conn->hdev->hci_ver < 2)
124 return;
125
126 bacpy(&cp.bdaddr, &conn->dst);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200127 hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200128}
129
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
131{
132 struct hci_cp_disconnect cp;
133
134 BT_DBG("%p", conn);
135
136 conn->state = BT_DISCONN;
137
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700138 cp.handle = cpu_to_le16(conn->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 cp.reason = reason;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200140 hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141}
142
143void hci_add_sco(struct hci_conn *conn, __u16 handle)
144{
145 struct hci_dev *hdev = conn->hdev;
146 struct hci_cp_add_sco cp;
147
148 BT_DBG("%p", conn);
149
150 conn->state = BT_CONNECT;
151 conn->out = 1;
152
Marcel Holtmannefc76882009-02-06 09:13:37 +0100153 conn->attempt++;
154
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700155 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200156 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200158 hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159}
160
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200161void hci_setup_sync(struct hci_conn *conn, __u16 handle)
162{
163 struct hci_dev *hdev = conn->hdev;
164 struct hci_cp_setup_sync_conn cp;
165
166 BT_DBG("%p", conn);
167
168 conn->state = BT_CONNECT;
169 conn->out = 1;
170
Marcel Holtmannefc76882009-02-06 09:13:37 +0100171 conn->attempt++;
172
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200173 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200174 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200175
176 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
177 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
178 cp.max_latency = cpu_to_le16(0xffff);
179 cp.voice_setting = cpu_to_le16(hdev->voice_setting);
180 cp.retrans_effort = 0xff;
181
182 hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
183}
184
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400185/* Device _must_ be locked */
186void hci_sco_setup(struct hci_conn *conn, __u8 status)
187{
188 struct hci_conn *sco = conn->link;
189
190 BT_DBG("%p", conn);
191
192 if (!sco)
193 return;
194
195 if (!status) {
196 if (lmp_esco_capable(conn->hdev))
197 hci_setup_sync(sco, conn->handle);
198 else
199 hci_add_sco(sco, conn->handle);
200 } else {
201 hci_proto_connect_cfm(sco, status);
202 hci_conn_del(sco);
203 }
204}
205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206static void hci_conn_timeout(unsigned long arg)
207{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200208 struct hci_conn *conn = (void *) arg;
209 struct hci_dev *hdev = conn->hdev;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100210 __u8 reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
212 BT_DBG("conn %p state %d", conn, conn->state);
213
214 if (atomic_read(&conn->refcnt))
215 return;
216
217 hci_dev_lock(hdev);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200218
219 switch (conn->state) {
220 case BT_CONNECT:
Marcel Holtmann769be972008-07-14 20:13:49 +0200221 case BT_CONNECT2:
Ville Tervofcd89c02011-02-10 22:38:47 -0300222 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 }
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200228 break;
Marcel Holtmann769be972008-07-14 20:13:49 +0200229 case BT_CONFIG:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900230 case BT_CONNECTED:
Marcel Holtmann2950f212009-02-12 14:02:50 +0100231 reason = hci_proto_disconn_ind(conn);
232 hci_acl_disconn(conn, reason);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200233 break;
234 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 conn->state = BT_CLOSED;
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200236 break;
237 }
238
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240}
241
Marcel Holtmann04837f62006-07-03 10:02:33 +0200242static void hci_conn_idle(unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200244 struct hci_conn *conn = (void *) arg;
245
246 BT_DBG("conn %p mode %d", conn, conn->mode);
247
248 hci_conn_enter_sniff_mode(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249}
250
251struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
252{
253 struct hci_conn *conn;
254
255 BT_DBG("%s dst %s", hdev->name, batostr(dst));
256
Marcel Holtmann04837f62006-07-03 10:02:33 +0200257 conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC);
258 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
261 bacpy(&conn->dst, dst);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200262 conn->hdev = hdev;
263 conn->type = type;
264 conn->mode = HCI_CM_ACTIVE;
265 conn->state = BT_OPEN;
Andrei Emeltchenko93f19c92009-09-03 12:34:19 +0300266 conn->auth_type = HCI_AT_GENERAL_BONDING;
Johan Hedberg17fa4b92011-01-25 13:28:33 +0200267 conn->io_capability = hdev->io_capability;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Marcel Holtmann04837f62006-07-03 10:02:33 +0200269 conn->power_save = 1;
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200270 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200271
Marcel Holtmanna8746412008-07-14 20:13:46 +0200272 switch (type) {
273 case ACL_LINK:
274 conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
275 break;
276 case SCO_LINK:
277 if (lmp_esco_capable(hdev))
Marcel Holtmannefc76882009-02-06 09:13:37 +0100278 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
279 (hdev->esco_type & EDR_ESCO_MASK);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200280 else
281 conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
282 break;
283 case ESCO_LINK:
Marcel Holtmannefc76882009-02-06 09:13:37 +0100284 conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200285 break;
286 }
287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 skb_queue_head_init(&conn->data_q);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200289
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800290 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
291 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292
293 atomic_set(&conn->refcnt, 0);
294
295 hci_dev_hold(hdev);
296
297 tasklet_disable(&hdev->tx_task);
298
299 hci_conn_hash_add(hdev, conn);
300 if (hdev->notify)
301 hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
302
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700303 atomic_set(&conn->devref, 0);
304
Marcel Holtmanna67e8992009-05-02 18:24:06 -0700305 hci_conn_init_sysfs(conn);
306
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 tasklet_enable(&hdev->tx_task);
308
309 return conn;
310}
311
312int hci_conn_del(struct hci_conn *conn)
313{
314 struct hci_dev *hdev = conn->hdev;
315
316 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
317
Marcel Holtmann04837f62006-07-03 10:02:33 +0200318 del_timer(&conn->idle_timer);
319
320 del_timer(&conn->disc_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200322 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 struct hci_conn *sco = conn->link;
324 if (sco)
325 sco->link = NULL;
326
327 /* Unacked frames */
328 hdev->acl_cnt += conn->sent;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200329 } else {
330 struct hci_conn *acl = conn->link;
331 if (acl) {
332 acl->link = NULL;
333 hci_conn_put(acl);
334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 }
336
337 tasklet_disable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200338
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 hci_conn_hash_del(hdev, conn);
340 if (hdev->notify)
341 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 tasklet_enable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200344
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 skb_queue_purge(&conn->data_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700347 hci_conn_put_device(conn);
Dave Young2ae9a6b2009-02-21 16:13:34 +0800348
Marcel Holtmann384943e2009-05-08 18:20:43 -0700349 hci_dev_put(hdev);
350
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 return 0;
352}
353
354struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
355{
356 int use_src = bacmp(src, BDADDR_ANY);
357 struct hci_dev *hdev = NULL;
358 struct list_head *p;
359
360 BT_DBG("%s -> %s", batostr(src), batostr(dst));
361
362 read_lock_bh(&hci_dev_list_lock);
363
364 list_for_each(p, &hci_dev_list) {
365 struct hci_dev *d = list_entry(p, struct hci_dev, list);
366
367 if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
368 continue;
369
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900370 /* Simple routing:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 * No source address - find interface with bdaddr != dst
372 * Source address - find interface with bdaddr == src
373 */
374
375 if (use_src) {
376 if (!bacmp(&d->bdaddr, src)) {
377 hdev = d; break;
378 }
379 } else {
380 if (bacmp(&d->bdaddr, dst)) {
381 hdev = d; break;
382 }
383 }
384 }
385
386 if (hdev)
387 hdev = hci_dev_hold(hdev);
388
389 read_unlock_bh(&hci_dev_list_lock);
390 return hdev;
391}
392EXPORT_SYMBOL(hci_get_route);
393
Ville Tervofcd89c02011-02-10 22:38:47 -0300394/* Create SCO, ACL or LE connection.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 * Device _must_ be locked */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100396struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397{
398 struct hci_conn *acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200399 struct hci_conn *sco;
Ville Tervofcd89c02011-02-10 22:38:47 -0300400 struct hci_conn *le;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402 BT_DBG("%s dst %s", hdev->name, batostr(dst));
403
Ville Tervofcd89c02011-02-10 22:38:47 -0300404 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
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200418 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
419 if (!acl) {
420 acl = hci_conn_add(hdev, ACL_LINK, dst);
421 if (!acl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 return NULL;
423 }
424
425 hci_conn_hold(acl);
426
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200427 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
Johan Hedberg765c2a92011-01-19 12:06:52 +0530428 acl->sec_level = BT_SECURITY_LOW;
429 acl->pending_sec_level = sec_level;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200430 acl->auth_type = auth_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 hci_acl_connect(acl);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200434 if (type == ACL_LINK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 return acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200436
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200437 sco = hci_conn_hash_lookup_ba(hdev, type, dst);
438 if (!sco) {
439 sco = hci_conn_add(hdev, type, dst);
440 if (!sco) {
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200441 hci_conn_put(acl);
442 return NULL;
443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200445
446 acl->link = sco;
447 sco->link = acl;
448
449 hci_conn_hold(sco);
450
451 if (acl->state == BT_CONNECTED &&
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200452 (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
Nick Pellyc3902162009-11-13 14:16:32 -0800453 acl->power_save = 1;
454 hci_conn_enter_active_mode(acl);
455
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400456 if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
457 /* defer SCO setup until mode change completed */
458 set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
459 return sco;
460 }
461
462 hci_sco_setup(acl, 0x00);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200463 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200464
465 return sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466}
467EXPORT_SYMBOL(hci_connect);
468
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200469/* Check link security requirement */
470int hci_conn_check_link_mode(struct hci_conn *conn)
471{
472 BT_DBG("conn %p", conn);
473
474 if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
475 !(conn->link_mode & HCI_LM_ENCRYPT))
476 return 0;
477
478 return 1;
479}
480EXPORT_SYMBOL(hci_conn_check_link_mode);
481
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482/* Authenticate remote device */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100483static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
485 BT_DBG("conn %p", conn);
486
Johan Hedberg765c2a92011-01-19 12:06:52 +0530487 if (conn->pending_sec_level > sec_level)
488 sec_level = conn->pending_sec_level;
489
Marcel Holtmann96a31832009-02-12 16:23:03 +0100490 if (sec_level > conn->sec_level)
Johan Hedberg765c2a92011-01-19 12:06:52 +0530491 conn->pending_sec_level = sec_level;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100492 else if (conn->link_mode & HCI_LM_AUTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 return 1;
494
Johan Hedberg65cf6862011-01-19 12:06:49 +0530495 /* Make sure we preserve an existing MITM requirement*/
496 auth_type |= (conn->auth_type & 0x01);
497
Marcel Holtmann96a31832009-02-12 16:23:03 +0100498 conn->auth_type = auth_type;
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
501 struct hci_cp_auth_requested cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700502 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200503 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
504 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 return 0;
508}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100510/* Enable security */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100511int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512{
513 BT_DBG("conn %p", conn);
514
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100515 if (sec_level == BT_SECURITY_SDP)
516 return 1;
517
Marcel Holtmann3fdca1e2009-04-28 09:04:55 -0700518 if (sec_level == BT_SECURITY_LOW &&
519 (!conn->ssp_mode || !conn->hdev->ssp_mode))
520 return 1;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100521
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 if (conn->link_mode & HCI_LM_ENCRYPT)
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100523 return hci_conn_auth(conn, sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
525 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
526 return 0;
527
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100528 if (hci_conn_auth(conn, sec_level, auth_type)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 struct hci_cp_set_conn_encrypt cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700530 cp.handle = cpu_to_le16(conn->handle);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900531 cp.encrypt = 1;
Marcel Holtmann40be4922008-07-14 20:13:50 +0200532 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
533 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100535
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 return 0;
537}
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100538EXPORT_SYMBOL(hci_conn_security);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
540/* Change link key */
541int hci_conn_change_link_key(struct hci_conn *conn)
542{
543 BT_DBG("conn %p", conn);
544
545 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
546 struct hci_cp_change_conn_link_key cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700547 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200548 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
549 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100551
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 return 0;
553}
554EXPORT_SYMBOL(hci_conn_change_link_key);
555
556/* Switch role */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100557int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
559 BT_DBG("conn %p", conn);
560
561 if (!role && conn->link_mode & HCI_LM_MASTER)
562 return 1;
563
564 if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
565 struct hci_cp_switch_role cp;
566 bacpy(&cp.bdaddr, &conn->dst);
567 cp.role = role;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200568 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100570
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 return 0;
572}
573EXPORT_SYMBOL(hci_conn_switch_role);
574
Marcel Holtmann04837f62006-07-03 10:02:33 +0200575/* Enter active mode */
576void hci_conn_enter_active_mode(struct hci_conn *conn)
577{
578 struct hci_dev *hdev = conn->hdev;
579
580 BT_DBG("conn %p mode %d", conn, conn->mode);
581
582 if (test_bit(HCI_RAW, &hdev->flags))
583 return;
584
585 if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
586 goto timer;
587
588 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
589 struct hci_cp_exit_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700590 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200591 hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200592 }
593
594timer:
595 if (hdev->idle_timeout > 0)
596 mod_timer(&conn->idle_timer,
597 jiffies + msecs_to_jiffies(hdev->idle_timeout));
598}
599
600/* Enter sniff mode */
601void hci_conn_enter_sniff_mode(struct hci_conn *conn)
602{
603 struct hci_dev *hdev = conn->hdev;
604
605 BT_DBG("conn %p mode %d", conn, conn->mode);
606
607 if (test_bit(HCI_RAW, &hdev->flags))
608 return;
609
610 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
611 return;
612
613 if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
614 return;
615
616 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
617 struct hci_cp_sniff_subrate cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700618 cp.handle = cpu_to_le16(conn->handle);
619 cp.max_latency = cpu_to_le16(0);
620 cp.min_remote_timeout = cpu_to_le16(0);
621 cp.min_local_timeout = cpu_to_le16(0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200622 hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200623 }
624
625 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
626 struct hci_cp_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700627 cp.handle = cpu_to_le16(conn->handle);
628 cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
629 cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
630 cp.attempt = cpu_to_le16(4);
631 cp.timeout = cpu_to_le16(1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200632 hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200633 }
634}
635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636/* Drop all connection on the device */
637void hci_conn_hash_flush(struct hci_dev *hdev)
638{
639 struct hci_conn_hash *h = &hdev->conn_hash;
640 struct list_head *p;
641
642 BT_DBG("hdev %s", hdev->name);
643
644 p = h->list.next;
645 while (p != &h->list) {
646 struct hci_conn *c;
647
648 c = list_entry(p, struct hci_conn, list);
649 p = p->next;
650
651 c->state = BT_CLOSED;
652
Marcel Holtmann2950f212009-02-12 14:02:50 +0100653 hci_proto_disconn_cfm(c, 0x16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 hci_conn_del(c);
655 }
656}
657
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200658/* Check pending connect attempts */
659void hci_conn_check_pending(struct hci_dev *hdev)
660{
661 struct hci_conn *conn;
662
663 BT_DBG("hdev %s", hdev->name);
664
665 hci_dev_lock(hdev);
666
667 conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
668 if (conn)
669 hci_acl_connect(conn);
670
671 hci_dev_unlock(hdev);
672}
673
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700674void hci_conn_hold_device(struct hci_conn *conn)
675{
676 atomic_inc(&conn->devref);
677}
678EXPORT_SYMBOL(hci_conn_hold_device);
679
680void hci_conn_put_device(struct hci_conn *conn)
681{
682 if (atomic_dec_and_test(&conn->devref))
683 hci_conn_del_sysfs(conn);
684}
685EXPORT_SYMBOL(hci_conn_put_device);
686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687int hci_get_conn_list(void __user *arg)
688{
689 struct hci_conn_list_req req, *cl;
690 struct hci_conn_info *ci;
691 struct hci_dev *hdev;
692 struct list_head *p;
693 int n = 0, size, err;
694
695 if (copy_from_user(&req, arg, sizeof(req)))
696 return -EFAULT;
697
698 if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
699 return -EINVAL;
700
701 size = sizeof(req) + req.conn_num * sizeof(*ci);
702
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200703 cl = kmalloc(size, GFP_KERNEL);
704 if (!cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 return -ENOMEM;
706
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200707 hdev = hci_dev_get(req.dev_id);
708 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 kfree(cl);
710 return -ENODEV;
711 }
712
713 ci = cl->conn_info;
714
715 hci_dev_lock_bh(hdev);
716 list_for_each(p, &hdev->conn_hash.list) {
717 register struct hci_conn *c;
718 c = list_entry(p, struct hci_conn, list);
719
720 bacpy(&(ci + n)->bdaddr, &c->dst);
721 (ci + n)->handle = c->handle;
722 (ci + n)->type = c->type;
723 (ci + n)->out = c->out;
724 (ci + n)->state = c->state;
725 (ci + n)->link_mode = c->link_mode;
726 if (++n >= req.conn_num)
727 break;
728 }
729 hci_dev_unlock_bh(hdev);
730
731 cl->dev_id = hdev->id;
732 cl->conn_num = n;
733 size = sizeof(req) + n * sizeof(*ci);
734
735 hci_dev_put(hdev);
736
737 err = copy_to_user(arg, cl, size);
738 kfree(cl);
739
740 return err ? -EFAULT : 0;
741}
742
743int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
744{
745 struct hci_conn_info_req req;
746 struct hci_conn_info ci;
747 struct hci_conn *conn;
748 char __user *ptr = arg + sizeof(req);
749
750 if (copy_from_user(&req, arg, sizeof(req)))
751 return -EFAULT;
752
753 hci_dev_lock_bh(hdev);
754 conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
755 if (conn) {
756 bacpy(&ci.bdaddr, &conn->dst);
757 ci.handle = conn->handle;
758 ci.type = conn->type;
759 ci.out = conn->out;
760 ci.state = conn->state;
761 ci.link_mode = conn->link_mode;
762 }
763 hci_dev_unlock_bh(hdev);
764
765 if (!conn)
766 return -ENOENT;
767
768 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
769}
Marcel Holtmann40be4922008-07-14 20:13:50 +0200770
771int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
772{
773 struct hci_auth_info_req req;
774 struct hci_conn *conn;
775
776 if (copy_from_user(&req, arg, sizeof(req)))
777 return -EFAULT;
778
779 hci_dev_lock_bh(hdev);
780 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
781 if (conn)
782 req.type = conn->auth_type;
783 hci_dev_unlock_bh(hdev);
784
785 if (!conn)
786 return -ENOENT;
787
788 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
789}