blob: 3bb2d552a88849468480954055679fc700615aaf [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));
Anderson Lizardo0e833912011-07-27 18:40:09 -030043 cp.scan_interval = cpu_to_le16(0x0060);
44 cp.scan_window = 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;
Anderson Lizardo0e833912011-07-27 18:40:09 -030047 cp.conn_interval_min = cpu_to_le16(0x0028);
48 cp.conn_interval_max = cpu_to_le16(0x0038);
49 cp.supervision_timeout = cpu_to_le16(0x002a);
50 cp.min_ce_len = cpu_to_le16(0x0000);
51 cp.max_ce_len = 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 |
88 cpu_to_le16(0x8000);
89 }
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
164 cp.tx_bandwidth = cpu_to_le32(0x00001f40);
165 cp.rx_bandwidth = cpu_to_le32(0x00001f40);
166 cp.max_latency = cpu_to_le16(0xffff);
167 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);
186 cp.min_ce_len = cpu_to_le16(0x0001);
187 cp.max_ce_len = cpu_to_le16(0x0001);
188
189 hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
190}
191EXPORT_SYMBOL(hci_le_conn_update);
192
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300193void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300194 __u8 ltk[16])
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300195{
196 struct hci_dev *hdev = conn->hdev;
197 struct hci_cp_le_start_enc cp;
198
199 BT_DBG("%p", conn);
200
201 memset(&cp, 0, sizeof(cp));
202
203 cp.handle = cpu_to_le16(conn->handle);
204 memcpy(cp.ltk, ltk, sizeof(cp.ltk));
205 cp.ediv = ediv;
Anderson Briglia51beabd2011-09-19 14:41:09 -0400206 memcpy(cp.rand, rand, sizeof(cp.rand));
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300207
208 hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
209}
210EXPORT_SYMBOL(hci_le_start_enc);
211
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400212/* Device _must_ be locked */
213void hci_sco_setup(struct hci_conn *conn, __u8 status)
214{
215 struct hci_conn *sco = conn->link;
216
217 BT_DBG("%p", conn);
218
219 if (!sco)
220 return;
221
222 if (!status) {
223 if (lmp_esco_capable(conn->hdev))
224 hci_setup_sync(sco, conn->handle);
225 else
226 hci_add_sco(sco, conn->handle);
227 } else {
228 hci_proto_connect_cfm(sco, status);
229 hci_conn_del(sco);
230 }
231}
232
Gustavo F. Padovan19c40e32011-06-17 13:03:21 -0300233static void hci_conn_timeout(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234{
Gustavo F. Padovan19c40e32011-06-17 13:03:21 -0300235 struct hci_conn *conn = container_of(work, struct hci_conn,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300236 disc_work.work);
Marcel Holtmann2950f212009-02-12 14:02:50 +0100237 __u8 reason;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Andrei Emeltchenkoe05dcc32012-02-17 11:40:56 +0200239 BT_DBG("conn %p state %s", conn, state_to_string(conn->state));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
241 if (atomic_read(&conn->refcnt))
242 return;
243
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200244 switch (conn->state) {
245 case BT_CONNECT:
Marcel Holtmann769be972008-07-14 20:13:49 +0200246 case BT_CONNECT2:
Ville Tervofcd89c02011-02-10 22:38:47 -0300247 if (conn->out) {
248 if (conn->type == ACL_LINK)
249 hci_acl_connect_cancel(conn);
250 else if (conn->type == LE_LINK)
251 hci_le_connect_cancel(conn);
252 }
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200253 break;
Marcel Holtmann769be972008-07-14 20:13:49 +0200254 case BT_CONFIG:
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900255 case BT_CONNECTED:
Marcel Holtmann2950f212009-02-12 14:02:50 +0100256 reason = hci_proto_disconn_ind(conn);
257 hci_acl_disconn(conn, reason);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200258 break;
259 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 conn->state = BT_CLOSED;
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200261 break;
262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263}
264
Gustavo F. Padovan416dc942011-12-07 13:24:33 -0200265/* Enter sniff mode */
266static void hci_conn_enter_sniff_mode(struct hci_conn *conn)
267{
268 struct hci_dev *hdev = conn->hdev;
269
270 BT_DBG("conn %p mode %d", conn, conn->mode);
271
272 if (test_bit(HCI_RAW, &hdev->flags))
273 return;
274
275 if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
276 return;
277
278 if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
279 return;
280
281 if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
282 struct hci_cp_sniff_subrate cp;
283 cp.handle = cpu_to_le16(conn->handle);
284 cp.max_latency = cpu_to_le16(0);
285 cp.min_remote_timeout = cpu_to_le16(0);
286 cp.min_local_timeout = cpu_to_le16(0);
287 hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
288 }
289
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200290 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
Gustavo F. Padovan416dc942011-12-07 13:24:33 -0200291 struct hci_cp_sniff_mode cp;
292 cp.handle = cpu_to_le16(conn->handle);
293 cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
294 cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
295 cp.attempt = cpu_to_le16(4);
296 cp.timeout = cpu_to_le16(1);
297 hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
298 }
299}
300
Marcel Holtmann04837f62006-07-03 10:02:33 +0200301static void hci_conn_idle(unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302{
Marcel Holtmann04837f62006-07-03 10:02:33 +0200303 struct hci_conn *conn = (void *) arg;
304
305 BT_DBG("conn %p mode %d", conn, conn->mode);
306
307 hci_conn_enter_sniff_mode(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308}
309
Johan Hedberg9f616562011-04-28 11:28:54 -0700310static void hci_conn_auto_accept(unsigned long arg)
311{
312 struct hci_conn *conn = (void *) arg;
313 struct hci_dev *hdev = conn->hdev;
314
Johan Hedberg9f616562011-04-28 11:28:54 -0700315 hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300316 &conn->dst);
Johan Hedberg9f616562011-04-28 11:28:54 -0700317}
318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
320{
321 struct hci_conn *conn;
322
323 BT_DBG("%s dst %s", hdev->name, batostr(dst));
324
Andre Guedescb601d72012-01-30 09:22:09 -0300325 conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200326 if (!conn)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328
329 bacpy(&conn->dst, dst);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200330 conn->hdev = hdev;
331 conn->type = type;
332 conn->mode = HCI_CM_ACTIVE;
333 conn->state = BT_OPEN;
Andrei Emeltchenko93f19c92009-09-03 12:34:19 +0300334 conn->auth_type = HCI_AT_GENERAL_BONDING;
Johan Hedberg17fa4b92011-01-25 13:28:33 +0200335 conn->io_capability = hdev->io_capability;
Johan Hedberga9583552011-02-19 12:06:01 -0300336 conn->remote_auth = 0xff;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200337 conn->key_type = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
Johan Hedberg58a681e2012-01-16 06:47:28 +0200339 set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200340 conn->disc_timeout = HCI_DISCONN_TIMEOUT;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200341
Marcel Holtmanna8746412008-07-14 20:13:46 +0200342 switch (type) {
343 case ACL_LINK:
344 conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
345 break;
346 case SCO_LINK:
347 if (lmp_esco_capable(hdev))
Marcel Holtmannefc76882009-02-06 09:13:37 +0100348 conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
349 (hdev->esco_type & EDR_ESCO_MASK);
Marcel Holtmanna8746412008-07-14 20:13:46 +0200350 else
351 conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
352 break;
353 case ESCO_LINK:
Marcel Holtmannefc76882009-02-06 09:13:37 +0100354 conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
Marcel Holtmanna8746412008-07-14 20:13:46 +0200355 break;
356 }
357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 skb_queue_head_init(&conn->data_q);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200359
Marcel Holtmann70c1f202012-02-22 12:06:43 +0100360 INIT_LIST_HEAD(&conn->chan_list);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200361
Gustavo F. Padovan19c40e32011-06-17 13:03:21 -0300362 INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800363 setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
Johan Hedberg9f616562011-04-28 11:28:54 -0700364 setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300365 (unsigned long) conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 atomic_set(&conn->refcnt, 0);
368
369 hci_dev_hold(hdev);
370
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 hci_conn_hash_add(hdev, conn);
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200372 if (hdev->notify)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
374
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700375 atomic_set(&conn->devref, 0);
376
Marcel Holtmanna67e8992009-05-02 18:24:06 -0700377 hci_conn_init_sysfs(conn);
378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 return conn;
380}
381
382int hci_conn_del(struct hci_conn *conn)
383{
384 struct hci_dev *hdev = conn->hdev;
385
386 BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
387
Marcel Holtmann04837f62006-07-03 10:02:33 +0200388 del_timer(&conn->idle_timer);
389
Gustavo F. Padovan19c40e32011-06-17 13:03:21 -0300390 cancel_delayed_work_sync(&conn->disc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Johan Hedberg9f616562011-04-28 11:28:54 -0700392 del_timer(&conn->auto_accept_timer);
393
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200394 if (conn->type == ACL_LINK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 struct hci_conn *sco = conn->link;
396 if (sco)
397 sco->link = NULL;
398
399 /* Unacked frames */
400 hdev->acl_cnt += conn->sent;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300401 } else if (conn->type == LE_LINK) {
402 if (hdev->le_pkts)
403 hdev->le_cnt += conn->sent;
404 else
405 hdev->acl_cnt += conn->sent;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200406 } else {
407 struct hci_conn *acl = conn->link;
408 if (acl) {
409 acl->link = NULL;
410 hci_conn_put(acl);
411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 }
413
Gustavo F. Padovan2c33c062011-12-14 13:02:51 -0200414 hci_chan_list_flush(conn);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 hci_conn_hash_del(hdev, conn);
Gustavo F. Padovan3c547112011-12-14 22:58:44 -0200417 if (hdev->notify)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
Marcel Holtmann7d0db0a2008-07-14 20:13:51 +0200419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 skb_queue_purge(&conn->data_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700422 hci_conn_put_device(conn);
Dave Young2ae9a6b2009-02-21 16:13:34 +0800423
Marcel Holtmann384943e2009-05-08 18:20:43 -0700424 hci_dev_put(hdev);
425
Tomas Targownik163f4da2011-06-30 16:30:44 -0300426 if (conn->handle == 0)
427 kfree(conn);
428
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 return 0;
430}
431
432struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
433{
434 int use_src = bacmp(src, BDADDR_ANY);
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200435 struct hci_dev *hdev = NULL, *d;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
437 BT_DBG("%s -> %s", batostr(src), batostr(dst));
438
Gustavo F. Padovanf20d09d2011-12-22 16:30:27 -0200439 read_lock(&hci_dev_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200441 list_for_each_entry(d, &hci_dev_list, list) {
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -0300442 if (!test_bit(HCI_UP, &d->flags) ||
443 test_bit(HCI_RAW, &d->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 continue;
445
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900446 /* Simple routing:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 * No source address - find interface with bdaddr != dst
448 * Source address - find interface with bdaddr == src
449 */
450
451 if (use_src) {
452 if (!bacmp(&d->bdaddr, src)) {
453 hdev = d; break;
454 }
455 } else {
456 if (bacmp(&d->bdaddr, dst)) {
457 hdev = d; break;
458 }
459 }
460 }
461
462 if (hdev)
463 hdev = hci_dev_hold(hdev);
464
Gustavo F. Padovanf20d09d2011-12-22 16:30:27 -0200465 read_unlock(&hci_dev_list_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 return hdev;
467}
468EXPORT_SYMBOL(hci_get_route);
469
Ville Tervofcd89c02011-02-10 22:38:47 -0300470/* Create SCO, ACL or LE connection.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 * Device _must_ be locked */
Andre Guedesb12f62c2012-04-24 21:02:54 -0300472struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
473 __u8 dst_type, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
475 struct hci_conn *acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200476 struct hci_conn *sco;
Ville Tervofcd89c02011-02-10 22:38:47 -0300477 struct hci_conn *le;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479 BT_DBG("%s dst %s", hdev->name, batostr(dst));
480
Ville Tervofcd89c02011-02-10 22:38:47 -0300481 if (type == LE_LINK) {
482 le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300483 if (!le) {
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300484 le = hci_conn_add(hdev, LE_LINK, dst);
485 if (!le)
486 return ERR_PTR(-ENOMEM);
Andre Guedeseda42b52011-05-31 14:20:56 -0300487
Andre Guedesb12f62c2012-04-24 21:02:54 -0300488 le->dst_type = bdaddr_to_le(dst_type);
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300489 hci_le_connect(le);
490 }
Andre Guedes893d6752011-05-31 14:20:55 -0300491
Vinicius Costa Gomes9f0caeb2012-04-20 15:46:08 -0300492 le->pending_sec_level = sec_level;
493 le->auth_type = auth_type;
Ville Tervofcd89c02011-02-10 22:38:47 -0300494
495 hci_conn_hold(le);
496
497 return le;
498 }
499
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200500 acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
501 if (!acl) {
502 acl = hci_conn_add(hdev, ACL_LINK, dst);
503 if (!acl)
Johan Hedberg48c7aba2012-02-19 14:06:48 +0200504 return ERR_PTR(-ENOMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 }
506
507 hci_conn_hold(acl);
508
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200509 if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
Johan Hedberg765c2a92011-01-19 12:06:52 +0530510 acl->sec_level = BT_SECURITY_LOW;
511 acl->pending_sec_level = sec_level;
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200512 acl->auth_type = auth_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 hci_acl_connect(acl);
Marcel Holtmann09ab6f42008-09-09 07:19:20 +0200514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200516 if (type == ACL_LINK)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 return acl;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200518
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200519 sco = hci_conn_hash_lookup_ba(hdev, type, dst);
520 if (!sco) {
521 sco = hci_conn_add(hdev, type, dst);
522 if (!sco) {
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200523 hci_conn_put(acl);
Johan Hedberg48c7aba2012-02-19 14:06:48 +0200524 return ERR_PTR(-ENOMEM);
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200527
528 acl->link = sco;
529 sco->link = acl;
530
531 hci_conn_hold(sco);
532
533 if (acl->state == BT_CONNECTED &&
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300534 (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
Johan Hedberg58a681e2012-01-16 06:47:28 +0200535 set_bit(HCI_CONN_POWER_SAVE, &acl->flags);
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700536 hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
Nick Pellyc3902162009-11-13 14:16:32 -0800537
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200538 if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->flags)) {
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400539 /* defer SCO setup until mode change completed */
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200540 set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->flags);
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400541 return sco;
542 }
543
544 hci_sco_setup(acl, 0x00);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200545 }
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200546
547 return sco;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548}
549EXPORT_SYMBOL(hci_connect);
550
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200551/* Check link security requirement */
552int hci_conn_check_link_mode(struct hci_conn *conn)
553{
554 BT_DBG("conn %p", conn);
555
Johan Hedbergaa64a8b2012-01-18 21:33:12 +0200556 if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT))
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200557 return 0;
558
559 return 1;
560}
561EXPORT_SYMBOL(hci_conn_check_link_mode);
562
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563/* Authenticate remote device */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100564static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 BT_DBG("conn %p", conn);
567
Johan Hedberg765c2a92011-01-19 12:06:52 +0530568 if (conn->pending_sec_level > sec_level)
569 sec_level = conn->pending_sec_level;
570
Marcel Holtmann96a31832009-02-12 16:23:03 +0100571 if (sec_level > conn->sec_level)
Johan Hedberg765c2a92011-01-19 12:06:52 +0530572 conn->pending_sec_level = sec_level;
Marcel Holtmann96a31832009-02-12 16:23:03 +0100573 else if (conn->link_mode & HCI_LM_AUTH)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 return 1;
575
Johan Hedberg65cf6862011-01-19 12:06:49 +0530576 /* Make sure we preserve an existing MITM requirement*/
577 auth_type |= (conn->auth_type & 0x01);
578
Marcel Holtmann96a31832009-02-12 16:23:03 +0100579 conn->auth_type = auth_type;
580
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200581 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 struct hci_cp_auth_requested cp;
Peter Hurleyb7d05ba2012-01-13 15:11:30 +0100583
584 /* encrypt must be pending if auth is also pending */
585 set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
586
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700587 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200588 hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300589 sizeof(cp), &cp);
Waldemar Rymarkiewicz19f8def2011-05-31 15:49:25 +0200590 if (conn->key_type != 0xff)
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200591 set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100593
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 return 0;
595}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200597/* Encrypt the the link */
598static void hci_conn_encrypt(struct hci_conn *conn)
599{
600 BT_DBG("conn %p", conn);
601
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200602 if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200603 struct hci_cp_set_conn_encrypt cp;
604 cp.handle = cpu_to_le16(conn->handle);
605 cp.encrypt = 0x01;
606 hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300607 &cp);
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200608 }
609}
610
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100611/* Enable security */
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100612int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
614 BT_DBG("conn %p", conn);
615
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200616 /* For sdp we don't need the link key. */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100617 if (sec_level == BT_SECURITY_SDP)
618 return 1;
619
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200620 /* For non 2.1 devices and low security level we don't need the link
621 key. */
Johan Hedbergaa64a8b2012-01-18 21:33:12 +0200622 if (sec_level == BT_SECURITY_LOW && !hci_conn_ssp_enabled(conn))
Marcel Holtmann3fdca1e2009-04-28 09:04:55 -0700623 return 1;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100624
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200625 /* For other security levels we need the link key. */
626 if (!(conn->link_mode & HCI_LM_AUTH))
627 goto auth;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200629 /* An authenticated combination key has sufficient security for any
630 security level. */
631 if (conn->key_type == HCI_LK_AUTH_COMBINATION)
632 goto encrypt;
633
634 /* An unauthenticated combination key has sufficient security for
635 security level 1 and 2. */
636 if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300637 (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW))
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200638 goto encrypt;
639
640 /* A combination key has always sufficient security for the security
641 levels 1 or 2. High security level requires the combination key
642 is generated using maximum PIN code length (16).
643 For pre 2.1 units. */
644 if (conn->key_type == HCI_LK_COMBINATION &&
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300645 (sec_level != BT_SECURITY_HIGH || conn->pin_length == 16))
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200646 goto encrypt;
647
648auth:
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200649 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 return 0;
651
Luiz Augusto von Dentz6fdf6582011-06-13 15:37:35 +0300652 if (!hci_conn_auth(conn, sec_level, auth_type))
653 return 0;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100654
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200655encrypt:
656 if (conn->link_mode & HCI_LM_ENCRYPT)
657 return 1;
658
659 hci_conn_encrypt(conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 return 0;
661}
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100662EXPORT_SYMBOL(hci_conn_security);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
Waldemar Rymarkiewiczb3b1b062011-05-06 09:42:31 +0200664/* Check secure link requirement */
665int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
666{
667 BT_DBG("conn %p", conn);
668
669 if (sec_level != BT_SECURITY_HIGH)
670 return 1; /* Accept if non-secure is required */
671
Waldemar Rymarkiewiczef4177e2011-06-02 14:24:52 +0200672 if (conn->sec_level == BT_SECURITY_HIGH)
Waldemar Rymarkiewiczb3b1b062011-05-06 09:42:31 +0200673 return 1;
674
675 return 0; /* Reject not secure link */
676}
677EXPORT_SYMBOL(hci_conn_check_secure);
678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679/* Change link key */
680int hci_conn_change_link_key(struct hci_conn *conn)
681{
682 BT_DBG("conn %p", conn);
683
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200684 if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 struct hci_cp_change_conn_link_key cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700686 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200687 hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300688 sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100690
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 return 0;
692}
693EXPORT_SYMBOL(hci_conn_change_link_key);
694
695/* Switch role */
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100696int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697{
698 BT_DBG("conn %p", conn);
699
700 if (!role && conn->link_mode & HCI_LM_MASTER)
701 return 1;
702
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200703 if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 struct hci_cp_switch_role cp;
705 bacpy(&cp.bdaddr, &conn->dst);
706 cp.role = role;
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200707 hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 }
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100709
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 return 0;
711}
712EXPORT_SYMBOL(hci_conn_switch_role);
713
Marcel Holtmann04837f62006-07-03 10:02:33 +0200714/* Enter active mode */
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700715void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200716{
717 struct hci_dev *hdev = conn->hdev;
718
719 BT_DBG("conn %p mode %d", conn, conn->mode);
720
721 if (test_bit(HCI_RAW, &hdev->flags))
722 return;
723
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700724 if (conn->mode != HCI_CM_SNIFF)
725 goto timer;
726
Johan Hedberg58a681e2012-01-16 06:47:28 +0200727 if (!test_bit(HCI_CONN_POWER_SAVE, &conn->flags) && !force_active)
Marcel Holtmann04837f62006-07-03 10:02:33 +0200728 goto timer;
729
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200730 if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +0200731 struct hci_cp_exit_sniff_mode cp;
YOSHIFUJI Hideakiaca31922007-03-25 20:12:50 -0700732 cp.handle = cpu_to_le16(conn->handle);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200733 hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200734 }
735
736timer:
737 if (hdev->idle_timeout > 0)
738 mod_timer(&conn->idle_timer,
Gustavo Padovan5974e4c2012-05-17 00:36:25 -0300739 jiffies + msecs_to_jiffies(hdev->idle_timeout));
Marcel Holtmann04837f62006-07-03 10:02:33 +0200740}
741
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742/* Drop all connection on the device */
743void hci_conn_hash_flush(struct hci_dev *hdev)
744{
745 struct hci_conn_hash *h = &hdev->conn_hash;
Andrei Emeltchenko3c4e0df02012-02-02 10:32:17 +0200746 struct hci_conn *c, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
748 BT_DBG("hdev %s", hdev->name);
749
Andrei Emeltchenko3c4e0df02012-02-02 10:32:17 +0200750 list_for_each_entry_safe(c, n, &h->list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 c->state = BT_CLOSED;
752
Andrei Emeltchenko9f5a0d72011-11-07 14:20:25 +0200753 hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 hci_conn_del(c);
755 }
756}
757
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200758/* Check pending connect attempts */
759void hci_conn_check_pending(struct hci_dev *hdev)
760{
761 struct hci_conn *conn;
762
763 BT_DBG("hdev %s", hdev->name);
764
765 hci_dev_lock(hdev);
766
767 conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
768 if (conn)
769 hci_acl_connect(conn);
770
771 hci_dev_unlock(hdev);
772}
773
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700774void hci_conn_hold_device(struct hci_conn *conn)
775{
776 atomic_inc(&conn->devref);
777}
778EXPORT_SYMBOL(hci_conn_hold_device);
779
780void hci_conn_put_device(struct hci_conn *conn)
781{
782 if (atomic_dec_and_test(&conn->devref))
783 hci_conn_del_sysfs(conn);
784}
785EXPORT_SYMBOL(hci_conn_put_device);
786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787int hci_get_conn_list(void __user *arg)
788{
Gustavo Padovanfc5fef62012-05-23 04:04:19 -0300789 struct hci_conn *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 struct hci_conn_list_req req, *cl;
791 struct hci_conn_info *ci;
792 struct hci_dev *hdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 int n = 0, size, err;
794
795 if (copy_from_user(&req, arg, sizeof(req)))
796 return -EFAULT;
797
798 if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
799 return -EINVAL;
800
801 size = sizeof(req) + req.conn_num * sizeof(*ci);
802
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200803 cl = kmalloc(size, GFP_KERNEL);
804 if (!cl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 return -ENOMEM;
806
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200807 hdev = hci_dev_get(req.dev_id);
808 if (!hdev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 kfree(cl);
810 return -ENODEV;
811 }
812
813 ci = cl->conn_info;
814
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300815 hci_dev_lock(hdev);
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200816 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 bacpy(&(ci + n)->bdaddr, &c->dst);
818 (ci + n)->handle = c->handle;
819 (ci + n)->type = c->type;
820 (ci + n)->out = c->out;
821 (ci + n)->state = c->state;
822 (ci + n)->link_mode = c->link_mode;
823 if (++n >= req.conn_num)
824 break;
825 }
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300826 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
828 cl->dev_id = hdev->id;
829 cl->conn_num = n;
830 size = sizeof(req) + n * sizeof(*ci);
831
832 hci_dev_put(hdev);
833
834 err = copy_to_user(arg, cl, size);
835 kfree(cl);
836
837 return err ? -EFAULT : 0;
838}
839
840int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
841{
842 struct hci_conn_info_req req;
843 struct hci_conn_info ci;
844 struct hci_conn *conn;
845 char __user *ptr = arg + sizeof(req);
846
847 if (copy_from_user(&req, arg, sizeof(req)))
848 return -EFAULT;
849
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300850 hci_dev_lock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
852 if (conn) {
853 bacpy(&ci.bdaddr, &conn->dst);
854 ci.handle = conn->handle;
855 ci.type = conn->type;
856 ci.out = conn->out;
857 ci.state = conn->state;
858 ci.link_mode = conn->link_mode;
859 }
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300860 hci_dev_unlock(hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
862 if (!conn)
863 return -ENOENT;
864
865 return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
866}
Marcel Holtmann40be4922008-07-14 20:13:50 +0200867
868int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
869{
870 struct hci_auth_info_req req;
871 struct hci_conn *conn;
872
873 if (copy_from_user(&req, arg, sizeof(req)))
874 return -EFAULT;
875
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300876 hci_dev_lock(hdev);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200877 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
878 if (conn)
879 req.type = conn->auth_type;
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300880 hci_dev_unlock(hdev);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200881
882 if (!conn)
883 return -ENOENT;
884
885 return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
886}
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200887
888struct hci_chan *hci_chan_create(struct hci_conn *conn)
889{
890 struct hci_dev *hdev = conn->hdev;
891 struct hci_chan *chan;
892
893 BT_DBG("%s conn %p", hdev->name, conn);
894
Andre Guedes75d77352012-01-30 09:22:10 -0300895 chan = kzalloc(sizeof(struct hci_chan), GFP_KERNEL);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200896 if (!chan)
897 return NULL;
898
899 chan->conn = conn;
900 skb_queue_head_init(&chan->data_q);
901
Gustavo F. Padovan8192ede2011-12-14 15:08:48 -0200902 list_add_rcu(&chan->list, &conn->chan_list);
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200903
904 return chan;
905}
906
907int hci_chan_del(struct hci_chan *chan)
908{
909 struct hci_conn *conn = chan->conn;
910 struct hci_dev *hdev = conn->hdev;
911
912 BT_DBG("%s conn %p chan %p", hdev->name, conn, chan);
913
Gustavo F. Padovan8192ede2011-12-14 15:08:48 -0200914 list_del_rcu(&chan->list);
915
916 synchronize_rcu();
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200917
918 skb_queue_purge(&chan->data_q);
919 kfree(chan);
920
921 return 0;
922}
923
Gustavo F. Padovan2c33c062011-12-14 13:02:51 -0200924void hci_chan_list_flush(struct hci_conn *conn)
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200925{
Andrei Emeltchenko2a5a5ec2012-02-02 10:32:18 +0200926 struct hci_chan *chan, *n;
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200927
928 BT_DBG("conn %p", conn);
929
Andrei Emeltchenko2a5a5ec2012-02-02 10:32:18 +0200930 list_for_each_entry_safe(chan, n, &conn->chan_list, list)
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200931 hci_chan_del(chan);
932}