From f9be9e8661323fd259a5cc1bec67e3d6bb43ec41 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Dec 2014 00:35:45 +0100 Subject: Bluetooth: Check for force_lesc_support when enabling SMP over BR/EDR The SMP over BR/EDR support for cross-transport pairing should also be enabled when the debugfs setting force_lesc_support has been enabled. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8da7ea9c2c0..cc518eb48dc8 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6967,8 +6967,9 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) test_bit(HCI_HS_ENABLED, &hcon->hdev->dev_flags)) conn->local_fixed_chan |= L2CAP_FC_A2MP; - if (bredr_sc_enabled(hcon->hdev) && - test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) + if (test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags) && + (bredr_sc_enabled(hcon->hdev) || + test_bit(HCI_FORCE_LESC, &hcon->hdev->dbg_flags))) conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; mutex_init(&conn->ident_lock); -- cgit v1.2.3-59-g8ed1b From 08f63cc5026f20b9124828619c9025738ecb5a5e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 7 Dec 2014 16:19:12 +0100 Subject: Bluetooth: Check for force_lesc_support before rejecting SMP over BR/EDR The SMP over BR/EDR requests for cross-transport pairing should also accepted when the debugfs setting force_lesc_support has been enabled. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/smp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 96bf16dcd9e9..3e174f94a46b 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -1674,7 +1674,8 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) /* SMP over BR/EDR requires special treatment */ if (conn->hcon->type == ACL_LINK) { /* We must have a BR/EDR SC link */ - if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags)) + if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) && + !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags)) return SMP_CROSS_TRANSP_NOT_ALLOWED; set_bit(SMP_FLAG_SC, &smp->flags); -- cgit v1.2.3-59-g8ed1b From 9437d2edc39ed8f7e40536281ee53ec3fd5a14ca Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 7 Dec 2014 20:13:17 +0100 Subject: Bluetooth: Fix generation of non-resolvable private addresses When the host decides to use a non-resolvable private address, it must ensure that this generated address does not match the public address of the controller. Add an extra check to ensure this required behavior. In addition rename the variable from urpa to nrpa and fix all of the comments in the code that use the term unresolvable instead of the term non-resolvable as used in the Bluetooth specification. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 2 +- net/bluetooth/hci_core.c | 24 ++++++++++++++++++------ net/bluetooth/mgmt.c | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 79d84b88b8f0..fe18825cc8a4 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -661,7 +661,7 @@ static void hci_req_add_le_create_conn(struct hci_request *req, memset(&cp, 0, sizeof(cp)); /* Update random address, but set require_privacy to false so - * that we never connect with an unresolvable address. + * that we never connect with an non-resolvable address. */ if (hci_update_random_address(req, false, &own_addr_type)) return; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 93f92a085506..96e7321c57a4 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3959,17 +3959,29 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, } /* In case of required privacy without resolvable private address, - * use an unresolvable private address. This is useful for active + * use an non-resolvable private address. This is useful for active * scanning and non-connectable advertising. */ if (require_privacy) { - bdaddr_t urpa; + bdaddr_t nrpa; - get_random_bytes(&urpa, 6); - urpa.b[5] &= 0x3f; /* Clear two most significant bits */ + while (true) { + /* The non-resolvable private address is generated + * from random six bytes with the two most significant + * bits cleared. + */ + get_random_bytes(&nrpa, 6); + nrpa.b[5] &= 0x3f; + + /* The non-resolvable private address shall not be + * equal to the public address. + */ + if (bacmp(&hdev->bdaddr, &nrpa)) + break; + } *own_addr_type = ADDR_LE_DEV_RANDOM; - set_random_addr(req, &urpa); + set_random_addr(req, &nrpa); return 0; } @@ -5625,7 +5637,7 @@ void hci_req_add_le_passive_scan(struct hci_request *req) u8 filter_policy; /* Set require_privacy to false since no SCAN_REQ are send - * during passive scanning. Not using an unresolvable address + * during passive scanning. Not using an non-resolvable address * here is important so that peer devices using direct * advertising with our address will be correctly reported * by the controller. diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a91e484886fe..44b20deb6038 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3791,7 +3791,7 @@ static bool trigger_discovery(struct hci_request *req, u8 *status) /* All active scans will be done with either a resolvable * private address (when privacy feature has been enabled) - * or unresolvable private address. + * or non-resolvable private address. */ err = hci_update_random_address(req, true, &own_addr_type); if (err < 0) { -- cgit v1.2.3-59-g8ed1b From fe7007719742e4c0c1255e2f45bdd4ed97afc369 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Mon, 8 Dec 2014 03:04:38 +0800 Subject: Bluetooth: fix err_cast.cocci warnings net/bluetooth/smp.c:2650:9-16: WARNING: ERR_CAST can be used with tfm_aes Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(...)) Generated by: scripts/coccinelle/api/err_cast.cocci Signed-off-by: Fengguang Wu Signed-off-by: Marcel Holtmann --- net/bluetooth/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 3e174f94a46b..04489856ca68 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -2931,7 +2931,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 0); if (IS_ERR(tfm_aes)) { BT_ERR("Unable to create crypto context"); - return ERR_PTR(PTR_ERR(tfm_aes)); + return ERR_CAST(tfm_aes); } create_chan: -- cgit v1.2.3-59-g8ed1b From 3ad675827f4a3623b7fc51ffe8fdb0347b3cbc53 Mon Sep 17 00:00:00 2001 From: Jaganath Kanakkassery Date: Thu, 11 Dec 2014 11:43:12 +0530 Subject: Bluetooth: Fix missing hci_dev_lock/unlock in mgmt req_complete() mgmt_pending_remove() should be called with hci_dev_lock protection and currently the rule to take dev lock is that all mgmt req_complete functions should take dev lock. So this patch fixes the same in the missing functions Without this patch there is a chance of invalid memory access while accessing the mgmt_pending list like below bluetoothd: 392] [0] Backtrace: bluetoothd: 392] [0] [] (pending_eir_or_class+0x0/0x68) from [] (add_uuid+0x34/0x1c4) bluetoothd: 392] [0] [] (add_uuid+0x0/0x1c4) from [] (mgmt_control+0x204/0x274) bluetoothd: 392] [0] [] (mgmt_control+0x0/0x274) from [] (hci_sock_sendmsg+0x80/0x308) bluetoothd: 392] [0] [] (hci_sock_sendmsg+0x0/0x308) from [] (sock_aio_write+0x144/0x174) bluetoothd: 392] [0] r8:00000000 r7 7c1be90 r6 7c1be18 r5:00000017 r4 a90ea80 bluetoothd: 392] [0] [] (sock_aio_write+0x0/0x174) from [] (do_sync_write+0xb0/0xe0) bluetoothd: 392] [0] [] (do_sync_write+0x0/0xe0) from [] (vfs_write+0x134/0x13c) bluetoothd: 392] [0] r8:00000000 r7 7c1bf70 r6:beeca5c8 r5:00000017 r4 7c05900 bluetoothd: 392] [0] [] (vfs_write+0x0/0x13c) from [] (sys_write+0x44/0x70) bluetoothd: 392] [0] r8:00000000 r7:00000004 r6:00000017 r5:beeca5c8 r4 7c05900 bluetoothd: 392] [0] [] (sys_write+0x0/0x70) from [] (ret_fast_syscall+0x0/0x30) bluetoothd: 392] [0] r9 7c1a000 r8:c000e568 r6:400b5f10 r5:403896d8 r4:beeca604 bluetoothd: 392] [0] Code: e28cc00c e152000c 0a00000f e3a00001 (e1d210b8) bluetoothd: 392] [0] ---[ end trace 67b6ac67435864c4 ]--- bluetoothd: 392] [0] Kernel panic - not syncing: Fatal exception Signed-off-by: Jaganath Kanakkassery Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_core.c | 2 ++ net/bluetooth/mgmt.c | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 96e7321c57a4..ecd7c01317bc 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3083,7 +3083,9 @@ static void hci_power_on(struct work_struct *work) err = hci_dev_do_open(hdev); if (err < 0) { + hci_dev_lock(hdev); mgmt_set_powered_failed(hdev, err); + hci_dev_unlock(hdev); return; } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 44b20deb6038..16ac03730f4d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2199,12 +2199,14 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status) { struct cmd_lookup match = { NULL, hdev }; + hci_dev_lock(hdev); + if (status) { u8 mgmt_err = mgmt_status(status); mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, &mgmt_err); - return; + goto unlock; } mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); @@ -2222,17 +2224,16 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status) if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { struct hci_request req; - hci_dev_lock(hdev); - hci_req_init(&req, hdev); update_adv_data(&req); update_scan_rsp_data(&req); hci_req_run(&req, NULL); hci_update_background_scan(hdev); - - hci_dev_unlock(hdev); } + +unlock: + hci_dev_unlock(hdev); } static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) @@ -4279,12 +4280,14 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status) { struct cmd_lookup match = { NULL, hdev }; + hci_dev_lock(hdev); + if (status) { u8 mgmt_err = mgmt_status(status); mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, cmd_status_rsp, &mgmt_err); - return; + goto unlock; } if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) @@ -4299,6 +4302,9 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status) if (match.sk) sock_put(match.sk); + +unlock: + hci_dev_unlock(hdev); } static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, -- cgit v1.2.3-59-g8ed1b From 5c1a4c8f28059e592da4fff40c0dc54202fb5cc6 Mon Sep 17 00:00:00 2001 From: Jaganath Kanakkassery Date: Thu, 11 Dec 2014 18:58:15 +0530 Subject: Bluetooth: Fix missing hci_dev_lock/unlock in hci_event mgmt_pending_remove() should be called with hci_dev_lock protection and all hci_event.c functions which calls mgmt_complete() (which eventually calls mgmt_pending_remove()) should hold the lock. So this patch fixes the same Signed-off-by: Jaganath Kanakkassery Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'net') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 322abbbbcef9..39a5c8a01726 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -257,6 +257,8 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) if (!sent) return; + hci_dev_lock(hdev); + if (!status) { __u8 param = *((__u8 *) sent); @@ -268,6 +270,8 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) if (test_bit(HCI_MGMT, &hdev->dev_flags)) mgmt_auth_enable_complete(hdev, status); + + hci_dev_unlock(hdev); } static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) @@ -443,6 +447,8 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) if (!sent) return; + hci_dev_lock(hdev); + if (!status) { if (sent->mode) hdev->features[1][0] |= LMP_HOST_SSP; @@ -458,6 +464,8 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) else clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); } + + hci_dev_unlock(hdev); } static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) @@ -471,6 +479,8 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) if (!sent) return; + hci_dev_lock(hdev); + if (!status) { if (sent->support) hdev->features[1][0] |= LMP_HOST_SC; @@ -486,6 +496,8 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) else clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); } + + hci_dev_unlock(hdev); } static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) @@ -1135,6 +1147,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, if (!cp) return; + hci_dev_lock(hdev); + switch (cp->enable) { case LE_SCAN_ENABLE: set_bit(HCI_LE_SCAN, &hdev->dev_flags); @@ -1184,6 +1198,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); break; } + + hci_dev_unlock(hdev); } static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, @@ -1278,6 +1294,8 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, if (!sent) return; + hci_dev_lock(hdev); + if (sent->le) { hdev->features[1][0] |= LMP_HOST_LE; set_bit(HCI_LE_ENABLED, &hdev->dev_flags); @@ -1291,6 +1309,8 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, hdev->features[1][0] |= LMP_HOST_LE_BREDR; else hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; + + hci_dev_unlock(hdev); } static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) -- cgit v1.2.3-59-g8ed1b From 417287de88bfbb724bab2f50782395d2606b28e1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 11 Dec 2014 20:21:54 +0100 Subject: Bluetooth: Fix check for support for page scan related commands The Read Page Scan Activity and Read Page Scan Type commands are not supported by all controllers. Move the execution of both commands into the 3rd phase of the init procedure. And then check the bit mask of supported commands before adding them to the init sequence. With this re-ordering of the init sequence, the extra check for AVM BlueFritz! controllers is no longer needed. They will report that these two commands are not supported. This fixes an issue with the Microsoft Corp. Wireless Transceiver for Bluetooth 2.0 (ID 045e:009c). Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ecd7c01317bc..cc60465ea774 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1373,8 +1373,6 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt) static void bredr_setup(struct hci_request *req) { - struct hci_dev *hdev = req->hdev; - __le16 param; __u8 flt_type; @@ -1403,14 +1401,6 @@ static void bredr_setup(struct hci_request *req) /* Connection accept timeout ~20 secs */ param = cpu_to_le16(0x7d00); hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); - - /* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2, - * but it does not support page scan related HCI commands. - */ - if (hdev->manufacturer != 31 && hdev->hci_ver > BLUETOOTH_VER_1_1) { - hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); - hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL); - } } static void le_setup(struct hci_request *req) @@ -1718,6 +1708,16 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) if (hdev->commands[5] & 0x10) hci_setup_link_policy(req); + if (hdev->commands[8] & 0x01) + hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); + + /* Some older Broadcom based Bluetooth 1.2 controllers do not + * support the Read Page Scan Type command. Check support for + * this command in the bit mask of supported commands. + */ + if (hdev->commands[13] & 0x01) + hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL); + if (lmp_le_capable(hdev)) { u8 events[8]; -- cgit v1.2.3-59-g8ed1b From 15013aeb63fb4df7ff809d63246c8398e9703736 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 11 Dec 2014 21:45:44 +0200 Subject: Bluetooth: Fix calling hci_conn_put too early The pairing_complete() function relies on a hci_conn reference to be able to access the hci_conn object. It should therefore only release this reference once it's done accessing the object, i.e. at the end of the function. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 16ac03730f4d..34da65ccc888 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3115,14 +3115,14 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) conn->disconn_cfm_cb = NULL; hci_conn_drop(conn); - hci_conn_put(conn); - mgmt_pending_remove(cmd); /* The device is paired so there is no need to remove * its connection parameters anymore. */ clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags); + + hci_conn_put(conn); } void mgmt_smp_complete(struct hci_conn *conn, bool complete) -- cgit v1.2.3-59-g8ed1b From a511b35ba4f02cca526c7239723c48445a8b127d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 11 Dec 2014 21:45:45 +0200 Subject: Bluetooth: Fix incorrect pending cmd removal in pairing_complete() The pairing_complete() function is used as a pending mgmt command cmd_complete callback. The expectation of such functions is that they are not responsible themselves for calling mgmt_pending_remove(). This patch fixes the incorrect mgmt_pending_remove() call in pairing_complete() and adds it to the appropriate changes. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'net') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 34da65ccc888..827107d5a424 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3115,7 +3115,6 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) conn->disconn_cfm_cb = NULL; hci_conn_drop(conn); - mgmt_pending_remove(cmd); /* The device is paired so there is no need to remove * its connection parameters anymore. @@ -3131,8 +3130,10 @@ void mgmt_smp_complete(struct hci_conn *conn, bool complete) struct pending_cmd *cmd; cmd = find_pairing(conn); - if (cmd) + if (cmd) { cmd->cmd_complete(cmd, status); + mgmt_pending_remove(cmd); + } } static void pairing_complete_cb(struct hci_conn *conn, u8 status) @@ -3142,10 +3143,13 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status) BT_DBG("status %u", status); cmd = find_pairing(conn); - if (!cmd) + if (!cmd) { BT_DBG("Unable to find a pending command"); - else - cmd->cmd_complete(cmd, mgmt_status(status)); + return; + } + + cmd->cmd_complete(cmd, mgmt_status(status)); + mgmt_pending_remove(cmd); } static void le_pairing_complete_cb(struct hci_conn *conn, u8 status) @@ -3158,10 +3162,13 @@ static void le_pairing_complete_cb(struct hci_conn *conn, u8 status) return; cmd = find_pairing(conn); - if (!cmd) + if (!cmd) { BT_DBG("Unable to find a pending command"); - else - cmd->cmd_complete(cmd, mgmt_status(status)); + return; + } + + cmd->cmd_complete(cmd, mgmt_status(status)); + mgmt_pending_remove(cmd); } static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, @@ -3275,8 +3282,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, cmd->user_data = hci_conn_get(conn); if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) && - hci_conn_security(conn, sec_level, auth_type, true)) - pairing_complete(cmd, 0); + hci_conn_security(conn, sec_level, auth_type, true)) { + cmd->cmd_complete(cmd, 0); + mgmt_pending_remove(cmd); + } err = 0; @@ -3318,7 +3327,8 @@ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data, goto unlock; } - pairing_complete(cmd, MGMT_STATUS_CANCELLED); + cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED); + mgmt_pending_remove(cmd); err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0, addr, sizeof(*addr)); @@ -6687,8 +6697,10 @@ void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status) mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev), cmd ? cmd->sk : NULL); - if (cmd) - pairing_complete(cmd, status); + if (cmd) { + cmd->cmd_complete(cmd, status); + mgmt_pending_remove(cmd); + } } void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) -- cgit v1.2.3-59-g8ed1b From 1aeb9c651c06282e84c33eb838d1069582879af8 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 11 Dec 2014 21:45:46 +0200 Subject: Bluetooth: Fix notifying mgmt power off before flushing connection list This patch moves the mgmt_powered() notification earlier in the hci_dev_do_close() function. This way the correct "not powered" error gets passed to any pending mgmt commands. Without the patch the pending commands would instead get a misleading "disconnected" response when powering down the adapter. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_core.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index cc60465ea774..5dcacf9607e4 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2634,6 +2634,12 @@ static int hci_dev_do_close(struct hci_dev *hdev) drain_workqueue(hdev->workqueue); hci_dev_lock(hdev); + + if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { + if (hdev->dev_type == HCI_BREDR) + mgmt_powered(hdev, 0); + } + hci_inquiry_cache_flush(hdev); hci_pend_le_actions_clear(hdev); hci_conn_hash_flush(hdev); @@ -2681,14 +2687,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) hdev->flags &= BIT(HCI_RAW); hdev->dev_flags &= ~HCI_PERSISTENT_MASK; - if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { - if (hdev->dev_type == HCI_BREDR) { - hci_dev_lock(hdev); - mgmt_powered(hdev, 0); - hci_dev_unlock(hdev); - } - } - /* Controller radio is available but is currently powered down */ hdev->amp_status = AMP_STATUS_POWERED_DOWN; -- cgit v1.2.3-59-g8ed1b From ec6f99b807e4bd50566c48fff8994da2fb1bf9fe Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 12 Dec 2014 13:30:11 +0200 Subject: Bluetooth: Fix enabling BR/EDR SC when powering on If we're in the AUTO_OFF stage the powered_update_hci() function is responsible for doing the updates to the HCI state that were not done during the actual mgmt command handlers. One of the updates needing done is for BR/EDR SC support. This patch adds the missing HCI command for SC support to the powered_update_hci() function. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 827107d5a424..1e33880ed562 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6097,6 +6097,11 @@ static int powered_update_hci(struct hci_dev *hdev) hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp); } + if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) { + u8 sc = 0x01; + hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, sizeof(sc), &sc); + } + if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && lmp_bredr_capable(hdev)) { struct hci_cp_write_le_host_supported cp; -- cgit v1.2.3-59-g8ed1b From 9845904fd489288bcf693642c1b31cc463c0b660 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 12 Dec 2014 11:15:21 +0200 Subject: Bluetooth: Fix mgmt response status when removing adapter When an adapter is removed (hci_unregister_dev) any pending mgmt commands for that adapter should get the appropriate INVALID_INDEX response. Since hci_unregister_dev() calls hci_dev_do_close() first that'd so far have caused "not powered" responses to be sent. Skipping the HCI_UNREGISTER case in mgmt_powered() is also not a solution since before reaching the mgmt_index_removed() stage any hci_conn callbacks (e.g. used by pairing) will get called, thereby causing "disconnected" status responses to be sent. The fix that covers all scenarios is to handle both INVALID_INDEX and NOT_POWERED responses through the mgmt_powered() function. The INVALID_INDEX response sending from mgmt_index_removed() is left untouched since there are a couple of places not related to powering off or removing an adapter that call it (e.g. configuring a new bdaddr). Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 1e33880ed562..23a0ca5a4737 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6151,8 +6151,7 @@ static int powered_update_hci(struct hci_dev *hdev) int mgmt_powered(struct hci_dev *hdev, u8 powered) { struct cmd_lookup match = { NULL, hdev }; - u8 status_not_powered = MGMT_STATUS_NOT_POWERED; - u8 zero_cod[] = { 0, 0, 0 }; + u8 status, zero_cod[] = { 0, 0, 0 }; int err; if (!test_bit(HCI_MGMT, &hdev->dev_flags)) @@ -6168,7 +6167,20 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) } mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); - mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered); + + /* If the power off is because of hdev unregistration let + * use the appropriate INVALID_INDEX status. Otherwise use + * NOT_POWERED. We cover both scenarios here since later in + * mgmt_index_removed() any hci_conn callbacks will have already + * been triggered, potentially causing misleading DISCONNECTED + * status responses. + */ + if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) + status = MGMT_STATUS_INVALID_INDEX; + else + status = MGMT_STATUS_NOT_POWERED; + + mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status); if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, -- cgit v1.2.3-59-g8ed1b