From af750e942ea138553ee5693210c2f918448f58dc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Sep 2013 18:08:37 -0700 Subject: Bluetooth: Disable upper layer connections when user channel is active When the device has the user channel flag set, it means it is driven by an user application. In that case do not allow any connections from L2CAP or SCO sockets. This is the same situation as when the device has the raw flag set and it will then return EHOSTUNREACH. Signed-off-by: Marcel Holtmann Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index f0817121ec5e..d2380e0c7df0 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -518,6 +518,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) list_for_each_entry(d, &hci_dev_list, list) { if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags) || + test_bit(HCI_USER_CHANNEL, &d->dev_flags) || d->dev_type != HCI_BREDR) continue; -- cgit v1.2.3 From 56f8790102f48a4959a729ecdccff332591014e1 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 2 Oct 2013 13:43:13 +0300 Subject: Bluetooth: Introduce a new HCI_BREDR_ENABLED flag To allow treating dual-mode (BR/EDR/LE) controllers as single-mode ones (LE-only) we want to introduce a new HCI_BREDR_ENABLED flag to track whether BR/EDR is enabled or not (previously we simply looked at the feature bit with lmp_bredr_enabled). This patch add the new flag and updates the relevant places to test against it instead of using lmp_bredr_enabled. The flag is by default enabled when registering an adapter and only cleared if necessary once the local features have been read during the HCI init procedure. We cannot completely block BR/EDR usage in case user space uses raw HCI sockets but the patch tries to block this in places where possible, such as the various BR/EDR specific ioctls. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index d2380e0c7df0..514148b7a66b 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -581,6 +581,9 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, { struct hci_conn *acl; + if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) + return ERR_PTR(-ENOTSUPP); + acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); if (!acl) { acl = hci_conn_add(hdev, ACL_LINK, dst); -- cgit v1.2.3 From f1e5d54743b99cbbea0e0cfb2b3f8053f045b3d7 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Thu, 3 Oct 2013 18:25:44 -0300 Subject: Bluetooth: Rename hci_conn variable in hci_connect_le() This patch simply rename the hci_conn variable "le" to "conn" since it is a better name. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 514148b7a66b..5aba520cddfe 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -549,31 +549,31 @@ EXPORT_SYMBOL(hci_get_route); static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u8 auth_type) { - struct hci_conn *le; + struct hci_conn *conn; if (test_bit(HCI_LE_PERIPHERAL, &hdev->flags)) return ERR_PTR(-ENOTSUPP); - le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); - if (!le) { - le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - if (le) + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); + if (!conn) { + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (conn) return ERR_PTR(-EBUSY); - le = hci_conn_add(hdev, LE_LINK, dst); - if (!le) + conn = hci_conn_add(hdev, LE_LINK, dst); + if (!conn) return ERR_PTR(-ENOMEM); - le->dst_type = bdaddr_to_le(dst_type); - hci_le_create_connection(le); + conn->dst_type = bdaddr_to_le(dst_type); + hci_le_create_connection(conn); } - le->pending_sec_level = sec_level; - le->auth_type = auth_type; + conn->pending_sec_level = sec_level; + conn->auth_type = auth_type; - hci_conn_hold(le); + hci_conn_hold(conn); - return le; + return conn; } static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, -- cgit v1.2.3 From 46a190cbd3d8992a017664367e9227dcd357ce53 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Thu, 3 Oct 2013 18:25:45 -0300 Subject: Bluetooth: Initialize hci_conn fields in hci_connect_le This patch moves some hci_conn fields initialization from hci_le_ create_connection() to hci_connect_le(). It makes more sense to initialize these fields within the function that creates the hci_ conn object. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5aba520cddfe..08e601c68314 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -54,11 +54,6 @@ static void hci_le_create_connection(struct hci_conn *conn) struct hci_dev *hdev = conn->hdev; struct hci_cp_le_create_conn cp; - conn->state = BT_CONNECT; - conn->out = true; - conn->link_mode |= HCI_LM_MASTER; - conn->sec_level = BT_SECURITY_LOW; - memset(&cp, 0, sizeof(cp)); cp.scan_interval = __constant_cpu_to_le16(0x0060); cp.scan_window = __constant_cpu_to_le16(0x0030); @@ -565,6 +560,11 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, return ERR_PTR(-ENOMEM); conn->dst_type = bdaddr_to_le(dst_type); + conn->state = BT_CONNECT; + conn->out = true; + conn->link_mode |= HCI_LM_MASTER; + conn->sec_level = BT_SECURITY_LOW; + hci_le_create_connection(conn); } -- cgit v1.2.3 From f3d3444a4d7f76e79841c59c78105a45295cc4b0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 5 Oct 2013 12:01:04 +0200 Subject: Bluetooth: Rename HCI_LE_PERIPHERAL to HCI_ADVERTISING This flag is used to indicate whether we want to have advertising enabled or not, so give it a more suitable name. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 08e601c68314..8b0d08fb6158 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -546,7 +546,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, { struct hci_conn *conn; - if (test_bit(HCI_LE_PERIPHERAL, &hdev->flags)) + if (test_bit(HCI_ADVERTISING, &hdev->flags)) return ERR_PTR(-ENOTSUPP); conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); -- cgit v1.2.3 From c25dfc610b983f74f05b3c12d9ad4ff4af6cd858 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 02:08:36 -0700 Subject: Bluetooth: Use random address if public address is not available For single mode LE-only controllers, it is possible that they come without a public address. If a public address is not available, then use the random address for connection establishment and scanning. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 8b0d08fb6158..2a220a8c9869 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -59,6 +59,10 @@ static void hci_le_create_connection(struct hci_conn *conn) cp.scan_window = __constant_cpu_to_le16(0x0030); bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + cp.own_address_type = ADDR_LE_DEV_PUBLIC; + else + cp.own_address_type = ADDR_LE_DEV_RANDOM; cp.conn_interval_min = __constant_cpu_to_le16(0x0028); cp.conn_interval_max = __constant_cpu_to_le16(0x0038); cp.supervision_timeout = __constant_cpu_to_le16(0x002a); -- cgit v1.2.3 From 1d399ae5c74619c841fa13834c4f79506aaf6957 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 8 Oct 2013 08:21:17 -0300 Subject: 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 Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 91 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 24 deletions(-) (limited to 'net/bluetooth/hci_conn.c') 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[] = { { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ }; -static void hci_le_create_connection(struct hci_conn *conn) -{ - struct hci_dev *hdev = conn->hdev; - struct hci_cp_le_create_conn cp; - - memset(&cp, 0, sizeof(cp)); - cp.scan_interval = __constant_cpu_to_le16(0x0060); - cp.scan_window = __constant_cpu_to_le16(0x0030); - bacpy(&cp.peer_addr, &conn->dst); - cp.peer_addr_type = conn->dst_type; - if (bacmp(&hdev->bdaddr, BDADDR_ANY)) - cp.own_address_type = ADDR_LE_DEV_PUBLIC; - else - cp.own_address_type = ADDR_LE_DEV_RANDOM; - cp.conn_interval_min = __constant_cpu_to_le16(0x0028); - cp.conn_interval_max = __constant_cpu_to_le16(0x0038); - cp.supervision_timeout = __constant_cpu_to_le16(0x002a); - cp.min_ce_len = __constant_cpu_to_le16(0x0000); - cp.max_ce_len = __constant_cpu_to_le16(0x0000); - - hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); -} - static void hci_le_create_connection_cancel(struct hci_conn *conn) { 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) } EXPORT_SYMBOL(hci_get_route); +static void create_le_conn_complete(struct hci_dev *hdev, u8 status) +{ + struct hci_conn *conn; + + if (status == 0) + return; + + BT_ERR("HCI request failed to create LE connection: status 0x%2.2x", + status); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (!conn) + goto done; + + conn->state = BT_CLOSED; + + mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, + status); + + hci_proto_connect_cfm(conn, status); + + hci_conn_del(conn); + +done: + hci_dev_unlock(hdev); +} + +static int hci_create_le_conn(struct hci_conn *conn) +{ + struct hci_dev *hdev = conn->hdev; + struct hci_cp_le_create_conn cp; + struct hci_request req; + int err; + + hci_req_init(&req, hdev); + + memset(&cp, 0, sizeof(cp)); + cp.scan_interval = __constant_cpu_to_le16(0x0060); + cp.scan_window = __constant_cpu_to_le16(0x0030); + bacpy(&cp.peer_addr, &conn->dst); + cp.peer_addr_type = conn->dst_type; + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + cp.own_address_type = ADDR_LE_DEV_PUBLIC; + else + cp.own_address_type = ADDR_LE_DEV_RANDOM; + cp.conn_interval_min = __constant_cpu_to_le16(0x0028); + cp.conn_interval_max = __constant_cpu_to_le16(0x0038); + cp.supervision_timeout = __constant_cpu_to_le16(0x002a); + cp.min_ce_len = __constant_cpu_to_le16(0x0000); + cp.max_ce_len = __constant_cpu_to_le16(0x0000); + hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); + + err = hci_req_run(&req, create_le_conn_complete); + if (err) { + hci_conn_del(conn); + return err; + } + + return 0; +} + static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u8 auth_type) { struct hci_conn *conn; + int err; if (test_bit(HCI_ADVERTISING, &hdev->flags)) return ERR_PTR(-ENOTSUPP); @@ -569,7 +610,9 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->link_mode |= HCI_LM_MASTER; conn->sec_level = BT_SECURITY_LOW; - hci_le_create_connection(conn); + err = hci_create_le_conn(conn); + if (err) + return ERR_PTR(err); } conn->pending_sec_level = sec_level; -- cgit v1.2.3 From 620ad5219c0f0aa43731b2fd8fd9efac78c10deb Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 8 Oct 2013 08:21:18 -0300 Subject: Bluetooth: Refactor hci_connect_le This patch does some code refactoring in hci_connect_le() by moving the exception code into if statements and letting the main flow in first level of function scope. It also adds extra comments to improve the code readability. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 51 +++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1800b50558e4..dedd1ea5dd4c 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -594,32 +594,47 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, if (test_bit(HCI_ADVERTISING, &hdev->flags)) return ERR_PTR(-ENOTSUPP); + /* Some devices send ATT messages as soon as the physical link is + * established. To be able to handle these ATT messages, the user- + * space first establishes the connection and then starts the pairing + * process. + * + * So if a hci_conn object already exists for the following connection + * attempt, we simply update pending_sec_level and auth_type fields + * and return the object found. + */ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); - if (!conn) { - conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - if (conn) - return ERR_PTR(-EBUSY); - - conn = hci_conn_add(hdev, LE_LINK, dst); - if (!conn) - return ERR_PTR(-ENOMEM); + if (conn) { + conn->pending_sec_level = sec_level; + conn->auth_type = auth_type; + goto done; + } - conn->dst_type = bdaddr_to_le(dst_type); - conn->state = BT_CONNECT; - conn->out = true; - conn->link_mode |= HCI_LM_MASTER; - conn->sec_level = BT_SECURITY_LOW; + /* Since the controller supports only one LE connection attempt at a + * time, we return -EBUSY if there is any connection attempt running. + */ + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (conn) + return ERR_PTR(-EBUSY); - err = hci_create_le_conn(conn); - if (err) - return ERR_PTR(err); - } + conn = hci_conn_add(hdev, LE_LINK, dst); + if (!conn) + return ERR_PTR(-ENOMEM); + conn->dst_type = bdaddr_to_le(dst_type); + conn->state = BT_CONNECT; + conn->out = true; + conn->link_mode |= HCI_LM_MASTER; + conn->sec_level = BT_SECURITY_LOW; conn->pending_sec_level = sec_level; conn->auth_type = auth_type; - hci_conn_hold(conn); + err = hci_create_le_conn(conn); + if (err) + return ERR_PTR(err); +done: + hci_conn_hold(conn); return conn; } -- cgit v1.2.3 From 7024728ee534d739380dc4fd31f020cfc6e86c28 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 14:54:15 -0700 Subject: Bluetooth: Move a2mp.h header file into net/bluetooth/ The a2mp.h header file is only used internally by the bluetooth.ko module and is not a public API. So make it local to the core Bluetooth module. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index dedd1ea5dd4c..8141c8d83139 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -28,9 +28,10 @@ #include #include -#include #include +#include "a2mp.h" + struct sco_param { u16 pkt_type; u16 max_latency; -- cgit v1.2.3 From ac4b7236610cef99821f40f44a74030b85d85270 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 14:54:16 -0700 Subject: Bluetooth: Move smp.h header file into net/bluetooth/ The smp.h header file is only used internally by the bluetooth.ko module and is not a public API. So make it local to the core Bluetooth module. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 8141c8d83139..139587159200 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -28,8 +28,8 @@ #include #include -#include +#include "smp.h" #include "a2mp.h" struct sco_param { -- cgit v1.2.3 From bef64738e3fb87eabc6fbeededad0c44ea173384 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 11 Oct 2013 08:23:19 -0700 Subject: Bluetooth: Make LE scan interval and window a controller option The scan interval and window for LE passive scanning and connection establishment should be configurable on a per controller basis. So introduce a setting that later on will allow modifying it. This setting does not affect LE active scanning during device discovery phase. As long as that phase uses interleaved discovery, it will continuously scan. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 139587159200..c52bfb7e44fd 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -562,8 +562,8 @@ static int hci_create_le_conn(struct hci_conn *conn) hci_req_init(&req, hdev); memset(&cp, 0, sizeof(cp)); - cp.scan_interval = __constant_cpu_to_le16(0x0060); - cp.scan_window = __constant_cpu_to_le16(0x0030); + cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); + cp.scan_window = cpu_to_le16(hdev->le_scan_window); bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; if (bacmp(&hdev->bdaddr, BDADDR_ANY)) -- cgit v1.2.3 From 79d95a19a445f5758571b3342064f2c1e40b6c5f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 03:57:38 -0700 Subject: Bluetooth: Remove pointless bdaddr_to_le() helper function The bdaddr_to_le() function tries to convert the internal address type to one that matches the HCI address type for LE. It does not handle any address types not used by LE and in the end just make the code a lot harder to read. So instead of just hiding behind a magic function, just convert the internal address type where it needs to be converted. And it turns out that these are only two cases anyway. One when creating new LE connections and the other when loading the long term keys. In both cases this makes it more clear on what it going on. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index c52bfb7e44fd..bb32f48b88f9 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -622,7 +622,10 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, if (!conn) return ERR_PTR(-ENOMEM); - conn->dst_type = bdaddr_to_le(dst_type); + if (dst_type == BDADDR_LE_PUBLIC) + conn->dst_type = ADDR_LE_DEV_PUBLIC; + else + conn->dst_type = ADDR_LE_DEV_RANDOM; conn->state = BT_CONNECT; conn->out = true; conn->link_mode |= HCI_LM_MASTER; -- cgit v1.2.3 From e7c4096e16f0e362c6cf902baab0de37ebfc1266 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 03:57:39 -0700 Subject: Bluetooth: Store the source address type of LE connections When establishing LE connections, it is possible to use a public address (if available) or a random address. The type of address is only known when creating connections, so make sure it is stored in hci_conn structure. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index bb32f48b88f9..d9f7f93b813e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -566,10 +566,7 @@ static int hci_create_le_conn(struct hci_conn *conn) cp.scan_window = cpu_to_le16(hdev->le_scan_window); bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; - if (bacmp(&hdev->bdaddr, BDADDR_ANY)) - cp.own_address_type = ADDR_LE_DEV_PUBLIC; - else - cp.own_address_type = ADDR_LE_DEV_RANDOM; + cp.own_address_type = conn->src_type; cp.conn_interval_min = __constant_cpu_to_le16(0x0028); cp.conn_interval_max = __constant_cpu_to_le16(0x0038); cp.supervision_timeout = __constant_cpu_to_le16(0x002a); @@ -626,6 +623,12 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->dst_type = ADDR_LE_DEV_PUBLIC; else conn->dst_type = ADDR_LE_DEV_RANDOM; + + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + conn->src_type = ADDR_LE_DEV_PUBLIC; + else + conn->src_type = ADDR_LE_DEV_RANDOM; + conn->state = BT_CONNECT; conn->out = true; conn->link_mode |= HCI_LM_MASTER; -- cgit v1.2.3 From 662e8820f38dcc458e0d4769194db5ed3469224f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 05:23:59 -0700 Subject: Bluetooth: Store source address of HCI connections The source addressed was based on the public address of the HCI device, but with LE connections this not always the case. For example single mode LE-only controllers would use a static random address. And this address is configured by userspace. To not complicate the lookup of what kind of address is in use, store the correct source address for each HCI connection. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index d9f7f93b813e..ff04b051792d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -381,6 +381,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) return NULL; bacpy(&conn->dst, dst); + bacpy(&conn->src, &hdev->bdaddr); conn->hdev = hdev; conn->type = type; conn->mode = HCI_CM_ACTIVE; @@ -624,10 +625,12 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, else conn->dst_type = ADDR_LE_DEV_RANDOM; - if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + if (bacmp(&conn->src, BDADDR_ANY)) { conn->src_type = ADDR_LE_DEV_PUBLIC; - else + } else { + bacpy(&conn->src, &hdev->static_addr); conn->src_type = ADDR_LE_DEV_RANDOM; + } conn->state = BT_CONNECT; conn->out = true; -- cgit v1.2.3 From 7bc18d9d3d7ffbc09dabb201933a063583a39027 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Oct 2013 18:11:39 +0300 Subject: Bluetooth: Convert auto accept timer to use delayed work Since the entire Bluetooth subsystem runs in workqueues these days there is no need to use a timer for deferring work. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ff04b051792d..8d1f466520a5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -361,12 +361,12 @@ static void hci_conn_idle(unsigned long arg) hci_conn_enter_sniff_mode(conn); } -static void hci_conn_auto_accept(unsigned long arg) +static void hci_conn_auto_accept(struct work_struct *work) { - struct hci_conn *conn = (void *) arg; - struct hci_dev *hdev = conn->hdev; + struct hci_conn *conn = container_of(work, struct hci_conn, + auto_accept_work.work); - hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), + hci_send_cmd(conn->hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), &conn->dst); } @@ -415,9 +415,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) INIT_LIST_HEAD(&conn->chan_list); INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); + INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept); setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); - setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, - (unsigned long) conn); atomic_set(&conn->refcnt, 0); @@ -441,8 +440,7 @@ int hci_conn_del(struct hci_conn *conn) del_timer(&conn->idle_timer); cancel_delayed_work_sync(&conn->disc_work); - - del_timer(&conn->auto_accept_timer); + cancel_delayed_work_sync(&conn->auto_accept_work); if (conn->type == ACL_LINK) { struct hci_conn *sco = conn->link; -- cgit v1.2.3 From a74a84f696537f38fa994c1b95a0dca9ae386865 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 16 Oct 2013 18:11:40 +0300 Subject: Bluetooth: Convert idle timer to use delayed work There is no need to use a timer since the entire Bluetooth subsystem runs using workqueues these days. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 8d1f466520a5..4e726505f52b 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -317,8 +317,10 @@ static void hci_conn_timeout(struct work_struct *work) } /* Enter sniff mode */ -static void hci_conn_enter_sniff_mode(struct hci_conn *conn) +static void hci_conn_idle(struct work_struct *work) { + struct hci_conn *conn = container_of(work, struct hci_conn, + idle_work.work); struct hci_dev *hdev = conn->hdev; BT_DBG("hcon %p mode %d", conn, conn->mode); @@ -352,15 +354,6 @@ static void hci_conn_enter_sniff_mode(struct hci_conn *conn) } } -static void hci_conn_idle(unsigned long arg) -{ - struct hci_conn *conn = (void *) arg; - - BT_DBG("hcon %p mode %d", conn, conn->mode); - - hci_conn_enter_sniff_mode(conn); -} - static void hci_conn_auto_accept(struct work_struct *work) { struct hci_conn *conn = container_of(work, struct hci_conn, @@ -416,7 +409,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept); - setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); + INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle); atomic_set(&conn->refcnt, 0); @@ -437,10 +430,9 @@ int hci_conn_del(struct hci_conn *conn) BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle); - del_timer(&conn->idle_timer); - cancel_delayed_work_sync(&conn->disc_work); cancel_delayed_work_sync(&conn->auto_accept_work); + cancel_delayed_work_sync(&conn->idle_work); if (conn->type == ACL_LINK) { struct hci_conn *sco = conn->link; @@ -920,8 +912,8 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) timer: if (hdev->idle_timeout > 0) - mod_timer(&conn->idle_timer, - jiffies + msecs_to_jiffies(hdev->idle_timeout)); + queue_delayed_work(hdev->workqueue, &conn->idle_work, + msecs_to_jiffies(hdev->idle_timeout)); } /* Drop all connection on the device */ -- cgit v1.2.3 From 79830f66e3cbd224bcf697b032dce9828b5a3c9e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 18 Oct 2013 16:38:09 -0700 Subject: Bluetooth: Select the own address type during initial setup phase The own address type is based on the fact if the controller has a public address or not. This means that this detail can be just configured once during setup phase. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 4e726505f52b..974d7bccbb6f 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -615,12 +615,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, else conn->dst_type = ADDR_LE_DEV_RANDOM; - if (bacmp(&conn->src, BDADDR_ANY)) { - conn->src_type = ADDR_LE_DEV_PUBLIC; - } else { - bacpy(&conn->src, &hdev->static_addr); - conn->src_type = ADDR_LE_DEV_RANDOM; - } + conn->src_type = hdev->own_addr_type; conn->state = BT_CONNECT; conn->out = true; -- cgit v1.2.3 From 4e70c7e71c5f9cf11013628ab5a0ced449b1c7b2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 19 Oct 2013 07:09:13 -0700 Subject: Bluetooth: Expose debugfs settings for LE connection interval For testing purposes expose the default LE connection interval values via debugfs. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 974d7bccbb6f..ba5366c320da 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -558,11 +558,12 @@ static int hci_create_le_conn(struct hci_conn *conn) bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; cp.own_address_type = conn->src_type; - cp.conn_interval_min = __constant_cpu_to_le16(0x0028); - cp.conn_interval_max = __constant_cpu_to_le16(0x0038); + cp.conn_interval_min = cpu_to_le16(hdev->le_conn_min_interval); + cp.conn_interval_max = cpu_to_le16(hdev->le_conn_max_interval); cp.supervision_timeout = __constant_cpu_to_le16(0x002a); cp.min_ce_len = __constant_cpu_to_le16(0x0000); cp.max_ce_len = __constant_cpu_to_le16(0x0000); + hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); err = hci_req_run(&req, create_le_conn_complete); -- cgit v1.2.3