blob: b7ff6e3ee25c5c6b103099d8f9871dac195287d3 [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;
Vinicius Costa Gomesb92a6222011-02-10 22:38:52 -030055 conn->link_mode |= HCI_LM_MASTER;
Vinicius Costa Gomes403d2c82011-06-09 18:50:50 -030056 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -030057
58 memset(&cp, 0, sizeof(cp));
59 cp.scan_interval = cpu_to_le16(0x0004);
60 cp.scan_window = cpu_to_le16(0x0004);
61 bacpy(&cp.peer_addr, &conn->dst);
Andre Guedesc7f0d992011-05-31 14:20:57 -030062 cp.peer_addr_type = conn->dst_type;
Ville Tervofcd89c02011-02-10 22:38:47 -030063 cp.conn_interval_min = cpu_to_le16(0x0008);
64 cp.conn_interval_max = cpu_to_le16(0x0100);
65 cp.supervision_timeout = cpu_to_le16(0x0064);
66 cp.min_ce_len = cpu_to_le16(0x0001);
67 cp.max_ce_len = cpu_to_le16(0x0001);
68
69 hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
70}
71
72static void hci_le_connect_cancel(struct hci_conn *conn)
73{
74 hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
75}
76
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020077void hci_acl_connect(struct hci_conn *conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -070078{
79 struct hci_dev *hdev = conn->hdev;
80 struct inquiry_entry *ie;
81 struct hci_cp_create_conn cp;
82
83 BT_DBG("%p", conn);
84
85 conn->state = BT_CONNECT;
Marcel Holtmanna8746412008-07-14 20:13:46 +020086 conn->out = 1;
87
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 conn->link_mode = HCI_LM_MASTER;
89
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020090 conn->attempt++;
91
Marcel Holtmanne4e8e372008-07-14 20:13:47 +020092 conn->link_policy = hdev->link_policy;
93
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 memset(&cp, 0, sizeof(cp));
95 bacpy(&cp.bdaddr, &conn->dst);
96 cp.pscan_rep_mode = 0x02;
97
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020098 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
99 if (ie) {
Marcel Holtmann41a96212008-07-14 20:13:48 +0200100 if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
101 cp.pscan_rep_mode = ie->data.pscan_rep_mode;
102 cp.pscan_mode = ie->data.pscan_mode;
103 cp.clock_offset = ie->data.clock_offset |
104 cpu_to_le16(0x8000);
105 }
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 memcpy(conn->dev_class, ie->data.dev_class, 3);
Marcel Holtmann41a96212008-07-14 20:13:48 +0200108 conn->ssp_mode = ie->data.ssp_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 }
110
Marcel Holtmanna8746412008-07-14 20:13:46 +0200111 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200113 cp.role_switch = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 else
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200115 cp.role_switch = 0x00;
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200116
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200117 hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118}
119
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200120static void hci_acl_connect_cancel(struct hci_conn *conn)
121{
122 struct hci_cp_create_conn_cancel cp;
123
124 BT_DBG("%p", conn);
125
126 if (conn->hdev->hci_ver < 2)
127 return;
128
129 bacpy(&cp.bdaddr, &conn->dst);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200130 hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200131}
132
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
134{
135 struct hci_cp_disconnect cp;
136
137 BT_DBG("%p", conn);
138
139 conn->state = BT_DISCONN;
140
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700141 cp.handle = cpu_to_le16(conn->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 cp.reason = reason;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200143 hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144}
145
146void hci_add_sco(struct hci_conn *conn, __u16 handle)
147{
148 struct hci_dev *hdev = conn->hdev;
149 struct hci_cp_add_sco cp;
150
151 BT_DBG("%p", conn);
152
153 conn->state = BT_CONNECT;
154 conn->out = 1;
155
Marcel Holtmannefc76882009-02-06 09:13:37 +0100156 conn->attempt++;
157
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700158 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200159 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200161 hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162}
163
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200164void hci_setup_sync(struct hci_conn *conn, __u16 handle)
165{
166 struct hci_dev *hdev = conn->hdev;
167 struct hci_cp_setup_sync_conn cp;
168
169 BT_DBG("%p", conn);
170
171 conn->state = BT_CONNECT;
172 conn->out = 1;
173
Marcel Holtmannefc76882009-02-06 09:13:37 +0100174 conn->attempt++;
175
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200176 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200177 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200178
179 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
180 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
181 cp.max_latency = cpu_to_le16(0xffff);
182 cp.voice_setting = cpu_to_le16(hdev->voice_setting);
183 cp.retrans_effort = 0xff;
184
185 hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
186}
187
Claudio Takahasi2ce603e2011-02-16 20:44:53 -0200188void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
189 u16 latency, u16 to_multiplier)
190{
191 struct hci_cp_le_conn_update cp;
192 struct hci_dev *hdev = conn->hdev;
193
194 memset(&cp, 0, sizeof(cp));
195
196 cp.handle = cpu_to_le16(conn->handle);
197 cp.conn_interval_min = cpu_to_le16(min);
198 cp.conn_interval_max = cpu_to_le16(max);
199 cp.conn_latency = cpu_to_le16(latency);
200 cp.supervision_timeout = cpu_to_le16(to_multiplier);
201 cp.min_ce_len = cpu_to_le16(0x0001);
202 cp.max_ce_len = cpu_to_le16(0x0001);
203
204 hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
205}
206EXPORT_SYMBOL(hci_le_conn_update);
207
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300208void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
209 __u8 ltk[16])
210{
211 struct hci_dev *hdev = conn->hdev;
212 struct hci_cp_le_start_enc cp;
213
214 BT_DBG("%p", conn);
215
216 memset(&cp, 0, sizeof(cp));
217
218 cp.handle = cpu_to_le16(conn->handle);
219 memcpy(cp.ltk, ltk, sizeof(cp.ltk));
220 cp.ediv = ediv;
221 memcpy(cp.rand, rand, sizeof(rand));
222
223 hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
224}
225EXPORT_SYMBOL(hci_le_start_enc);
226
227void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
228{
229 struct hci_dev *hdev = conn->hdev;
230 struct hci_cp_le_ltk_reply cp;
231
232 BT_DBG("%p", conn);
233
234 memset(&cp, 0, sizeof(cp));
235
236 cp.handle = cpu_to_le16(conn->handle);
237 memcpy(cp.ltk, ltk, sizeof(ltk));
238
239 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
240}
241EXPORT_SYMBOL(hci_le_ltk_reply);
242
243void hci_le_ltk_neg_reply(struct hci_conn *conn)
244{
245 struct hci_dev *hdev = conn->hdev;
246 struct hci_cp_le_ltk_neg_reply cp;
247
248 BT_DBG("%p", conn);
249
250 memset(&cp, 0, sizeof(cp));
251
252 cp.handle = cpu_to_le16(conn->handle);
253
254 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
255}
256
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400257/* Device _must_ be locked */
258void hci_sco_setup(struct hci_conn *conn, __u8 status)
259{
260 struct hci_conn *sco = conn->link;
261
262 BT_DBG("%p", conn);
263
264 if (!sco)
265 return;
266
267 if (!status) {
268 if (lmp_esco_capable(conn->hdev))
269 hci_setup_sync(sco, conn->handle);
270 else
271 hci_add_sco(sco, conn->handle);
272 } else {
273 hci_proto_connect_cfm(sco, status);
274 hci_conn_del(sco);
275 }
276}
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278static void hci_conn_timeout(unsigned long arg)
279{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200280 struct hci_conn *conn = (void *) arg;
281 struct hci_dev *hdev = conn->hdev;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100282 __u8 reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284 BT_DBG("conn %p state %d", conn, conn->state);
285
286 if (atomic_read(&conn->refcnt))
287 return;
288
289 hci_dev_lock(hdev);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200290
291 switch (conn->state) {
292 case BT_CONNECT:
Marcel Holtmann769be972008-07-14 20:13:49 +0200293 case BT_CONNECT2:
Ville Tervofcd89c02011-02-10 22:38:47 -0300294 if (conn->out) {
295 if (conn->type == ACL_LINK)
296 hci_acl_connect_cancel(conn);
297 else if (conn->type == LE_LINK)
298 hci_le_connect_cancel(conn);
299 }
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200300 break;
Marcel Holtmann769be972008-07-14 20:13:49 +0200301 case BT_CONFIG:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900302 case BT_CONNECTED:
Marcel Holtmann2950f212009-02-12 14:02:50 +0100303 reason = hci_proto_disconn_ind(conn);
304 hci_acl_disconn(conn, reason);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200305 break;
306 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 conn->state = BT_CLOSED;
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200308 break;
309 }
310
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312}
313
Marcel Holtmann04837f62006-07-03 10:02:33 +0200314static void hci_conn_idle(unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200316 struct hci_conn *conn = (void *) arg;
317
318 BT_DBG("conn %p mode %d", conn, conn->mode);
319
320 hci_conn_enter_sniff_mode(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321}
322
Johan Hedberg9f616562011-04-28 11:28:54 -0700323static void hci_conn_auto_accept(unsigned long arg)
324{
325 struct hci_conn *conn = (void *) arg;
326 struct hci_dev *hdev = conn->hdev;
327
328 hci_dev_lock(hdev);
329
330 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
331 &conn->dst);
332
333 hci_dev_unlock(hdev);
334}
335
Nick Pellybbcda3b2010-02-11 11:54:28 -0800336struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
337 __u16 pkt_type, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338{
339 struct hci_conn *conn;
340
341 BT_DBG("%s dst %s", hdev->name, batostr(dst));
342
Marcel Holtmann04837f62006-07-03 10:02:33 +0200343 conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC);
344 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
347 bacpy(&conn->dst, dst);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200348 conn->hdev = hdev;
349 conn->type = type;
350 conn->mode = HCI_CM_ACTIVE;
351 conn->state = BT_OPEN;
Andrei Emeltchenko93f19c92009-09-03 12:34:19 +0300352 conn->auth_type = HCI_AT_GENERAL_BONDING;
Johan Hedberg17fa4b92011-01-25 13:28:33 +0200353 conn->io_capability = hdev->io_capability;
Johan Hedberga9583552011-02-19 12:06:01 -0300354 conn->remote_auth = 0xff;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200355 conn->key_type = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
Marcel Holtmann04837f62006-07-03 10:02:33 +0200357 conn->power_save = 1;
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200358 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200359
Marcel Holtmanna8746412008-07-14 20:13:46 +0200360 switch (type) {
361 case ACL_LINK:
362 conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
363 break;
364 case SCO_LINK:
Nick Pellybbcda3b2010-02-11 11:54:28 -0800365 if (!pkt_type)
366 pkt_type = SCO_ESCO_MASK;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200367 case ESCO_LINK:
Nick Pellybbcda3b2010-02-11 11:54:28 -0800368 if (!pkt_type)
369 pkt_type = ALL_ESCO_MASK;
370 if (lmp_esco_capable(hdev)) {
371 /* HCI Setup Synchronous Connection Command uses
372 reverse logic on the EDR_ESCO_MASK bits */
373 conn->pkt_type = (pkt_type ^ EDR_ESCO_MASK) &
374 hdev->esco_type;
375 } else {
376 /* Legacy HCI Add Sco Connection Command uses a
377 shifted bitmask */
378 conn->pkt_type = (pkt_type << 5) & hdev->pkt_type &
379 SCO_PTYPE_MASK;
380 }
Marcel Holtmanna8746412008-07-14 20:13:46 +0200381 break;
382 }
383
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 skb_queue_head_init(&conn->data_q);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200385
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800386 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
387 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
Johan Hedberg9f616562011-04-28 11:28:54 -0700388 setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
389 (unsigned long) conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
391 atomic_set(&conn->refcnt, 0);
392
393 hci_dev_hold(hdev);
394
395 tasklet_disable(&hdev->tx_task);
396
397 hci_conn_hash_add(hdev, conn);
398 if (hdev->notify)
399 hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
400
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700401 atomic_set(&conn->devref, 0);
402
Marcel Holtmanna67e8992009-05-02 18:24:06 -0700403 hci_conn_init_sysfs(conn);
404
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 tasklet_enable(&hdev->tx_task);
406
407 return conn;
408}
409
410int hci_conn_del(struct hci_conn *conn)
411{
412 struct hci_dev *hdev = conn->hdev;
413
414 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
415
Marcel Holtmann04837f62006-07-03 10:02:33 +0200416 del_timer(&conn->idle_timer);
417
418 del_timer(&conn->disc_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Johan Hedberg9f616562011-04-28 11:28:54 -0700420 del_timer(&conn->auto_accept_timer);
421
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200422 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 struct hci_conn *sco = conn->link;
424 if (sco)
425 sco->link = NULL;
426
427 /* Unacked frames */
428 hdev->acl_cnt += conn->sent;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300429 } else if (conn->type == LE_LINK) {
430 if (hdev->le_pkts)
431 hdev->le_cnt += conn->sent;
432 else
433 hdev->acl_cnt += conn->sent;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200434 } else {
435 struct hci_conn *acl = conn->link;
436 if (acl) {
437 acl->link = NULL;
438 hci_conn_put(acl);
439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 }
441
442 tasklet_disable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200443
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 hci_conn_hash_del(hdev, conn);
445 if (hdev->notify)
446 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200447
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 tasklet_enable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200449
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 skb_queue_purge(&conn->data_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700452 hci_conn_put_device(conn);
Dave Young2ae9a6b2009-02-21 16:13:34 +0800453
Marcel Holtmann384943e2009-05-08 18:20:43 -0700454 hci_dev_put(hdev);
455
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 return 0;
457}
458
459struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
460{
461 int use_src = bacmp(src, BDADDR_ANY);
462 struct hci_dev *hdev = NULL;
463 struct list_head *p;
464
465 BT_DBG("%s -> %s", batostr(src), batostr(dst));
466
467 read_lock_bh(&hci_dev_list_lock);
468
469 list_for_each(p, &hci_dev_list) {
470 struct hci_dev *d = list_entry(p, struct hci_dev, list);
471
472 if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
473 continue;
474
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900475 /* Simple routing:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 * No source address - find interface with bdaddr != dst
477 * Source address - find interface with bdaddr == src
478 */
479
480 if (use_src) {
481 if (!bacmp(&d->bdaddr, src)) {
482 hdev = d; break;
483 }
484 } else {
485 if (bacmp(&d->bdaddr, dst)) {
486 hdev = d; break;
487 }
488 }
489 }
490
491 if (hdev)
492 hdev = hci_dev_hold(hdev);
493
494 read_unlock_bh(&hci_dev_list_lock);
495 return hdev;
496}
497EXPORT_SYMBOL(hci_get_route);
498
Ville Tervofcd89c02011-02-10 22:38:47 -0300499/* Create SCO, ACL or LE connection.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 * Device _must_ be locked */
Nick Pellybbcda3b2010-02-11 11:54:28 -0800501struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
502 __u16 pkt_type, bdaddr_t *dst,
503 __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
505 struct hci_conn *acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200506 struct hci_conn *sco;
Ville Tervofcd89c02011-02-10 22:38:47 -0300507 struct hci_conn *le;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
509 BT_DBG("%s dst %s", hdev->name, batostr(dst));
510
Ville Tervofcd89c02011-02-10 22:38:47 -0300511 if (type == LE_LINK) {
Andre Guedes5e89ece2011-05-31 14:20:56 -0300512 struct adv_entry *entry;
513
Ville Tervofcd89c02011-02-10 22:38:47 -0300514 le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
Anderson Briglia15c47942011-02-21 15:09:23 -0300515 if (le)
Ville Tervo30e76272011-02-22 16:10:53 -0300516 return ERR_PTR(-EBUSY);
Andre Guedes5e89ece2011-05-31 14:20:56 -0300517
518 entry = hci_find_adv_entry(hdev, dst);
519 if (!entry)
520 return ERR_PTR(-EHOSTUNREACH);
521
Nick Pellybbcda3b2010-02-11 11:54:28 -0800522 le = hci_conn_add(hdev, LE_LINK, 0, dst);
Ville Tervofcd89c02011-02-10 22:38:47 -0300523 if (!le)
Ville Tervo30e76272011-02-22 16:10:53 -0300524 return ERR_PTR(-ENOMEM);
Andre Guedes92398c82011-05-31 14:20:55 -0300525
Andre Guedes5e89ece2011-05-31 14:20:56 -0300526 le->dst_type = entry->bdaddr_type;
527
Andre Guedes92398c82011-05-31 14:20:55 -0300528 hci_le_connect(le);
Ville Tervofcd89c02011-02-10 22:38:47 -0300529
530 hci_conn_hold(le);
531
532 return le;
533 }
534
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200535 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
536 if (!acl) {
Nick Pellybbcda3b2010-02-11 11:54:28 -0800537 acl = hci_conn_add(hdev, ACL_LINK, 0, dst);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200538 if (!acl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 return NULL;
540 }
541
542 hci_conn_hold(acl);
543
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200544 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
Johan Hedberg765c2a92011-01-19 12:06:52 +0530545 acl->sec_level = BT_SECURITY_LOW;
546 acl->pending_sec_level = sec_level;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200547 acl->auth_type = auth_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 hci_acl_connect(acl);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200549 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200551 if (type == ACL_LINK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 return acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200553
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200554 sco = hci_conn_hash_lookup_ba(hdev, type, dst);
555 if (!sco) {
Nick Pellybbcda3b2010-02-11 11:54:28 -0800556 sco = hci_conn_add(hdev, type, pkt_type, dst);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200557 if (!sco) {
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200558 hci_conn_put(acl);
559 return NULL;
560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200562
563 acl->link = sco;
564 sco->link = acl;
565
566 hci_conn_hold(sco);
567
568 if (acl->state == BT_CONNECTED &&
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200569 (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
Nick Pellyc3902162009-11-13 14:16:32 -0800570 acl->power_save = 1;
Jaikumar Ganesh514abe62011-05-23 18:06:04 -0700571 hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
Nick Pellyc3902162009-11-13 14:16:32 -0800572
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400573 if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
574 /* defer SCO setup until mode change completed */
575 set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
576 return sco;
577 }
578
579 hci_sco_setup(acl, 0x00);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200580 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200581
582 return sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583}
584EXPORT_SYMBOL(hci_connect);
585
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200586/* Check link security requirement */
587int hci_conn_check_link_mode(struct hci_conn *conn)
588{
589 BT_DBG("conn %p", conn);
590
591 if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
592 !(conn->link_mode & HCI_LM_ENCRYPT))
593 return 0;
594
595 return 1;
596}
597EXPORT_SYMBOL(hci_conn_check_link_mode);
598
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599/* Authenticate remote device */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100600static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601{
602 BT_DBG("conn %p", conn);
603
Johan Hedberg765c2a92011-01-19 12:06:52 +0530604 if (conn->pending_sec_level > sec_level)
605 sec_level = conn->pending_sec_level;
606
Marcel Holtmann96a31832009-02-12 16:23:03 +0100607 if (sec_level > conn->sec_level)
Johan Hedberg765c2a92011-01-19 12:06:52 +0530608 conn->pending_sec_level = sec_level;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100609 else if (conn->link_mode & HCI_LM_AUTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 return 1;
611
Johan Hedberg65cf6862011-01-19 12:06:49 +0530612 /* Make sure we preserve an existing MITM requirement*/
613 auth_type |= (conn->auth_type & 0x01);
614
Marcel Holtmann96a31832009-02-12 16:23:03 +0100615 conn->auth_type = auth_type;
616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
618 struct hci_cp_auth_requested cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700619 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200620 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
621 sizeof(cp), &cp);
Waldemar Rymarkiewicz62c5f522011-05-31 15:49:25 +0200622 if (conn->key_type != 0xff)
623 set_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 return 0;
627}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200629/* Encrypt the the link */
630static void hci_conn_encrypt(struct hci_conn *conn)
631{
632 BT_DBG("conn %p", conn);
633
634 if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
635 struct hci_cp_set_conn_encrypt cp;
636 cp.handle = cpu_to_le16(conn->handle);
637 cp.encrypt = 0x01;
638 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
639 &cp);
640 }
641}
642
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100643/* Enable security */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100644int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 BT_DBG("conn %p", conn);
647
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200648 /* For sdp we don't need the link key. */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100649 if (sec_level == BT_SECURITY_SDP)
650 return 1;
651
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200652 /* For non 2.1 devices and low security level we don't need the link
653 key. */
Marcel Holtmann3fdca1e2009-04-28 09:04:55 -0700654 if (sec_level == BT_SECURITY_LOW &&
655 (!conn->ssp_mode || !conn->hdev->ssp_mode))
656 return 1;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100657
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200658 /* For other security levels we need the link key. */
659 if (!(conn->link_mode & HCI_LM_AUTH))
660 goto auth;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200662 /* An authenticated combination key has sufficient security for any
663 security level. */
664 if (conn->key_type == HCI_LK_AUTH_COMBINATION)
665 goto encrypt;
666
667 /* An unauthenticated combination key has sufficient security for
668 security level 1 and 2. */
669 if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
670 (sec_level == BT_SECURITY_MEDIUM ||
671 sec_level == BT_SECURITY_LOW))
672 goto encrypt;
673
674 /* A combination key has always sufficient security for the security
675 levels 1 or 2. High security level requires the combination key
676 is generated using maximum PIN code length (16).
677 For pre 2.1 units. */
678 if (conn->key_type == HCI_LK_COMBINATION &&
679 (sec_level != BT_SECURITY_HIGH ||
680 conn->pin_length == 16))
681 goto encrypt;
682
683auth:
Ilia Kolomisnky33060542011-06-15 06:52:26 +0300684 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 return 0;
686
Luiz Augusto von Dentz6fdf6582011-06-13 15:37:35 +0300687 if (!hci_conn_auth(conn, sec_level, auth_type))
688 return 0;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100689
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200690encrypt:
691 if (conn->link_mode & HCI_LM_ENCRYPT)
692 return 1;
693
694 hci_conn_encrypt(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 return 0;
696}
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100697EXPORT_SYMBOL(hci_conn_security);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
Waldemar Rymarkiewiczb3b1b062011-05-06 09:42:31 +0200699/* Check secure link requirement */
700int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
701{
702 BT_DBG("conn %p", conn);
703
704 if (sec_level != BT_SECURITY_HIGH)
705 return 1; /* Accept if non-secure is required */
706
Waldemar Rymarkiewicz8b00cf02011-06-02 14:24:52 +0200707 if (conn->sec_level == BT_SECURITY_HIGH)
Waldemar Rymarkiewiczb3b1b062011-05-06 09:42:31 +0200708 return 1;
709
710 return 0; /* Reject not secure link */
711}
712EXPORT_SYMBOL(hci_conn_check_secure);
713
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714/* Change link key */
715int hci_conn_change_link_key(struct hci_conn *conn)
716{
717 BT_DBG("conn %p", conn);
718
719 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
720 struct hci_cp_change_conn_link_key cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700721 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200722 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
723 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100725
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 return 0;
727}
728EXPORT_SYMBOL(hci_conn_change_link_key);
729
730/* Switch role */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100731int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732{
733 BT_DBG("conn %p", conn);
734
735 if (!role && conn->link_mode & HCI_LM_MASTER)
736 return 1;
737
738 if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
739 struct hci_cp_switch_role cp;
740 bacpy(&cp.bdaddr, &conn->dst);
741 cp.role = role;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200742 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100744
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 return 0;
746}
747EXPORT_SYMBOL(hci_conn_switch_role);
748
Marcel Holtmann04837f62006-07-03 10:02:33 +0200749/* Enter active mode */
Jaikumar Ganesh514abe62011-05-23 18:06:04 -0700750void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200751{
752 struct hci_dev *hdev = conn->hdev;
753
754 BT_DBG("conn %p mode %d", conn, conn->mode);
755
756 if (test_bit(HCI_RAW, &hdev->flags))
757 return;
758
Jaikumar Ganesh514abe62011-05-23 18:06:04 -0700759 if (conn->mode != HCI_CM_SNIFF)
760 goto timer;
761
762 if (!conn->power_save && !force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200763 goto timer;
764
765 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
766 struct hci_cp_exit_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700767 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200768 hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200769 }
770
771timer:
772 if (hdev->idle_timeout > 0)
773 mod_timer(&conn->idle_timer,
774 jiffies + msecs_to_jiffies(hdev->idle_timeout));
775}
776
777/* Enter sniff mode */
778void hci_conn_enter_sniff_mode(struct hci_conn *conn)
779{
780 struct hci_dev *hdev = conn->hdev;
781
782 BT_DBG("conn %p mode %d", conn, conn->mode);
783
784 if (test_bit(HCI_RAW, &hdev->flags))
785 return;
786
787 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
788 return;
789
790 if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
791 return;
792
793 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
794 struct hci_cp_sniff_subrate cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700795 cp.handle = cpu_to_le16(conn->handle);
796 cp.max_latency = cpu_to_le16(0);
797 cp.min_remote_timeout = cpu_to_le16(0);
798 cp.min_local_timeout = cpu_to_le16(0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200799 hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200800 }
801
802 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
803 struct hci_cp_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700804 cp.handle = cpu_to_le16(conn->handle);
805 cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
806 cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
807 cp.attempt = cpu_to_le16(4);
808 cp.timeout = cpu_to_le16(1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200809 hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200810 }
811}
812
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813/* Drop all connection on the device */
814void hci_conn_hash_flush(struct hci_dev *hdev)
815{
816 struct hci_conn_hash *h = &hdev->conn_hash;
817 struct list_head *p;
818
819 BT_DBG("hdev %s", hdev->name);
820
821 p = h->list.next;
822 while (p != &h->list) {
823 struct hci_conn *c;
824
825 c = list_entry(p, struct hci_conn, list);
826 p = p->next;
827
828 c->state = BT_CLOSED;
829
Marcel Holtmann2950f212009-02-12 14:02:50 +0100830 hci_proto_disconn_cfm(c, 0x16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 hci_conn_del(c);
832 }
833}
834
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200835/* Check pending connect attempts */
836void hci_conn_check_pending(struct hci_dev *hdev)
837{
838 struct hci_conn *conn;
839
840 BT_DBG("hdev %s", hdev->name);
841
842 hci_dev_lock(hdev);
843
844 conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
845 if (conn)
846 hci_acl_connect(conn);
847
848 hci_dev_unlock(hdev);
849}
850
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700851void hci_conn_hold_device(struct hci_conn *conn)
852{
853 atomic_inc(&conn->devref);
854}
855EXPORT_SYMBOL(hci_conn_hold_device);
856
857void hci_conn_put_device(struct hci_conn *conn)
858{
859 if (atomic_dec_and_test(&conn->devref))
860 hci_conn_del_sysfs(conn);
861}
862EXPORT_SYMBOL(hci_conn_put_device);
863
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864int hci_get_conn_list(void __user *arg)
865{
866 struct hci_conn_list_req req, *cl;
867 struct hci_conn_info *ci;
868 struct hci_dev *hdev;
869 struct list_head *p;
870 int n = 0, size, err;
871
872 if (copy_from_user(&req, arg, sizeof(req)))
873 return -EFAULT;
874
875 if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
876 return -EINVAL;
877
878 size = sizeof(req) + req.conn_num * sizeof(*ci);
879
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200880 cl = kmalloc(size, GFP_KERNEL);
881 if (!cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 return -ENOMEM;
883
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200884 hdev = hci_dev_get(req.dev_id);
885 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 kfree(cl);
887 return -ENODEV;
888 }
889
890 ci = cl->conn_info;
891
892 hci_dev_lock_bh(hdev);
893 list_for_each(p, &hdev->conn_hash.list) {
894 register struct hci_conn *c;
895 c = list_entry(p, struct hci_conn, list);
896
897 bacpy(&(ci + n)->bdaddr, &c->dst);
898 (ci + n)->handle = c->handle;
899 (ci + n)->type = c->type;
900 (ci + n)->out = c->out;
901 (ci + n)->state = c->state;
902 (ci + n)->link_mode = c->link_mode;
Nick Pellyc1728492009-12-09 00:15:41 -0800903 if (c->type == SCO_LINK) {
904 (ci + n)->mtu = hdev->sco_mtu;
905 (ci + n)->cnt = hdev->sco_cnt;
906 (ci + n)->pkts = hdev->sco_pkts;
907 } else {
908 (ci + n)->mtu = hdev->acl_mtu;
909 (ci + n)->cnt = hdev->acl_cnt;
910 (ci + n)->pkts = hdev->acl_pkts;
911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 if (++n >= req.conn_num)
913 break;
914 }
915 hci_dev_unlock_bh(hdev);
916
917 cl->dev_id = hdev->id;
918 cl->conn_num = n;
919 size = sizeof(req) + n * sizeof(*ci);
920
921 hci_dev_put(hdev);
922
923 err = copy_to_user(arg, cl, size);
924 kfree(cl);
925
926 return err ? -EFAULT : 0;
927}
928
929int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
930{
931 struct hci_conn_info_req req;
932 struct hci_conn_info ci;
933 struct hci_conn *conn;
934 char __user *ptr = arg + sizeof(req);
935
936 if (copy_from_user(&req, arg, sizeof(req)))
937 return -EFAULT;
938
939 hci_dev_lock_bh(hdev);
940 conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
941 if (conn) {
942 bacpy(&ci.bdaddr, &conn->dst);
943 ci.handle = conn->handle;
944 ci.type = conn->type;
945 ci.out = conn->out;
946 ci.state = conn->state;
947 ci.link_mode = conn->link_mode;
Nick Pellyc1728492009-12-09 00:15:41 -0800948 if (req.type == SCO_LINK) {
949 ci.mtu = hdev->sco_mtu;
950 ci.cnt = hdev->sco_cnt;
951 ci.pkts = hdev->sco_pkts;
952 } else {
953 ci.mtu = hdev->acl_mtu;
954 ci.cnt = hdev->acl_cnt;
955 ci.pkts = hdev->acl_pkts;
956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 }
958 hci_dev_unlock_bh(hdev);
959
960 if (!conn)
961 return -ENOENT;
962
963 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
964}
Marcel Holtmann40be4922008-07-14 20:13:50 +0200965
966int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
967{
968 struct hci_auth_info_req req;
969 struct hci_conn *conn;
970
971 if (copy_from_user(&req, arg, sizeof(req)))
972 return -EFAULT;
973
974 hci_dev_lock_bh(hdev);
975 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
976 if (conn)
977 req.type = conn->auth_type;
978 hci_dev_unlock_bh(hdev);
979
980 if (!conn)
981 return -ENOENT;
982
983 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
984}