blob: 6175ce841e9e84e116705f9a93e2e2fa142182da [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
3 Copyright (C) 2000-2001 Qualcomm Incorporated
4
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>
42#include <asm/uaccess.h>
43#include <asm/unaligned.h>
44
45#include <net/bluetooth/bluetooth.h>
46#include <net/bluetooth/hci_core.h>
47
48#ifndef CONFIG_BT_HCI_CORE_DEBUG
49#undef BT_DBG
50#define BT_DBG(D...)
51#endif
52
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020053void hci_acl_connect(struct hci_conn *conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -070054{
55 struct hci_dev *hdev = conn->hdev;
56 struct inquiry_entry *ie;
57 struct hci_cp_create_conn cp;
58
59 BT_DBG("%p", conn);
60
61 conn->state = BT_CONNECT;
Marcel Holtmanna8746412008-07-14 20:13:46 +020062 conn->out = 1;
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 conn->link_mode = HCI_LM_MASTER;
65
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020066 conn->attempt++;
67
Marcel Holtmanne4e8e372008-07-14 20:13:47 +020068 conn->link_policy = hdev->link_policy;
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 memset(&cp, 0, sizeof(cp));
71 bacpy(&cp.bdaddr, &conn->dst);
72 cp.pscan_rep_mode = 0x02;
73
74 if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)) &&
75 inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
76 cp.pscan_rep_mode = ie->data.pscan_rep_mode;
77 cp.pscan_mode = ie->data.pscan_mode;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -070078 cp.clock_offset = ie->data.clock_offset | cpu_to_le16(0x8000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 memcpy(conn->dev_class, ie->data.dev_class, 3);
80 }
81
Marcel Holtmanna8746412008-07-14 20:13:46 +020082 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +020084 cp.role_switch = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 else
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +020086 cp.role_switch = 0x00;
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020087
Marcel Holtmanna9de9242007-10-20 13:33:56 +020088 hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089}
90
Marcel Holtmann6ac59342006-09-26 09:43:48 +020091static void hci_acl_connect_cancel(struct hci_conn *conn)
92{
93 struct hci_cp_create_conn_cancel cp;
94
95 BT_DBG("%p", conn);
96
97 if (conn->hdev->hci_ver < 2)
98 return;
99
100 bacpy(&cp.bdaddr, &conn->dst);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200101 hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200102}
103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
105{
106 struct hci_cp_disconnect cp;
107
108 BT_DBG("%p", conn);
109
110 conn->state = BT_DISCONN;
111
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700112 cp.handle = cpu_to_le16(conn->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 cp.reason = reason;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200114 hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
116
117void hci_add_sco(struct hci_conn *conn, __u16 handle)
118{
119 struct hci_dev *hdev = conn->hdev;
120 struct hci_cp_add_sco cp;
121
122 BT_DBG("%p", conn);
123
124 conn->state = BT_CONNECT;
125 conn->out = 1;
126
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700127 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200128 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200130 hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131}
132
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200133void hci_setup_sync(struct hci_conn *conn, __u16 handle)
134{
135 struct hci_dev *hdev = conn->hdev;
136 struct hci_cp_setup_sync_conn cp;
137
138 BT_DBG("%p", conn);
139
140 conn->state = BT_CONNECT;
141 conn->out = 1;
142
143 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200144 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200145
146 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
147 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
148 cp.max_latency = cpu_to_le16(0xffff);
149 cp.voice_setting = cpu_to_le16(hdev->voice_setting);
150 cp.retrans_effort = 0xff;
151
152 hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
153}
154
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155static void hci_conn_timeout(unsigned long arg)
156{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200157 struct hci_conn *conn = (void *) arg;
158 struct hci_dev *hdev = conn->hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
160 BT_DBG("conn %p state %d", conn, conn->state);
161
162 if (atomic_read(&conn->refcnt))
163 return;
164
165 hci_dev_lock(hdev);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200166
167 switch (conn->state) {
168 case BT_CONNECT:
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200169 if (conn->type == ACL_LINK)
170 hci_acl_connect_cancel(conn);
171 else
172 hci_acl_disconn(conn, 0x13);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200173 break;
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900174 case BT_CONNECTED:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 hci_acl_disconn(conn, 0x13);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200176 break;
177 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 conn->state = BT_CLOSED;
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200179 break;
180 }
181
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183}
184
Marcel Holtmann04837f62006-07-03 10:02:33 +0200185static void hci_conn_idle(unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200187 struct hci_conn *conn = (void *) arg;
188
189 BT_DBG("conn %p mode %d", conn, conn->mode);
190
191 hci_conn_enter_sniff_mode(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192}
193
194struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
195{
196 struct hci_conn *conn;
197
198 BT_DBG("%s dst %s", hdev->name, batostr(dst));
199
Marcel Holtmann04837f62006-07-03 10:02:33 +0200200 conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC);
201 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204 bacpy(&conn->dst, dst);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200205 conn->hdev = hdev;
206 conn->type = type;
207 conn->mode = HCI_CM_ACTIVE;
208 conn->state = BT_OPEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
Marcel Holtmann04837f62006-07-03 10:02:33 +0200210 conn->power_save = 1;
211
Marcel Holtmanna8746412008-07-14 20:13:46 +0200212 switch (type) {
213 case ACL_LINK:
214 conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
215 break;
216 case SCO_LINK:
217 if (lmp_esco_capable(hdev))
218 conn->pkt_type = hdev->esco_type & SCO_ESCO_MASK;
219 else
220 conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
221 break;
222 case ESCO_LINK:
223 conn->pkt_type = hdev->esco_type;
224 break;
225 }
226
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 skb_queue_head_init(&conn->data_q);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200228
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800229 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
230 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
232 atomic_set(&conn->refcnt, 0);
233
234 hci_dev_hold(hdev);
235
236 tasklet_disable(&hdev->tx_task);
237
238 hci_conn_hash_add(hdev, conn);
239 if (hdev->notify)
240 hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
241
Marcel Holtmannb219e3a2006-07-06 12:38:46 +0200242 hci_conn_add_sysfs(conn);
243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 tasklet_enable(&hdev->tx_task);
245
246 return conn;
247}
248
249int hci_conn_del(struct hci_conn *conn)
250{
251 struct hci_dev *hdev = conn->hdev;
252
253 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
254
Marcel Holtmann04837f62006-07-03 10:02:33 +0200255 del_timer(&conn->idle_timer);
256
257 del_timer(&conn->disc_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200259 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 struct hci_conn *sco = conn->link;
261 if (sco)
262 sco->link = NULL;
263
264 /* Unacked frames */
265 hdev->acl_cnt += conn->sent;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200266 } else {
267 struct hci_conn *acl = conn->link;
268 if (acl) {
269 acl->link = NULL;
270 hci_conn_put(acl);
271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 }
273
274 tasklet_disable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 hci_conn_hash_del(hdev, conn);
276 if (hdev->notify)
277 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 tasklet_enable(&hdev->tx_task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 skb_queue_purge(&conn->data_q);
Dave Young38b7da02007-12-29 19:17:47 -0800280 hci_conn_del_sysfs(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 return 0;
283}
284
285struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
286{
287 int use_src = bacmp(src, BDADDR_ANY);
288 struct hci_dev *hdev = NULL;
289 struct list_head *p;
290
291 BT_DBG("%s -> %s", batostr(src), batostr(dst));
292
293 read_lock_bh(&hci_dev_list_lock);
294
295 list_for_each(p, &hci_dev_list) {
296 struct hci_dev *d = list_entry(p, struct hci_dev, list);
297
298 if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
299 continue;
300
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900301 /* Simple routing:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 * No source address - find interface with bdaddr != dst
303 * Source address - find interface with bdaddr == src
304 */
305
306 if (use_src) {
307 if (!bacmp(&d->bdaddr, src)) {
308 hdev = d; break;
309 }
310 } else {
311 if (bacmp(&d->bdaddr, dst)) {
312 hdev = d; break;
313 }
314 }
315 }
316
317 if (hdev)
318 hdev = hci_dev_hold(hdev);
319
320 read_unlock_bh(&hci_dev_list_lock);
321 return hdev;
322}
323EXPORT_SYMBOL(hci_get_route);
324
325/* Create SCO or ACL connection.
326 * Device _must_ be locked */
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200327struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328{
329 struct hci_conn *acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200330 struct hci_conn *sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
332 BT_DBG("%s dst %s", hdev->name, batostr(dst));
333
334 if (!(acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst))) {
335 if (!(acl = hci_conn_add(hdev, ACL_LINK, dst)))
336 return NULL;
337 }
338
339 hci_conn_hold(acl);
340
341 if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
342 hci_acl_connect(acl);
343
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200344 if (type == ACL_LINK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 return acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200346
347 if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) {
348 if (!(sco = hci_conn_add(hdev, type, dst))) {
349 hci_conn_put(acl);
350 return NULL;
351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200353
354 acl->link = sco;
355 sco->link = acl;
356
357 hci_conn_hold(sco);
358
359 if (acl->state == BT_CONNECTED &&
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200360 (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
361 if (lmp_esco_capable(hdev))
362 hci_setup_sync(sco, acl->handle);
363 else
364 hci_add_sco(sco, acl->handle);
365 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200366
367 return sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368}
369EXPORT_SYMBOL(hci_connect);
370
371/* Authenticate remote device */
372int hci_conn_auth(struct hci_conn *conn)
373{
374 BT_DBG("conn %p", conn);
375
376 if (conn->link_mode & HCI_LM_AUTH)
377 return 1;
378
379 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
380 struct hci_cp_auth_requested cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700381 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200382 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 }
384 return 0;
385}
386EXPORT_SYMBOL(hci_conn_auth);
387
388/* Enable encryption */
389int hci_conn_encrypt(struct hci_conn *conn)
390{
391 BT_DBG("conn %p", conn);
392
393 if (conn->link_mode & HCI_LM_ENCRYPT)
394 return 1;
395
396 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
397 return 0;
398
399 if (hci_conn_auth(conn)) {
400 struct hci_cp_set_conn_encrypt cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700401 cp.handle = cpu_to_le16(conn->handle);
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900402 cp.encrypt = 1;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200403 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 }
405 return 0;
406}
407EXPORT_SYMBOL(hci_conn_encrypt);
408
409/* Change link key */
410int hci_conn_change_link_key(struct hci_conn *conn)
411{
412 BT_DBG("conn %p", conn);
413
414 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
415 struct hci_cp_change_conn_link_key cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700416 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200417 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 }
419 return 0;
420}
421EXPORT_SYMBOL(hci_conn_change_link_key);
422
423/* Switch role */
424int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
425{
426 BT_DBG("conn %p", conn);
427
428 if (!role && conn->link_mode & HCI_LM_MASTER)
429 return 1;
430
431 if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
432 struct hci_cp_switch_role cp;
433 bacpy(&cp.bdaddr, &conn->dst);
434 cp.role = role;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200435 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 }
437 return 0;
438}
439EXPORT_SYMBOL(hci_conn_switch_role);
440
Marcel Holtmann04837f62006-07-03 10:02:33 +0200441/* Enter active mode */
442void hci_conn_enter_active_mode(struct hci_conn *conn)
443{
444 struct hci_dev *hdev = conn->hdev;
445
446 BT_DBG("conn %p mode %d", conn, conn->mode);
447
448 if (test_bit(HCI_RAW, &hdev->flags))
449 return;
450
451 if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
452 goto timer;
453
454 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
455 struct hci_cp_exit_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700456 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200457 hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200458 }
459
460timer:
461 if (hdev->idle_timeout > 0)
462 mod_timer(&conn->idle_timer,
463 jiffies + msecs_to_jiffies(hdev->idle_timeout));
464}
465
466/* Enter sniff mode */
467void hci_conn_enter_sniff_mode(struct hci_conn *conn)
468{
469 struct hci_dev *hdev = conn->hdev;
470
471 BT_DBG("conn %p mode %d", conn, conn->mode);
472
473 if (test_bit(HCI_RAW, &hdev->flags))
474 return;
475
476 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
477 return;
478
479 if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
480 return;
481
482 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
483 struct hci_cp_sniff_subrate cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700484 cp.handle = cpu_to_le16(conn->handle);
485 cp.max_latency = cpu_to_le16(0);
486 cp.min_remote_timeout = cpu_to_le16(0);
487 cp.min_local_timeout = cpu_to_le16(0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200488 hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200489 }
490
491 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
492 struct hci_cp_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700493 cp.handle = cpu_to_le16(conn->handle);
494 cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
495 cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
496 cp.attempt = cpu_to_le16(4);
497 cp.timeout = cpu_to_le16(1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200498 hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200499 }
500}
501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502/* Drop all connection on the device */
503void hci_conn_hash_flush(struct hci_dev *hdev)
504{
505 struct hci_conn_hash *h = &hdev->conn_hash;
506 struct list_head *p;
507
508 BT_DBG("hdev %s", hdev->name);
509
510 p = h->list.next;
511 while (p != &h->list) {
512 struct hci_conn *c;
513
514 c = list_entry(p, struct hci_conn, list);
515 p = p->next;
516
517 c->state = BT_CLOSED;
518
519 hci_proto_disconn_ind(c, 0x16);
520 hci_conn_del(c);
521 }
522}
523
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200524/* Check pending connect attempts */
525void hci_conn_check_pending(struct hci_dev *hdev)
526{
527 struct hci_conn *conn;
528
529 BT_DBG("hdev %s", hdev->name);
530
531 hci_dev_lock(hdev);
532
533 conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
534 if (conn)
535 hci_acl_connect(conn);
536
537 hci_dev_unlock(hdev);
538}
539
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540int hci_get_conn_list(void __user *arg)
541{
542 struct hci_conn_list_req req, *cl;
543 struct hci_conn_info *ci;
544 struct hci_dev *hdev;
545 struct list_head *p;
546 int n = 0, size, err;
547
548 if (copy_from_user(&req, arg, sizeof(req)))
549 return -EFAULT;
550
551 if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
552 return -EINVAL;
553
554 size = sizeof(req) + req.conn_num * sizeof(*ci);
555
Jesper Juhl12fe2c52006-01-10 13:08:21 -0800556 if (!(cl = kmalloc(size, GFP_KERNEL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 return -ENOMEM;
558
559 if (!(hdev = hci_dev_get(req.dev_id))) {
560 kfree(cl);
561 return -ENODEV;
562 }
563
564 ci = cl->conn_info;
565
566 hci_dev_lock_bh(hdev);
567 list_for_each(p, &hdev->conn_hash.list) {
568 register struct hci_conn *c;
569 c = list_entry(p, struct hci_conn, list);
570
571 bacpy(&(ci + n)->bdaddr, &c->dst);
572 (ci + n)->handle = c->handle;
573 (ci + n)->type = c->type;
574 (ci + n)->out = c->out;
575 (ci + n)->state = c->state;
576 (ci + n)->link_mode = c->link_mode;
577 if (++n >= req.conn_num)
578 break;
579 }
580 hci_dev_unlock_bh(hdev);
581
582 cl->dev_id = hdev->id;
583 cl->conn_num = n;
584 size = sizeof(req) + n * sizeof(*ci);
585
586 hci_dev_put(hdev);
587
588 err = copy_to_user(arg, cl, size);
589 kfree(cl);
590
591 return err ? -EFAULT : 0;
592}
593
594int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
595{
596 struct hci_conn_info_req req;
597 struct hci_conn_info ci;
598 struct hci_conn *conn;
599 char __user *ptr = arg + sizeof(req);
600
601 if (copy_from_user(&req, arg, sizeof(req)))
602 return -EFAULT;
603
604 hci_dev_lock_bh(hdev);
605 conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
606 if (conn) {
607 bacpy(&ci.bdaddr, &conn->dst);
608 ci.handle = conn->handle;
609 ci.type = conn->type;
610 ci.out = conn->out;
611 ci.state = conn->state;
612 ci.link_mode = conn->link_mode;
613 }
614 hci_dev_unlock_bh(hdev);
615
616 if (!conn)
617 return -ENOENT;
618
619 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
620}