blob: aecd78e6cceb06ca163e7de53d660dec51eb2e0d [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;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300329 } else if (conn->type == LE_LINK) {
330 if (hdev->le_pkts)
331 hdev->le_cnt += conn->sent;
332 else
333 hdev->acl_cnt += conn->sent;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200334 } else {
335 struct hci_conn *acl = conn->link;
336 if (acl) {
337 acl->link = NULL;
338 hci_conn_put(acl);
339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 }
341
342 tasklet_disable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200343
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 hci_conn_hash_del(hdev, conn);
345 if (hdev->notify)
346 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200347
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 tasklet_enable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 skb_queue_purge(&conn->data_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700352 hci_conn_put_device(conn);
Dave Young2ae9a6b2009-02-21 16:13:34 +0800353
Marcel Holtmann384943e2009-05-08 18:20:43 -0700354 hci_dev_put(hdev);
355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 return 0;
357}
358
359struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
360{
361 int use_src = bacmp(src, BDADDR_ANY);
362 struct hci_dev *hdev = NULL;
363 struct list_head *p;
364
365 BT_DBG("%s -> %s", batostr(src), batostr(dst));
366
367 read_lock_bh(&hci_dev_list_lock);
368
369 list_for_each(p, &hci_dev_list) {
370 struct hci_dev *d = list_entry(p, struct hci_dev, list);
371
372 if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
373 continue;
374
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900375 /* Simple routing:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 * No source address - find interface with bdaddr != dst
377 * Source address - find interface with bdaddr == src
378 */
379
380 if (use_src) {
381 if (!bacmp(&d->bdaddr, src)) {
382 hdev = d; break;
383 }
384 } else {
385 if (bacmp(&d->bdaddr, dst)) {
386 hdev = d; break;
387 }
388 }
389 }
390
391 if (hdev)
392 hdev = hci_dev_hold(hdev);
393
394 read_unlock_bh(&hci_dev_list_lock);
395 return hdev;
396}
397EXPORT_SYMBOL(hci_get_route);
398
Ville Tervofcd89c02011-02-10 22:38:47 -0300399/* Create SCO, ACL or LE connection.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 * Device _must_ be locked */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100401struct 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 -0700402{
403 struct hci_conn *acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200404 struct hci_conn *sco;
Ville Tervofcd89c02011-02-10 22:38:47 -0300405 struct hci_conn *le;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
407 BT_DBG("%s dst %s", hdev->name, batostr(dst));
408
Ville Tervofcd89c02011-02-10 22:38:47 -0300409 if (type == LE_LINK) {
410 le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
411 if (!le)
412 le = hci_conn_add(hdev, LE_LINK, dst);
413 if (!le)
414 return NULL;
415 if (le->state == BT_OPEN)
416 hci_le_connect(le);
417
418 hci_conn_hold(le);
419
420 return le;
421 }
422
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200423 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
424 if (!acl) {
425 acl = hci_conn_add(hdev, ACL_LINK, dst);
426 if (!acl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 return NULL;
428 }
429
430 hci_conn_hold(acl);
431
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200432 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
Johan Hedberg765c2a92011-01-19 12:06:52 +0530433 acl->sec_level = BT_SECURITY_LOW;
434 acl->pending_sec_level = sec_level;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200435 acl->auth_type = auth_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 hci_acl_connect(acl);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200439 if (type == ACL_LINK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 return acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200441
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200442 sco = hci_conn_hash_lookup_ba(hdev, type, dst);
443 if (!sco) {
444 sco = hci_conn_add(hdev, type, dst);
445 if (!sco) {
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200446 hci_conn_put(acl);
447 return NULL;
448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200450
451 acl->link = sco;
452 sco->link = acl;
453
454 hci_conn_hold(sco);
455
456 if (acl->state == BT_CONNECTED &&
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200457 (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
Nick Pellyc3902162009-11-13 14:16:32 -0800458 acl->power_save = 1;
459 hci_conn_enter_active_mode(acl);
460
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400461 if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
462 /* defer SCO setup until mode change completed */
463 set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
464 return sco;
465 }
466
467 hci_sco_setup(acl, 0x00);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200468 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200469
470 return sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471}
472EXPORT_SYMBOL(hci_connect);
473
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200474/* Check link security requirement */
475int hci_conn_check_link_mode(struct hci_conn *conn)
476{
477 BT_DBG("conn %p", conn);
478
479 if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
480 !(conn->link_mode & HCI_LM_ENCRYPT))
481 return 0;
482
483 return 1;
484}
485EXPORT_SYMBOL(hci_conn_check_link_mode);
486
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487/* Authenticate remote device */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100488static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
490 BT_DBG("conn %p", conn);
491
Johan Hedberg765c2a92011-01-19 12:06:52 +0530492 if (conn->pending_sec_level > sec_level)
493 sec_level = conn->pending_sec_level;
494
Marcel Holtmann96a31832009-02-12 16:23:03 +0100495 if (sec_level > conn->sec_level)
Johan Hedberg765c2a92011-01-19 12:06:52 +0530496 conn->pending_sec_level = sec_level;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100497 else if (conn->link_mode & HCI_LM_AUTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 return 1;
499
Johan Hedberg65cf6862011-01-19 12:06:49 +0530500 /* Make sure we preserve an existing MITM requirement*/
501 auth_type |= (conn->auth_type & 0x01);
502
Marcel Holtmann96a31832009-02-12 16:23:03 +0100503 conn->auth_type = auth_type;
504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
506 struct hci_cp_auth_requested cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700507 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200508 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
509 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100511
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 return 0;
513}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100515/* Enable security */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100516int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517{
518 BT_DBG("conn %p", conn);
519
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100520 if (sec_level == BT_SECURITY_SDP)
521 return 1;
522
Marcel Holtmann3fdca1e2009-04-28 09:04:55 -0700523 if (sec_level == BT_SECURITY_LOW &&
524 (!conn->ssp_mode || !conn->hdev->ssp_mode))
525 return 1;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 if (conn->link_mode & HCI_LM_ENCRYPT)
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100528 return hci_conn_auth(conn, sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529
530 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
531 return 0;
532
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100533 if (hci_conn_auth(conn, sec_level, auth_type)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 struct hci_cp_set_conn_encrypt cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700535 cp.handle = cpu_to_le16(conn->handle);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900536 cp.encrypt = 1;
Marcel Holtmann40be4922008-07-14 20:13:50 +0200537 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
538 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100540
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 return 0;
542}
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100543EXPORT_SYMBOL(hci_conn_security);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
545/* Change link key */
546int hci_conn_change_link_key(struct hci_conn *conn)
547{
548 BT_DBG("conn %p", conn);
549
550 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
551 struct hci_cp_change_conn_link_key cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700552 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200553 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
554 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 return 0;
558}
559EXPORT_SYMBOL(hci_conn_change_link_key);
560
561/* Switch role */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100562int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563{
564 BT_DBG("conn %p", conn);
565
566 if (!role && conn->link_mode & HCI_LM_MASTER)
567 return 1;
568
569 if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
570 struct hci_cp_switch_role cp;
571 bacpy(&cp.bdaddr, &conn->dst);
572 cp.role = role;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200573 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100575
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 return 0;
577}
578EXPORT_SYMBOL(hci_conn_switch_role);
579
Marcel Holtmann04837f62006-07-03 10:02:33 +0200580/* Enter active mode */
581void hci_conn_enter_active_mode(struct hci_conn *conn)
582{
583 struct hci_dev *hdev = conn->hdev;
584
585 BT_DBG("conn %p mode %d", conn, conn->mode);
586
587 if (test_bit(HCI_RAW, &hdev->flags))
588 return;
589
590 if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
591 goto timer;
592
593 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
594 struct hci_cp_exit_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700595 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200596 hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200597 }
598
599timer:
600 if (hdev->idle_timeout > 0)
601 mod_timer(&conn->idle_timer,
602 jiffies + msecs_to_jiffies(hdev->idle_timeout));
603}
604
605/* Enter sniff mode */
606void hci_conn_enter_sniff_mode(struct hci_conn *conn)
607{
608 struct hci_dev *hdev = conn->hdev;
609
610 BT_DBG("conn %p mode %d", conn, conn->mode);
611
612 if (test_bit(HCI_RAW, &hdev->flags))
613 return;
614
615 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
616 return;
617
618 if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
619 return;
620
621 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
622 struct hci_cp_sniff_subrate cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700623 cp.handle = cpu_to_le16(conn->handle);
624 cp.max_latency = cpu_to_le16(0);
625 cp.min_remote_timeout = cpu_to_le16(0);
626 cp.min_local_timeout = cpu_to_le16(0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200627 hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200628 }
629
630 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
631 struct hci_cp_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700632 cp.handle = cpu_to_le16(conn->handle);
633 cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
634 cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
635 cp.attempt = cpu_to_le16(4);
636 cp.timeout = cpu_to_le16(1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200637 hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200638 }
639}
640
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641/* Drop all connection on the device */
642void hci_conn_hash_flush(struct hci_dev *hdev)
643{
644 struct hci_conn_hash *h = &hdev->conn_hash;
645 struct list_head *p;
646
647 BT_DBG("hdev %s", hdev->name);
648
649 p = h->list.next;
650 while (p != &h->list) {
651 struct hci_conn *c;
652
653 c = list_entry(p, struct hci_conn, list);
654 p = p->next;
655
656 c->state = BT_CLOSED;
657
Marcel Holtmann2950f212009-02-12 14:02:50 +0100658 hci_proto_disconn_cfm(c, 0x16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 hci_conn_del(c);
660 }
661}
662
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200663/* Check pending connect attempts */
664void hci_conn_check_pending(struct hci_dev *hdev)
665{
666 struct hci_conn *conn;
667
668 BT_DBG("hdev %s", hdev->name);
669
670 hci_dev_lock(hdev);
671
672 conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
673 if (conn)
674 hci_acl_connect(conn);
675
676 hci_dev_unlock(hdev);
677}
678
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700679void hci_conn_hold_device(struct hci_conn *conn)
680{
681 atomic_inc(&conn->devref);
682}
683EXPORT_SYMBOL(hci_conn_hold_device);
684
685void hci_conn_put_device(struct hci_conn *conn)
686{
687 if (atomic_dec_and_test(&conn->devref))
688 hci_conn_del_sysfs(conn);
689}
690EXPORT_SYMBOL(hci_conn_put_device);
691
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692int hci_get_conn_list(void __user *arg)
693{
694 struct hci_conn_list_req req, *cl;
695 struct hci_conn_info *ci;
696 struct hci_dev *hdev;
697 struct list_head *p;
698 int n = 0, size, err;
699
700 if (copy_from_user(&req, arg, sizeof(req)))
701 return -EFAULT;
702
703 if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
704 return -EINVAL;
705
706 size = sizeof(req) + req.conn_num * sizeof(*ci);
707
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200708 cl = kmalloc(size, GFP_KERNEL);
709 if (!cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 return -ENOMEM;
711
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200712 hdev = hci_dev_get(req.dev_id);
713 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 kfree(cl);
715 return -ENODEV;
716 }
717
718 ci = cl->conn_info;
719
720 hci_dev_lock_bh(hdev);
721 list_for_each(p, &hdev->conn_hash.list) {
722 register struct hci_conn *c;
723 c = list_entry(p, struct hci_conn, list);
724
725 bacpy(&(ci + n)->bdaddr, &c->dst);
726 (ci + n)->handle = c->handle;
727 (ci + n)->type = c->type;
728 (ci + n)->out = c->out;
729 (ci + n)->state = c->state;
730 (ci + n)->link_mode = c->link_mode;
731 if (++n >= req.conn_num)
732 break;
733 }
734 hci_dev_unlock_bh(hdev);
735
736 cl->dev_id = hdev->id;
737 cl->conn_num = n;
738 size = sizeof(req) + n * sizeof(*ci);
739
740 hci_dev_put(hdev);
741
742 err = copy_to_user(arg, cl, size);
743 kfree(cl);
744
745 return err ? -EFAULT : 0;
746}
747
748int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
749{
750 struct hci_conn_info_req req;
751 struct hci_conn_info ci;
752 struct hci_conn *conn;
753 char __user *ptr = arg + sizeof(req);
754
755 if (copy_from_user(&req, arg, sizeof(req)))
756 return -EFAULT;
757
758 hci_dev_lock_bh(hdev);
759 conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
760 if (conn) {
761 bacpy(&ci.bdaddr, &conn->dst);
762 ci.handle = conn->handle;
763 ci.type = conn->type;
764 ci.out = conn->out;
765 ci.state = conn->state;
766 ci.link_mode = conn->link_mode;
767 }
768 hci_dev_unlock_bh(hdev);
769
770 if (!conn)
771 return -ENOENT;
772
773 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
774}
Marcel Holtmann40be4922008-07-14 20:13:50 +0200775
776int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
777{
778 struct hci_auth_info_req req;
779 struct hci_conn *conn;
780
781 if (copy_from_user(&req, arg, sizeof(req)))
782 return -EFAULT;
783
784 hci_dev_lock_bh(hdev);
785 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
786 if (conn)
787 req.type = conn->auth_type;
788 hci_dev_unlock_bh(hdev);
789
790 if (!conn)
791 return -ENOENT;
792
793 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
794}