blob: 079538bf75fe1372673ebc27a22ad7a5f2192e7c [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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07003 Copyright (c) 2000-2001, 2010-2011 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{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 BT_DBG("%p", conn);
136
137 conn->state = BT_DISCONN;
138
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700139 if (conn->hdev->dev_type == HCI_BREDR) {
140 struct hci_cp_disconnect cp;
141 cp.handle = cpu_to_le16(conn->handle);
142 cp.reason = reason;
143 hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
144 } else {
145 struct hci_cp_disconn_phys_link cp;
146 cp.phy_handle = (u8) conn->handle;
147 cp.reason = reason;
148 hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHYS_LINK,
149 sizeof(cp), &cp);
150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151}
152
153void hci_add_sco(struct hci_conn *conn, __u16 handle)
154{
155 struct hci_dev *hdev = conn->hdev;
156 struct hci_cp_add_sco cp;
157
158 BT_DBG("%p", conn);
159
160 conn->state = BT_CONNECT;
161 conn->out = 1;
162
Marcel Holtmannefc76882009-02-06 09:13:37 +0100163 conn->attempt++;
164
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700165 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200166 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200168 hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169}
170
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200171void hci_setup_sync(struct hci_conn *conn, __u16 handle)
172{
173 struct hci_dev *hdev = conn->hdev;
174 struct hci_cp_setup_sync_conn cp;
175
176 BT_DBG("%p", conn);
177
178 conn->state = BT_CONNECT;
179 conn->out = 1;
180
Marcel Holtmannefc76882009-02-06 09:13:37 +0100181 conn->attempt++;
182
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200183 cp.handle = cpu_to_le16(handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200184
185 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
186 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
Kun Han Kim15b911f2011-07-08 09:30:28 -0700187 if (conn->hdev->is_wbs) {
188 /* Transparent Data */
189 uint16_t voice_setting = hdev->voice_setting | ACF_TRANS;
190 cp.max_latency = cpu_to_le16(0x000D);
191 cp.pkt_type = cpu_to_le16(ESCO_WBS);
192 cp.voice_setting = cpu_to_le16(voice_setting);
193 /* Retransmission Effort */
194 cp.retrans_effort = RE_LINK_QUALITY;
195 } else {
196 cp.max_latency = cpu_to_le16(0x000A);
197 cp.pkt_type = cpu_to_le16(conn->pkt_type);
198 cp.voice_setting = cpu_to_le16(hdev->voice_setting);
199 cp.retrans_effort = RE_POWER_CONSUMP;
200 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200201
202 hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
203}
204
Claudio Takahasi2ce603e2011-02-16 20:44:53 -0200205void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
206 u16 latency, u16 to_multiplier)
207{
208 struct hci_cp_le_conn_update cp;
209 struct hci_dev *hdev = conn->hdev;
210
211 memset(&cp, 0, sizeof(cp));
212
213 cp.handle = cpu_to_le16(conn->handle);
214 cp.conn_interval_min = cpu_to_le16(min);
215 cp.conn_interval_max = cpu_to_le16(max);
216 cp.conn_latency = cpu_to_le16(latency);
217 cp.supervision_timeout = cpu_to_le16(to_multiplier);
218 cp.min_ce_len = cpu_to_le16(0x0001);
219 cp.max_ce_len = cpu_to_le16(0x0001);
220
221 hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
222}
223EXPORT_SYMBOL(hci_le_conn_update);
224
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300225void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
226 __u8 ltk[16])
227{
228 struct hci_dev *hdev = conn->hdev;
229 struct hci_cp_le_start_enc cp;
230
231 BT_DBG("%p", conn);
232
233 memset(&cp, 0, sizeof(cp));
234
235 cp.handle = cpu_to_le16(conn->handle);
236 memcpy(cp.ltk, ltk, sizeof(cp.ltk));
237 cp.ediv = ediv;
Brian Gix842bc5e2011-09-07 08:13:41 -0700238 memcpy(cp.rand, rand, sizeof(cp.rand));
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300239
240 hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
241}
242EXPORT_SYMBOL(hci_le_start_enc);
243
244void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
245{
246 struct hci_dev *hdev = conn->hdev;
247 struct hci_cp_le_ltk_reply cp;
248
249 BT_DBG("%p", conn);
250
251 memset(&cp, 0, sizeof(cp));
252
253 cp.handle = cpu_to_le16(conn->handle);
254 memcpy(cp.ltk, ltk, sizeof(ltk));
255
256 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
257}
258EXPORT_SYMBOL(hci_le_ltk_reply);
259
260void hci_le_ltk_neg_reply(struct hci_conn *conn)
261{
262 struct hci_dev *hdev = conn->hdev;
263 struct hci_cp_le_ltk_neg_reply cp;
264
265 BT_DBG("%p", conn);
266
267 memset(&cp, 0, sizeof(cp));
268
269 cp.handle = cpu_to_le16(conn->handle);
270
271 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
272}
273
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400274/* Device _must_ be locked */
275void hci_sco_setup(struct hci_conn *conn, __u8 status)
276{
277 struct hci_conn *sco = conn->link;
278
279 BT_DBG("%p", conn);
280
281 if (!sco)
282 return;
283
284 if (!status) {
285 if (lmp_esco_capable(conn->hdev))
286 hci_setup_sync(sco, conn->handle);
287 else
288 hci_add_sco(sco, conn->handle);
289 } else {
290 hci_proto_connect_cfm(sco, status);
291 hci_conn_del(sco);
292 }
293}
294
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295static void hci_conn_timeout(unsigned long arg)
296{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200297 struct hci_conn *conn = (void *) arg;
298 struct hci_dev *hdev = conn->hdev;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100299 __u8 reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 BT_DBG("conn %p state %d", conn, conn->state);
302
303 if (atomic_read(&conn->refcnt))
304 return;
305
306 hci_dev_lock(hdev);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200307
308 switch (conn->state) {
309 case BT_CONNECT:
Marcel Holtmann769be972008-07-14 20:13:49 +0200310 case BT_CONNECT2:
Ville Tervofcd89c02011-02-10 22:38:47 -0300311 if (conn->out) {
312 if (conn->type == ACL_LINK)
313 hci_acl_connect_cancel(conn);
314 else if (conn->type == LE_LINK)
315 hci_le_connect_cancel(conn);
316 }
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200317 break;
Marcel Holtmann769be972008-07-14 20:13:49 +0200318 case BT_CONFIG:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900319 case BT_CONNECTED:
Marcel Holtmann2950f212009-02-12 14:02:50 +0100320 reason = hci_proto_disconn_ind(conn);
321 hci_acl_disconn(conn, reason);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200322 break;
323 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 conn->state = BT_CLOSED;
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200325 break;
326 }
327
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329}
330
Marcel Holtmann04837f62006-07-03 10:02:33 +0200331static void hci_conn_idle(unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200333 struct hci_conn *conn = (void *) arg;
334
335 BT_DBG("conn %p mode %d", conn, conn->mode);
336
337 hci_conn_enter_sniff_mode(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338}
339
Nick Pellybbcda3b2010-02-11 11:54:28 -0800340struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
341 __u16 pkt_type, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342{
343 struct hci_conn *conn;
344
345 BT_DBG("%s dst %s", hdev->name, batostr(dst));
346
Marcel Holtmann04837f62006-07-03 10:02:33 +0200347 conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC);
348 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351 bacpy(&conn->dst, dst);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200352 conn->hdev = hdev;
353 conn->type = type;
354 conn->mode = HCI_CM_ACTIVE;
355 conn->state = BT_OPEN;
Andrei Emeltchenko93f19c92009-09-03 12:34:19 +0300356 conn->auth_type = HCI_AT_GENERAL_BONDING;
Johan Hedberg17fa4b92011-01-25 13:28:33 +0200357 conn->io_capability = hdev->io_capability;
Johan Hedberga9583552011-02-19 12:06:01 -0300358 conn->remote_auth = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Marcel Holtmann04837f62006-07-03 10:02:33 +0200360 conn->power_save = 1;
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200361 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200362
Marcel Holtmanna8746412008-07-14 20:13:46 +0200363 switch (type) {
364 case ACL_LINK:
365 conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
366 break;
367 case SCO_LINK:
Nick Pellybbcda3b2010-02-11 11:54:28 -0800368 if (!pkt_type)
369 pkt_type = SCO_ESCO_MASK;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200370 case ESCO_LINK:
Nick Pellybbcda3b2010-02-11 11:54:28 -0800371 if (!pkt_type)
372 pkt_type = ALL_ESCO_MASK;
373 if (lmp_esco_capable(hdev)) {
374 /* HCI Setup Synchronous Connection Command uses
375 reverse logic on the EDR_ESCO_MASK bits */
376 conn->pkt_type = (pkt_type ^ EDR_ESCO_MASK) &
377 hdev->esco_type;
378 } else {
379 /* Legacy HCI Add Sco Connection Command uses a
380 shifted bitmask */
381 conn->pkt_type = (pkt_type << 5) & hdev->pkt_type &
382 SCO_PTYPE_MASK;
383 }
Marcel Holtmanna8746412008-07-14 20:13:46 +0200384 break;
385 }
386
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 skb_queue_head_init(&conn->data_q);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200388
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800389 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
390 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
392 atomic_set(&conn->refcnt, 0);
393
394 hci_dev_hold(hdev);
395
396 tasklet_disable(&hdev->tx_task);
397
398 hci_conn_hash_add(hdev, conn);
399 if (hdev->notify)
400 hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
401
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700402 atomic_set(&conn->devref, 0);
403
Marcel Holtmanna67e8992009-05-02 18:24:06 -0700404 hci_conn_init_sysfs(conn);
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 tasklet_enable(&hdev->tx_task);
407
408 return conn;
409}
410
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700411struct hci_conn *hci_le_conn_add(struct hci_dev *hdev, bdaddr_t *dst,
412 __u8 addr_type)
413{
414 struct hci_conn *conn = hci_conn_add(hdev, LE_LINK, 0, dst);
415 if (!conn)
416 return NULL;
417
418 conn->dst_type = addr_type;
419
420 return conn;
421}
422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423int hci_conn_del(struct hci_conn *conn)
424{
425 struct hci_dev *hdev = conn->hdev;
426
427 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
428
Marcel Holtmann04837f62006-07-03 10:02:33 +0200429 del_timer(&conn->idle_timer);
430
431 del_timer(&conn->disc_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200433 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 struct hci_conn *sco = conn->link;
435 if (sco)
436 sco->link = NULL;
437
438 /* Unacked frames */
439 hdev->acl_cnt += conn->sent;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300440 } else if (conn->type == LE_LINK) {
441 if (hdev->le_pkts)
442 hdev->le_cnt += conn->sent;
443 else
444 hdev->acl_cnt += conn->sent;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200445 } else {
446 struct hci_conn *acl = conn->link;
447 if (acl) {
448 acl->link = NULL;
449 hci_conn_put(acl);
450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 }
452
453 tasklet_disable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200454
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 hci_conn_hash_del(hdev, conn);
456 if (hdev->notify)
457 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200458
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 tasklet_enable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200460
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 skb_queue_purge(&conn->data_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700463 hci_conn_put_device(conn);
Dave Young2ae9a6b2009-02-21 16:13:34 +0800464
Marcel Holtmann384943e2009-05-08 18:20:43 -0700465 hci_dev_put(hdev);
466
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700467 return 0;
468}
469
470struct hci_chan *hci_chan_add(struct hci_dev *hdev)
471{
472 struct hci_chan *chan;
473
474 BT_DBG("%s", hdev->name);
475
476 chan = kzalloc(sizeof(struct hci_chan), GFP_ATOMIC);
477 if (!chan)
478 return NULL;
479
480 atomic_set(&chan->refcnt, 0);
481
482 hci_dev_hold(hdev);
483
484 chan->hdev = hdev;
485
486 list_add(&chan->list, &hdev->chan_list.list);
487
488 return chan;
489}
490
491int hci_chan_del(struct hci_chan *chan)
492{
493 BT_DBG("%s chan %p", chan->hdev->name, chan);
494
495 list_del(&chan->list);
496
497 hci_conn_put(chan->conn);
498 hci_dev_put(chan->hdev);
499
500 kfree(chan);
Tomas Targownik1be668d2011-06-30 16:30:44 -0300501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 return 0;
503}
504
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700505void hci_chan_put(struct hci_chan *chan)
506{
507 struct hci_cp_disconn_logical_link cp;
508
509 BT_DBG("chan %p refcnt %d", chan, atomic_read(&chan->refcnt));
510 if (!atomic_dec_and_test(&chan->refcnt))
511 return;
512
513 BT_DBG("chan->conn->state %d", chan->conn->state);
514 if (chan->conn->state == BT_CONNECTED) {
515 cp.log_handle = cpu_to_le16(chan->ll_handle);
516 hci_send_cmd(chan->conn->hdev, HCI_OP_DISCONN_LOGICAL_LINK,
517 sizeof(cp), &cp);
518 } else
519 hci_chan_del(chan);
520}
521EXPORT_SYMBOL(hci_chan_put);
522
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
524{
525 int use_src = bacmp(src, BDADDR_ANY);
526 struct hci_dev *hdev = NULL;
527 struct list_head *p;
528
529 BT_DBG("%s -> %s", batostr(src), batostr(dst));
530
531 read_lock_bh(&hci_dev_list_lock);
532
533 list_for_each(p, &hci_dev_list) {
534 struct hci_dev *d = list_entry(p, struct hci_dev, list);
535
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700536 if (d->dev_type != HCI_BREDR)
537 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
539 continue;
540
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900541 /* Simple routing:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 * No source address - find interface with bdaddr != dst
543 * Source address - find interface with bdaddr == src
544 */
545
546 if (use_src) {
547 if (!bacmp(&d->bdaddr, src)) {
548 hdev = d; break;
549 }
550 } else {
551 if (bacmp(&d->bdaddr, dst)) {
552 hdev = d; break;
553 }
554 }
555 }
556
557 if (hdev)
558 hdev = hci_dev_hold(hdev);
559
560 read_unlock_bh(&hci_dev_list_lock);
561 return hdev;
562}
563EXPORT_SYMBOL(hci_get_route);
564
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565struct hci_dev *hci_dev_get_type(u8 amp_type)
566{
567 struct hci_dev *hdev = NULL;
568 struct hci_dev *d;
569
570 BT_DBG("amp_type %d", amp_type);
571
572 read_lock_bh(&hci_dev_list_lock);
573
574 list_for_each_entry(d, &hci_dev_list, list) {
575 if ((d->amp_type == amp_type) && test_bit(HCI_UP, &d->flags)) {
576 hdev = d;
577 break;
578 }
579 }
580
581 if (hdev)
582 hdev = hci_dev_hold(hdev);
583
584 read_unlock_bh(&hci_dev_list_lock);
585 return hdev;
586}
587EXPORT_SYMBOL(hci_dev_get_type);
588
589struct hci_dev *hci_dev_get_amp(bdaddr_t *dst)
590{
591 struct hci_dev *d;
592 struct hci_dev *hdev = NULL;
593
594 BT_DBG("%s dst %s", hdev->name, batostr(dst));
595
596 read_lock_bh(&hci_dev_list_lock);
597
598 list_for_each_entry(d, &hci_dev_list, list) {
599 struct hci_conn *conn;
600 if (d->dev_type == HCI_BREDR)
601 continue;
602 conn = hci_conn_hash_lookup_ba(d, ACL_LINK, dst);
603 if (conn) {
604 hdev = d;
605 break;
606 }
607 }
608
609 if (hdev)
610 hdev = hci_dev_hold(hdev);
611
612 read_unlock_bh(&hci_dev_list_lock);
613 return hdev;
614}
615EXPORT_SYMBOL(hci_dev_get_amp);
616
Ville Tervofcd89c02011-02-10 22:38:47 -0300617/* Create SCO, ACL or LE connection.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 * Device _must_ be locked */
Nick Pellybbcda3b2010-02-11 11:54:28 -0800619struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
620 __u16 pkt_type, bdaddr_t *dst,
621 __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
623 struct hci_conn *acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200624 struct hci_conn *sco;
Ville Tervofcd89c02011-02-10 22:38:47 -0300625 struct hci_conn *le;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627 BT_DBG("%s dst %s", hdev->name, batostr(dst));
628
Ville Tervofcd89c02011-02-10 22:38:47 -0300629 if (type == LE_LINK) {
Andre Guedes5e89ece2011-05-31 14:20:56 -0300630 struct adv_entry *entry;
631
Ville Tervofcd89c02011-02-10 22:38:47 -0300632 le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
Brian Gix2e2f50d2011-09-13 12:36:04 -0700633 if (le) {
634 hci_conn_hold(le);
Brian Gixa68668b2011-08-11 15:49:36 -0700635 return le;
Brian Gix2e2f50d2011-09-13 12:36:04 -0700636 }
Andre Guedes5e89ece2011-05-31 14:20:56 -0300637
638 entry = hci_find_adv_entry(hdev, dst);
639 if (!entry)
Brian Gixa68668b2011-08-11 15:49:36 -0700640 le = hci_le_conn_add(hdev, dst, 0);
641 else
642 le = hci_le_conn_add(hdev, dst, entry->bdaddr_type);
Andre Guedes5e89ece2011-05-31 14:20:56 -0300643
Ville Tervofcd89c02011-02-10 22:38:47 -0300644 if (!le)
Ville Tervo30e76272011-02-22 16:10:53 -0300645 return ERR_PTR(-ENOMEM);
Andre Guedes92398c82011-05-31 14:20:55 -0300646
647 hci_le_connect(le);
Ville Tervofcd89c02011-02-10 22:38:47 -0300648
649 hci_conn_hold(le);
650
651 return le;
652 }
653
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200654 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
655 if (!acl) {
Nick Pellybbcda3b2010-02-11 11:54:28 -0800656 acl = hci_conn_add(hdev, ACL_LINK, 0, dst);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200657 if (!acl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 return NULL;
659 }
660
661 hci_conn_hold(acl);
662
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200663 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
Johan Hedberg765c2a92011-01-19 12:06:52 +0530664 acl->sec_level = BT_SECURITY_LOW;
665 acl->pending_sec_level = sec_level;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200666 acl->auth_type = auth_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 hci_acl_connect(acl);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200670 if (type == ACL_LINK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 return acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200672
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200673 sco = hci_conn_hash_lookup_ba(hdev, type, dst);
674 if (!sco) {
Nick Pellybbcda3b2010-02-11 11:54:28 -0800675 sco = hci_conn_add(hdev, type, pkt_type, dst);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200676 if (!sco) {
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200677 hci_conn_put(acl);
678 return NULL;
679 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200681
682 acl->link = sco;
683 sco->link = acl;
684
685 hci_conn_hold(sco);
686
687 if (acl->state == BT_CONNECTED &&
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200688 (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
Nick Pellyc3902162009-11-13 14:16:32 -0800689 acl->power_save = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690 hci_conn_enter_active_mode(acl, 1);
Nick Pellyc3902162009-11-13 14:16:32 -0800691
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400692 if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
693 /* defer SCO setup until mode change completed */
694 set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
695 return sco;
696 }
697
698 hci_sco_setup(acl, 0x00);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200699 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200700
701 return sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702}
703EXPORT_SYMBOL(hci_connect);
704
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705void hci_disconnect(struct hci_conn *conn, __u8 reason)
706{
707 BT_DBG("conn %p", conn);
708
709 hci_proto_disconn_cfm(conn, reason);
710}
711EXPORT_SYMBOL(hci_disconnect);
712
713void hci_disconnect_amp(struct hci_conn *conn, __u8 reason)
714{
715 struct hci_dev *hdev = NULL;
716
717 BT_DBG("conn %p", conn);
718
719 read_lock_bh(&hci_dev_list_lock);
720
721 list_for_each_entry(hdev, &hci_dev_list, list) {
722 struct hci_conn *c;
723 if (hdev == conn->hdev)
724 continue;
725 if (hdev->amp_type == HCI_BREDR)
726 continue;
727 c = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &conn->dst);
728 if (c)
729 hci_disconnect(c, reason);
730 }
731
732 read_unlock_bh(&hci_dev_list_lock);
733}
734
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200735/* Check link security requirement */
736int hci_conn_check_link_mode(struct hci_conn *conn)
737{
738 BT_DBG("conn %p", conn);
739
740 if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
741 !(conn->link_mode & HCI_LM_ENCRYPT))
742 return 0;
743
744 return 1;
745}
746EXPORT_SYMBOL(hci_conn_check_link_mode);
747
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748/* Authenticate remote device */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100749static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
751 BT_DBG("conn %p", conn);
752
Johan Hedberg765c2a92011-01-19 12:06:52 +0530753 if (conn->pending_sec_level > sec_level)
754 sec_level = conn->pending_sec_level;
755
Marcel Holtmann96a31832009-02-12 16:23:03 +0100756 if (sec_level > conn->sec_level)
Johan Hedberg765c2a92011-01-19 12:06:52 +0530757 conn->pending_sec_level = sec_level;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100758 else if (conn->link_mode & HCI_LM_AUTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 return 1;
760
Johan Hedberg65cf6862011-01-19 12:06:49 +0530761 /* Make sure we preserve an existing MITM requirement*/
762 auth_type |= (conn->auth_type & 0x01);
Marcel Holtmann96a31832009-02-12 16:23:03 +0100763 conn->auth_type = auth_type;
Brian Gixa68668b2011-08-11 15:49:36 -0700764 conn->auth_initiator = 1;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
767 struct hci_cp_auth_requested cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700768 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200769 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
770 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100772
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 return 0;
774}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100776/* Enable security */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100777int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778{
Brian Gixa68668b2011-08-11 15:49:36 -0700779 BT_DBG("conn %p %d %d", conn, sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100781 if (sec_level == BT_SECURITY_SDP)
782 return 1;
783
Marcel Holtmann3fdca1e2009-04-28 09:04:55 -0700784 if (sec_level == BT_SECURITY_LOW &&
785 (!conn->ssp_mode || !conn->hdev->ssp_mode))
786 return 1;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100787
Brian Gix2e2f50d2011-09-13 12:36:04 -0700788 if (conn->type == LE_LINK) {
789 if (conn->pending_sec_level > sec_level)
790 sec_level = conn->pending_sec_level;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200791
Brian Gix2e2f50d2011-09-13 12:36:04 -0700792 if (sec_level > conn->sec_level)
793 conn->pending_sec_level = sec_level;
794 hci_proto_connect_cfm(conn, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700795 return 0;
Brian Gix2e2f50d2011-09-13 12:36:04 -0700796 } else if (conn->link_mode & HCI_LM_ENCRYPT) {
797 return hci_conn_auth(conn, sec_level, auth_type);
798 } else if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
799 return 0;
800 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700801
802 if (hci_conn_auth(conn, sec_level, auth_type)) {
803 struct hci_cp_set_conn_encrypt cp;
804 cp.handle = cpu_to_le16(conn->handle);
805 cp.encrypt = 1;
806 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
807 sizeof(cp), &cp);
808 }
809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 return 0;
811}
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100812EXPORT_SYMBOL(hci_conn_security);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
814/* Change link key */
815int hci_conn_change_link_key(struct hci_conn *conn)
816{
817 BT_DBG("conn %p", conn);
818
819 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
820 struct hci_cp_change_conn_link_key cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700821 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200822 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
823 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100825
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 return 0;
827}
828EXPORT_SYMBOL(hci_conn_change_link_key);
829
830/* Switch role */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100831int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832{
833 BT_DBG("conn %p", conn);
834
835 if (!role && conn->link_mode & HCI_LM_MASTER)
836 return 1;
837
838 if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
839 struct hci_cp_switch_role cp;
840 bacpy(&cp.bdaddr, &conn->dst);
841 cp.role = role;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200842 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100844
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 return 0;
846}
847EXPORT_SYMBOL(hci_conn_switch_role);
848
Marcel Holtmann04837f62006-07-03 10:02:33 +0200849/* Enter active mode */
Jaikumar Ganesh514abe62011-05-23 18:06:04 -0700850void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200851{
852 struct hci_dev *hdev = conn->hdev;
853
854 BT_DBG("conn %p mode %d", conn, conn->mode);
855
856 if (test_bit(HCI_RAW, &hdev->flags))
857 return;
858
Jaikumar Ganesh514abe62011-05-23 18:06:04 -0700859 if (conn->mode != HCI_CM_SNIFF)
860 goto timer;
861
862 if (!conn->power_save && !force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200863 goto timer;
864
865 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
866 struct hci_cp_exit_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700867 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200868 hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200869 }
870
871timer:
872 if (hdev->idle_timeout > 0)
873 mod_timer(&conn->idle_timer,
874 jiffies + msecs_to_jiffies(hdev->idle_timeout));
875}
876
877/* Enter sniff mode */
878void hci_conn_enter_sniff_mode(struct hci_conn *conn)
879{
880 struct hci_dev *hdev = conn->hdev;
881
882 BT_DBG("conn %p mode %d", conn, conn->mode);
883
884 if (test_bit(HCI_RAW, &hdev->flags))
885 return;
886
887 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
888 return;
889
890 if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
891 return;
892
893 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
894 struct hci_cp_sniff_subrate cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700895 cp.handle = cpu_to_le16(conn->handle);
896 cp.max_latency = cpu_to_le16(0);
897 cp.min_remote_timeout = cpu_to_le16(0);
898 cp.min_local_timeout = cpu_to_le16(0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200899 hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200900 }
901
902 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
903 struct hci_cp_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700904 cp.handle = cpu_to_le16(conn->handle);
905 cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
906 cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
907 cp.attempt = cpu_to_le16(4);
908 cp.timeout = cpu_to_le16(1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200909 hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200910 }
911}
912
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700913struct hci_chan *hci_chan_accept(struct hci_conn *conn,
914 struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
915{
916 struct hci_chan *chan;
917 struct hci_cp_create_logical_link cp;
918
919 chan = hci_chan_add(conn->hdev);
920 if (!chan)
921 return NULL;
922
923 chan->state = BT_CONNECT;
924 chan->conn = conn;
925 chan->tx_fs = *tx_fs;
926 chan->rx_fs = *rx_fs;
927 cp.phy_handle = chan->conn->handle;
928 cp.tx_fs.id = chan->tx_fs.id;
929 cp.tx_fs.type = chan->tx_fs.type;
930 cp.tx_fs.max_sdu = cpu_to_le16(chan->tx_fs.max_sdu);
931 cp.tx_fs.sdu_arr_time = cpu_to_le32(chan->tx_fs.sdu_arr_time);
932 cp.tx_fs.acc_latency = cpu_to_le32(chan->tx_fs.acc_latency);
933 cp.tx_fs.flush_to = cpu_to_le32(chan->tx_fs.flush_to);
934 cp.rx_fs.id = chan->rx_fs.id;
935 cp.rx_fs.type = chan->rx_fs.type;
936 cp.rx_fs.max_sdu = cpu_to_le16(chan->rx_fs.max_sdu);
937 cp.rx_fs.sdu_arr_time = cpu_to_le32(chan->rx_fs.sdu_arr_time);
938 cp.rx_fs.acc_latency = cpu_to_le32(chan->rx_fs.acc_latency);
939 cp.rx_fs.flush_to = cpu_to_le32(chan->rx_fs.flush_to);
940 hci_conn_hold(chan->conn);
941 hci_send_cmd(conn->hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp), &cp);
942 return chan;
943}
944EXPORT_SYMBOL(hci_chan_accept);
945
946struct hci_chan *hci_chan_create(struct hci_conn *conn,
947 struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
948{
949 struct hci_chan *chan;
950 struct hci_cp_create_logical_link cp;
951
952 chan = hci_chan_add(conn->hdev);
953 if (!chan)
954 return NULL;
955
956 chan->state = BT_CONNECT;
957 chan->conn = conn;
958 chan->tx_fs = *tx_fs;
959 chan->rx_fs = *rx_fs;
960 cp.phy_handle = chan->conn->handle;
961 cp.tx_fs.id = chan->tx_fs.id;
962 cp.tx_fs.type = chan->tx_fs.type;
963 cp.tx_fs.max_sdu = cpu_to_le16(chan->tx_fs.max_sdu);
964 cp.tx_fs.sdu_arr_time = cpu_to_le32(chan->tx_fs.sdu_arr_time);
965 cp.tx_fs.acc_latency = cpu_to_le32(chan->tx_fs.acc_latency);
966 cp.tx_fs.flush_to = cpu_to_le32(chan->tx_fs.flush_to);
967 cp.rx_fs.id = chan->rx_fs.id;
968 cp.rx_fs.type = chan->rx_fs.type;
969 cp.rx_fs.max_sdu = cpu_to_le16(chan->rx_fs.max_sdu);
970 cp.rx_fs.sdu_arr_time = cpu_to_le32(chan->rx_fs.sdu_arr_time);
971 cp.rx_fs.acc_latency = cpu_to_le32(chan->rx_fs.acc_latency);
972 cp.rx_fs.flush_to = cpu_to_le32(chan->rx_fs.flush_to);
973 hci_conn_hold(chan->conn);
974 hci_send_cmd(conn->hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp), &cp);
975 return chan;
976}
977EXPORT_SYMBOL(hci_chan_create);
978
979void hci_chan_modify(struct hci_chan *chan,
980 struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
981{
982 struct hci_cp_flow_spec_modify cp;
983
984 chan->tx_fs = *tx_fs;
985 chan->rx_fs = *rx_fs;
986 cp.log_handle = cpu_to_le16(chan->ll_handle);
987 cp.tx_fs.id = tx_fs->id;
988 cp.tx_fs.type = tx_fs->type;
989 cp.tx_fs.max_sdu = cpu_to_le16(tx_fs->max_sdu);
990 cp.tx_fs.sdu_arr_time = cpu_to_le32(tx_fs->sdu_arr_time);
991 cp.tx_fs.acc_latency = cpu_to_le32(tx_fs->acc_latency);
992 cp.tx_fs.flush_to = cpu_to_le32(tx_fs->flush_to);
993 cp.rx_fs.id = rx_fs->id;
994 cp.rx_fs.type = rx_fs->type;
995 cp.rx_fs.max_sdu = cpu_to_le16(rx_fs->max_sdu);
996 cp.rx_fs.sdu_arr_time = cpu_to_le32(rx_fs->sdu_arr_time);
997 cp.rx_fs.acc_latency = cpu_to_le32(rx_fs->acc_latency);
998 cp.rx_fs.flush_to = cpu_to_le32(rx_fs->flush_to);
999 hci_conn_hold(chan->conn);
1000 hci_send_cmd(chan->conn->hdev, HCI_OP_FLOW_SPEC_MODIFY, sizeof(cp),
1001 &cp);
1002}
1003EXPORT_SYMBOL(hci_chan_modify);
1004
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005/* Drop all connection on the device */
1006void hci_conn_hash_flush(struct hci_dev *hdev)
1007{
1008 struct hci_conn_hash *h = &hdev->conn_hash;
1009 struct list_head *p;
1010
1011 BT_DBG("hdev %s", hdev->name);
1012
1013 p = h->list.next;
1014 while (p != &h->list) {
1015 struct hci_conn *c;
1016
1017 c = list_entry(p, struct hci_conn, list);
1018 p = p->next;
1019
1020 c->state = BT_CLOSED;
1021
Marcel Holtmann2950f212009-02-12 14:02:50 +01001022 hci_proto_disconn_cfm(c, 0x16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 hci_conn_del(c);
1024 }
1025}
1026
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001027/* Check pending connect attempts */
1028void hci_conn_check_pending(struct hci_dev *hdev)
1029{
1030 struct hci_conn *conn;
1031
1032 BT_DBG("hdev %s", hdev->name);
1033
1034 hci_dev_lock(hdev);
1035
1036 conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
1037 if (conn)
1038 hci_acl_connect(conn);
1039
1040 hci_dev_unlock(hdev);
1041}
1042
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001043void hci_conn_hold_device(struct hci_conn *conn)
1044{
1045 atomic_inc(&conn->devref);
1046}
1047EXPORT_SYMBOL(hci_conn_hold_device);
1048
1049void hci_conn_put_device(struct hci_conn *conn)
1050{
1051 if (atomic_dec_and_test(&conn->devref))
1052 hci_conn_del_sysfs(conn);
1053}
1054EXPORT_SYMBOL(hci_conn_put_device);
1055
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056int hci_get_conn_list(void __user *arg)
1057{
1058 struct hci_conn_list_req req, *cl;
1059 struct hci_conn_info *ci;
1060 struct hci_dev *hdev;
1061 struct list_head *p;
1062 int n = 0, size, err;
1063
1064 if (copy_from_user(&req, arg, sizeof(req)))
1065 return -EFAULT;
1066
1067 if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
1068 return -EINVAL;
1069
1070 size = sizeof(req) + req.conn_num * sizeof(*ci);
1071
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001072 cl = kmalloc(size, GFP_KERNEL);
1073 if (!cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 return -ENOMEM;
1075
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001076 hdev = hci_dev_get(req.dev_id);
1077 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 kfree(cl);
1079 return -ENODEV;
1080 }
1081
1082 ci = cl->conn_info;
1083
1084 hci_dev_lock_bh(hdev);
1085 list_for_each(p, &hdev->conn_hash.list) {
1086 register struct hci_conn *c;
1087 c = list_entry(p, struct hci_conn, list);
1088
1089 bacpy(&(ci + n)->bdaddr, &c->dst);
1090 (ci + n)->handle = c->handle;
1091 (ci + n)->type = c->type;
1092 (ci + n)->out = c->out;
1093 (ci + n)->state = c->state;
1094 (ci + n)->link_mode = c->link_mode;
Nick Pellyc1728492009-12-09 00:15:41 -08001095 if (c->type == SCO_LINK) {
1096 (ci + n)->mtu = hdev->sco_mtu;
1097 (ci + n)->cnt = hdev->sco_cnt;
1098 (ci + n)->pkts = hdev->sco_pkts;
1099 } else {
1100 (ci + n)->mtu = hdev->acl_mtu;
1101 (ci + n)->cnt = hdev->acl_cnt;
1102 (ci + n)->pkts = hdev->acl_pkts;
1103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 if (++n >= req.conn_num)
1105 break;
1106 }
1107 hci_dev_unlock_bh(hdev);
1108
1109 cl->dev_id = hdev->id;
1110 cl->conn_num = n;
1111 size = sizeof(req) + n * sizeof(*ci);
1112
1113 hci_dev_put(hdev);
1114
1115 err = copy_to_user(arg, cl, size);
1116 kfree(cl);
1117
1118 return err ? -EFAULT : 0;
1119}
1120
1121int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
1122{
1123 struct hci_conn_info_req req;
1124 struct hci_conn_info ci;
1125 struct hci_conn *conn;
1126 char __user *ptr = arg + sizeof(req);
1127
1128 if (copy_from_user(&req, arg, sizeof(req)))
1129 return -EFAULT;
1130
1131 hci_dev_lock_bh(hdev);
1132 conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
1133 if (conn) {
1134 bacpy(&ci.bdaddr, &conn->dst);
1135 ci.handle = conn->handle;
1136 ci.type = conn->type;
1137 ci.out = conn->out;
1138 ci.state = conn->state;
1139 ci.link_mode = conn->link_mode;
Nick Pellyc1728492009-12-09 00:15:41 -08001140 if (req.type == SCO_LINK) {
1141 ci.mtu = hdev->sco_mtu;
1142 ci.cnt = hdev->sco_cnt;
1143 ci.pkts = hdev->sco_pkts;
1144 } else {
1145 ci.mtu = hdev->acl_mtu;
1146 ci.cnt = hdev->acl_cnt;
1147 ci.pkts = hdev->acl_pkts;
1148 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001149 ci.pending_sec_level = conn->pending_sec_level;
1150 ci.ssp_mode = conn->ssp_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 }
1152 hci_dev_unlock_bh(hdev);
1153
1154 if (!conn)
1155 return -ENOENT;
1156
1157 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
1158}
Marcel Holtmann40be4922008-07-14 20:13:50 +02001159
1160int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
1161{
1162 struct hci_auth_info_req req;
1163 struct hci_conn *conn;
1164
1165 if (copy_from_user(&req, arg, sizeof(req)))
1166 return -EFAULT;
1167
1168 hci_dev_lock_bh(hdev);
1169 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
1170 if (conn)
1171 req.type = conn->auth_type;
1172 hci_dev_unlock_bh(hdev);
1173
1174 if (!conn)
1175 return -ENOENT;
1176
1177 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
1178}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001179
1180int hci_set_auth_info(struct hci_dev *hdev, void __user *arg)
1181{
1182 struct hci_auth_info_req req;
1183 struct hci_conn *conn;
1184
1185 if (copy_from_user(&req, arg, sizeof(req)))
1186 return -EFAULT;
1187
1188 hci_dev_lock_bh(hdev);
1189 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
1190 if (conn)
1191 conn->auth_type = req.type;
1192 hci_dev_unlock_bh(hdev);
1193
1194 if (!conn)
1195 return -ENOENT;
1196
1197 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
1198}