Blame view

net/bluetooth/hci_conn.c 22.3 KB
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
     BlueZ - Bluetooth protocol stack for Linux
2d0a03460   Ron Shaffer   Bluetooth: Reassi...
3
     Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
9
10
11
12
13
14
  
     Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation;
  
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
     IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
15
16
17
     CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
     WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
19
20
     ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
     SOFTWARE IS DISCLAIMED.
  */
  
  /* Bluetooth HCI connection handling. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
  #include <linux/module.h>
  
  #include <linux/types.h>
  #include <linux/errno.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
36
37
38
39
  #include <linux/slab.h>
  #include <linux/poll.h>
  #include <linux/fcntl.h>
  #include <linux/init.h>
  #include <linux/skbuff.h>
  #include <linux/interrupt.h>
  #include <linux/notifier.h>
  #include <net/sock.h>
  
  #include <asm/system.h>
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
40
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
  #include <asm/unaligned.h>
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
45
46
47
48
49
50
51
  static void hci_le_connect(struct hci_conn *conn)
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct hci_cp_le_create_conn cp;
  
  	conn->state = BT_CONNECT;
  	conn->out = 1;
b92a62238   Vinicius Costa Gomes   Bluetooth: Fix in...
52
  	conn->link_mode |= HCI_LM_MASTER;
7b5c0d524   Vinicius Costa Gomes   Bluetooth: Fix in...
53
  	conn->sec_level = BT_SECURITY_LOW;
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
54
55
  
  	memset(&cp, 0, sizeof(cp));
0e8339151   Anderson Lizardo   Bluetooth: use re...
56
57
  	cp.scan_interval = cpu_to_le16(0x0060);
  	cp.scan_window = cpu_to_le16(0x0030);
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
58
  	bacpy(&cp.peer_addr, &conn->dst);
6d3ce0e79   Andre Guedes   Bluetooth: Set 'p...
59
  	cp.peer_addr_type = conn->dst_type;
0e8339151   Anderson Lizardo   Bluetooth: use re...
60
61
62
63
64
  	cp.conn_interval_min = cpu_to_le16(0x0028);
  	cp.conn_interval_max = cpu_to_le16(0x0038);
  	cp.supervision_timeout = cpu_to_le16(0x002a);
  	cp.min_ce_len = cpu_to_le16(0x0000);
  	cp.max_ce_len = cpu_to_le16(0x0000);
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
65
66
67
68
69
70
71
72
  
  	hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
  }
  
  static void hci_le_connect_cancel(struct hci_conn *conn)
  {
  	hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
  }
4c67bc74f   Marcel Holtmann   [Bluetooth] Suppo...
73
  void hci_acl_connect(struct hci_conn *conn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
78
79
80
81
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct inquiry_entry *ie;
  	struct hci_cp_create_conn cp;
  
  	BT_DBG("%p", conn);
  
  	conn->state = BT_CONNECT;
a8746417e   Marcel Holtmann   [Bluetooth] Track...
82
  	conn->out = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  	conn->link_mode = HCI_LM_MASTER;
4c67bc74f   Marcel Holtmann   [Bluetooth] Suppo...
84
  	conn->attempt++;
e4e8e37c4   Marcel Holtmann   [Bluetooth] Make ...
85
  	conn->link_policy = hdev->link_policy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
  	memset(&cp, 0, sizeof(cp));
  	bacpy(&cp.bdaddr, &conn->dst);
  	cp.pscan_rep_mode = 0x02;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
89
90
  	ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
  	if (ie) {
41a96212b   Marcel Holtmann   [Bluetooth] Track...
91
92
93
94
95
96
  		if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
  			cp.pscan_rep_mode = ie->data.pscan_rep_mode;
  			cp.pscan_mode     = ie->data.pscan_mode;
  			cp.clock_offset   = ie->data.clock_offset |
  							cpu_to_le16(0x8000);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  		memcpy(conn->dev_class, ie->data.dev_class, 3);
41a96212b   Marcel Holtmann   [Bluetooth] Track...
98
  		conn->ssp_mode = ie->data.ssp_mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  	}
a8746417e   Marcel Holtmann   [Bluetooth] Track...
100
  	cp.pkt_type = cpu_to_le16(conn->pkt_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
  	if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
102
  		cp.role_switch = 0x01;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  	else
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
104
  		cp.role_switch = 0x00;
4c67bc74f   Marcel Holtmann   [Bluetooth] Suppo...
105

a9de92480   Marcel Holtmann   [Bluetooth] Switc...
106
  	hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  }
6ac59344e   Marcel Holtmann   [Bluetooth] Suppo...
108
109
110
111
112
  static void hci_acl_connect_cancel(struct hci_conn *conn)
  {
  	struct hci_cp_create_conn_cancel cp;
  
  	BT_DBG("%p", conn);
d095c1ebd   Andrei Emeltchenko   Bluetooth: Remove...
113
  	if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2)
6ac59344e   Marcel Holtmann   [Bluetooth] Suppo...
114
115
116
  		return;
  
  	bacpy(&cp.bdaddr, &conn->dst);
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
117
  	hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
6ac59344e   Marcel Holtmann   [Bluetooth] Suppo...
118
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
122
123
124
125
  void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
  {
  	struct hci_cp_disconnect cp;
  
  	BT_DBG("%p", conn);
  
  	conn->state = BT_DISCONN;
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
126
  	cp.handle = cpu_to_le16(conn->handle);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  	cp.reason = reason;
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
128
  	hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
133
134
135
136
137
138
139
  }
  
  void hci_add_sco(struct hci_conn *conn, __u16 handle)
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct hci_cp_add_sco cp;
  
  	BT_DBG("%p", conn);
  
  	conn->state = BT_CONNECT;
  	conn->out = 1;
efc7688b5   Marcel Holtmann   Bluetooth: Add SC...
140
  	conn->attempt++;
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
141
  	cp.handle   = cpu_to_le16(handle);
a8746417e   Marcel Holtmann   [Bluetooth] Track...
142
  	cp.pkt_type = cpu_to_le16(conn->pkt_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

a9de92480   Marcel Holtmann   [Bluetooth] Switc...
144
  	hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  }
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
146
147
148
149
150
151
152
153
154
  void hci_setup_sync(struct hci_conn *conn, __u16 handle)
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct hci_cp_setup_sync_conn cp;
  
  	BT_DBG("%p", conn);
  
  	conn->state = BT_CONNECT;
  	conn->out = 1;
efc7688b5   Marcel Holtmann   Bluetooth: Add SC...
155
  	conn->attempt++;
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
156
  	cp.handle   = cpu_to_le16(handle);
a8746417e   Marcel Holtmann   [Bluetooth] Track...
157
  	cp.pkt_type = cpu_to_le16(conn->pkt_type);
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
158
159
160
161
162
163
164
165
166
  
  	cp.tx_bandwidth   = cpu_to_le32(0x00001f40);
  	cp.rx_bandwidth   = cpu_to_le32(0x00001f40);
  	cp.max_latency    = cpu_to_le16(0xffff);
  	cp.voice_setting  = cpu_to_le16(hdev->voice_setting);
  	cp.retrans_effort = 0xff;
  
  	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
  }
2ce603ebe   Claudio Takahasi   Bluetooth: Send L...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
  					u16 latency, u16 to_multiplier)
  {
  	struct hci_cp_le_conn_update cp;
  	struct hci_dev *hdev = conn->hdev;
  
  	memset(&cp, 0, sizeof(cp));
  
  	cp.handle		= cpu_to_le16(conn->handle);
  	cp.conn_interval_min	= cpu_to_le16(min);
  	cp.conn_interval_max	= cpu_to_le16(max);
  	cp.conn_latency		= cpu_to_le16(latency);
  	cp.supervision_timeout	= cpu_to_le16(to_multiplier);
  	cp.min_ce_len		= cpu_to_le16(0x0001);
  	cp.max_ce_len		= cpu_to_le16(0x0001);
  
  	hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
  }
  EXPORT_SYMBOL(hci_le_conn_update);
a7a595f67   Vinicius Costa Gomes   Bluetooth: Add su...
186
187
188
189
190
191
192
193
194
195
196
197
198
  void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
  							__u8 ltk[16])
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct hci_cp_le_start_enc cp;
  
  	BT_DBG("%p", conn);
  
  	memset(&cp, 0, sizeof(cp));
  
  	cp.handle = cpu_to_le16(conn->handle);
  	memcpy(cp.ltk, ltk, sizeof(cp.ltk));
  	cp.ediv = ediv;
51beabdf6   Anderson Briglia   Bluetooth: Fix wr...
199
  	memcpy(cp.rand, rand, sizeof(cp.rand));
a7a595f67   Vinicius Costa Gomes   Bluetooth: Add su...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  
  	hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
  }
  EXPORT_SYMBOL(hci_le_start_enc);
  
  void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct hci_cp_le_ltk_reply cp;
  
  	BT_DBG("%p", conn);
  
  	memset(&cp, 0, sizeof(cp));
  
  	cp.handle = cpu_to_le16(conn->handle);
  	memcpy(cp.ltk, ltk, sizeof(ltk));
  
  	hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
  }
  EXPORT_SYMBOL(hci_le_ltk_reply);
  
  void hci_le_ltk_neg_reply(struct hci_conn *conn)
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct hci_cp_le_ltk_neg_reply cp;
  
  	BT_DBG("%p", conn);
  
  	memset(&cp, 0, sizeof(cp));
  
  	cp.handle = cpu_to_le16(conn->handle);
  
  	hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
  }
e73439d8c   Marcel Holtmann   Bluetooth: Defer ...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  /* Device _must_ be locked */
  void hci_sco_setup(struct hci_conn *conn, __u8 status)
  {
  	struct hci_conn *sco = conn->link;
  
  	BT_DBG("%p", conn);
  
  	if (!sco)
  		return;
  
  	if (!status) {
  		if (lmp_esco_capable(conn->hdev))
  			hci_setup_sync(sco, conn->handle);
  		else
  			hci_add_sco(sco, conn->handle);
  	} else {
  		hci_proto_connect_cfm(sco, status);
  		hci_conn_del(sco);
  	}
  }
19c40e3bc   Gustavo F. Padovan   Bluetooth: Use de...
254
  static void hci_conn_timeout(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  {
19c40e3bc   Gustavo F. Padovan   Bluetooth: Use de...
256
257
  	struct hci_conn *conn = container_of(work, struct hci_conn,
  							disc_work.work);
04837f644   Marcel Holtmann   [Bluetooth] Add a...
258
  	struct hci_dev *hdev = conn->hdev;
2950f21ac   Marcel Holtmann   Bluetooth: Ask up...
259
  	__u8 reason;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
264
265
266
  
  	BT_DBG("conn %p state %d", conn, conn->state);
  
  	if (atomic_read(&conn->refcnt))
  		return;
  
  	hci_dev_lock(hdev);
6ac59344e   Marcel Holtmann   [Bluetooth] Suppo...
267
268
269
  
  	switch (conn->state) {
  	case BT_CONNECT:
769be974d   Marcel Holtmann   [Bluetooth] Use A...
270
  	case BT_CONNECT2:
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
271
272
273
274
275
276
  		if (conn->out) {
  			if (conn->type == ACL_LINK)
  				hci_acl_connect_cancel(conn);
  			else if (conn->type == LE_LINK)
  				hci_le_connect_cancel(conn);
  		}
6ac59344e   Marcel Holtmann   [Bluetooth] Suppo...
277
  		break;
769be974d   Marcel Holtmann   [Bluetooth] Use A...
278
  	case BT_CONFIG:
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
279
  	case BT_CONNECTED:
2950f21ac   Marcel Holtmann   Bluetooth: Ask up...
280
281
  		reason = hci_proto_disconn_ind(conn);
  		hci_acl_disconn(conn, reason);
6ac59344e   Marcel Holtmann   [Bluetooth] Suppo...
282
283
  		break;
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  		conn->state = BT_CLOSED;
6ac59344e   Marcel Holtmann   [Bluetooth] Suppo...
285
286
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  }
416dc94ba   Gustavo F. Padovan   Bluetooth: make h...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
  /* Enter sniff mode */
  static void hci_conn_enter_sniff_mode(struct hci_conn *conn)
  {
  	struct hci_dev *hdev = conn->hdev;
  
  	BT_DBG("conn %p mode %d", conn, conn->mode);
  
  	if (test_bit(HCI_RAW, &hdev->flags))
  		return;
  
  	if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn))
  		return;
  
  	if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF))
  		return;
  
  	if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) {
  		struct hci_cp_sniff_subrate cp;
  		cp.handle             = cpu_to_le16(conn->handle);
  		cp.max_latency        = cpu_to_le16(0);
  		cp.min_remote_timeout = cpu_to_le16(0);
  		cp.min_local_timeout  = cpu_to_le16(0);
  		hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
  	}
  
  	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
  		struct hci_cp_sniff_mode cp;
  		cp.handle       = cpu_to_le16(conn->handle);
  		cp.max_interval = cpu_to_le16(hdev->sniff_max_interval);
  		cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
  		cp.attempt      = cpu_to_le16(4);
  		cp.timeout      = cpu_to_le16(1);
  		hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
  	}
  }
04837f644   Marcel Holtmann   [Bluetooth] Add a...
324
  static void hci_conn_idle(unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  {
04837f644   Marcel Holtmann   [Bluetooth] Add a...
326
327
328
329
330
  	struct hci_conn *conn = (void *) arg;
  
  	BT_DBG("conn %p mode %d", conn, conn->mode);
  
  	hci_conn_enter_sniff_mode(conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  }
9f61656a6   Johan Hedberg   Bluetooth: Add va...
332
333
334
335
  static void hci_conn_auto_accept(unsigned long arg)
  {
  	struct hci_conn *conn = (void *) arg;
  	struct hci_dev *hdev = conn->hdev;
9f61656a6   Johan Hedberg   Bluetooth: Add va...
336
337
  	hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
  								&conn->dst);
9f61656a6   Johan Hedberg   Bluetooth: Add va...
338
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
  struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
  {
  	struct hci_conn *conn;
  
  	BT_DBG("%s dst %s", hdev->name, batostr(dst));
04837f644   Marcel Holtmann   [Bluetooth] Add a...
344
345
  	conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC);
  	if (!conn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
  
  	bacpy(&conn->dst, dst);
a8746417e   Marcel Holtmann   [Bluetooth] Track...
349
350
351
352
  	conn->hdev  = hdev;
  	conn->type  = type;
  	conn->mode  = HCI_CM_ACTIVE;
  	conn->state = BT_OPEN;
93f19c9fc   Andrei Emeltchenko   Bluetooth: Set ge...
353
  	conn->auth_type = HCI_AT_GENERAL_BONDING;
17fa4b9df   Johan Hedberg   Bluetooth: Add se...
354
  	conn->io_capability = hdev->io_capability;
a95835569   Johan Hedberg   Bluetooth: Fix in...
355
  	conn->remote_auth = 0xff;
13d39315c   Waldemar Rymarkiewicz   Bluetooth: Map se...
356
  	conn->key_type = 0xff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357

04837f644   Marcel Holtmann   [Bluetooth] Add a...
358
  	conn->power_save = 1;
052b30b0a   Marcel Holtmann   Bluetooth: Add di...
359
  	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
04837f644   Marcel Holtmann   [Bluetooth] Add a...
360

a8746417e   Marcel Holtmann   [Bluetooth] Track...
361
362
363
364
365
366
  	switch (type) {
  	case ACL_LINK:
  		conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
  		break;
  	case SCO_LINK:
  		if (lmp_esco_capable(hdev))
efc7688b5   Marcel Holtmann   Bluetooth: Add SC...
367
368
  			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
  					(hdev->esco_type & EDR_ESCO_MASK);
a8746417e   Marcel Holtmann   [Bluetooth] Track...
369
370
371
372
  		else
  			conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
  		break;
  	case ESCO_LINK:
efc7688b5   Marcel Holtmann   Bluetooth: Add SC...
373
  		conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
a8746417e   Marcel Holtmann   [Bluetooth] Track...
374
375
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  	skb_queue_head_init(&conn->data_q);
04837f644   Marcel Holtmann   [Bluetooth] Add a...
377

2c33c06a8   Gustavo F. Padovan   Bluetooth: remove...
378
  	INIT_LIST_HEAD(&conn->chan_list);;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
379

19c40e3bc   Gustavo F. Padovan   Bluetooth: Use de...
380
  	INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
b24b8a247   Pavel Emelyanov   [NET]: Convert in...
381
  	setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
9f61656a6   Johan Hedberg   Bluetooth: Add va...
382
383
  	setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
  							(unsigned long) conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
387
  
  	atomic_set(&conn->refcnt, 0);
  
  	hci_dev_hold(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  	hci_conn_hash_add(hdev, conn);
3c54711c4   Gustavo F. Padovan   Bluetooth: Don't ...
389
  	if (hdev->notify)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
  		hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
9eba32b86   Marcel Holtmann   Bluetooth: Add ex...
391
  	atomic_set(&conn->devref, 0);
a67e899cf   Marcel Holtmann   Bluetooth: Fix is...
392
  	hci_conn_init_sysfs(conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
397
398
399
400
  	return conn;
  }
  
  int hci_conn_del(struct hci_conn *conn)
  {
  	struct hci_dev *hdev = conn->hdev;
  
  	BT_DBG("%s conn %p handle %d", hdev->name, conn, conn->handle);
04837f644   Marcel Holtmann   [Bluetooth] Add a...
401
  	del_timer(&conn->idle_timer);
19c40e3bc   Gustavo F. Padovan   Bluetooth: Use de...
402
  	cancel_delayed_work_sync(&conn->disc_work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403

9f61656a6   Johan Hedberg   Bluetooth: Add va...
404
  	del_timer(&conn->auto_accept_timer);
5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
405
  	if (conn->type == ACL_LINK) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
409
410
411
  		struct hci_conn *sco = conn->link;
  		if (sco)
  			sco->link = NULL;
  
  		/* Unacked frames */
  		hdev->acl_cnt += conn->sent;
6ed58ec52   Ville Tervo   Bluetooth: Use LE...
412
413
414
415
416
  	} else if (conn->type == LE_LINK) {
  		if (hdev->le_pkts)
  			hdev->le_cnt += conn->sent;
  		else
  			hdev->acl_cnt += conn->sent;
5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
417
418
419
420
421
422
  	} else {
  		struct hci_conn *acl = conn->link;
  		if (acl) {
  			acl->link = NULL;
  			hci_conn_put(acl);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  	}
7d0db0a37   Marcel Holtmann   [Bluetooth] Use a...
424

2c33c06a8   Gustavo F. Padovan   Bluetooth: remove...
425
  	hci_chan_list_flush(conn);
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
426

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  	hci_conn_hash_del(hdev, conn);
3c54711c4   Gustavo F. Padovan   Bluetooth: Don't ...
428
  	if (hdev->notify)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
  		hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
7d0db0a37   Marcel Holtmann   [Bluetooth] Use a...
430

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  	skb_queue_purge(&conn->data_q);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432

9eba32b86   Marcel Holtmann   Bluetooth: Add ex...
433
  	hci_conn_put_device(conn);
2ae9a6be5   Dave Young   Bluetooth: Move h...
434

384943ec1   Marcel Holtmann   Bluetooth: Fix wr...
435
  	hci_dev_put(hdev);
163f4dabe   Tomas Targownik   Bluetooth: Fix me...
436
437
  	if (conn->handle == 0)
  		kfree(conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
440
441
442
443
  	return 0;
  }
  
  struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
  {
  	int use_src = bacmp(src, BDADDR_ANY);
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
444
  	struct hci_dev *hdev = NULL, *d;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
446
  
  	BT_DBG("%s -> %s", batostr(src), batostr(dst));
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
447
  	read_lock(&hci_dev_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448

8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
449
  	list_for_each_entry(d, &hci_dev_list, list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
  		if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
  			continue;
8e87d1425   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
452
  		/* Simple routing:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
  		 *   No source address - find interface with bdaddr != dst
  		 *   Source address    - find interface with bdaddr == src
  		 */
  
  		if (use_src) {
  			if (!bacmp(&d->bdaddr, src)) {
  				hdev = d; break;
  			}
  		} else {
  			if (bacmp(&d->bdaddr, dst)) {
  				hdev = d; break;
  			}
  		}
  	}
  
  	if (hdev)
  		hdev = hci_dev_hold(hdev);
f20d09d5f   Gustavo F. Padovan   Bluetooth: remove...
470
  	read_unlock(&hci_dev_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
473
  	return hdev;
  }
  EXPORT_SYMBOL(hci_get_route);
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
474
  /* Create SCO, ACL or LE connection.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
   * Device _must_ be locked */
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
476
  struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
  {
  	struct hci_conn *acl;
5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
479
  	struct hci_conn *sco;
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
480
  	struct hci_conn *le;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
  
  	BT_DBG("%s dst %s", hdev->name, batostr(dst));
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
483
  	if (type == LE_LINK) {
eda42b503   Andre Guedes   Bluetooth: Check ...
484
  		struct adv_entry *entry;
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
485
  		le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
15c4794fe   Anderson Briglia   Bluetooth: Fix LE...
486
  		if (le)
30e762721   Ville Tervo   Bluetooth: Use ER...
487
  			return ERR_PTR(-EBUSY);
eda42b503   Andre Guedes   Bluetooth: Check ...
488
489
490
491
  
  		entry = hci_find_adv_entry(hdev, dst);
  		if (!entry)
  			return ERR_PTR(-EHOSTUNREACH);
15c4794fe   Anderson Briglia   Bluetooth: Fix LE...
492
  		le = hci_conn_add(hdev, LE_LINK, dst);
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
493
  		if (!le)
30e762721   Ville Tervo   Bluetooth: Use ER...
494
  			return ERR_PTR(-ENOMEM);
893d67514   Andre Guedes   Bluetooth: Remove...
495

eda42b503   Andre Guedes   Bluetooth: Check ...
496
  		le->dst_type = entry->bdaddr_type;
893d67514   Andre Guedes   Bluetooth: Remove...
497
  		hci_le_connect(le);
fcd89c09a   Ville Tervo   Bluetooth: Add LE...
498
499
500
501
502
  
  		hci_conn_hold(le);
  
  		return le;
  	}
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
503
504
505
506
  	acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
  	if (!acl) {
  		acl = hci_conn_add(hdev, ACL_LINK, dst);
  		if (!acl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
508
509
510
  			return NULL;
  	}
  
  	hci_conn_hold(acl);
09ab6f4c2   Marcel Holtmann   [Bluetooth] Enfor...
511
  	if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
765c2a964   Johan Hedberg   Bluetooth: Fix ra...
512
513
  		acl->sec_level = BT_SECURITY_LOW;
  		acl->pending_sec_level = sec_level;
09ab6f4c2   Marcel Holtmann   [Bluetooth] Enfor...
514
  		acl->auth_type = auth_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  		hci_acl_connect(acl);
09ab6f4c2   Marcel Holtmann   [Bluetooth] Enfor...
516
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517

5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
518
519
  	if (type == ACL_LINK)
  		return acl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520

70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
521
522
523
524
  	sco = hci_conn_hash_lookup_ba(hdev, type, dst);
  	if (!sco) {
  		sco = hci_conn_add(hdev, type, dst);
  		if (!sco) {
5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
525
526
  			hci_conn_put(acl);
  			return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  		}
5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
528
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529

5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
530
531
  	acl->link = sco;
  	sco->link = acl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532

5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
533
  	hci_conn_hold(sco);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534

5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
535
  	if (acl->state == BT_CONNECTED &&
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
536
  			(sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
c390216b3   Nick Pelly   Bluetooth: Enter ...
537
  		acl->power_save = 1;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
538
  		hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
c390216b3   Nick Pelly   Bluetooth: Enter ...
539

e73439d8c   Marcel Holtmann   Bluetooth: Defer ...
540
541
542
543
544
545
546
  		if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
  			/* defer SCO setup until mode change completed */
  			set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
  			return sco;
  		}
  
  		hci_sco_setup(acl, 0x00);
b6a0dc822   Marcel Holtmann   [Bluetooth] Add s...
547
  	}
5b7f99092   Marcel Holtmann   [Bluetooth] Add b...
548
549
  
  	return sco;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
  }
  EXPORT_SYMBOL(hci_connect);
e7c29cb16   Marcel Holtmann   [Bluetooth] Rejec...
552
553
554
555
556
557
558
559
560
561
562
563
  /* Check link security requirement */
  int hci_conn_check_link_mode(struct hci_conn *conn)
  {
  	BT_DBG("conn %p", conn);
  
  	if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
  					!(conn->link_mode & HCI_LM_ENCRYPT))
  		return 0;
  
  	return 1;
  }
  EXPORT_SYMBOL(hci_conn_check_link_mode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  /* Authenticate remote device */
0684e5f9f   Marcel Holtmann   Bluetooth: Use ge...
565
  static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
  {
  	BT_DBG("conn %p", conn);
765c2a964   Johan Hedberg   Bluetooth: Fix ra...
568
569
  	if (conn->pending_sec_level > sec_level)
  		sec_level = conn->pending_sec_level;
96a318332   Marcel Holtmann   Bluetooth: Set au...
570
  	if (sec_level > conn->sec_level)
765c2a964   Johan Hedberg   Bluetooth: Fix ra...
571
  		conn->pending_sec_level = sec_level;
96a318332   Marcel Holtmann   Bluetooth: Set au...
572
  	else if (conn->link_mode & HCI_LM_AUTH)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  		return 1;
65cf686ee   Johan Hedberg   Bluetooth: Fix MI...
574
575
  	/* Make sure we preserve an existing MITM requirement*/
  	auth_type |= (conn->auth_type & 0x01);
96a318332   Marcel Holtmann   Bluetooth: Set au...
576
  	conn->auth_type = auth_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
  	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
  		struct hci_cp_auth_requested cp;
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
579
  		cp.handle = cpu_to_le16(conn->handle);
40be492fe   Marcel Holtmann   [Bluetooth] Expor...
580
581
  		hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
  							sizeof(cp), &cp);
19f8def03   Waldemar Rymarkiewicz   Bluetooth: Fix au...
582
583
  		if (conn->key_type != 0xff)
  			set_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  	}
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
585

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588

13d39315c   Waldemar Rymarkiewicz   Bluetooth: Map se...
589
590
591
592
593
594
595
596
597
598
599
600
601
  /* Encrypt the the link */
  static void hci_conn_encrypt(struct hci_conn *conn)
  {
  	BT_DBG("conn %p", conn);
  
  	if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
  		struct hci_cp_set_conn_encrypt cp;
  		cp.handle  = cpu_to_le16(conn->handle);
  		cp.encrypt = 0x01;
  		hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
  									&cp);
  	}
  }
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
602
  /* Enable security */
0684e5f9f   Marcel Holtmann   Bluetooth: Use ge...
603
  int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
  {
  	BT_DBG("conn %p", conn);
13d39315c   Waldemar Rymarkiewicz   Bluetooth: Map se...
606
  	/* For sdp we don't need the link key. */
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
607
608
  	if (sec_level == BT_SECURITY_SDP)
  		return 1;
13d39315c   Waldemar Rymarkiewicz   Bluetooth: Map se...
609
610
  	/* For non 2.1 devices and low security level we don't need the link
  	   key. */
3fdca1e13   Marcel Holtmann   Bluetooth: Fix co...
611
612
613
  	if (sec_level == BT_SECURITY_LOW &&
  				(!conn->ssp_mode || !conn->hdev->ssp_mode))
  		return 1;
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
614

13d39315c   Waldemar Rymarkiewicz   Bluetooth: Map se...
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  	/* For other security levels we need the link key. */
  	if (!(conn->link_mode & HCI_LM_AUTH))
  		goto auth;
  
  	/* An authenticated combination key has sufficient security for any
  	   security level. */
  	if (conn->key_type == HCI_LK_AUTH_COMBINATION)
  		goto encrypt;
  
  	/* An unauthenticated combination key has sufficient security for
  	   security level 1 and 2. */
  	if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
  			(sec_level == BT_SECURITY_MEDIUM ||
  			sec_level == BT_SECURITY_LOW))
  		goto encrypt;
  
  	/* A combination key has always sufficient security for the security
  	   levels 1 or 2. High security level requires the combination key
  	   is generated using maximum PIN code length (16).
  	   For pre 2.1 units. */
  	if (conn->key_type == HCI_LK_COMBINATION &&
  			(sec_level != BT_SECURITY_HIGH ||
  			conn->pin_length == 16))
  		goto encrypt;
  
  auth:
d7660918f   Gustavo F. Padovan   Revert "Bluetooth...
641
  	if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
  		return 0;
6fdf658c9   Luiz Augusto von Dentz   Bluetooth: Fix L2...
643
644
  	if (!hci_conn_auth(conn, sec_level, auth_type))
  		return 0;
13d39315c   Waldemar Rymarkiewicz   Bluetooth: Map se...
645
646
647
648
  
  encrypt:
  	if (conn->link_mode & HCI_LM_ENCRYPT)
  		return 1;
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
649

13d39315c   Waldemar Rymarkiewicz   Bluetooth: Map se...
650
  	hci_conn_encrypt(conn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
  	return 0;
  }
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
653
  EXPORT_SYMBOL(hci_conn_security);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654

b3b1b0615   Waldemar Rymarkiewicz   Bluetooth: Double...
655
656
657
658
659
660
661
  /* Check secure link requirement */
  int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
  {
  	BT_DBG("conn %p", conn);
  
  	if (sec_level != BT_SECURITY_HIGH)
  		return 1; /* Accept if non-secure is required */
ef4177e2b   Waldemar Rymarkiewicz   Bluetooth: Simpli...
662
  	if (conn->sec_level == BT_SECURITY_HIGH)
b3b1b0615   Waldemar Rymarkiewicz   Bluetooth: Double...
663
664
665
666
667
  		return 1;
  
  	return 0; /* Reject not secure link */
  }
  EXPORT_SYMBOL(hci_conn_check_secure);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
670
671
672
673
674
  /* Change link key */
  int hci_conn_change_link_key(struct hci_conn *conn)
  {
  	BT_DBG("conn %p", conn);
  
  	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
  		struct hci_cp_change_conn_link_key cp;
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
675
  		cp.handle = cpu_to_le16(conn->handle);
40be492fe   Marcel Holtmann   [Bluetooth] Expor...
676
677
  		hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
  							sizeof(cp), &cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
  	}
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
679

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
681
682
683
684
  	return 0;
  }
  EXPORT_SYMBOL(hci_conn_change_link_key);
  
  /* Switch role */
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
685
  int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
689
690
691
692
693
694
695
  {
  	BT_DBG("conn %p", conn);
  
  	if (!role && conn->link_mode & HCI_LM_MASTER)
  		return 1;
  
  	if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
  		struct hci_cp_switch_role cp;
  		bacpy(&cp.bdaddr, &conn->dst);
  		cp.role = role;
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
696
  		hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
  	}
8c1b23559   Marcel Holtmann   Bluetooth: Add en...
698

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
701
  	return 0;
  }
  EXPORT_SYMBOL(hci_conn_switch_role);
04837f644   Marcel Holtmann   [Bluetooth] Add a...
702
  /* Enter active mode */
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
703
  void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
04837f644   Marcel Holtmann   [Bluetooth] Add a...
704
705
706
707
708
709
710
  {
  	struct hci_dev *hdev = conn->hdev;
  
  	BT_DBG("conn %p mode %d", conn, conn->mode);
  
  	if (test_bit(HCI_RAW, &hdev->flags))
  		return;
14b12d0b9   Jaikumar Ganesh   Bluetooth: Add BT...
711
712
713
714
  	if (conn->mode != HCI_CM_SNIFF)
  		goto timer;
  
  	if (!conn->power_save && !force_active)
04837f644   Marcel Holtmann   [Bluetooth] Add a...
715
716
717
718
  		goto timer;
  
  	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
  		struct hci_cp_exit_sniff_mode cp;
aca3192cc   YOSHIFUJI Hideaki   [NET] BLUETOOTH: ...
719
  		cp.handle = cpu_to_le16(conn->handle);
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
720
  		hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
04837f644   Marcel Holtmann   [Bluetooth] Add a...
721
722
723
724
725
726
727
  	}
  
  timer:
  	if (hdev->idle_timeout > 0)
  		mod_timer(&conn->idle_timer,
  			jiffies + msecs_to_jiffies(hdev->idle_timeout));
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
730
731
  /* Drop all connection on the device */
  void hci_conn_hash_flush(struct hci_dev *hdev)
  {
  	struct hci_conn_hash *h = &hdev->conn_hash;
3e9c40a6f   Gustavo F. Padovan   Bluetooth: Use li...
732
  	struct hci_conn *c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
  
  	BT_DBG("hdev %s", hdev->name);
bf4c63252   Gustavo F. Padovan   Bluetooth: conver...
735
  	list_for_each_entry_rcu(c, &h->list, list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  		c->state = BT_CLOSED;
9f5a0d7bf   Andrei Emeltchenko   Bluetooth: Define...
737
  		hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
739
740
  		hci_conn_del(c);
  	}
  }
a9de92480   Marcel Holtmann   [Bluetooth] Switc...
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
  /* Check pending connect attempts */
  void hci_conn_check_pending(struct hci_dev *hdev)
  {
  	struct hci_conn *conn;
  
  	BT_DBG("hdev %s", hdev->name);
  
  	hci_dev_lock(hdev);
  
  	conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
  	if (conn)
  		hci_acl_connect(conn);
  
  	hci_dev_unlock(hdev);
  }
9eba32b86   Marcel Holtmann   Bluetooth: Add ex...
756
757
758
759
760
761
762
763
764
765
766
767
  void hci_conn_hold_device(struct hci_conn *conn)
  {
  	atomic_inc(&conn->devref);
  }
  EXPORT_SYMBOL(hci_conn_hold_device);
  
  void hci_conn_put_device(struct hci_conn *conn)
  {
  	if (atomic_dec_and_test(&conn->devref))
  		hci_conn_del_sysfs(conn);
  }
  EXPORT_SYMBOL(hci_conn_put_device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
769
  int hci_get_conn_list(void __user *arg)
  {
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
770
  	register struct hci_conn *c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
772
773
  	struct hci_conn_list_req req, *cl;
  	struct hci_conn_info *ci;
  	struct hci_dev *hdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
776
777
778
779
780
781
782
  	int n = 0, size, err;
  
  	if (copy_from_user(&req, arg, sizeof(req)))
  		return -EFAULT;
  
  	if (!req.conn_num || req.conn_num > (PAGE_SIZE * 2) / sizeof(*ci))
  		return -EINVAL;
  
  	size = sizeof(req) + req.conn_num * sizeof(*ci);
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
783
784
  	cl = kmalloc(size, GFP_KERNEL);
  	if (!cl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
  		return -ENOMEM;
70f23020e   Andrei Emeltchenko   Bluetooth: clean ...
786
787
  	hdev = hci_dev_get(req.dev_id);
  	if (!hdev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
790
791
792
  		kfree(cl);
  		return -ENODEV;
  	}
  
  	ci = cl->conn_info;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
793
  	hci_dev_lock(hdev);
8035ded46   Luiz Augusto von Dentz   Bluetooth: replac...
794
  	list_for_each_entry(c, &hdev->conn_hash.list, list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795
796
797
798
799
800
801
802
803
  		bacpy(&(ci + n)->bdaddr, &c->dst);
  		(ci + n)->handle = c->handle;
  		(ci + n)->type  = c->type;
  		(ci + n)->out   = c->out;
  		(ci + n)->state = c->state;
  		(ci + n)->link_mode = c->link_mode;
  		if (++n >= req.conn_num)
  			break;
  	}
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
804
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
  
  	cl->dev_id = hdev->id;
  	cl->conn_num = n;
  	size = sizeof(req) + n * sizeof(*ci);
  
  	hci_dev_put(hdev);
  
  	err = copy_to_user(arg, cl, size);
  	kfree(cl);
  
  	return err ? -EFAULT : 0;
  }
  
  int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
  {
  	struct hci_conn_info_req req;
  	struct hci_conn_info ci;
  	struct hci_conn *conn;
  	char __user *ptr = arg + sizeof(req);
  
  	if (copy_from_user(&req, arg, sizeof(req)))
  		return -EFAULT;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
827
  	hci_dev_lock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
829
830
831
832
833
834
835
836
  	conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
  	if (conn) {
  		bacpy(&ci.bdaddr, &conn->dst);
  		ci.handle = conn->handle;
  		ci.type  = conn->type;
  		ci.out   = conn->out;
  		ci.state = conn->state;
  		ci.link_mode = conn->link_mode;
  	}
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
837
  	hci_dev_unlock(hdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
  
  	if (!conn)
  		return -ENOENT;
  
  	return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
  }
40be492fe   Marcel Holtmann   [Bluetooth] Expor...
844
845
846
847
848
849
850
851
  
  int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
  {
  	struct hci_auth_info_req req;
  	struct hci_conn *conn;
  
  	if (copy_from_user(&req, arg, sizeof(req)))
  		return -EFAULT;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
852
  	hci_dev_lock(hdev);
40be492fe   Marcel Holtmann   [Bluetooth] Expor...
853
854
855
  	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
  	if (conn)
  		req.type = conn->auth_type;
09fd0de5b   Gustavo F. Padovan   Bluetooth: Replac...
856
  	hci_dev_unlock(hdev);
40be492fe   Marcel Holtmann   [Bluetooth] Expor...
857
858
859
860
861
862
  
  	if (!conn)
  		return -ENOENT;
  
  	return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
  }
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
863
864
865
866
867
868
869
870
871
872
873
874
875
876
  
  struct hci_chan *hci_chan_create(struct hci_conn *conn)
  {
  	struct hci_dev *hdev = conn->hdev;
  	struct hci_chan *chan;
  
  	BT_DBG("%s conn %p", hdev->name, conn);
  
  	chan = kzalloc(sizeof(struct hci_chan), GFP_ATOMIC);
  	if (!chan)
  		return NULL;
  
  	chan->conn = conn;
  	skb_queue_head_init(&chan->data_q);
8192edef0   Gustavo F. Padovan   Bluetooth: Use RC...
877
  	list_add_rcu(&chan->list, &conn->chan_list);
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
878
879
880
881
882
883
884
885
886
887
  
  	return chan;
  }
  
  int hci_chan_del(struct hci_chan *chan)
  {
  	struct hci_conn *conn = chan->conn;
  	struct hci_dev *hdev = conn->hdev;
  
  	BT_DBG("%s conn %p chan %p", hdev->name, conn, chan);
8192edef0   Gustavo F. Padovan   Bluetooth: Use RC...
888
889
890
  	list_del_rcu(&chan->list);
  
  	synchronize_rcu();
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
891
892
893
894
895
896
  
  	skb_queue_purge(&chan->data_q);
  	kfree(chan);
  
  	return 0;
  }
2c33c06a8   Gustavo F. Padovan   Bluetooth: remove...
897
  void hci_chan_list_flush(struct hci_conn *conn)
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
898
  {
8192edef0   Gustavo F. Padovan   Bluetooth: Use RC...
899
  	struct hci_chan *chan;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
900
901
  
  	BT_DBG("conn %p", conn);
8192edef0   Gustavo F. Padovan   Bluetooth: Use RC...
902
  	list_for_each_entry_rcu(chan, &conn->chan_list, list)
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
903
904
  		hci_chan_del(chan);
  }