blob: 126876d915f566d5095cb6ef3495dc1229ea4484 [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI connection handling. */
26
Gustavo Padovan8c520a52012-05-23 04:04:22 -030027#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
29#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
31
Ville Tervofcd89c02011-02-10 22:38:47 -030032static void hci_le_connect(struct hci_conn *conn)
33{
34 struct hci_dev *hdev = conn->hdev;
35 struct hci_cp_le_create_conn cp;
36
37 conn->state = BT_CONNECT;
Johan Hedberga0c808b2012-01-16 09:49:58 +020038 conn->out = true;
Vinicius Costa Gomesb92a6222011-02-10 22:38:52 -030039 conn->link_mode |= HCI_LM_MASTER;
Vinicius Costa Gomes7b5c0d52011-06-09 18:50:50 -030040 conn->sec_level = BT_SECURITY_LOW;
Ville Tervofcd89c02011-02-10 22:38:47 -030041
42 memset(&cp, 0, sizeof(cp));
Andrei Emeltchenko82781e62012-05-25 11:38:27 +030043 cp.scan_interval = __constant_cpu_to_le16(0x0060);
44 cp.scan_window = __constant_cpu_to_le16(0x0030);
Ville Tervofcd89c02011-02-10 22:38:47 -030045 bacpy(&cp.peer_addr, &conn->dst);
Andre Guedes6d3ce0e72011-05-31 14:20:57 -030046 cp.peer_addr_type = conn->dst_type;
Andrei Emeltchenko82781e62012-05-25 11:38:27 +030047 cp.conn_interval_min = __constant_cpu_to_le16(0x0028);
48 cp.conn_interval_max = __constant_cpu_to_le16(0x0038);
49 cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
50 cp.min_ce_len = __constant_cpu_to_le16(0x0000);
51 cp.max_ce_len = __constant_cpu_to_le16(0x0000);
Ville Tervofcd89c02011-02-10 22:38:47 -030052
53 hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
54}
55
56static void hci_le_connect_cancel(struct hci_conn *conn)
57{
58 hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
59}
60
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020061void hci_acl_connect(struct hci_conn *conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -070062{
63 struct hci_dev *hdev = conn->hdev;
64 struct inquiry_entry *ie;
65 struct hci_cp_create_conn cp;
66
Andrei Emeltchenko42d2d872012-02-17 11:40:57 +020067 BT_DBG("hcon %p", conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
69 conn->state = BT_CONNECT;
Johan Hedberga0c808b2012-01-16 09:49:58 +020070 conn->out = true;
Marcel Holtmanna8746412008-07-14 20:13:46 +020071
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 conn->link_mode = HCI_LM_MASTER;
73
Marcel Holtmann4c67bc72006-10-15 17:30:56 +020074 conn->attempt++;
75
Marcel Holtmanne4e8e372008-07-14 20:13:47 +020076 conn->link_policy = hdev->link_policy;
77
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 memset(&cp, 0, sizeof(cp));
79 bacpy(&cp.bdaddr, &conn->dst);
80 cp.pscan_rep_mode = 0x02;
81
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020082 ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
83 if (ie) {
Marcel Holtmann41a96212008-07-14 20:13:48 +020084 if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
85 cp.pscan_rep_mode = ie->data.pscan_rep_mode;
86 cp.pscan_mode = ie->data.pscan_mode;
87 cp.clock_offset = ie->data.clock_offset |
Andrei Emeltchenko82781e62012-05-25 11:38:27 +030088 __constant_cpu_to_le16(0x8000);
Marcel Holtmann41a96212008-07-14 20:13:48 +020089 }
90
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 memcpy(conn->dev_class, ie->data.dev_class, 3);
Johan Hedberg58a681e2012-01-16 06:47:28 +020092 if (ie->data.ssp_mode > 0)
93 set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 }
95
Marcel Holtmanna8746412008-07-14 20:13:46 +020096 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +020098 cp.role_switch = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 else
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200100 cp.role_switch = 0x00;
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200101
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200102 hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103}
104
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200105static void hci_acl_connect_cancel(struct hci_conn *conn)
106{
107 struct hci_cp_create_conn_cancel cp;
108
109 BT_DBG("%p", conn);
110
Andrei Emeltchenkod095c1e2011-12-01 14:33:27 +0200111 if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2)
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200112 return;
113
114 bacpy(&cp.bdaddr, &conn->dst);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200115 hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200116}
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
119{
120 struct hci_cp_disconnect cp;
121
122 BT_DBG("%p", conn);
123
124 conn->state = BT_DISCONN;
125
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700126 cp.handle = cpu_to_le16(conn->handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 cp.reason = reason;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200128 hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129}
130
131void hci_add_sco(struct hci_conn *conn, __u16 handle)
132{
133 struct hci_dev *hdev = conn->hdev;
134 struct hci_cp_add_sco cp;
135
136 BT_DBG("%p", conn);
137
138 conn->state = BT_CONNECT;
Johan Hedberga0c808b2012-01-16 09:49:58 +0200139 conn->out = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Marcel Holtmannefc76882009-02-06 09:13:37 +0100141 conn->attempt++;
142
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700143 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200144 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200146 hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147}
148
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200149void hci_setup_sync(struct hci_conn *conn, __u16 handle)
150{
151 struct hci_dev *hdev = conn->hdev;
152 struct hci_cp_setup_sync_conn cp;
153
154 BT_DBG("%p", conn);
155
156 conn->state = BT_CONNECT;
Johan Hedberga0c808b2012-01-16 09:49:58 +0200157 conn->out = true;
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200158
Marcel Holtmannefc76882009-02-06 09:13:37 +0100159 conn->attempt++;
160
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200161 cp.handle = cpu_to_le16(handle);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200162 cp.pkt_type = cpu_to_le16(conn->pkt_type);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200163
Andrei Emeltchenko82781e62012-05-25 11:38:27 +0300164 cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40);
165 cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40);
166 cp.max_latency = __constant_cpu_to_le16(0xffff);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200167 cp.voice_setting = cpu_to_le16(hdev->voice_setting);
168 cp.retrans_effort = 0xff;
169
170 hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
171}
172
Claudio Takahasi2ce603e2011-02-16 20:44:53 -0200173void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300174 u16 latency, u16 to_multiplier)
Claudio Takahasi2ce603e2011-02-16 20:44:53 -0200175{
176 struct hci_cp_le_conn_update cp;
177 struct hci_dev *hdev = conn->hdev;
178
179 memset(&cp, 0, sizeof(cp));
180
181 cp.handle = cpu_to_le16(conn->handle);
182 cp.conn_interval_min = cpu_to_le16(min);
183 cp.conn_interval_max = cpu_to_le16(max);
184 cp.conn_latency = cpu_to_le16(latency);
185 cp.supervision_timeout = cpu_to_le16(to_multiplier);
Andrei Emeltchenko82781e62012-05-25 11:38:27 +0300186 cp.min_ce_len = __constant_cpu_to_le16(0x0001);
187 cp.max_ce_len = __constant_cpu_to_le16(0x0001);
Claudio Takahasi2ce603e2011-02-16 20:44:53 -0200188
189 hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
190}
Claudio Takahasi2ce603e2011-02-16 20:44:53 -0200191
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300192void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300193 __u8 ltk[16])
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300194{
195 struct hci_dev *hdev = conn->hdev;
196 struct hci_cp_le_start_enc cp;
197
198 BT_DBG("%p", conn);
199
200 memset(&cp, 0, sizeof(cp));
201
202 cp.handle = cpu_to_le16(conn->handle);
203 memcpy(cp.ltk, ltk, sizeof(cp.ltk));
204 cp.ediv = ediv;
Anderson Briglia51beabd2011-09-19 14:41:09 -0400205 memcpy(cp.rand, rand, sizeof(cp.rand));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300206
207 hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
208}
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300209
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400210/* Device _must_ be locked */
211void hci_sco_setup(struct hci_conn *conn, __u8 status)
212{
213 struct hci_conn *sco = conn->link;
214
215 BT_DBG("%p", conn);
216
217 if (!sco)
218 return;
219
220 if (!status) {
221 if (lmp_esco_capable(conn->hdev))
222 hci_setup_sync(sco, conn->handle);
223 else
224 hci_add_sco(sco, conn->handle);
225 } else {
226 hci_proto_connect_cfm(sco, status);
227 hci_conn_del(sco);
228 }
229}
230
Gustavo F. Padovan19c40e32011-06-17 13:03:21 -0300231static void hci_conn_timeout(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232{
Gustavo F. Padovan19c40e32011-06-17 13:03:21 -0300233 struct hci_conn *conn = container_of(work, struct hci_conn,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300234 disc_work.work);
Marcel Holtmann2950f212009-02-12 14:02:50 +0100235 __u8 reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200237 BT_DBG("conn %p state %s", conn, state_to_string(conn->state));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
239 if (atomic_read(&conn->refcnt))
240 return;
241
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200242 switch (conn->state) {
243 case BT_CONNECT:
Marcel Holtmann769be972008-07-14 20:13:49 +0200244 case BT_CONNECT2:
Ville Tervofcd89c02011-02-10 22:38:47 -0300245 if (conn->out) {
246 if (conn->type == ACL_LINK)
247 hci_acl_connect_cancel(conn);
248 else if (conn->type == LE_LINK)
249 hci_le_connect_cancel(conn);
250 }
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200251 break;
Marcel Holtmann769be972008-07-14 20:13:49 +0200252 case BT_CONFIG:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900253 case BT_CONNECTED:
Marcel Holtmann2950f212009-02-12 14:02:50 +0100254 reason = hci_proto_disconn_ind(conn);
255 hci_acl_disconn(conn, reason);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200256 break;
257 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 conn->state = BT_CLOSED;
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200259 break;
260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261}
262
Gustavo F. Padovan416dc942011-12-07 13:24:33 -0200263/* Enter sniff mode */
264static void hci_conn_enter_sniff_mode(struct hci_conn *conn)
265{
266 struct hci_dev *hdev = conn->hdev;
267
268 BT_DBG("conn %p mode %d", conn, conn->mode);
269
270 if (test_bit(HCI_RAW, &hdev->flags))
271 return;
272
273 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
274 return;
275
276 if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
277 return;
278
279 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
280 struct hci_cp_sniff_subrate cp;
281 cp.handle = cpu_to_le16(conn->handle);
Andrei Emeltchenko82781e62012-05-25 11:38:27 +0300282 cp.max_latency = __constant_cpu_to_le16(0);
283 cp.min_remote_timeout = __constant_cpu_to_le16(0);
284 cp.min_local_timeout = __constant_cpu_to_le16(0);
Gustavo F. Padovan416dc942011-12-07 13:24:33 -0200285 hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
286 }
287
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200288 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
Gustavo F. Padovan416dc942011-12-07 13:24:33 -0200289 struct hci_cp_sniff_mode cp;
290 cp.handle = cpu_to_le16(conn->handle);
291 cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
292 cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
Andrei Emeltchenko82781e62012-05-25 11:38:27 +0300293 cp.attempt = __constant_cpu_to_le16(4);
294 cp.timeout = __constant_cpu_to_le16(1);
Gustavo F. Padovan416dc942011-12-07 13:24:33 -0200295 hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
296 }
297}
298
Marcel Holtmann04837f62006-07-03 10:02:33 +0200299static void hci_conn_idle(unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200301 struct hci_conn *conn = (void *) arg;
302
303 BT_DBG("conn %p mode %d", conn, conn->mode);
304
305 hci_conn_enter_sniff_mode(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306}
307
Johan Hedberg9f616562011-04-28 11:28:54 -0700308static void hci_conn_auto_accept(unsigned long arg)
309{
310 struct hci_conn *conn = (void *) arg;
311 struct hci_dev *hdev = conn->hdev;
312
Johan Hedberg9f616562011-04-28 11:28:54 -0700313 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300314 &conn->dst);
Johan Hedberg9f616562011-04-28 11:28:54 -0700315}
316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
318{
319 struct hci_conn *conn;
320
321 BT_DBG("%s dst %s", hdev->name, batostr(dst));
322
Andre Guedescb601d72012-01-30 09:22:09 -0300323 conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200324 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
327 bacpy(&conn->dst, dst);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200328 conn->hdev = hdev;
329 conn->type = type;
330 conn->mode = HCI_CM_ACTIVE;
331 conn->state = BT_OPEN;
Andrei Emeltchenko93f19c92009-09-03 12:34:19 +0300332 conn->auth_type = HCI_AT_GENERAL_BONDING;
Johan Hedberg17fa4b92011-01-25 13:28:33 +0200333 conn->io_capability = hdev->io_capability;
Johan Hedberga9583552011-02-19 12:06:01 -0300334 conn->remote_auth = 0xff;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200335 conn->key_type = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
Johan Hedberg58a681e2012-01-16 06:47:28 +0200337 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200338 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200339
Marcel Holtmanna8746412008-07-14 20:13:46 +0200340 switch (type) {
341 case ACL_LINK:
342 conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
343 break;
344 case SCO_LINK:
345 if (lmp_esco_capable(hdev))
Marcel Holtmannefc76882009-02-06 09:13:37 +0100346 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
347 (hdev->esco_type & EDR_ESCO_MASK);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200348 else
349 conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
350 break;
351 case ESCO_LINK:
Marcel Holtmannefc76882009-02-06 09:13:37 +0100352 conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200353 break;
354 }
355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 skb_queue_head_init(&conn->data_q);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200357
Marcel Holtmann70c1f202012-02-22 12:06:43 +0100358 INIT_LIST_HEAD(&conn->chan_list);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200359
Gustavo F. Padovan19c40e32011-06-17 13:03:21 -0300360 INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800361 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
Johan Hedberg9f616562011-04-28 11:28:54 -0700362 setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300363 (unsigned long) conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
365 atomic_set(&conn->refcnt, 0);
366
367 hci_dev_hold(hdev);
368
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 hci_conn_hash_add(hdev, conn);
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200370 if (hdev->notify)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
372
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700373 atomic_set(&conn->devref, 0);
374
Marcel Holtmanna67e8992009-05-02 18:24:06 -0700375 hci_conn_init_sysfs(conn);
376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 return conn;
378}
379
380int hci_conn_del(struct hci_conn *conn)
381{
382 struct hci_dev *hdev = conn->hdev;
383
384 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
385
Marcel Holtmann04837f62006-07-03 10:02:33 +0200386 del_timer(&conn->idle_timer);
387
Gustavo F. Padovan19c40e32011-06-17 13:03:21 -0300388 cancel_delayed_work_sync(&conn->disc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Johan Hedberg9f616562011-04-28 11:28:54 -0700390 del_timer(&conn->auto_accept_timer);
391
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200392 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 struct hci_conn *sco = conn->link;
394 if (sco)
395 sco->link = NULL;
396
397 /* Unacked frames */
398 hdev->acl_cnt += conn->sent;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300399 } else if (conn->type == LE_LINK) {
400 if (hdev->le_pkts)
401 hdev->le_cnt += conn->sent;
402 else
403 hdev->acl_cnt += conn->sent;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200404 } else {
405 struct hci_conn *acl = conn->link;
406 if (acl) {
407 acl->link = NULL;
408 hci_conn_put(acl);
409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 }
411
Gustavo F. Padovan2c33c062011-12-14 13:02:51 -0200412 hci_chan_list_flush(conn);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200413
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 hci_conn_hash_del(hdev, conn);
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200415 if (hdev->notify)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200417
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 skb_queue_purge(&conn->data_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700420 hci_conn_put_device(conn);
Dave Young2ae9a6b2009-02-21 16:13:34 +0800421
Marcel Holtmann384943e2009-05-08 18:20:43 -0700422 hci_dev_put(hdev);
423
Tomas Targownik163f4da2011-06-30 16:30:44 -0300424 if (conn->handle == 0)
425 kfree(conn);
426
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 return 0;
428}
429
430struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
431{
432 int use_src = bacmp(src, BDADDR_ANY);
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200433 struct hci_dev *hdev = NULL, *d;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
435 BT_DBG("%s -> %s", batostr(src), batostr(dst));
436
Gustavo F. Padovanf20d09d2011-12-22 16:30:27 -0200437 read_lock(&hci_dev_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200439 list_for_each_entry(d, &hci_dev_list, list) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300440 if (!test_bit(HCI_UP, &d->flags) ||
441 test_bit(HCI_RAW, &d->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 continue;
443
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900444 /* Simple routing:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 * No source address - find interface with bdaddr != dst
446 * Source address - find interface with bdaddr == src
447 */
448
449 if (use_src) {
450 if (!bacmp(&d->bdaddr, src)) {
451 hdev = d; break;
452 }
453 } else {
454 if (bacmp(&d->bdaddr, dst)) {
455 hdev = d; break;
456 }
457 }
458 }
459
460 if (hdev)
461 hdev = hci_dev_hold(hdev);
462
Gustavo F. Padovanf20d09d2011-12-22 16:30:27 -0200463 read_unlock(&hci_dev_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 return hdev;
465}
466EXPORT_SYMBOL(hci_get_route);
467
Ville Tervofcd89c02011-02-10 22:38:47 -0300468/* Create SCO, ACL or LE connection.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 * Device _must_ be locked */
Andre Guedesb12f62c2012-04-24 21:02:54 -0300470struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
471 __u8 dst_type, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
473 struct hci_conn *acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200474 struct hci_conn *sco;
Ville Tervofcd89c02011-02-10 22:38:47 -0300475 struct hci_conn *le;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
477 BT_DBG("%s dst %s", hdev->name, batostr(dst));
478
Ville Tervofcd89c02011-02-10 22:38:47 -0300479 if (type == LE_LINK) {
480 le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300481 if (!le) {
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300482 le = hci_conn_add(hdev, LE_LINK, dst);
483 if (!le)
484 return ERR_PTR(-ENOMEM);
Andre Guedeseda42b52011-05-31 14:20:56 -0300485
Andre Guedesb12f62c2012-04-24 21:02:54 -0300486 le->dst_type = bdaddr_to_le(dst_type);
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300487 hci_le_connect(le);
488 }
Andre Guedes893d6752011-05-31 14:20:55 -0300489
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300490 le->pending_sec_level = sec_level;
491 le->auth_type = auth_type;
Ville Tervofcd89c02011-02-10 22:38:47 -0300492
493 hci_conn_hold(le);
494
495 return le;
496 }
497
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200498 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
499 if (!acl) {
500 acl = hci_conn_add(hdev, ACL_LINK, dst);
501 if (!acl)
Johan Hedberg48c7aba2012-02-19 14:06:48 +0200502 return ERR_PTR(-ENOMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 }
504
505 hci_conn_hold(acl);
506
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200507 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
Johan Hedberg765c2a92011-01-19 12:06:52 +0530508 acl->sec_level = BT_SECURITY_LOW;
509 acl->pending_sec_level = sec_level;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200510 acl->auth_type = auth_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 hci_acl_connect(acl);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200514 if (type == ACL_LINK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 return acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200516
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200517 sco = hci_conn_hash_lookup_ba(hdev, type, dst);
518 if (!sco) {
519 sco = hci_conn_add(hdev, type, dst);
520 if (!sco) {
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200521 hci_conn_put(acl);
Johan Hedberg48c7aba2012-02-19 14:06:48 +0200522 return ERR_PTR(-ENOMEM);
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200525
526 acl->link = sco;
527 sco->link = acl;
528
529 hci_conn_hold(sco);
530
531 if (acl->state == BT_CONNECTED &&
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300532 (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
Johan Hedberg58a681e2012-01-16 06:47:28 +0200533 set_bit(HCI_CONN_POWER_SAVE, &acl->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700534 hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
Nick Pellyc3902162009-11-13 14:16:32 -0800535
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200536 if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->flags)) {
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400537 /* defer SCO setup until mode change completed */
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200538 set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->flags);
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400539 return sco;
540 }
541
542 hci_sco_setup(acl, 0x00);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200543 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200544
545 return sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200548/* Check link security requirement */
549int hci_conn_check_link_mode(struct hci_conn *conn)
550{
551 BT_DBG("conn %p", conn);
552
Johan Hedbergaa64a8b2012-01-18 21:33:12 +0200553 if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT))
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200554 return 0;
555
556 return 1;
557}
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200558
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559/* Authenticate remote device */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100560static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561{
562 BT_DBG("conn %p", conn);
563
Johan Hedberg765c2a92011-01-19 12:06:52 +0530564 if (conn->pending_sec_level > sec_level)
565 sec_level = conn->pending_sec_level;
566
Marcel Holtmann96a31832009-02-12 16:23:03 +0100567 if (sec_level > conn->sec_level)
Johan Hedberg765c2a92011-01-19 12:06:52 +0530568 conn->pending_sec_level = sec_level;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100569 else if (conn->link_mode & HCI_LM_AUTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 return 1;
571
Johan Hedberg65cf6862011-01-19 12:06:49 +0530572 /* Make sure we preserve an existing MITM requirement*/
573 auth_type |= (conn->auth_type & 0x01);
574
Marcel Holtmann96a31832009-02-12 16:23:03 +0100575 conn->auth_type = auth_type;
576
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200577 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 struct hci_cp_auth_requested cp;
Peter Hurleyb7d05ba2012-01-13 15:11:30 +0100579
580 /* encrypt must be pending if auth is also pending */
581 set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
582
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700583 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200584 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300585 sizeof(cp), &cp);
Waldemar Rymarkiewicz19f8def2011-05-31 15:49:25 +0200586 if (conn->key_type != 0xff)
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200587 set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100589
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 return 0;
591}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200593/* Encrypt the the link */
594static void hci_conn_encrypt(struct hci_conn *conn)
595{
596 BT_DBG("conn %p", conn);
597
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200598 if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200599 struct hci_cp_set_conn_encrypt cp;
600 cp.handle = cpu_to_le16(conn->handle);
601 cp.encrypt = 0x01;
602 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300603 &cp);
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200604 }
605}
606
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100607/* Enable security */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100608int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
610 BT_DBG("conn %p", conn);
611
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200612 /* For sdp we don't need the link key. */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100613 if (sec_level == BT_SECURITY_SDP)
614 return 1;
615
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200616 /* For non 2.1 devices and low security level we don't need the link
617 key. */
Johan Hedbergaa64a8b2012-01-18 21:33:12 +0200618 if (sec_level == BT_SECURITY_LOW && !hci_conn_ssp_enabled(conn))
Marcel Holtmann3fdca1e2009-04-28 09:04:55 -0700619 return 1;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100620
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200621 /* For other security levels we need the link key. */
622 if (!(conn->link_mode & HCI_LM_AUTH))
623 goto auth;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200625 /* An authenticated combination key has sufficient security for any
626 security level. */
627 if (conn->key_type == HCI_LK_AUTH_COMBINATION)
628 goto encrypt;
629
630 /* An unauthenticated combination key has sufficient security for
631 security level 1 and 2. */
632 if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300633 (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW))
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200634 goto encrypt;
635
636 /* A combination key has always sufficient security for the security
637 levels 1 or 2. High security level requires the combination key
638 is generated using maximum PIN code length (16).
639 For pre 2.1 units. */
640 if (conn->key_type == HCI_LK_COMBINATION &&
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300641 (sec_level != BT_SECURITY_HIGH || conn->pin_length == 16))
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200642 goto encrypt;
643
644auth:
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200645 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 return 0;
647
Luiz Augusto von Dentz6fdf6582011-06-13 15:37:35 +0300648 if (!hci_conn_auth(conn, sec_level, auth_type))
649 return 0;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100650
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200651encrypt:
652 if (conn->link_mode & HCI_LM_ENCRYPT)
653 return 1;
654
655 hci_conn_encrypt(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 return 0;
657}
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100658EXPORT_SYMBOL(hci_conn_security);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Waldemar Rymarkiewiczb3b1b062011-05-06 09:42:31 +0200660/* Check secure link requirement */
661int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
662{
663 BT_DBG("conn %p", conn);
664
665 if (sec_level != BT_SECURITY_HIGH)
666 return 1; /* Accept if non-secure is required */
667
Waldemar Rymarkiewiczef4177e2011-06-02 14:24:52 +0200668 if (conn->sec_level == BT_SECURITY_HIGH)
Waldemar Rymarkiewiczb3b1b062011-05-06 09:42:31 +0200669 return 1;
670
671 return 0; /* Reject not secure link */
672}
673EXPORT_SYMBOL(hci_conn_check_secure);
674
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675/* Change link key */
676int hci_conn_change_link_key(struct hci_conn *conn)
677{
678 BT_DBG("conn %p", conn);
679
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200680 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 struct hci_cp_change_conn_link_key cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700682 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200683 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300684 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100686
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 return 0;
688}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
690/* Switch role */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100691int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692{
693 BT_DBG("conn %p", conn);
694
695 if (!role && conn->link_mode & HCI_LM_MASTER)
696 return 1;
697
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200698 if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 struct hci_cp_switch_role cp;
700 bacpy(&cp.bdaddr, &conn->dst);
701 cp.role = role;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200702 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100704
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 return 0;
706}
707EXPORT_SYMBOL(hci_conn_switch_role);
708
Marcel Holtmann04837f62006-07-03 10:02:33 +0200709/* Enter active mode */
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700710void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200711{
712 struct hci_dev *hdev = conn->hdev;
713
714 BT_DBG("conn %p mode %d", conn, conn->mode);
715
716 if (test_bit(HCI_RAW, &hdev->flags))
717 return;
718
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700719 if (conn->mode != HCI_CM_SNIFF)
720 goto timer;
721
Johan Hedberg58a681e2012-01-16 06:47:28 +0200722 if (!test_bit(HCI_CONN_POWER_SAVE, &conn->flags) && !force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200723 goto timer;
724
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200725 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +0200726 struct hci_cp_exit_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700727 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200728 hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200729 }
730
731timer:
732 if (hdev->idle_timeout > 0)
733 mod_timer(&conn->idle_timer,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300734 jiffies + msecs_to_jiffies(hdev->idle_timeout));
Marcel Holtmann04837f62006-07-03 10:02:33 +0200735}
736
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737/* Drop all connection on the device */
738void hci_conn_hash_flush(struct hci_dev *hdev)
739{
740 struct hci_conn_hash *h = &hdev->conn_hash;
Andrei Emeltchenko3c4e0df2012-02-02 10:32:17 +0200741 struct hci_conn *c, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
743 BT_DBG("hdev %s", hdev->name);
744
Andrei Emeltchenko3c4e0df2012-02-02 10:32:17 +0200745 list_for_each_entry_safe(c, n, &h->list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 c->state = BT_CLOSED;
747
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200748 hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 hci_conn_del(c);
750 }
751}
752
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200753/* Check pending connect attempts */
754void hci_conn_check_pending(struct hci_dev *hdev)
755{
756 struct hci_conn *conn;
757
758 BT_DBG("hdev %s", hdev->name);
759
760 hci_dev_lock(hdev);
761
762 conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
763 if (conn)
764 hci_acl_connect(conn);
765
766 hci_dev_unlock(hdev);
767}
768
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700769void hci_conn_hold_device(struct hci_conn *conn)
770{
771 atomic_inc(&conn->devref);
772}
773EXPORT_SYMBOL(hci_conn_hold_device);
774
775void hci_conn_put_device(struct hci_conn *conn)
776{
777 if (atomic_dec_and_test(&conn->devref))
778 hci_conn_del_sysfs(conn);
779}
780EXPORT_SYMBOL(hci_conn_put_device);
781
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782int hci_get_conn_list(void __user *arg)
783{
Gustavo Padovanfc5fef62012-05-23 04:04:19 -0300784 struct hci_conn *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 struct hci_conn_list_req req, *cl;
786 struct hci_conn_info *ci;
787 struct hci_dev *hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 int n = 0, size, err;
789
790 if (copy_from_user(&req, arg, sizeof(req)))
791 return -EFAULT;
792
793 if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
794 return -EINVAL;
795
796 size = sizeof(req) + req.conn_num * sizeof(*ci);
797
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200798 cl = kmalloc(size, GFP_KERNEL);
799 if (!cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 return -ENOMEM;
801
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200802 hdev = hci_dev_get(req.dev_id);
803 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 kfree(cl);
805 return -ENODEV;
806 }
807
808 ci = cl->conn_info;
809
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300810 hci_dev_lock(hdev);
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200811 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 bacpy(&(ci + n)->bdaddr, &c->dst);
813 (ci + n)->handle = c->handle;
814 (ci + n)->type = c->type;
815 (ci + n)->out = c->out;
816 (ci + n)->state = c->state;
817 (ci + n)->link_mode = c->link_mode;
818 if (++n >= req.conn_num)
819 break;
820 }
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300821 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
823 cl->dev_id = hdev->id;
824 cl->conn_num = n;
825 size = sizeof(req) + n * sizeof(*ci);
826
827 hci_dev_put(hdev);
828
829 err = copy_to_user(arg, cl, size);
830 kfree(cl);
831
832 return err ? -EFAULT : 0;
833}
834
835int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
836{
837 struct hci_conn_info_req req;
838 struct hci_conn_info ci;
839 struct hci_conn *conn;
840 char __user *ptr = arg + sizeof(req);
841
842 if (copy_from_user(&req, arg, sizeof(req)))
843 return -EFAULT;
844
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300845 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
847 if (conn) {
848 bacpy(&ci.bdaddr, &conn->dst);
849 ci.handle = conn->handle;
850 ci.type = conn->type;
851 ci.out = conn->out;
852 ci.state = conn->state;
853 ci.link_mode = conn->link_mode;
854 }
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300855 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
857 if (!conn)
858 return -ENOENT;
859
860 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
861}
Marcel Holtmann40be4922008-07-14 20:13:50 +0200862
863int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
864{
865 struct hci_auth_info_req req;
866 struct hci_conn *conn;
867
868 if (copy_from_user(&req, arg, sizeof(req)))
869 return -EFAULT;
870
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300871 hci_dev_lock(hdev);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200872 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
873 if (conn)
874 req.type = conn->auth_type;
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300875 hci_dev_unlock(hdev);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200876
877 if (!conn)
878 return -ENOENT;
879
880 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
881}
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200882
883struct hci_chan *hci_chan_create(struct hci_conn *conn)
884{
885 struct hci_dev *hdev = conn->hdev;
886 struct hci_chan *chan;
887
888 BT_DBG("%s conn %p", hdev->name, conn);
889
Andre Guedes75d77352012-01-30 09:22:10 -0300890 chan = kzalloc(sizeof(struct hci_chan), GFP_KERNEL);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200891 if (!chan)
892 return NULL;
893
894 chan->conn = conn;
895 skb_queue_head_init(&chan->data_q);
896
Gustavo F. Padovan8192ede2011-12-14 15:08:48 -0200897 list_add_rcu(&chan->list, &conn->chan_list);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200898
899 return chan;
900}
901
902int hci_chan_del(struct hci_chan *chan)
903{
904 struct hci_conn *conn = chan->conn;
905 struct hci_dev *hdev = conn->hdev;
906
907 BT_DBG("%s conn %p chan %p", hdev->name, conn, chan);
908
Gustavo F. Padovan8192ede2011-12-14 15:08:48 -0200909 list_del_rcu(&chan->list);
910
911 synchronize_rcu();
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200912
913 skb_queue_purge(&chan->data_q);
914 kfree(chan);
915
916 return 0;
917}
918
Gustavo F. Padovan2c33c062011-12-14 13:02:51 -0200919void hci_chan_list_flush(struct hci_conn *conn)
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200920{
Andrei Emeltchenko2a5a5ec2012-02-02 10:32:18 +0200921 struct hci_chan *chan, *n;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200922
923 BT_DBG("conn %p", conn);
924
Andrei Emeltchenko2a5a5ec2012-02-02 10:32:18 +0200925 list_for_each_entry_safe(chan, n, &conn->chan_list, list)
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200926 hci_chan_del(chan);
927}