blob: d60bf00bbb284dd0f05d75fb095c003717935239 [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
Brian Gix3cd62042012-01-11 15:18:17 -08003 Copyright (c) 2000-2001, 2010-2012 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
Brian Gix114f3a62011-09-27 14:02:20 -070053 BT_DBG("%p", conn);
54
Ville Tervofcd89c02011-02-10 22:38:47 -030055 conn->state = BT_CONNECT;
56 conn->out = 1;
Vinicius Costa Gomesb92a6222011-02-10 22:38:52 -030057 conn->link_mode |= HCI_LM_MASTER;
Vinicius Costa Gomes403d2c82011-06-09 18:50:50 -030058 conn->sec_level = BT_SECURITY_LOW;
Brian Gix114f3a62011-09-27 14:02:20 -070059 conn->type = LE_LINK;
Ville Tervofcd89c02011-02-10 22:38:47 -030060
61 memset(&cp, 0, sizeof(cp));
62 cp.scan_interval = cpu_to_le16(0x0004);
63 cp.scan_window = cpu_to_le16(0x0004);
64 bacpy(&cp.peer_addr, &conn->dst);
Andre Guedesc7f0d992011-05-31 14:20:57 -030065 cp.peer_addr_type = conn->dst_type;
Ville Tervofcd89c02011-02-10 22:38:47 -030066 cp.conn_interval_min = cpu_to_le16(0x0008);
67 cp.conn_interval_max = cpu_to_le16(0x0100);
Archana Ramachandrand6d25e12012-01-23 16:31:09 -080068 cp.supervision_timeout = cpu_to_le16(1000);
Ville Tervofcd89c02011-02-10 22:38:47 -030069 cp.min_ce_len = cpu_to_le16(0x0001);
70 cp.max_ce_len = cpu_to_le16(0x0001);
71
72 hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
73}
74
75static void hci_le_connect_cancel(struct hci_conn *conn)
76{
77 hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
78}
79
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020080void hci_acl_connect(struct hci_conn *conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
82 struct hci_dev *hdev = conn->hdev;
83 struct inquiry_entry *ie;
84 struct hci_cp_create_conn cp;
85
86 BT_DBG("%p", conn);
87
88 conn->state = BT_CONNECT;
Marcel Holtmanna8746412008-07-14 20:13:46 +020089 conn->out = 1;
90
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 conn->link_mode = HCI_LM_MASTER;
92
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020093 conn->attempt++;
94
Marcel Holtmanne4e8e372008-07-14 20:13:47 +020095 conn->link_policy = hdev->link_policy;
96
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 memset(&cp, 0, sizeof(cp));
98 bacpy(&cp.bdaddr, &conn->dst);
99 cp.pscan_rep_mode = 0x02;
100
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200101 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
102 if (ie) {
Marcel Holtmann41a96212008-07-14 20:13:48 +0200103 if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
104 cp.pscan_rep_mode = ie->data.pscan_rep_mode;
105 cp.pscan_mode = ie->data.pscan_mode;
106 cp.clock_offset = ie->data.clock_offset |
107 cpu_to_le16(0x8000);
108 }
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110 memcpy(conn->dev_class, ie->data.dev_class, 3);
Marcel Holtmann41a96212008-07-14 20:13:48 +0200111 conn->ssp_mode = ie->data.ssp_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 }
113
Marcel Holtmanna8746412008-07-14 20:13:46 +0200114 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200116 cp.role_switch = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 else
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200118 cp.role_switch = 0x00;
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200119
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200120 hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121}
122
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200123static void hci_acl_connect_cancel(struct hci_conn *conn)
124{
125 struct hci_cp_create_conn_cancel cp;
126
127 BT_DBG("%p", conn);
128
129 if (conn->hdev->hci_ver < 2)
130 return;
131
132 bacpy(&cp.bdaddr, &conn->dst);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200133 hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200134}
135
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
137{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 BT_DBG("%p", conn);
139
140 conn->state = BT_DISCONN;
141
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700142 if (conn->hdev->dev_type == HCI_BREDR) {
143 struct hci_cp_disconnect cp;
144 cp.handle = cpu_to_le16(conn->handle);
145 cp.reason = reason;
146 hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
147 } else {
148 struct hci_cp_disconn_phys_link cp;
149 cp.phy_handle = (u8) conn->handle;
150 cp.reason = reason;
151 hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHYS_LINK,
152 sizeof(cp), &cp);
153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154}
155
156void hci_add_sco(struct hci_conn *conn, __u16 handle)
157{
158 struct hci_dev *hdev = conn->hdev;
159 struct hci_cp_add_sco cp;
160
161 BT_DBG("%p", conn);
162
163 conn->state = BT_CONNECT;
164 conn->out = 1;
165
Marcel Holtmannefc76882009-02-06 09:13:37 +0100166 conn->attempt++;
167
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700168 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200169 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200171 hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172}
173
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200174void hci_setup_sync(struct hci_conn *conn, __u16 handle)
175{
176 struct hci_dev *hdev = conn->hdev;
177 struct hci_cp_setup_sync_conn cp;
178
179 BT_DBG("%p", conn);
180
181 conn->state = BT_CONNECT;
182 conn->out = 1;
183
Marcel Holtmannefc76882009-02-06 09:13:37 +0100184 conn->attempt++;
185
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200186 cp.handle = cpu_to_le16(handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200187
188 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
189 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
Kun Han Kim15b911f2011-07-08 09:30:28 -0700190 if (conn->hdev->is_wbs) {
191 /* Transparent Data */
192 uint16_t voice_setting = hdev->voice_setting | ACF_TRANS;
193 cp.max_latency = cpu_to_le16(0x000D);
194 cp.pkt_type = cpu_to_le16(ESCO_WBS);
195 cp.voice_setting = cpu_to_le16(voice_setting);
196 /* Retransmission Effort */
197 cp.retrans_effort = RE_LINK_QUALITY;
198 } else {
199 cp.max_latency = cpu_to_le16(0x000A);
200 cp.pkt_type = cpu_to_le16(conn->pkt_type);
201 cp.voice_setting = cpu_to_le16(hdev->voice_setting);
202 cp.retrans_effort = RE_POWER_CONSUMP;
203 }
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200204
205 hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
206}
207
Claudio Takahasi2ce603e2011-02-16 20:44:53 -0200208void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
209 u16 latency, u16 to_multiplier)
210{
211 struct hci_cp_le_conn_update cp;
212 struct hci_dev *hdev = conn->hdev;
213
214 memset(&cp, 0, sizeof(cp));
215
216 cp.handle = cpu_to_le16(conn->handle);
217 cp.conn_interval_min = cpu_to_le16(min);
218 cp.conn_interval_max = cpu_to_le16(max);
219 cp.conn_latency = cpu_to_le16(latency);
220 cp.supervision_timeout = cpu_to_le16(to_multiplier);
221 cp.min_ce_len = cpu_to_le16(0x0001);
222 cp.max_ce_len = cpu_to_le16(0x0001);
223
224 hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
225}
226EXPORT_SYMBOL(hci_le_conn_update);
227
Archana Ramachandran26a752b2011-12-20 11:27:40 -0800228void hci_read_rssi(struct hci_conn *conn)
229{
230 struct hci_cp_read_rssi cp;
231 struct hci_dev *hdev = conn->hdev;
232
233 memset(&cp, 0, sizeof(cp));
234 cp.handle = cpu_to_le16(conn->handle);
235
236 hci_send_cmd(hdev, HCI_OP_READ_RSSI, sizeof(cp), &cp);
237}
238EXPORT_SYMBOL(hci_read_rssi);
239
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300240void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
241 __u8 ltk[16])
242{
243 struct hci_dev *hdev = conn->hdev;
244 struct hci_cp_le_start_enc cp;
245
246 BT_DBG("%p", conn);
247
248 memset(&cp, 0, sizeof(cp));
249
250 cp.handle = cpu_to_le16(conn->handle);
251 memcpy(cp.ltk, ltk, sizeof(cp.ltk));
252 cp.ediv = ediv;
Brian Gix842bc5e2011-09-07 08:13:41 -0700253 memcpy(cp.rand, rand, sizeof(cp.rand));
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300254
255 hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
256}
257EXPORT_SYMBOL(hci_le_start_enc);
258
259void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
260{
261 struct hci_dev *hdev = conn->hdev;
262 struct hci_cp_le_ltk_reply cp;
263
264 BT_DBG("%p", conn);
265
266 memset(&cp, 0, sizeof(cp));
267
268 cp.handle = cpu_to_le16(conn->handle);
269 memcpy(cp.ltk, ltk, sizeof(ltk));
270
271 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
272}
273EXPORT_SYMBOL(hci_le_ltk_reply);
274
275void hci_le_ltk_neg_reply(struct hci_conn *conn)
276{
277 struct hci_dev *hdev = conn->hdev;
278 struct hci_cp_le_ltk_neg_reply cp;
279
280 BT_DBG("%p", conn);
281
282 memset(&cp, 0, sizeof(cp));
283
284 cp.handle = cpu_to_le16(conn->handle);
285
286 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
287}
288
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400289/* Device _must_ be locked */
290void hci_sco_setup(struct hci_conn *conn, __u8 status)
291{
292 struct hci_conn *sco = conn->link;
293
294 BT_DBG("%p", conn);
295
296 if (!sco)
297 return;
298
299 if (!status) {
300 if (lmp_esco_capable(conn->hdev))
301 hci_setup_sync(sco, conn->handle);
302 else
303 hci_add_sco(sco, conn->handle);
304 } else {
305 hci_proto_connect_cfm(sco, status);
306 hci_conn_del(sco);
307 }
308}
309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310static void hci_conn_timeout(unsigned long arg)
311{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200312 struct hci_conn *conn = (void *) arg;
313 struct hci_dev *hdev = conn->hdev;
Marcel Holtmann2950f212009-02-12 14:02:50 +0100314 __u8 reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
316 BT_DBG("conn %p state %d", conn, conn->state);
317
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 hci_dev_lock(hdev);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200319
320 switch (conn->state) {
321 case BT_CONNECT:
Marcel Holtmann769be972008-07-14 20:13:49 +0200322 case BT_CONNECT2:
Ville Tervofcd89c02011-02-10 22:38:47 -0300323 if (conn->out) {
324 if (conn->type == ACL_LINK)
325 hci_acl_connect_cancel(conn);
326 else if (conn->type == LE_LINK)
327 hci_le_connect_cancel(conn);
328 }
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200329 break;
Marcel Holtmann769be972008-07-14 20:13:49 +0200330 case BT_CONFIG:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900331 case BT_CONNECTED:
Brian Gix114f3a62011-09-27 14:02:20 -0700332 if (!atomic_read(&conn->refcnt)) {
333 reason = hci_proto_disconn_ind(conn);
334 hci_acl_disconn(conn, reason);
335 }
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200336 break;
337 default:
Brian Gix114f3a62011-09-27 14:02:20 -0700338 if (!atomic_read(&conn->refcnt))
339 conn->state = BT_CLOSED;
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200340 break;
341 }
342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344}
345
Marcel Holtmann04837f62006-07-03 10:02:33 +0200346static void hci_conn_idle(unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200348 struct hci_conn *conn = (void *) arg;
349
350 BT_DBG("conn %p mode %d", conn, conn->mode);
351
352 hci_conn_enter_sniff_mode(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353}
354
Archana Ramachandran26a752b2011-12-20 11:27:40 -0800355static void hci_conn_rssi_update(struct work_struct *work)
356{
357 struct delayed_work *delayed =
358 container_of(work, struct delayed_work, work);
359 struct hci_conn *conn =
360 container_of(delayed, struct hci_conn, rssi_update_work);
361
362 BT_DBG("conn %p mode %d", conn, conn->mode);
363
364 hci_read_rssi(conn);
365}
366
Prabhakaran Mcafface82012-04-10 11:38:35 +0530367static void encryption_disabled_timeout(unsigned long userdata)
368{
369 struct hci_conn *conn = (struct hci_conn *)userdata;
370 BT_INFO("conn %p Grace Prd Exp ", conn);
371
372 hci_encrypt_cfm(conn, 0, 0);
373
374 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
375 struct hci_cp_set_conn_encrypt cp;
376 BT_INFO("HCI_CONN_ENCRYPT_PEND is set");
377 cp.handle = cpu_to_le16(conn->handle);
378 cp.encrypt = 1;
379 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
380 sizeof(cp), &cp);
381 }
382
383}
384
Nick Pellybbcda3b2010-02-11 11:54:28 -0800385struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
386 __u16 pkt_type, bdaddr_t *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387{
388 struct hci_conn *conn;
389
390 BT_DBG("%s dst %s", hdev->name, batostr(dst));
391
Marcel Holtmann04837f62006-07-03 10:02:33 +0200392 conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC);
393 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
396 bacpy(&conn->dst, dst);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200397 conn->hdev = hdev;
398 conn->type = type;
399 conn->mode = HCI_CM_ACTIVE;
400 conn->state = BT_OPEN;
Andrei Emeltchenko93f19c92009-09-03 12:34:19 +0300401 conn->auth_type = HCI_AT_GENERAL_BONDING;
Johan Hedberg17fa4b92011-01-25 13:28:33 +0200402 conn->io_capability = hdev->io_capability;
Johan Hedberga9583552011-02-19 12:06:01 -0300403 conn->remote_auth = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Marcel Holtmann04837f62006-07-03 10:02:33 +0200405 conn->power_save = 1;
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200406 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200407
Marcel Holtmanna8746412008-07-14 20:13:46 +0200408 switch (type) {
409 case ACL_LINK:
410 conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
Rahul Kashyapd5553ba2012-01-02 19:27:19 +0530411 conn->link_policy = hdev->link_policy;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200412 break;
413 case SCO_LINK:
Nick Pellybbcda3b2010-02-11 11:54:28 -0800414 if (!pkt_type)
415 pkt_type = SCO_ESCO_MASK;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200416 case ESCO_LINK:
Nick Pellybbcda3b2010-02-11 11:54:28 -0800417 if (!pkt_type)
418 pkt_type = ALL_ESCO_MASK;
419 if (lmp_esco_capable(hdev)) {
420 /* HCI Setup Synchronous Connection Command uses
421 reverse logic on the EDR_ESCO_MASK bits */
422 conn->pkt_type = (pkt_type ^ EDR_ESCO_MASK) &
423 hdev->esco_type;
424 } else {
425 /* Legacy HCI Add Sco Connection Command uses a
426 shifted bitmask */
427 conn->pkt_type = (pkt_type << 5) & hdev->pkt_type &
428 SCO_PTYPE_MASK;
429 }
Marcel Holtmanna8746412008-07-14 20:13:46 +0200430 break;
431 }
432
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 skb_queue_head_init(&conn->data_q);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200434
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800435 setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
436 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
Archana Ramachandran26a752b2011-12-20 11:27:40 -0800437 INIT_DELAYED_WORK(&conn->rssi_update_work, hci_conn_rssi_update);
Prabhakaran Mcafface82012-04-10 11:38:35 +0530438 setup_timer(&conn->encrypt_pause_timer, encryption_disabled_timeout,
439 (unsigned long)conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
441 atomic_set(&conn->refcnt, 0);
442
443 hci_dev_hold(hdev);
444
445 tasklet_disable(&hdev->tx_task);
446
447 hci_conn_hash_add(hdev, conn);
448 if (hdev->notify)
449 hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
450
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700451 atomic_set(&conn->devref, 0);
452
Marcel Holtmanna67e8992009-05-02 18:24:06 -0700453 hci_conn_init_sysfs(conn);
454
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 tasklet_enable(&hdev->tx_task);
456
457 return conn;
458}
459
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460struct hci_conn *hci_le_conn_add(struct hci_dev *hdev, bdaddr_t *dst,
461 __u8 addr_type)
462{
463 struct hci_conn *conn = hci_conn_add(hdev, LE_LINK, 0, dst);
464 if (!conn)
465 return NULL;
466
467 conn->dst_type = addr_type;
468
469 return conn;
470}
471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472int hci_conn_del(struct hci_conn *conn)
473{
474 struct hci_dev *hdev = conn->hdev;
475
476 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
477
Brian Gix3cd62042012-01-11 15:18:17 -0800478 /* Make sure no timers are running */
Marcel Holtmann04837f62006-07-03 10:02:33 +0200479 del_timer(&conn->idle_timer);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200480 del_timer(&conn->disc_timer);
Brian Gix3cd62042012-01-11 15:18:17 -0800481 del_timer(&conn->smp_timer);
Archana Ramachandran26a752b2011-12-20 11:27:40 -0800482 __cancel_delayed_work(&conn->rssi_update_work);
Prabhakaran Mcafface82012-04-10 11:38:35 +0530483 del_timer(&conn->encrypt_pause_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200485 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 struct hci_conn *sco = conn->link;
487 if (sco)
488 sco->link = NULL;
489
490 /* Unacked frames */
491 hdev->acl_cnt += conn->sent;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300492 } else if (conn->type == LE_LINK) {
493 if (hdev->le_pkts)
494 hdev->le_cnt += conn->sent;
495 else
496 hdev->acl_cnt += conn->sent;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200497 } else {
498 struct hci_conn *acl = conn->link;
499 if (acl) {
500 acl->link = NULL;
501 hci_conn_put(acl);
502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 }
504
505 tasklet_disable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 hci_conn_hash_del(hdev, conn);
508 if (hdev->notify)
509 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200510
AnubhavGupta01d9e362011-12-17 17:14:51 +0530511 tasklet_schedule(&hdev->tx_task);
512
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 tasklet_enable(&hdev->tx_task);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 skb_queue_purge(&conn->data_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700517 hci_conn_put_device(conn);
Dave Young2ae9a6b2009-02-21 16:13:34 +0800518
Marcel Holtmann384943e2009-05-08 18:20:43 -0700519 hci_dev_put(hdev);
520
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700521 return 0;
522}
523
524struct hci_chan *hci_chan_add(struct hci_dev *hdev)
525{
526 struct hci_chan *chan;
527
528 BT_DBG("%s", hdev->name);
529
530 chan = kzalloc(sizeof(struct hci_chan), GFP_ATOMIC);
531 if (!chan)
532 return NULL;
533
534 atomic_set(&chan->refcnt, 0);
535
536 hci_dev_hold(hdev);
537
538 chan->hdev = hdev;
539
540 list_add(&chan->list, &hdev->chan_list.list);
541
542 return chan;
543}
Peter Krystada8417e62012-03-21 16:58:17 -0700544EXPORT_SYMBOL(hci_chan_add);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700545
546int hci_chan_del(struct hci_chan *chan)
547{
548 BT_DBG("%s chan %p", chan->hdev->name, chan);
549
550 list_del(&chan->list);
551
552 hci_conn_put(chan->conn);
553 hci_dev_put(chan->hdev);
554
555 kfree(chan);
Tomas Targownik1be668d2011-06-30 16:30:44 -0300556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 return 0;
558}
559
Peter Krystadd6a9ceb2011-12-01 15:44:54 -0800560int hci_chan_put(struct hci_chan *chan)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700561{
562 struct hci_cp_disconn_logical_link cp;
Mat Martineau9f8d4672011-12-14 12:10:46 -0800563 struct hci_conn *hcon;
564 u16 ll_handle;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565
566 BT_DBG("chan %p refcnt %d", chan, atomic_read(&chan->refcnt));
567 if (!atomic_dec_and_test(&chan->refcnt))
Peter Krystadd6a9ceb2011-12-01 15:44:54 -0800568 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569
Mat Martineau9f8d4672011-12-14 12:10:46 -0800570 hcon = chan->conn;
571 ll_handle = chan->ll_handle;
572
573 hci_chan_del(chan);
574
575 BT_DBG("chan->conn->state %d", hcon->state);
576 if (hcon->state == BT_CONNECTED) {
577 cp.log_handle = cpu_to_le16(ll_handle);
578 hci_send_cmd(hcon->hdev, HCI_OP_DISCONN_LOGICAL_LINK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700579 sizeof(cp), &cp);
Mat Martineau9f8d4672011-12-14 12:10:46 -0800580 }
Peter Krystadd6a9ceb2011-12-01 15:44:54 -0800581
582 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583}
584EXPORT_SYMBOL(hci_chan_put);
585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
587{
588 int use_src = bacmp(src, BDADDR_ANY);
589 struct hci_dev *hdev = NULL;
590 struct list_head *p;
591
592 BT_DBG("%s -> %s", batostr(src), batostr(dst));
593
594 read_lock_bh(&hci_dev_list_lock);
595
596 list_for_each(p, &hci_dev_list) {
597 struct hci_dev *d = list_entry(p, struct hci_dev, list);
598
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599 if (d->dev_type != HCI_BREDR)
600 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
602 continue;
603
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900604 /* Simple routing:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 * No source address - find interface with bdaddr != dst
606 * Source address - find interface with bdaddr == src
607 */
608
609 if (use_src) {
610 if (!bacmp(&d->bdaddr, src)) {
611 hdev = d; break;
612 }
613 } else {
614 if (bacmp(&d->bdaddr, dst)) {
615 hdev = d; break;
616 }
617 }
618 }
619
620 if (hdev)
621 hdev = hci_dev_hold(hdev);
622
623 read_unlock_bh(&hci_dev_list_lock);
624 return hdev;
625}
626EXPORT_SYMBOL(hci_get_route);
627
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700628struct hci_dev *hci_dev_get_type(u8 amp_type)
629{
630 struct hci_dev *hdev = NULL;
631 struct hci_dev *d;
632
633 BT_DBG("amp_type %d", amp_type);
634
635 read_lock_bh(&hci_dev_list_lock);
636
637 list_for_each_entry(d, &hci_dev_list, list) {
638 if ((d->amp_type == amp_type) && test_bit(HCI_UP, &d->flags)) {
639 hdev = d;
640 break;
641 }
642 }
643
644 if (hdev)
645 hdev = hci_dev_hold(hdev);
646
647 read_unlock_bh(&hci_dev_list_lock);
648 return hdev;
649}
650EXPORT_SYMBOL(hci_dev_get_type);
651
652struct hci_dev *hci_dev_get_amp(bdaddr_t *dst)
653{
654 struct hci_dev *d;
655 struct hci_dev *hdev = NULL;
656
657 BT_DBG("%s dst %s", hdev->name, batostr(dst));
658
659 read_lock_bh(&hci_dev_list_lock);
660
661 list_for_each_entry(d, &hci_dev_list, list) {
662 struct hci_conn *conn;
663 if (d->dev_type == HCI_BREDR)
664 continue;
665 conn = hci_conn_hash_lookup_ba(d, ACL_LINK, dst);
666 if (conn) {
667 hdev = d;
668 break;
669 }
670 }
671
672 if (hdev)
673 hdev = hci_dev_hold(hdev);
674
675 read_unlock_bh(&hci_dev_list_lock);
676 return hdev;
677}
678EXPORT_SYMBOL(hci_dev_get_amp);
679
Ville Tervofcd89c02011-02-10 22:38:47 -0300680/* Create SCO, ACL or LE connection.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 * Device _must_ be locked */
Nick Pellybbcda3b2010-02-11 11:54:28 -0800682struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
683 __u16 pkt_type, bdaddr_t *dst,
684 __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
686 struct hci_conn *acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200687 struct hci_conn *sco;
Ville Tervofcd89c02011-02-10 22:38:47 -0300688 struct hci_conn *le;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
690 BT_DBG("%s dst %s", hdev->name, batostr(dst));
691
Ville Tervofcd89c02011-02-10 22:38:47 -0300692 if (type == LE_LINK) {
Andre Guedes5e89ece2011-05-31 14:20:56 -0300693 struct adv_entry *entry;
Brian Gixcf956772011-10-20 15:18:51 -0700694 struct link_key *key;
Andre Guedes5e89ece2011-05-31 14:20:56 -0300695
Ville Tervofcd89c02011-02-10 22:38:47 -0300696 le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
Brian Gix2e2f50d2011-09-13 12:36:04 -0700697 if (le) {
698 hci_conn_hold(le);
Brian Gixa68668b2011-08-11 15:49:36 -0700699 return le;
Brian Gix2e2f50d2011-09-13 12:36:04 -0700700 }
Andre Guedes5e89ece2011-05-31 14:20:56 -0300701
Brian Gixcf956772011-10-20 15:18:51 -0700702 key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
703 if (!key) {
704 entry = hci_find_adv_entry(hdev, dst);
705 if (entry)
706 le = hci_le_conn_add(hdev, dst,
707 entry->bdaddr_type);
708 else
709 le = hci_le_conn_add(hdev, dst, 0);
710 } else {
711 le = hci_le_conn_add(hdev, dst, key->addr_type);
712 }
Andre Guedes5e89ece2011-05-31 14:20:56 -0300713
Ville Tervofcd89c02011-02-10 22:38:47 -0300714 if (!le)
Ville Tervo30e76272011-02-22 16:10:53 -0300715 return ERR_PTR(-ENOMEM);
Andre Guedes92398c82011-05-31 14:20:55 -0300716
717 hci_le_connect(le);
Ville Tervofcd89c02011-02-10 22:38:47 -0300718
719 hci_conn_hold(le);
720
721 return le;
722 }
723
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200724 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
725 if (!acl) {
Nick Pellybbcda3b2010-02-11 11:54:28 -0800726 acl = hci_conn_add(hdev, ACL_LINK, 0, dst);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200727 if (!acl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 return NULL;
729 }
730
731 hci_conn_hold(acl);
732
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200733 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
Johan Hedberg765c2a92011-01-19 12:06:52 +0530734 acl->sec_level = BT_SECURITY_LOW;
735 acl->pending_sec_level = sec_level;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200736 acl->auth_type = auth_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 hci_acl_connect(acl);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200738 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200740 if (type == ACL_LINK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 return acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200742
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200743 sco = hci_conn_hash_lookup_ba(hdev, type, dst);
744 if (!sco) {
Nick Pellybbcda3b2010-02-11 11:54:28 -0800745 sco = hci_conn_add(hdev, type, pkt_type, dst);
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200746 if (!sco) {
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200747 hci_conn_put(acl);
748 return NULL;
749 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200751
752 acl->link = sco;
753 sco->link = acl;
754
755 hci_conn_hold(sco);
756
757 if (acl->state == BT_CONNECTED &&
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200758 (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
Nick Pellyc3902162009-11-13 14:16:32 -0800759 acl->power_save = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700760 hci_conn_enter_active_mode(acl, 1);
Nick Pellyc3902162009-11-13 14:16:32 -0800761
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400762 if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
763 /* defer SCO setup until mode change completed */
764 set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
765 return sco;
766 }
767
768 hci_sco_setup(acl, 0x00);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200769 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200770
771 return sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772}
773EXPORT_SYMBOL(hci_connect);
774
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700775void hci_disconnect(struct hci_conn *conn, __u8 reason)
776{
777 BT_DBG("conn %p", conn);
778
Mat Martineau3b9239a2012-02-16 11:54:30 -0800779 hci_proto_disconn_cfm(conn, reason, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780}
781EXPORT_SYMBOL(hci_disconnect);
782
783void hci_disconnect_amp(struct hci_conn *conn, __u8 reason)
784{
785 struct hci_dev *hdev = NULL;
786
787 BT_DBG("conn %p", conn);
788
789 read_lock_bh(&hci_dev_list_lock);
790
791 list_for_each_entry(hdev, &hci_dev_list, list) {
792 struct hci_conn *c;
793 if (hdev == conn->hdev)
794 continue;
795 if (hdev->amp_type == HCI_BREDR)
796 continue;
797 c = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &conn->dst);
798 if (c)
799 hci_disconnect(c, reason);
800 }
801
802 read_unlock_bh(&hci_dev_list_lock);
803}
804
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200805/* Check link security requirement */
806int hci_conn_check_link_mode(struct hci_conn *conn)
807{
808 BT_DBG("conn %p", conn);
809
810 if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
811 !(conn->link_mode & HCI_LM_ENCRYPT))
812 return 0;
813
814 return 1;
815}
816EXPORT_SYMBOL(hci_conn_check_link_mode);
817
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818/* Authenticate remote device */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100819static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820{
821 BT_DBG("conn %p", conn);
822
Johan Hedberg765c2a92011-01-19 12:06:52 +0530823 if (conn->pending_sec_level > sec_level)
824 sec_level = conn->pending_sec_level;
825
Marcel Holtmann96a31832009-02-12 16:23:03 +0100826 if (sec_level > conn->sec_level)
Johan Hedberg765c2a92011-01-19 12:06:52 +0530827 conn->pending_sec_level = sec_level;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100828 else if (conn->link_mode & HCI_LM_AUTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 return 1;
830
Johan Hedberg65cf6862011-01-19 12:06:49 +0530831 /* Make sure we preserve an existing MITM requirement*/
832 auth_type |= (conn->auth_type & 0x01);
Marcel Holtmann96a31832009-02-12 16:23:03 +0100833 conn->auth_type = auth_type;
Brian Gixa68668b2011-08-11 15:49:36 -0700834 conn->auth_initiator = 1;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100835
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
837 struct hci_cp_auth_requested cp;
Peter Hurleya5e5b082012-01-13 15:11:30 +0100838
839 /* encrypt must be pending if auth is also pending */
840 set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
841
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700842 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200843 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
844 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100846
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 return 0;
848}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100850/* Enable security */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100851int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852{
Brian Gixa68668b2011-08-11 15:49:36 -0700853 BT_DBG("conn %p %d %d", conn, sec_level, auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100855 if (sec_level == BT_SECURITY_SDP)
856 return 1;
857
Marcel Holtmann3fdca1e2009-04-28 09:04:55 -0700858 if (sec_level == BT_SECURITY_LOW &&
859 (!conn->ssp_mode || !conn->hdev->ssp_mode))
860 return 1;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100861
Brian Gix2e2f50d2011-09-13 12:36:04 -0700862 if (conn->type == LE_LINK) {
863 if (conn->pending_sec_level > sec_level)
864 sec_level = conn->pending_sec_level;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200865
Brian Gix2e2f50d2011-09-13 12:36:04 -0700866 if (sec_level > conn->sec_level)
867 conn->pending_sec_level = sec_level;
868 hci_proto_connect_cfm(conn, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700869 return 0;
Brian Gix2e2f50d2011-09-13 12:36:04 -0700870 } else if (conn->link_mode & HCI_LM_ENCRYPT) {
871 return hci_conn_auth(conn, sec_level, auth_type);
Ilia Kolomisnkyedc44dd2011-06-15 06:52:26 +0300872 } else if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
Brian Gix2e2f50d2011-09-13 12:36:04 -0700873 return 0;
874 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700875
876 if (hci_conn_auth(conn, sec_level, auth_type)) {
877 struct hci_cp_set_conn_encrypt cp;
Prabhakaran Mcafface82012-04-10 11:38:35 +0530878 if (timer_pending(&conn->encrypt_pause_timer)) {
879 BT_INFO("encrypt_pause_timer is pending");
880 return 0;
881 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700882 cp.handle = cpu_to_le16(conn->handle);
883 cp.encrypt = 1;
884 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
885 sizeof(cp), &cp);
886 }
887
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 return 0;
889}
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100890EXPORT_SYMBOL(hci_conn_security);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
892/* Change link key */
893int hci_conn_change_link_key(struct hci_conn *conn)
894{
895 BT_DBG("conn %p", conn);
896
897 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
898 struct hci_cp_change_conn_link_key cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700899 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200900 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
901 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 return 0;
905}
906EXPORT_SYMBOL(hci_conn_change_link_key);
907
908/* Switch role */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100909int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910{
911 BT_DBG("conn %p", conn);
912
913 if (!role && conn->link_mode & HCI_LM_MASTER)
914 return 1;
915
916 if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
917 struct hci_cp_switch_role cp;
918 bacpy(&cp.bdaddr, &conn->dst);
919 cp.role = role;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200920 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 return 0;
924}
925EXPORT_SYMBOL(hci_conn_switch_role);
926
Marcel Holtmann04837f62006-07-03 10:02:33 +0200927/* Enter active mode */
Jaikumar Ganesh514abe62011-05-23 18:06:04 -0700928void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200929{
930 struct hci_dev *hdev = conn->hdev;
931
932 BT_DBG("conn %p mode %d", conn, conn->mode);
933
934 if (test_bit(HCI_RAW, &hdev->flags))
935 return;
936
Jaikumar Ganesh514abe62011-05-23 18:06:04 -0700937 if (conn->mode != HCI_CM_SNIFF)
938 goto timer;
939
940 if (!conn->power_save && !force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200941 goto timer;
942
943 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
944 struct hci_cp_exit_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700945 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200946 hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200947 }
948
949timer:
950 if (hdev->idle_timeout > 0)
951 mod_timer(&conn->idle_timer,
952 jiffies + msecs_to_jiffies(hdev->idle_timeout));
953}
954
Archana Ramachandran26a752b2011-12-20 11:27:40 -0800955static inline void hci_conn_stop_rssi_timer(struct hci_conn *conn)
956{
957 BT_DBG("conn %p", conn);
958 cancel_delayed_work(&conn->rssi_update_work);
959}
960
961static inline void hci_conn_start_rssi_timer(struct hci_conn *conn,
962 u16 interval)
963{
964 struct hci_dev *hdev = conn->hdev;
965 BT_DBG("conn %p, pending %d", conn,
966 delayed_work_pending(&conn->rssi_update_work));
967 if (!delayed_work_pending(&conn->rssi_update_work)) {
968 queue_delayed_work(hdev->workqueue, &conn->rssi_update_work,
969 msecs_to_jiffies(interval));
970 }
971}
972
973void hci_conn_set_rssi_reporter(struct hci_conn *conn,
974 s8 rssi_threshold, u16 interval, u8 updateOnThreshExceed)
975{
976 if (conn) {
977 conn->rssi_threshold = rssi_threshold;
978 conn->rssi_update_interval = interval;
979 conn->rssi_update_thresh_exceed = updateOnThreshExceed;
980 hci_conn_start_rssi_timer(conn, interval);
981 }
982}
983
984void hci_conn_unset_rssi_reporter(struct hci_conn *conn)
985{
986 if (conn) {
987 BT_DBG("Deleting the rssi_update_timer");
988 hci_conn_stop_rssi_timer(conn);
989 }
990}
991
Marcel Holtmann04837f62006-07-03 10:02:33 +0200992/* Enter sniff mode */
993void hci_conn_enter_sniff_mode(struct hci_conn *conn)
994{
995 struct hci_dev *hdev = conn->hdev;
996
997 BT_DBG("conn %p mode %d", conn, conn->mode);
998
999 if (test_bit(HCI_RAW, &hdev->flags))
1000 return;
1001
1002 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
1003 return;
1004
Srinivas Krovvidi32ba9352012-01-26 10:48:08 +05301005 if (conn->mode != HCI_CM_ACTIVE ||
1006 !(conn->link_policy & HCI_LP_SNIFF) ||
1007 (hci_find_link_key(hdev, &conn->dst) == NULL))
Marcel Holtmann04837f62006-07-03 10:02:33 +02001008 return;
1009
1010 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
1011 struct hci_cp_sniff_subrate cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001012 cp.handle = cpu_to_le16(conn->handle);
1013 cp.max_latency = cpu_to_le16(0);
1014 cp.min_remote_timeout = cpu_to_le16(0);
1015 cp.min_local_timeout = cpu_to_le16(0);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001016 hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +02001017 }
1018
1019 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
1020 struct hci_cp_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -07001021 cp.handle = cpu_to_le16(conn->handle);
1022 cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
1023 cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
1024 cp.attempt = cpu_to_le16(4);
1025 cp.timeout = cpu_to_le16(1);
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001026 hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +02001027 }
1028}
1029
Peter Krystada8417e62012-03-21 16:58:17 -07001030struct hci_chan *hci_chan_create(struct hci_chan *chan,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001031 struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
1032{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001033 struct hci_cp_create_logical_link cp;
1034
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001035 chan->state = BT_CONNECT;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001036 chan->tx_fs = *tx_fs;
1037 chan->rx_fs = *rx_fs;
1038 cp.phy_handle = chan->conn->handle;
1039 cp.tx_fs.id = chan->tx_fs.id;
1040 cp.tx_fs.type = chan->tx_fs.type;
1041 cp.tx_fs.max_sdu = cpu_to_le16(chan->tx_fs.max_sdu);
1042 cp.tx_fs.sdu_arr_time = cpu_to_le32(chan->tx_fs.sdu_arr_time);
1043 cp.tx_fs.acc_latency = cpu_to_le32(chan->tx_fs.acc_latency);
1044 cp.tx_fs.flush_to = cpu_to_le32(chan->tx_fs.flush_to);
1045 cp.rx_fs.id = chan->rx_fs.id;
1046 cp.rx_fs.type = chan->rx_fs.type;
1047 cp.rx_fs.max_sdu = cpu_to_le16(chan->rx_fs.max_sdu);
1048 cp.rx_fs.sdu_arr_time = cpu_to_le32(chan->rx_fs.sdu_arr_time);
1049 cp.rx_fs.acc_latency = cpu_to_le32(chan->rx_fs.acc_latency);
1050 cp.rx_fs.flush_to = cpu_to_le32(chan->rx_fs.flush_to);
1051 hci_conn_hold(chan->conn);
Peter Krystada8417e62012-03-21 16:58:17 -07001052 if (chan->conn->out)
1053 hci_send_cmd(chan->conn->hdev, HCI_OP_CREATE_LOGICAL_LINK,
1054 sizeof(cp), &cp);
1055 else
1056 hci_send_cmd(chan->conn->hdev, HCI_OP_ACCEPT_LOGICAL_LINK,
1057 sizeof(cp), &cp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001058 return chan;
1059}
1060EXPORT_SYMBOL(hci_chan_create);
1061
1062void hci_chan_modify(struct hci_chan *chan,
1063 struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
1064{
1065 struct hci_cp_flow_spec_modify cp;
1066
1067 chan->tx_fs = *tx_fs;
1068 chan->rx_fs = *rx_fs;
1069 cp.log_handle = cpu_to_le16(chan->ll_handle);
1070 cp.tx_fs.id = tx_fs->id;
1071 cp.tx_fs.type = tx_fs->type;
1072 cp.tx_fs.max_sdu = cpu_to_le16(tx_fs->max_sdu);
1073 cp.tx_fs.sdu_arr_time = cpu_to_le32(tx_fs->sdu_arr_time);
1074 cp.tx_fs.acc_latency = cpu_to_le32(tx_fs->acc_latency);
1075 cp.tx_fs.flush_to = cpu_to_le32(tx_fs->flush_to);
1076 cp.rx_fs.id = rx_fs->id;
1077 cp.rx_fs.type = rx_fs->type;
1078 cp.rx_fs.max_sdu = cpu_to_le16(rx_fs->max_sdu);
1079 cp.rx_fs.sdu_arr_time = cpu_to_le32(rx_fs->sdu_arr_time);
1080 cp.rx_fs.acc_latency = cpu_to_le32(rx_fs->acc_latency);
1081 cp.rx_fs.flush_to = cpu_to_le32(rx_fs->flush_to);
1082 hci_conn_hold(chan->conn);
1083 hci_send_cmd(chan->conn->hdev, HCI_OP_FLOW_SPEC_MODIFY, sizeof(cp),
1084 &cp);
1085}
1086EXPORT_SYMBOL(hci_chan_modify);
1087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088/* Drop all connection on the device */
Mat Martineau3b9239a2012-02-16 11:54:30 -08001089void hci_conn_hash_flush(struct hci_dev *hdev, u8 is_process)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090{
1091 struct hci_conn_hash *h = &hdev->conn_hash;
1092 struct list_head *p;
1093
1094 BT_DBG("hdev %s", hdev->name);
1095
1096 p = h->list.next;
1097 while (p != &h->list) {
1098 struct hci_conn *c;
1099
1100 c = list_entry(p, struct hci_conn, list);
1101 p = p->next;
1102
1103 c->state = BT_CLOSED;
1104
Mat Martineau3b9239a2012-02-16 11:54:30 -08001105 hci_proto_disconn_cfm(c, 0x16, is_process);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 hci_conn_del(c);
1107 }
1108}
1109
Marcel Holtmanna9de9242007-10-20 13:33:56 +02001110/* Check pending connect attempts */
1111void hci_conn_check_pending(struct hci_dev *hdev)
1112{
1113 struct hci_conn *conn;
1114
1115 BT_DBG("hdev %s", hdev->name);
1116
1117 hci_dev_lock(hdev);
1118
1119 conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
1120 if (conn)
1121 hci_acl_connect(conn);
1122
1123 hci_dev_unlock(hdev);
1124}
1125
Marcel Holtmann9eba32b2009-08-22 14:19:26 -07001126void hci_conn_hold_device(struct hci_conn *conn)
1127{
1128 atomic_inc(&conn->devref);
1129}
1130EXPORT_SYMBOL(hci_conn_hold_device);
1131
1132void hci_conn_put_device(struct hci_conn *conn)
1133{
1134 if (atomic_dec_and_test(&conn->devref))
1135 hci_conn_del_sysfs(conn);
1136}
1137EXPORT_SYMBOL(hci_conn_put_device);
1138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139int hci_get_conn_list(void __user *arg)
1140{
1141 struct hci_conn_list_req req, *cl;
1142 struct hci_conn_info *ci;
1143 struct hci_dev *hdev;
1144 struct list_head *p;
1145 int n = 0, size, err;
1146
1147 if (copy_from_user(&req, arg, sizeof(req)))
1148 return -EFAULT;
1149
1150 if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
1151 return -EINVAL;
1152
1153 size = sizeof(req) + req.conn_num * sizeof(*ci);
1154
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001155 cl = kmalloc(size, GFP_KERNEL);
1156 if (!cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 return -ENOMEM;
1158
Andrei Emeltchenko70f230202010-12-01 16:58:25 +02001159 hdev = hci_dev_get(req.dev_id);
1160 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 kfree(cl);
1162 return -ENODEV;
1163 }
1164
1165 ci = cl->conn_info;
1166
1167 hci_dev_lock_bh(hdev);
1168 list_for_each(p, &hdev->conn_hash.list) {
1169 register struct hci_conn *c;
1170 c = list_entry(p, struct hci_conn, list);
1171
1172 bacpy(&(ci + n)->bdaddr, &c->dst);
1173 (ci + n)->handle = c->handle;
1174 (ci + n)->type = c->type;
1175 (ci + n)->out = c->out;
1176 (ci + n)->state = c->state;
1177 (ci + n)->link_mode = c->link_mode;
Nick Pellyc1728492009-12-09 00:15:41 -08001178 if (c->type == SCO_LINK) {
1179 (ci + n)->mtu = hdev->sco_mtu;
1180 (ci + n)->cnt = hdev->sco_cnt;
1181 (ci + n)->pkts = hdev->sco_pkts;
1182 } else {
1183 (ci + n)->mtu = hdev->acl_mtu;
1184 (ci + n)->cnt = hdev->acl_cnt;
1185 (ci + n)->pkts = hdev->acl_pkts;
1186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 if (++n >= req.conn_num)
1188 break;
1189 }
1190 hci_dev_unlock_bh(hdev);
1191
1192 cl->dev_id = hdev->id;
1193 cl->conn_num = n;
1194 size = sizeof(req) + n * sizeof(*ci);
1195
1196 hci_dev_put(hdev);
1197
1198 err = copy_to_user(arg, cl, size);
1199 kfree(cl);
1200
1201 return err ? -EFAULT : 0;
1202}
1203
1204int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
1205{
1206 struct hci_conn_info_req req;
1207 struct hci_conn_info ci;
1208 struct hci_conn *conn;
1209 char __user *ptr = arg + sizeof(req);
1210
1211 if (copy_from_user(&req, arg, sizeof(req)))
1212 return -EFAULT;
1213
1214 hci_dev_lock_bh(hdev);
1215 conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
1216 if (conn) {
1217 bacpy(&ci.bdaddr, &conn->dst);
1218 ci.handle = conn->handle;
1219 ci.type = conn->type;
1220 ci.out = conn->out;
1221 ci.state = conn->state;
1222 ci.link_mode = conn->link_mode;
Nick Pellyc1728492009-12-09 00:15:41 -08001223 if (req.type == SCO_LINK) {
1224 ci.mtu = hdev->sco_mtu;
1225 ci.cnt = hdev->sco_cnt;
1226 ci.pkts = hdev->sco_pkts;
1227 } else {
1228 ci.mtu = hdev->acl_mtu;
1229 ci.cnt = hdev->acl_cnt;
1230 ci.pkts = hdev->acl_pkts;
1231 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001232 ci.pending_sec_level = conn->pending_sec_level;
1233 ci.ssp_mode = conn->ssp_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 }
1235 hci_dev_unlock_bh(hdev);
1236
1237 if (!conn)
1238 return -ENOENT;
1239
1240 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
1241}
Marcel Holtmann40be4922008-07-14 20:13:50 +02001242
1243int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
1244{
1245 struct hci_auth_info_req req;
1246 struct hci_conn *conn;
1247
1248 if (copy_from_user(&req, arg, sizeof(req)))
1249 return -EFAULT;
1250
1251 hci_dev_lock_bh(hdev);
1252 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
1253 if (conn)
1254 req.type = conn->auth_type;
1255 hci_dev_unlock_bh(hdev);
1256
1257 if (!conn)
1258 return -ENOENT;
1259
1260 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
1261}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001262
1263int hci_set_auth_info(struct hci_dev *hdev, void __user *arg)
1264{
1265 struct hci_auth_info_req req;
1266 struct hci_conn *conn;
1267
1268 if (copy_from_user(&req, arg, sizeof(req)))
1269 return -EFAULT;
1270
1271 hci_dev_lock_bh(hdev);
1272 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
1273 if (conn)
1274 conn->auth_type = req.type;
1275 hci_dev_unlock_bh(hdev);
1276
1277 if (!conn)
1278 return -ENOENT;
1279
1280 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
1281}