diff options
author | Andre Guedes <andre.guedes@openbossa.org> | 2013-10-08 07:21:17 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2013-10-10 04:30:18 -0400 |
commit | 1d399ae5c74619c841fa13834c4f79506aaf6957 (patch) | |
tree | f028d24a7681f1bf3b91c4bf7cb468edf48f5ef8 | |
parent | f74ca9b8094b1b067a0b4069732065f2e1595c73 (diff) |
Bluetooth: Use HCI request for LE connection
This patch introduces a new helper, which uses the HCI request
framework, for creating LE connectons. All the handling is now
done by this function so we can remove the hci_cs_le_create_conn()
event handler.
This patch also removes the old hci_le_create_connection() since
it is not used anymore.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | net/bluetooth/hci_conn.c | 91 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 31 |
2 files changed, 67 insertions, 55 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2a220a8c9869..1800b50558e4 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -49,29 +49,6 @@ static const struct sco_param sco_param_wideband[] = { | |||
49 | { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ | 49 | { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static void hci_le_create_connection(struct hci_conn *conn) | ||
53 | { | ||
54 | struct hci_dev *hdev = conn->hdev; | ||
55 | struct hci_cp_le_create_conn cp; | ||
56 | |||
57 | memset(&cp, 0, sizeof(cp)); | ||
58 | cp.scan_interval = __constant_cpu_to_le16(0x0060); | ||
59 | cp.scan_window = __constant_cpu_to_le16(0x0030); | ||
60 | bacpy(&cp.peer_addr, &conn->dst); | ||
61 | cp.peer_addr_type = conn->dst_type; | ||
62 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | ||
63 | cp.own_address_type = ADDR_LE_DEV_PUBLIC; | ||
64 | else | ||
65 | cp.own_address_type = ADDR_LE_DEV_RANDOM; | ||
66 | cp.conn_interval_min = __constant_cpu_to_le16(0x0028); | ||
67 | cp.conn_interval_max = __constant_cpu_to_le16(0x0038); | ||
68 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); | ||
69 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); | ||
70 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); | ||
71 | |||
72 | hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | ||
73 | } | ||
74 | |||
75 | static void hci_le_create_connection_cancel(struct hci_conn *conn) | 52 | static void hci_le_create_connection_cancel(struct hci_conn *conn) |
76 | { | 53 | { |
77 | hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); | 54 | hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); |
@@ -545,10 +522,74 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) | |||
545 | } | 522 | } |
546 | EXPORT_SYMBOL(hci_get_route); | 523 | EXPORT_SYMBOL(hci_get_route); |
547 | 524 | ||
525 | static void create_le_conn_complete(struct hci_dev *hdev, u8 status) | ||
526 | { | ||
527 | struct hci_conn *conn; | ||
528 | |||
529 | if (status == 0) | ||
530 | return; | ||
531 | |||
532 | BT_ERR("HCI request failed to create LE connection: status 0x%2.2x", | ||
533 | status); | ||
534 | |||
535 | hci_dev_lock(hdev); | ||
536 | |||
537 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
538 | if (!conn) | ||
539 | goto done; | ||
540 | |||
541 | conn->state = BT_CLOSED; | ||
542 | |||
543 | mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, | ||
544 | status); | ||
545 | |||
546 | hci_proto_connect_cfm(conn, status); | ||
547 | |||
548 | hci_conn_del(conn); | ||
549 | |||
550 | done: | ||
551 | hci_dev_unlock(hdev); | ||
552 | } | ||
553 | |||
554 | static int hci_create_le_conn(struct hci_conn *conn) | ||
555 | { | ||
556 | struct hci_dev *hdev = conn->hdev; | ||
557 | struct hci_cp_le_create_conn cp; | ||
558 | struct hci_request req; | ||
559 | int err; | ||
560 | |||
561 | hci_req_init(&req, hdev); | ||
562 | |||
563 | memset(&cp, 0, sizeof(cp)); | ||
564 | cp.scan_interval = __constant_cpu_to_le16(0x0060); | ||
565 | cp.scan_window = __constant_cpu_to_le16(0x0030); | ||
566 | bacpy(&cp.peer_addr, &conn->dst); | ||
567 | cp.peer_addr_type = conn->dst_type; | ||
568 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | ||
569 | cp.own_address_type = ADDR_LE_DEV_PUBLIC; | ||
570 | else | ||
571 | cp.own_address_type = ADDR_LE_DEV_RANDOM; | ||
572 | cp.conn_interval_min = __constant_cpu_to_le16(0x0028); | ||
573 | cp.conn_interval_max = __constant_cpu_to_le16(0x0038); | ||
574 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); | ||
575 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); | ||
576 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); | ||
577 | hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | ||
578 | |||
579 | err = hci_req_run(&req, create_le_conn_complete); | ||
580 | if (err) { | ||
581 | hci_conn_del(conn); | ||
582 | return err; | ||
583 | } | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
548 | static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | 588 | static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, |
549 | u8 dst_type, u8 sec_level, u8 auth_type) | 589 | u8 dst_type, u8 sec_level, u8 auth_type) |
550 | { | 590 | { |
551 | struct hci_conn *conn; | 591 | struct hci_conn *conn; |
592 | int err; | ||
552 | 593 | ||
553 | if (test_bit(HCI_ADVERTISING, &hdev->flags)) | 594 | if (test_bit(HCI_ADVERTISING, &hdev->flags)) |
554 | return ERR_PTR(-ENOTSUPP); | 595 | return ERR_PTR(-ENOTSUPP); |
@@ -569,7 +610,9 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
569 | conn->link_mode |= HCI_LM_MASTER; | 610 | conn->link_mode |= HCI_LM_MASTER; |
570 | conn->sec_level = BT_SECURITY_LOW; | 611 | conn->sec_level = BT_SECURITY_LOW; |
571 | 612 | ||
572 | hci_le_create_connection(conn); | 613 | err = hci_create_le_conn(conn); |
614 | if (err) | ||
615 | return ERR_PTR(err); | ||
573 | } | 616 | } |
574 | 617 | ||
575 | conn->pending_sec_level = sec_level; | 618 | conn->pending_sec_level = sec_level; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 221a185cc951..ada3bf4d7e2a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1472,33 +1472,6 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) | |||
1472 | hci_dev_unlock(hdev); | 1472 | hci_dev_unlock(hdev); |
1473 | } | 1473 | } |
1474 | 1474 | ||
1475 | static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) | ||
1476 | { | ||
1477 | struct hci_conn *conn; | ||
1478 | |||
1479 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1480 | |||
1481 | if (status) { | ||
1482 | hci_dev_lock(hdev); | ||
1483 | |||
1484 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
1485 | if (!conn) { | ||
1486 | hci_dev_unlock(hdev); | ||
1487 | return; | ||
1488 | } | ||
1489 | |||
1490 | BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); | ||
1491 | |||
1492 | conn->state = BT_CLOSED; | ||
1493 | mgmt_connect_failed(hdev, &conn->dst, conn->type, | ||
1494 | conn->dst_type, status); | ||
1495 | hci_proto_connect_cfm(conn, status); | ||
1496 | hci_conn_del(conn); | ||
1497 | |||
1498 | hci_dev_unlock(hdev); | ||
1499 | } | ||
1500 | } | ||
1501 | |||
1502 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | 1475 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) |
1503 | { | 1476 | { |
1504 | struct hci_cp_create_phy_link *cp; | 1477 | struct hci_cp_create_phy_link *cp; |
@@ -2364,10 +2337,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2364 | hci_cs_disconnect(hdev, ev->status); | 2337 | hci_cs_disconnect(hdev, ev->status); |
2365 | break; | 2338 | break; |
2366 | 2339 | ||
2367 | case HCI_OP_LE_CREATE_CONN: | ||
2368 | hci_cs_le_create_conn(hdev, ev->status); | ||
2369 | break; | ||
2370 | |||
2371 | case HCI_OP_CREATE_PHY_LINK: | 2340 | case HCI_OP_CREATE_PHY_LINK: |
2372 | hci_cs_create_phylink(hdev, ev->status); | 2341 | hci_cs_create_phylink(hdev, ev->status); |
2373 | break; | 2342 | break; |