hci_conn.c 16.5 KB
Newer Older
1
/*
L
Linus Torvalds 已提交
2
   BlueZ - Bluetooth protocol stack for Linux
3
   Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
L
Linus Torvalds 已提交
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
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
L
Linus Torvalds 已提交
18 19
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

20 21
   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
L
Linus Torvalds 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
   SOFTWARE IS DISCLAIMED.
*/

/* Bluetooth HCI connection handling. */

#include <linux/module.h>

#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#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>
A
Andrei Emeltchenko 已提交
42
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
43 44 45 46 47
#include <asm/unaligned.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>

48
void hci_acl_connect(struct hci_conn *conn)
L
Linus Torvalds 已提交
49 50 51 52 53 54 55 56
{
	struct hci_dev *hdev = conn->hdev;
	struct inquiry_entry *ie;
	struct hci_cp_create_conn cp;

	BT_DBG("%p", conn);

	conn->state = BT_CONNECT;
57 58
	conn->out = 1;

L
Linus Torvalds 已提交
59 60
	conn->link_mode = HCI_LM_MASTER;

61 62
	conn->attempt++;

63 64
	conn->link_policy = hdev->link_policy;

L
Linus Torvalds 已提交
65 66 67 68
	memset(&cp, 0, sizeof(cp));
	bacpy(&cp.bdaddr, &conn->dst);
	cp.pscan_rep_mode = 0x02;

A
Andrei Emeltchenko 已提交
69 70
	ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
	if (ie) {
71 72 73 74 75 76 77
		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);
		}

L
Linus Torvalds 已提交
78
		memcpy(conn->dev_class, ie->data.dev_class, 3);
79
		conn->ssp_mode = ie->data.ssp_mode;
L
Linus Torvalds 已提交
80 81
	}

82
	cp.pkt_type = cpu_to_le16(conn->pkt_type);
L
Linus Torvalds 已提交
83
	if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
84
		cp.role_switch = 0x01;
L
Linus Torvalds 已提交
85
	else
86
		cp.role_switch = 0x00;
87

88
	hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
L
Linus Torvalds 已提交
89 90
}

91 92 93 94 95 96 97 98 99 100
static void hci_acl_connect_cancel(struct hci_conn *conn)
{
	struct hci_cp_create_conn_cancel cp;

	BT_DBG("%p", conn);

	if (conn->hdev->hci_ver < 2)
		return;

	bacpy(&cp.bdaddr, &conn->dst);
101
	hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
102 103
}

L
Linus Torvalds 已提交
104 105 106 107 108 109 110 111
void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
{
	struct hci_cp_disconnect cp;

	BT_DBG("%p", conn);

	conn->state = BT_DISCONN;

112
	cp.handle = cpu_to_le16(conn->handle);
L
Linus Torvalds 已提交
113
	cp.reason = reason;
114
	hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
L
Linus Torvalds 已提交
115 116 117 118 119 120 121 122 123 124 125 126
}

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;

127 128
	conn->attempt++;

129
	cp.handle   = cpu_to_le16(handle);
130
	cp.pkt_type = cpu_to_le16(conn->pkt_type);
L
Linus Torvalds 已提交
131

132
	hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
L
Linus Torvalds 已提交
133 134
}

135 136 137 138 139 140 141 142 143 144
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;

145 146
	conn->attempt++;

147
	cp.handle   = cpu_to_le16(handle);
148
	cp.pkt_type = cpu_to_le16(conn->pkt_type);
149 150 151 152 153 154 155 156 157 158

	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);
}

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
/* 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);
	}
}

L
Linus Torvalds 已提交
180 181
static void hci_conn_timeout(unsigned long arg)
{
182 183
	struct hci_conn *conn = (void *) arg;
	struct hci_dev *hdev = conn->hdev;
184
	__u8 reason;
L
Linus Torvalds 已提交
185 186 187 188 189 190 191

	BT_DBG("conn %p state %d", conn, conn->state);

	if (atomic_read(&conn->refcnt))
		return;

	hci_dev_lock(hdev);
192 193 194

	switch (conn->state) {
	case BT_CONNECT:
195
	case BT_CONNECT2:
196
		if (conn->type == ACL_LINK && conn->out)
197
			hci_acl_connect_cancel(conn);
198
		break;
199
	case BT_CONFIG:
200
	case BT_CONNECTED:
201 202
		reason = hci_proto_disconn_ind(conn);
		hci_acl_disconn(conn, reason);
203 204
		break;
	default:
L
Linus Torvalds 已提交
205
		conn->state = BT_CLOSED;
206 207 208
		break;
	}

L
Linus Torvalds 已提交
209 210 211
	hci_dev_unlock(hdev);
}

212
static void hci_conn_idle(unsigned long arg)
L
Linus Torvalds 已提交
213
{
214 215 216 217 218
	struct hci_conn *conn = (void *) arg;

	BT_DBG("conn %p mode %d", conn, conn->mode);

	hci_conn_enter_sniff_mode(conn);
L
Linus Torvalds 已提交
219 220 221 222 223 224 225 226
}

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));

227 228
	conn = kzalloc(sizeof(struct hci_conn), GFP_ATOMIC);
	if (!conn)
L
Linus Torvalds 已提交
229 230 231
		return NULL;

	bacpy(&conn->dst, dst);
232 233 234 235
	conn->hdev  = hdev;
	conn->type  = type;
	conn->mode  = HCI_CM_ACTIVE;
	conn->state = BT_OPEN;
236
	conn->auth_type = HCI_AT_GENERAL_BONDING;
237
	conn->io_capability = hdev->io_capability;
L
Linus Torvalds 已提交
238

239
	conn->power_save = 1;
240
	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
241

242 243 244 245 246 247
	switch (type) {
	case ACL_LINK:
		conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
		break;
	case SCO_LINK:
		if (lmp_esco_capable(hdev))
248 249
			conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
					(hdev->esco_type & EDR_ESCO_MASK);
250 251 252 253
		else
			conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
		break;
	case ESCO_LINK:
254
		conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
255 256 257
		break;
	}

L
Linus Torvalds 已提交
258
	skb_queue_head_init(&conn->data_q);
259

260 261
	setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
	setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
L
Linus Torvalds 已提交
262 263 264 265 266 267 268 269 270 271 272

	atomic_set(&conn->refcnt, 0);

	hci_dev_hold(hdev);

	tasklet_disable(&hdev->tx_task);

	hci_conn_hash_add(hdev, conn);
	if (hdev->notify)
		hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);

273 274
	atomic_set(&conn->devref, 0);

275 276
	hci_conn_init_sysfs(conn);

L
Linus Torvalds 已提交
277 278 279 280 281 282 283 284 285 286 287
	tasklet_enable(&hdev->tx_task);

	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);

288 289 290
	del_timer(&conn->idle_timer);

	del_timer(&conn->disc_timer);
L
Linus Torvalds 已提交
291

292
	if (conn->type == ACL_LINK) {
L
Linus Torvalds 已提交
293 294 295 296 297 298
		struct hci_conn *sco = conn->link;
		if (sco)
			sco->link = NULL;

		/* Unacked frames */
		hdev->acl_cnt += conn->sent;
299 300 301 302 303 304
	} else {
		struct hci_conn *acl = conn->link;
		if (acl) {
			acl->link = NULL;
			hci_conn_put(acl);
		}
L
Linus Torvalds 已提交
305 306 307
	}

	tasklet_disable(&hdev->tx_task);
308

L
Linus Torvalds 已提交
309 310 311
	hci_conn_hash_del(hdev, conn);
	if (hdev->notify)
		hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
312

L
Linus Torvalds 已提交
313
	tasklet_enable(&hdev->tx_task);
314

L
Linus Torvalds 已提交
315 316
	skb_queue_purge(&conn->data_q);

317
	hci_conn_put_device(conn);
318

319 320
	hci_dev_put(hdev);

L
Linus Torvalds 已提交
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
	return 0;
}

struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
{
	int use_src = bacmp(src, BDADDR_ANY);
	struct hci_dev *hdev = NULL;
	struct list_head *p;

	BT_DBG("%s -> %s", batostr(src), batostr(dst));

	read_lock_bh(&hci_dev_list_lock);

	list_for_each(p, &hci_dev_list) {
		struct hci_dev *d = list_entry(p, struct hci_dev, list);

		if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
			continue;

340
		/* Simple routing:
L
Linus Torvalds 已提交
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
		 *   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);

	read_unlock_bh(&hci_dev_list_lock);
	return hdev;
}
EXPORT_SYMBOL(hci_get_route);

/* Create SCO or ACL connection.
 * Device _must_ be locked */
366
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
L
Linus Torvalds 已提交
367 368
{
	struct hci_conn *acl;
369
	struct hci_conn *sco;
L
Linus Torvalds 已提交
370 371 372

	BT_DBG("%s dst %s", hdev->name, batostr(dst));

A
Andrei Emeltchenko 已提交
373 374 375 376
	acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
	if (!acl) {
		acl = hci_conn_add(hdev, ACL_LINK, dst);
		if (!acl)
L
Linus Torvalds 已提交
377 378 379 380 381
			return NULL;
	}

	hci_conn_hold(acl);

382
	if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
383 384
		acl->sec_level = BT_SECURITY_LOW;
		acl->pending_sec_level = sec_level;
385
		acl->auth_type = auth_type;
L
Linus Torvalds 已提交
386
		hci_acl_connect(acl);
387
	}
L
Linus Torvalds 已提交
388

389 390
	if (type == ACL_LINK)
		return acl;
L
Linus Torvalds 已提交
391

A
Andrei Emeltchenko 已提交
392 393 394 395
	sco = hci_conn_hash_lookup_ba(hdev, type, dst);
	if (!sco) {
		sco = hci_conn_add(hdev, type, dst);
		if (!sco) {
396 397
			hci_conn_put(acl);
			return NULL;
L
Linus Torvalds 已提交
398
		}
399
	}
L
Linus Torvalds 已提交
400

401 402
	acl->link = sco;
	sco->link = acl;
L
Linus Torvalds 已提交
403

404
	hci_conn_hold(sco);
L
Linus Torvalds 已提交
405

406
	if (acl->state == BT_CONNECTED &&
407
			(sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
408 409 410
		acl->power_save = 1;
		hci_conn_enter_active_mode(acl);

411 412 413 414 415 416 417
		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);
418
	}
419 420

	return sco;
L
Linus Torvalds 已提交
421 422 423
}
EXPORT_SYMBOL(hci_connect);

424 425 426 427 428 429 430 431 432 433 434 435 436
/* 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);

L
Linus Torvalds 已提交
437
/* Authenticate remote device */
438
static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
L
Linus Torvalds 已提交
439 440 441
{
	BT_DBG("conn %p", conn);

442 443 444
	if (conn->pending_sec_level > sec_level)
		sec_level = conn->pending_sec_level;

445
	if (sec_level > conn->sec_level)
446
		conn->pending_sec_level = sec_level;
447
	else if (conn->link_mode & HCI_LM_AUTH)
L
Linus Torvalds 已提交
448 449
		return 1;

450 451 452
	/* Make sure we preserve an existing MITM requirement*/
	auth_type |= (conn->auth_type & 0x01);

453 454
	conn->auth_type = auth_type;

L
Linus Torvalds 已提交
455 456
	if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
		struct hci_cp_auth_requested cp;
457
		cp.handle = cpu_to_le16(conn->handle);
458 459
		hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
							sizeof(cp), &cp);
L
Linus Torvalds 已提交
460
	}
461

L
Linus Torvalds 已提交
462 463 464
	return 0;
}

465
/* Enable security */
466
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
L
Linus Torvalds 已提交
467 468 469
{
	BT_DBG("conn %p", conn);

470 471 472
	if (sec_level == BT_SECURITY_SDP)
		return 1;

473 474 475
	if (sec_level == BT_SECURITY_LOW &&
				(!conn->ssp_mode || !conn->hdev->ssp_mode))
		return 1;
476

L
Linus Torvalds 已提交
477
	if (conn->link_mode & HCI_LM_ENCRYPT)
478
		return hci_conn_auth(conn, sec_level, auth_type);
L
Linus Torvalds 已提交
479 480 481 482

	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
		return 0;

483
	if (hci_conn_auth(conn, sec_level, auth_type)) {
L
Linus Torvalds 已提交
484
		struct hci_cp_set_conn_encrypt cp;
485
		cp.handle  = cpu_to_le16(conn->handle);
486
		cp.encrypt = 1;
487 488
		hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
							sizeof(cp), &cp);
L
Linus Torvalds 已提交
489
	}
490

L
Linus Torvalds 已提交
491 492
	return 0;
}
493
EXPORT_SYMBOL(hci_conn_security);
L
Linus Torvalds 已提交
494 495 496 497 498 499 500 501

/* 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;
502
		cp.handle = cpu_to_le16(conn->handle);
503 504
		hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
							sizeof(cp), &cp);
L
Linus Torvalds 已提交
505
	}
506

L
Linus Torvalds 已提交
507 508 509 510 511
	return 0;
}
EXPORT_SYMBOL(hci_conn_change_link_key);

/* Switch role */
512
int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
L
Linus Torvalds 已提交
513 514 515 516 517 518 519 520 521 522
{
	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;
523
		hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
L
Linus Torvalds 已提交
524
	}
525

L
Linus Torvalds 已提交
526 527 528 529
	return 0;
}
EXPORT_SYMBOL(hci_conn_switch_role);

530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
/* Enter active mode */
void hci_conn_enter_active_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 (conn->mode != HCI_CM_SNIFF || !conn->power_save)
		goto timer;

	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
		struct hci_cp_exit_sniff_mode cp;
545
		cp.handle = cpu_to_le16(conn->handle);
546
		hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
	}

timer:
	if (hdev->idle_timeout > 0)
		mod_timer(&conn->idle_timer,
			jiffies + msecs_to_jiffies(hdev->idle_timeout));
}

/* Enter sniff mode */
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;
573 574 575 576
		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);
577
		hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
578 579 580 581
	}

	if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
		struct hci_cp_sniff_mode cp;
582 583 584 585 586
		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);
587
		hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
588 589 590
	}
}

L
Linus Torvalds 已提交
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
/* Drop all connection on the device */
void hci_conn_hash_flush(struct hci_dev *hdev)
{
	struct hci_conn_hash *h = &hdev->conn_hash;
	struct list_head *p;

	BT_DBG("hdev %s", hdev->name);

	p = h->list.next;
	while (p != &h->list) {
		struct hci_conn *c;

		c = list_entry(p, struct hci_conn, list);
		p = p->next;

		c->state = BT_CLOSED;

608
		hci_proto_disconn_cfm(c, 0x16);
L
Linus Torvalds 已提交
609 610 611 612
		hci_conn_del(c);
	}
}

613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
/* 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);
}

629 630 631 632 633 634 635 636 637 638 639 640 641
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);

L
Linus Torvalds 已提交
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
int hci_get_conn_list(void __user *arg)
{
	struct hci_conn_list_req req, *cl;
	struct hci_conn_info *ci;
	struct hci_dev *hdev;
	struct list_head *p;
	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);

A
Andrei Emeltchenko 已提交
658 659
	cl = kmalloc(size, GFP_KERNEL);
	if (!cl)
L
Linus Torvalds 已提交
660 661
		return -ENOMEM;

A
Andrei Emeltchenko 已提交
662 663
	hdev = hci_dev_get(req.dev_id);
	if (!hdev) {
L
Linus Torvalds 已提交
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
		kfree(cl);
		return -ENODEV;
	}

	ci = cl->conn_info;

	hci_dev_lock_bh(hdev);
	list_for_each(p, &hdev->conn_hash.list) {
		register struct hci_conn *c;
		c = list_entry(p, struct hci_conn, list);

		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;
	}
	hci_dev_unlock_bh(hdev);

	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;

	hci_dev_lock_bh(hdev);
	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;
	}
	hci_dev_unlock_bh(hdev);

	if (!conn)
		return -ENOENT;

	return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
}
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744

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;

	hci_dev_lock_bh(hdev);
	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
	if (conn)
		req.type = conn->auth_type;
	hci_dev_unlock_bh(hdev);

	if (!conn)
		return -ENOENT;

	return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
}