From 033efa920a7f22a8caf7a38d851a2f451781bbf7 Mon Sep 17 00:00:00 2001 From: Dmitry Tunin Date: Sun, 18 Jan 2015 00:16:51 +0300 Subject: [PATCH 01/53] Bluetooth: ath3k: Add support of AR3012 bluetooth 13d3:3423 device Add support of 13d3:3423 device. BugLink: https://bugs.launchpad.net/bugs/1411193 T: Bus=01 Lev=02 Prnt=03 Port=00 Cnt=01 Dev#= 5 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=13d3 ProdID=3423 Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=01 I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Dmitry Tunin Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org --- drivers/bluetooth/ath3k.c | 2 ++ drivers/bluetooth/btusb.c | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 1ee27ac18de0..13a64d0c69e2 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -108,6 +108,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3393) }, { USB_DEVICE(0x13d3, 0x3402) }, { USB_DEVICE(0x13d3, 0x3408) }, + { USB_DEVICE(0x13d3, 0x3423) }, { USB_DEVICE(0x13d3, 0x3432) }, /* Atheros AR5BBU12 with sflash firmware */ @@ -162,6 +163,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4a6495ab9726..1211c74356b5 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -189,6 +189,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ From 9a5abdaaf9d2e80e157c7a756f9d9fd933dee48e Mon Sep 17 00:00:00 2001 From: Rick Dunn Date: Sat, 17 Jan 2015 05:29:12 +0100 Subject: [PATCH 02/53] Bluetooth: btusb: Add Broadcom patchram support for ASUSTek devices T: Bus=03 Lev=01 Prnt=01 Port=06 Cnt=02 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0b05 ProdID=17cf Rev= 1.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 S: SerialNumber=54271E3298CD C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Firmware is extracted from the latest Broadcom BCM4352 Windows driver by extracting the zip and searching the .hex file names for '17cf'. The hex file must then be converted to hcd format using the hex2hcd utility and then moved to /lib/firmware/brcm/. Signed-off-by: Rick Dunn Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org --- drivers/bluetooth/btusb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 1211c74356b5..ea3d33785a9f 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -119,7 +119,8 @@ static const struct usb_device_id btusb_table[] = { .driver_info = BTUSB_BCM_PATCHRAM }, /* ASUSTek Computer - Broadcom based */ - { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01), + .driver_info = BTUSB_BCM_PATCHRAM }, /* Belkin F8065bf - Broadcom based */ { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, From 91200e9f3e76af2652952e73ce5d9913f1c987c6 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 22 Jan 2015 16:57:05 +0100 Subject: [PATCH 03/53] Bluetooth: Fix reporting invalid RSSI for LE devices Start Discovery was reporting 0 RSSI for invalid RSSI only for BR/EDR devices. LE devices were reported with RSSI 127. Signed-off-by: Szymon Janc Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org # 3.19+ --- net/bluetooth/mgmt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f5c4d2eed9a1..a619d983c078 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -7238,7 +7238,8 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, * However when using service discovery, the value 127 will be * returned when the RSSI is not available. */ - if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi) + if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi && + link_type == ACL_LINK) rssi = 0; bacpy(&ev->addr.bdaddr, bdaddr); From 574ea3c7137c9deee75b107221be5159720ab501 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 22 Jan 2015 11:15:20 -0800 Subject: [PATCH 04/53] Bluetooth: Fix dependency for BR/EDR Secure Connections mode on SSP The BR/EDR Secure Connections feature should only be enabled when the Secure Simple Pairing mode has been enabled first. However since secure connections is feature that is valid for BR/EDR and LE, this needs special handling. When enabling secure connections on a LE only configured controller, thent the BR/EDR side should not be enabled in the controller. This patches makes the BR/EDR Secure Connections feature depending on enabling Secure Simple Pairing mode first. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 5 ++++- net/bluetooth/mgmt.c | 14 ++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 34c17a0645ce..bb831d678868 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -609,6 +609,7 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { u8 mode = 0x01; + hci_req_add(req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); } else { @@ -870,8 +871,10 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt) hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); /* Enable Secure Connections if supported and configured */ - if (bredr_sc_enabled(hdev)) { + if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && + bredr_sc_enabled(hdev)) { u8 support = 0x01; + hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT, sizeof(support), &support); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a619d983c078..3049a4815665 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6262,14 +6262,16 @@ static int powered_update_hci(struct hci_dev *hdev) if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && !lmp_host_ssp_capable(hdev)) { - u8 ssp = 1; + u8 mode = 0x01; - hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp); - } + hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode); - 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 (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) { + u8 support = 0x01; + + hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, + sizeof(support), &support); + } } if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && From 3a5486e1fdb0da7a18788f40b17d351af90d0ea7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 22 Jan 2015 11:15:21 -0800 Subject: [PATCH 05/53] Bluetooth: Limit BR/EDR switching for LE only with secure connections When a powered on dual-mode controller has been configured to operate as LE only with secure connections, then the BR/EDR side of things can not be switched back on. Do reconfigure the controller it first needs to be powered down. The secure connections feature is implemented in the BR/EDR controller while for LE it is implemented in the host. So explicitly forbid such a transaction to avoid inconsistent states. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 3049a4815665..e86b8d9105e9 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4691,9 +4691,16 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) * Dual-mode controllers shall operate with the public * address as its identity address for BR/EDR and LE. So * reject the attempt to create an invalid configuration. + * + * The same restrictions applies when secure connections + * has been enabled. For BR/EDR this is a controller feature + * while for LE it is a host stack feature. This means that + * switching BR/EDR back on when secure connections has been + * enabled is not a supported transaction. */ if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && - bacmp(&hdev->static_addr, BDADDR_ANY)) { + (bacmp(&hdev->static_addr, BDADDR_ANY) || + test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR, MGMT_STATUS_REJECTED); goto unlock; From ed93ec69c7e0e80d733dced5b73af0f23cc3b061 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 22 Jan 2015 11:15:22 -0800 Subject: [PATCH 06/53] Bluetooth: Require SSP enabling before BR/EDR Secure Connections When BR/EDR is supported by a controller, then it is required to enable Secure Simple Pairing first before enabling the Secure Connections feature. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index e86b8d9105e9..41e30055bae8 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4758,6 +4758,11 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, MGMT_STATUS_NOT_SUPPORTED); + if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && + !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) + return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, + MGMT_STATUS_REJECTED); + if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, MGMT_STATUS_INVALID_PARAMS); From 5d57e7964c3261827cc718b0e5317ac4950e2f21 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 23 Jan 2015 10:10:38 +0200 Subject: [PATCH 07/53] Bluetooth: Check for valid bdaddr in add_remote_oob_data Before doing any other verifications, the add_remote_oob_data function should first check that the given address is valid. This patch adds such a missing check to the beginning of the function. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 41e30055bae8..2c0de3e4e79a 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3633,10 +3633,16 @@ unlock: static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { + struct mgmt_addr_info *addr = data; int err; BT_DBG("%s ", hdev->name); + if (!bdaddr_type_is_valid(addr->type)) + return cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, + MGMT_STATUS_INVALID_PARAMS, addr, + sizeof(*addr)); + hci_dev_lock(hdev); if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) { From 484aabc1c4e869879e614a621e2dfabc9f98fb00 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 23 Jan 2015 10:10:39 +0200 Subject: [PATCH 08/53] Bluetooth: Remove incorrect check for BDADDR_BREDR address type The Add Remote OOB Data mgmt command should allow data to be passed for LE as well. This patch removes a left-over check for BDADDR_BREDR that should not be there anymore. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2c0de3e4e79a..862a005d9db2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3672,14 +3672,6 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, u8 *rand192, *hash192; u8 status; - if (cp->addr.type != BDADDR_BREDR) { - err = cmd_complete(sk, hdev->id, - MGMT_OP_ADD_REMOTE_OOB_DATA, - MGMT_STATUS_INVALID_PARAMS, - &cp->addr, sizeof(cp->addr)); - goto unlock; - } - if (bdaddr_type_is_le(cp->addr.type)) { rand192 = NULL; hash192 = NULL; From a1443f5a273713d4bfda360e45aa6e1d14fe7324 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 23 Jan 2015 15:42:46 +0200 Subject: [PATCH 09/53] Bluetooth: Convert Set SC to use HCI Request This patch converts the Set Secure Connection HCI handling to use a HCI request instead of using a hard-coded callback in hci_event.c. This e.g. ensures that we don't clear the flags incorrectly if something goes wrong with the power up process (not related to a mgmt Set SC command). The code can also be simplified a bit since only one pending Set SC command is allowed, i.e. mgmt_pending_foreach usage is not needed. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/hci_event.c | 4 +- net/bluetooth/mgmt.c | 92 +++++++++++++++++--------------- 3 files changed, 50 insertions(+), 47 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7777124bff55..0f5e59f1e3cb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1369,7 +1369,6 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_auth_failed(struct hci_conn *conn, u8 status); void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); -void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, u8 status); void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a58845e98921..e2b81adc232f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -525,9 +525,7 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) hdev->features[1][0] &= ~LMP_HOST_SC; } - if (test_bit(HCI_MGMT, &hdev->dev_flags)) - mgmt_sc_enable_complete(hdev, sent->support, status); - else if (!status) { + if (!test_bit(HCI_MGMT, &hdev->dev_flags) && !status) { if (sent->support) set_bit(HCI_SC_ENABLED, &hdev->dev_flags); else diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 862a005d9db2..25e40e82b9a2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4741,11 +4741,57 @@ unlock: return err; } +static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode) +{ + struct pending_cmd *cmd; + struct mgmt_mode *cp; + + BT_DBG("%s status %u", hdev->name, status); + + hci_dev_lock(hdev); + + cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev); + if (!cmd) + goto unlock; + + if (status) { + cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_status(status)); + goto remove; + } + + cp = cmd->param; + + switch (cp->val) { + case 0x00: + clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); + clear_bit(HCI_SC_ONLY, &hdev->dev_flags); + break; + case 0x01: + set_bit(HCI_SC_ENABLED, &hdev->dev_flags); + clear_bit(HCI_SC_ONLY, &hdev->dev_flags); + break; + case 0x02: + set_bit(HCI_SC_ENABLED, &hdev->dev_flags); + set_bit(HCI_SC_ONLY, &hdev->dev_flags); + break; + } + + send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev); + new_settings(hdev, cmd->sk); + +remove: + mgmt_pending_remove(cmd); +unlock: + hci_dev_unlock(hdev); +} + static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { struct mgmt_mode *cp = data; struct pending_cmd *cmd; + struct hci_request req; u8 val; int err; @@ -4814,17 +4860,14 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, goto failed; } - err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val); + hci_req_init(&req, hdev); + hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val); + err = hci_req_run(&req, sc_enable_complete); if (err < 0) { mgmt_pending_remove(cmd); goto failed; } - if (cp->val == 0x02) - set_bit(HCI_SC_ONLY, &hdev->dev_flags); - else - clear_bit(HCI_SC_ONLY, &hdev->dev_flags); - failed: hci_dev_unlock(hdev); return err; @@ -7001,43 +7044,6 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) hci_req_run(&req, NULL); } -void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) -{ - struct cmd_lookup match = { NULL, hdev }; - bool changed = false; - - if (status) { - u8 mgmt_err = mgmt_status(status); - - if (enable) { - if (test_and_clear_bit(HCI_SC_ENABLED, - &hdev->dev_flags)) - new_settings(hdev, NULL); - clear_bit(HCI_SC_ONLY, &hdev->dev_flags); - } - - mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, - cmd_status_rsp, &mgmt_err); - return; - } - - if (enable) { - changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags); - } else { - changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); - clear_bit(HCI_SC_ONLY, &hdev->dev_flags); - } - - mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, - settings_rsp, &match); - - if (changed) - new_settings(hdev, match.sk); - - if (match.sk) - sock_put(match.sk); -} - static void sk_lookup(struct pending_cmd *cmd, void *data) { struct cmd_lookup *match = data; From dfb2fae7cd0a1aa13610b11d54203bcd3893da07 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 23 Jan 2015 12:16:53 -0500 Subject: [PATCH 10/53] Bluetooth: Fix nested sleeps l2cap/rfcomm/sco_sock_accept() are wait loops which may acquire sleeping locks. Since both wait loops and sleeping locks use task_struct.state to sleep and wake, the nested sleeping locks destroy the wait loop state. Use the newly-minted wait_woken() and DEFINE_WAIT_FUNC() for the wait loop. DEFINE_WAIT_FUNC() allows an alternate wake function to be specified; in this case, the predefined scheduler function, woken_wake_function(). This wait construct ensures wakeups will not be missed without requiring the wait loop to set the task state before condition evaluation. How this works: CPU 0 | CPU 1 | | is set? | no set | | wake_up_interruptible | woken_wake_function | set WQ_FLAG_WOKEN | try_to_wake_up | | wait_woken | set TASK_INTERRUPTIBLE | WQ_FLAG_WOKEN? yes | set TASK_RUNNING | | - loop - | | is set? | yes - exit wait loop Fixes "do not call blocking ops when !TASK_RUNNING" warnings in l2cap_sock_accept(), rfcomm_sock_accept() and sco_sock_accept(). Signed-off-by: Peter Hurley Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_sock.c | 9 ++++----- net/bluetooth/rfcomm/sock.c | 9 ++++----- net/bluetooth/sco.c | 8 +++----- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 20206cd3acbc..60694f0f4c73 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -302,7 +302,7 @@ done: static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT_FUNC(wait, woken_wake_function); struct sock *sk = sock->sk, *nsk; long timeo; int err = 0; @@ -316,8 +316,6 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, /* Wait for an incoming connection. (wake-one). */ add_wait_queue_exclusive(sk_sleep(sk), &wait); while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (sk->sk_state != BT_LISTEN) { err = -EBADFD; break; @@ -338,10 +336,11 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, } release_sock(sk); - timeo = schedule_timeout(timeo); + + timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); + lock_sock_nested(sk, L2CAP_NESTING_PARENT); } - __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); if (err) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index d8a95755a8a8..3c6d2c8ac1a4 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -468,7 +468,7 @@ done: static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT_FUNC(wait, woken_wake_function); struct sock *sk = sock->sk, *nsk; long timeo; int err = 0; @@ -487,8 +487,6 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f /* Wait for an incoming connection. (wake-one). */ add_wait_queue_exclusive(sk_sleep(sk), &wait); while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (sk->sk_state != BT_LISTEN) { err = -EBADFD; break; @@ -509,10 +507,11 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f } release_sock(sk); - timeo = schedule_timeout(timeo); + + timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); } - __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); if (err) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 07ec7d23b843..76321b546e84 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -618,7 +618,7 @@ done: static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT_FUNC(wait, woken_wake_function); struct sock *sk = sock->sk, *ch; long timeo; int err = 0; @@ -632,8 +632,6 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag /* Wait for an incoming connection. (wake-one). */ add_wait_queue_exclusive(sk_sleep(sk), &wait); while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (sk->sk_state != BT_LISTEN) { err = -EBADFD; break; @@ -654,10 +652,10 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag } release_sock(sk); - timeo = schedule_timeout(timeo); + + timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); lock_sock(sk); } - __set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); if (err) From d049f4e513e861167361b06c7ca85f9e872c8cde Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Jan 2015 20:35:32 -0800 Subject: [PATCH 11/53] Bluetooth: btusb: Add support for Dynex/Insignia USB dongles The Dynex/Insignia USB dongles are Broadcom BCM20702B0 based and require firmware update before operation. T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=19ff ProdID=0239 Rev= 1.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Since this is an unsual USB vendor ID (0x19ff), these dongles are added via USB_DEVICE macro and not USB_VENDOR_AND_INTERFACE_INFO as done for mainstream Broadcom based dongles. The latest known working firmware is BCM20702B0_002.001.014.0527.0557.hex which needs to be converted using hex2hcd utility and then installed as /lib/firmware/brcm/BCM20702A0-19ff-0239.hcd to make this device fully operational. Bluetooth: hci0: BCM: patching hci_ver=06 hci_rev=2000 lmp_ver=06 lmp_subver=410e Bluetooth: hci0: BCM: firmware hci_ver=06 hci_rev=222d lmp_ver=06 lmp_subver=410e With this firmware the device reports support for connectionless slave broadcast (master and slave) feature used by 3D Glasses and TVs. < HCI Command: Read Local Extended Features (0x04|0x0004) plen 1 Page: 2 > HCI Event: Command Complete (0x0e) plen 14 Read Local Extended Features (0x04|0x0004) ncmd 1 Status: Success (0x00) Page: 2/2 Features: 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Connectionless Slave Broadcast - Master Connectionless Slave Broadcast - Slave Synchronization Train Synchronization Scan However there are some flaws with this feature. The Set Event Mask Page 2 command is actually not supported and with that all connectionless slave broadcast events are always enabled. < HCI Command: Set Event Mask Page 2 (0x03|0x0063) plen 8 Mask: 0x00000000000f0000 Synchronization Train Received Connectionless Slave Broadcast Receive Connectionless Slave Broadcast Timeout Truncated Page Complete > HCI Event: Command Complete (0x0e) plen 4 Set Event Mask Page 2 (0x03|0x0063) ncmd 1 Status: Unknown HCI Command (0x01) In addition the Synchronization Train Received event is actually broken on this controller. It mixes up the order of parameters. According to the Bluetooth Core specification the fields are like this: struct hci_ev_sync_train_received { __u8 status; bdaddr_t bdaddr; __le32 offset; __u8 map[10]; __u8 lt_addr; __le32 instant; __le16 interval; __u8 service_data; } __packed; This controller however sends the service_data as 5th parameter instead of having it as last parameter. struct hci_ev_sync_train_received { __u8 status; bdaddr_t bdaddr; __le32 offset; __u8 map[10]; __u8 service_data; __u8 lt_addr; __le32 instant; __le16 interval; } __packed; So anybody trying to use this hardware for utilizing connectionless slave broadcast receivers (aka 3D Glasses), be warned about this shortcoming. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg Cc: stable@vger.kernel.org --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index ea3d33785a9f..2901e703809d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -110,6 +110,9 @@ static const struct usb_device_id btusb_table[] = { { USB_DEVICE(0x13d3, 0x3404), .driver_info = BTUSB_BCM_PATCHRAM }, + /* Broadcom BCM20702B0 (Dynex/Insignia) */ + { USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM }, + /* Foxconn - Hon Hai */ { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM }, From cda0dd7809f89e8d7f88335690d84b8482d33111 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Jan 2015 21:33:48 -0800 Subject: [PATCH 12/53] Bluetooth: btusb: Add firmware loading for Intel Snowfield Peak devices The Intel Snowfield Peak devices do not come with Bluetooth firmware loaded and thus require a full download of the operational Bluetooth firmware when the device is connected via USB. Snowfield Peak devices start with a bootloader mode that only accepts a very limited set of HCI commands. The supported commands are enough to identify the hardware and select the right firmware to load. Previous patches to the btusb driver allow overwriting the handling for bulk receive endpoint packets and HCI events processing. The firmware loading makes heavy use of these new internal callbacks. This patch also introduces additional internal states to track if the device is in bootloader or operational mode. This allows for correct feedback about the firmware loading procedure. Output from /sys/kernel/debug/usb/devices for this device: T: Bus=02 Lev=02 Prnt=02 Port=05 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=8087 ProdID=0a2b Rev= 0.01 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms Based-on-patch-by: Tedd Ho-Jeong An Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 571 +++++++++++++++++++++++++++++++++++++- 1 file changed, 568 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2901e703809d..4fac6927ee11 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -28,7 +28,7 @@ #include #include -#define VERSION "0.6" +#define VERSION "0.7" static bool disable_scofix; static bool force_scofix; @@ -50,6 +50,7 @@ static struct usb_driver btusb_driver; #define BTUSB_BCM_PATCHRAM 0x400 #define BTUSB_MARVELL 0x800 #define BTUSB_SWAVE 0x1000 +#define BTUSB_INTEL_NEW 0x2000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -261,6 +262,7 @@ static const struct usb_device_id blacklist_table[] = { /* Intel Bluetooth device */ { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, + { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW }, /* Marvell device */ { USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL }, @@ -276,6 +278,10 @@ static const struct usb_device_id blacklist_table[] = { #define BTUSB_ISOC_RUNNING 2 #define BTUSB_SUSPENDING 3 #define BTUSB_DID_ISO_RESUME 4 +#define BTUSB_BOOTLOADER 5 +#define BTUSB_DOWNLOADING 6 +#define BTUSB_BOOTING 7 +#define BTUSB_FIRMWARE_FAILED 8 struct btusb_data { struct hci_dev *hdev; @@ -1300,6 +1306,26 @@ struct intel_version { u8 fw_patch_num; } __packed; +struct intel_boot_params { + __u8 status; + __u8 otp_format; + __u8 otp_content; + __u8 otp_patch; + __le16 dev_revid; + __u8 secure_boot; + __u8 key_from_hdr; + __u8 key_type; + __u8 otp_lock; + __u8 api_lock; + __u8 debug_lock; + bdaddr_t otp_bdaddr; + __u8 min_fw_build_nn; + __u8 min_fw_build_cw; + __u8 min_fw_build_yy; + __u8 limited_cce; + __u8 unlocked_state; +} __packed; + static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev, struct intel_version *ver) { @@ -1708,6 +1734,533 @@ exit_mfg_deactivate: return 0; } +static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode) +{ + struct sk_buff *skb; + struct hci_event_hdr *hdr; + struct hci_ev_cmd_complete *evt; + + skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + hdr = (struct hci_event_hdr *)skb_put(skb, sizeof(*hdr)); + hdr->evt = HCI_EV_CMD_COMPLETE; + hdr->plen = sizeof(*evt) + 1; + + evt = (struct hci_ev_cmd_complete *)skb_put(skb, sizeof(*evt)); + evt->ncmd = 0x01; + evt->opcode = cpu_to_le16(opcode); + + *skb_put(skb, 1) = 0x00; + + bt_cb(skb)->pkt_type = HCI_EVENT_PKT; + + return hci_recv_frame(hdev, skb); +} + +static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer, + int count) +{ + /* When the device is in bootloader mode, then it can send + * events via the bulk endpoint. These events are treated the + * same way as the ones received from the interrupt endpoint. + */ + if (test_bit(BTUSB_BOOTLOADER, &data->flags)) + return btusb_recv_intr(data, buffer, count); + + return btusb_recv_bulk(data, buffer, count); +} + +static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + + if (test_bit(BTUSB_BOOTLOADER, &data->flags)) { + struct hci_event_hdr *hdr = (void *)skb->data; + + /* When the firmware loading completes the device sends + * out a vendor specific event indicating the result of + * the firmware loading. + */ + if (skb->len == 7 && hdr->evt == 0xff && hdr->plen == 0x05 && + skb->data[2] == 0x06) { + if (skb->data[3] != 0x00) + test_bit(BTUSB_FIRMWARE_FAILED, &data->flags); + + if (test_and_clear_bit(BTUSB_DOWNLOADING, &data->flags)) + wake_up_interruptible(&hdev->req_wait_q); + } + + /* When switching to the operational firmware the device + * sends a vendor specific event indicating that the bootup + * completed. + */ + if (skb->len == 9 && hdr->evt == 0xff && hdr->plen == 0x07 && + skb->data[2] == 0x02) { + if (test_and_clear_bit(BTUSB_BOOTING, &data->flags)) + wake_up_interruptible(&hdev->req_wait_q); + } + } + + return hci_recv_frame(hdev, skb); +} + +static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + struct urb *urb; + + BT_DBG("%s", hdev->name); + + if (!test_bit(HCI_RUNNING, &hdev->flags)) + return -EBUSY; + + switch (bt_cb(skb)->pkt_type) { + case HCI_COMMAND_PKT: + if (test_bit(BTUSB_BOOTLOADER, &data->flags)) { + struct hci_command_hdr *cmd = (void *)skb->data; + __u16 opcode = le16_to_cpu(cmd->opcode); + + /* When in bootloader mode and the command 0xfc09 + * is received, it needs to be send down the + * bulk endpoint. So allocate a bulk URB instead. + */ + if (opcode == 0xfc09) + urb = alloc_bulk_urb(hdev, skb); + else + urb = alloc_ctrl_urb(hdev, skb); + + /* When the 0xfc01 command is issued to boot into + * the operational firmware, it will actually not + * send a command complete event. To keep the flow + * control working inject that event here. + */ + if (opcode == 0xfc01) + inject_cmd_complete(hdev, opcode); + } else { + urb = alloc_ctrl_urb(hdev, skb); + } + if (IS_ERR(urb)) + return PTR_ERR(urb); + + hdev->stat.cmd_tx++; + return submit_or_queue_tx_urb(hdev, urb); + + case HCI_ACLDATA_PKT: + urb = alloc_bulk_urb(hdev, skb); + if (IS_ERR(urb)) + return PTR_ERR(urb); + + hdev->stat.acl_tx++; + return submit_or_queue_tx_urb(hdev, urb); + + case HCI_SCODATA_PKT: + if (hci_conn_num(hdev, SCO_LINK) < 1) + return -ENODEV; + + urb = alloc_isoc_urb(hdev, skb); + if (IS_ERR(urb)) + return PTR_ERR(urb); + + hdev->stat.sco_tx++; + return submit_tx_urb(hdev, urb); + } + + return -EILSEQ; +} + +static int btusb_intel_secure_send(struct hci_dev *hdev, u8 fragment_type, + u32 plen, const void *param) +{ + while (plen > 0) { + struct sk_buff *skb; + u8 cmd_param[253], fragment_len = (plen > 252) ? 252 : plen; + + cmd_param[0] = fragment_type; + memcpy(cmd_param + 1, param, fragment_len); + + skb = __hci_cmd_sync(hdev, 0xfc09, fragment_len + 1, + cmd_param, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + kfree_skb(skb); + + plen -= fragment_len; + param += fragment_len; + } + + return 0; +} + +static void btusb_intel_version_info(struct hci_dev *hdev, + struct intel_version *ver) +{ + const char *variant; + + switch (ver->fw_variant) { + case 0x06: + variant = "Bootloader"; + break; + case 0x23: + variant = "Firmware"; + break; + default: + return; + } + + BT_INFO("%s: %s revision %u.%u build %u week %u %u", hdev->name, + variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f, + ver->fw_build_num, ver->fw_build_ww, 2000 + ver->fw_build_yy); +} + +static int btusb_setup_intel_new(struct hci_dev *hdev) +{ + static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01, + 0x00, 0x08, 0x04, 0x00 }; + struct btusb_data *data = hci_get_drvdata(hdev); + struct sk_buff *skb; + struct intel_version *ver; + struct intel_boot_params *params; + const struct firmware *fw; + const u8 *fw_ptr; + char fwname[64]; + ktime_t calltime, delta, rettime; + unsigned long long duration; + int err; + + BT_DBG("%s", hdev->name); + + calltime = ktime_get(); + + /* Read the Intel version information to determine if the device + * is in bootloader mode or if it already has operational firmware + * loaded. + */ + skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("%s: Reading Intel version information failed (%ld)", + hdev->name, PTR_ERR(skb)); + return PTR_ERR(skb); + } + + if (skb->len != sizeof(*ver)) { + BT_ERR("%s: Intel version event size mismatch", hdev->name); + kfree_skb(skb); + return -EILSEQ; + } + + ver = (struct intel_version *)skb->data; + if (ver->status) { + BT_ERR("%s: Intel version command failure (%02x)", + hdev->name, ver->status); + err = -bt_to_errno(ver->status); + kfree_skb(skb); + return err; + } + + /* The hardware platform number has a fixed value of 0x37 and + * for now only accept this single value. + */ + if (ver->hw_platform != 0x37) { + BT_ERR("%s: Unsupported Intel hardware platform (%u)", + hdev->name, ver->hw_platform); + kfree_skb(skb); + return -EINVAL; + } + + /* At the moment only the hardware variant iBT 3.0 (LnP/SfP) is + * supported by this firmware loading method. This check has been + * put in place to ensure correct forward compatibility options + * when newer hardware variants come along. + */ + if (ver->hw_variant != 0x0b) { + BT_ERR("%s: Unsupported Intel hardware variant (%u)", + hdev->name, ver->hw_variant); + kfree_skb(skb); + return -EINVAL; + } + + btusb_intel_version_info(hdev, ver); + + /* The firmware variant determines if the device is in bootloader + * mode or is running operational firmware. The value 0x06 identifies + * the bootloader and the value 0x23 identifies the operational + * firmware. + * + * When the operational firmware is already present, then only + * the check for valid Bluetooth device address is needed. This + * determines if the device will be added as configured or + * unconfigured controller. + * + * It is not possible to use the Secure Boot Parameters in this + * case since that command is only available in bootloader mode. + */ + if (ver->fw_variant == 0x23) { + kfree_skb(skb); + clear_bit(BTUSB_BOOTLOADER, &data->flags); + btusb_check_bdaddr_intel(hdev); + return 0; + } + + /* If the device is not in bootloader mode, then the only possible + * choice is to return an error and abort the device initialization. + */ + if (ver->fw_variant != 0x06) { + BT_ERR("%s: Unsupported Intel firmware variant (%u)", + hdev->name, ver->fw_variant); + kfree_skb(skb); + return -ENODEV; + } + + kfree_skb(skb); + + /* Read the secure boot parameters to identify the operating + * details of the bootloader. + */ + skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("%s: Reading Intel boot parameters failed (%ld)", + hdev->name, PTR_ERR(skb)); + return PTR_ERR(skb); + } + + if (skb->len != sizeof(*params)) { + BT_ERR("%s: Intel boot parameters size mismatch", hdev->name); + kfree_skb(skb); + return -EILSEQ; + } + + params = (struct intel_boot_params *)skb->data; + if (params->status) { + BT_ERR("%s: Intel boot parameters command failure (%02x)", + hdev->name, params->status); + err = -bt_to_errno(params->status); + kfree_skb(skb); + return err; + } + + BT_INFO("%s: Device revision is %u", hdev->name, + le16_to_cpu(params->dev_revid)); + + BT_INFO("%s: Secure boot is %s", hdev->name, + params->secure_boot ? "enabled" : "disabled"); + + BT_INFO("%s: Minimum firmware build %u week %u %u", hdev->name, + params->min_fw_build_nn, params->min_fw_build_cw, + 2000 + params->min_fw_build_yy); + + /* It is required that every single firmware fragment is acknowledged + * with a command complete event. If the boot parameters indicate + * that this bootloader does not send them, then abort the setup. + */ + if (params->limited_cce != 0x00) { + BT_ERR("%s: Unsupported Intel firmware loading method (%u)", + hdev->name, params->limited_cce); + kfree_skb(skb); + return -EINVAL; + } + + /* If the OTP has no valid Bluetooth device address, then there will + * also be no valid address for the operational firmware. + */ + if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { + BT_INFO("%s: No device address configured", hdev->name); + set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + } + + /* With this Intel bootloader only the hardware variant and device + * revision information are used to select the right firmware. + * + * Currently this bootloader support is limited to hardware variant + * iBT 3.0 (LnP/SfP) which is identified by the value 11 (0x0b). + */ + snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.sfi", + le16_to_cpu(params->dev_revid)); + + err = request_firmware(&fw, fwname, &hdev->dev); + if (err < 0) { + BT_ERR("%s: Failed to load Intel firmware file (%d)", + hdev->name, err); + kfree_skb(skb); + return err; + } + + BT_INFO("%s: Found device firmware: %s", hdev->name, fwname); + + kfree_skb(skb); + + if (fw->size < 644) { + BT_ERR("%s: Invalid size of firmware file (%zu)", + hdev->name, fw->size); + err = -EBADF; + goto done; + } + + set_bit(BTUSB_DOWNLOADING, &data->flags); + + /* Start the firmware download transaction with the Init fragment + * represented by the 128 bytes of CSS header. + */ + err = btusb_intel_secure_send(hdev, 0x00, 128, fw->data); + if (err < 0) { + BT_ERR("%s: Failed to send firmware header (%d)", + hdev->name, err); + goto done; + } + + /* Send the 256 bytes of public key information from the firmware + * as the PKey fragment. + */ + err = btusb_intel_secure_send(hdev, 0x03, 256, fw->data + 128); + if (err < 0) { + BT_ERR("%s: Failed to send firmware public key (%d)", + hdev->name, err); + goto done; + } + + /* Send the 256 bytes of signature information from the firmware + * as the Sign fragment. + */ + err = btusb_intel_secure_send(hdev, 0x02, 256, fw->data + 388); + if (err < 0) { + BT_ERR("%s: Failed to send firmware signature (%d)", + hdev->name, err); + goto done; + } + + fw_ptr = fw->data + 644; + + while (fw_ptr - fw->data < fw->size) { + struct hci_command_hdr *cmd = (void *)fw_ptr; + u8 cmd_len; + + cmd_len = sizeof(*cmd) + cmd->plen; + + /* Send each command from the firmware data buffer as + * a single Data fragment. + */ + err = btusb_intel_secure_send(hdev, 0x01, cmd_len, fw_ptr); + if (err < 0) { + BT_ERR("%s: Failed to send firmware data (%d)", + hdev->name, err); + goto done; + } + + fw_ptr += cmd_len; + } + + /* Before switching the device into operational mode and with that + * booting the loaded firmware, wait for the bootloader notification + * that all fragments have been successfully received. + * + * When the event processing receives the notification, then this + * flag will be cleared. So just in case that happens really quickly, + * check it first before adding the wait queue. + */ + if (test_bit(BTUSB_DOWNLOADING, &data->flags)) { + DECLARE_WAITQUEUE(wait, current); + signed long timeout; + + BT_INFO("%s: Waiting for firmware download to complete", + hdev->name); + + add_wait_queue(&hdev->req_wait_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + /* The firmware loading should not take longer than 5 seconds + * and thus just timeout if that happens and fail the setup + * of this device. + */ + timeout = schedule_timeout(msecs_to_jiffies(5000)); + + remove_wait_queue(&hdev->req_wait_q, &wait); + + if (signal_pending(current)) { + BT_ERR("%s: Firmware loading interrupted", hdev->name); + err = -EINTR; + goto done; + } + + if (!timeout) { + BT_ERR("%s: Firmware loading timeout", hdev->name); + err = -ETIMEDOUT; + goto done; + } + } + + if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) { + BT_ERR("%s: Firmware loading failed", hdev->name); + err = -ENOEXEC; + goto done; + } + + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + duration = (unsigned long long) ktime_to_ns(delta) >> 10; + + BT_INFO("%s: Firmware loaded in %llu usecs", hdev->name, duration); + +done: + release_firmware(fw); + + if (err < 0) + return err; + + calltime = ktime_get(); + + set_bit(BTUSB_BOOTING, &data->flags); + + skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(reset_param), reset_param, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + kfree_skb(skb); + + /* The bootloader will not indicate when the device is ready. This + * is done by the operational firmware sending bootup notification. + */ + if (test_bit(BTUSB_BOOTING, &data->flags)) { + DECLARE_WAITQUEUE(wait, current); + signed long timeout; + + BT_INFO("%s: Waiting for device to boot", hdev->name); + + add_wait_queue(&hdev->req_wait_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + /* Booting into operational firmware should not take + * longer than 1 second. However if that happens, then + * just fail the setup since something went wrong. + */ + timeout = schedule_timeout(msecs_to_jiffies(1000)); + + remove_wait_queue(&hdev->req_wait_q, &wait); + + if (signal_pending(current)) { + BT_ERR("%s: Device boot interrupted", hdev->name); + return -EINTR; + } + + if (!timeout) { + BT_ERR("%s: Device boot timeout", hdev->name); + return -ETIMEDOUT; + } + } + + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + duration = (unsigned long long) ktime_to_ns(delta) >> 10; + + BT_INFO("%s: Device booted in %llu usecs", hdev->name, duration); + + clear_bit(BTUSB_BOOTLOADER, &data->flags); + + return 0; +} + static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr) { struct sk_buff *skb; @@ -2054,8 +2607,14 @@ static int btusb_probe(struct usb_interface *intf, init_usb_anchor(&data->isoc_anchor); spin_lock_init(&data->rxlock); - data->recv_event = hci_recv_frame; - data->recv_bulk = btusb_recv_bulk; + if (id->driver_info & BTUSB_INTEL_NEW) { + data->recv_event = btusb_recv_event_intel; + data->recv_bulk = btusb_recv_bulk_intel; + set_bit(BTUSB_BOOTLOADER, &data->flags); + } else { + data->recv_event = hci_recv_frame; + data->recv_bulk = btusb_recv_bulk; + } hdev = hci_alloc_dev(); if (!hdev) @@ -2088,6 +2647,12 @@ static int btusb_probe(struct usb_interface *intf, hdev->set_bdaddr = btusb_set_bdaddr_intel; } + if (id->driver_info & BTUSB_INTEL_NEW) { + hdev->send = btusb_send_frame_intel; + hdev->setup = btusb_setup_intel_new; + hdev->set_bdaddr = btusb_set_bdaddr_intel; + } + if (id->driver_info & BTUSB_MARVELL) hdev->set_bdaddr = btusb_set_bdaddr_marvell; From d25b78e2ed60ea33dc1008d0f50b3410b73212a0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 27 Jan 2015 12:55:52 +0200 Subject: [PATCH 13/53] Bluetooth: Enforce zero-valued hash/rand192 for LE OOB Until legacy SMP OOB pairing is implemented user space should be given a clear error when trying to use it. This patch adds a corresponding check to the Add Remote OOB Data handler function which returns "invalid parameters" if non-zero Rand192 or Hash192 parameters were given for an LE address. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 25e40e82b9a2..8417ab387d1a 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -131,6 +131,9 @@ static const u16 mgmt_events[] = { #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) +#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \ + "\x00\x00\x00\x00\x00\x00\x00\x00" + struct pending_cmd { struct list_head list; u16 opcode; @@ -3673,6 +3676,18 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, u8 status; if (bdaddr_type_is_le(cp->addr.type)) { + /* Enforce zero-valued 192-bit parameters as + * long as legacy SMP OOB isn't implemented. + */ + if (memcmp(cp->rand192, ZERO_KEY, 16) || + memcmp(cp->hash192, ZERO_KEY, 16)) { + err = cmd_complete(sk, hdev->id, + MGMT_OP_ADD_REMOTE_OOB_DATA, + MGMT_STATUS_INVALID_PARAMS, + addr, sizeof(*addr)); + goto unlock; + } + rand192 = NULL; hash192 = NULL; } else { From 6665d057fba3376351346abe7bd1ebcaafc48a34 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 27 Jan 2015 16:04:31 -0800 Subject: [PATCH 14/53] Bluetooth: Clear P-192 values for OOB when in Secure Connections Only mode When Secure Connections Only mode has been enabled and remote OOB data is requested, then only provide P-256 hash and randomizer vaulues. The fields for P-192 hash and randomizer should be set to zero. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 52 ++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e2b81adc232f..0850cad8c368 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4163,34 +4163,40 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, goto unlock; data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR); - if (data) { - if (bredr_sc_enabled(hdev)) { - struct hci_cp_remote_oob_ext_data_reply cp; - - bacpy(&cp.bdaddr, &ev->bdaddr); - memcpy(cp.hash192, data->hash192, sizeof(cp.hash192)); - memcpy(cp.rand192, data->rand192, sizeof(cp.rand192)); - memcpy(cp.hash256, data->hash256, sizeof(cp.hash256)); - memcpy(cp.rand256, data->rand256, sizeof(cp.rand256)); - - hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY, - sizeof(cp), &cp); - } else { - struct hci_cp_remote_oob_data_reply cp; - - bacpy(&cp.bdaddr, &ev->bdaddr); - memcpy(cp.hash, data->hash192, sizeof(cp.hash)); - memcpy(cp.rand, data->rand192, sizeof(cp.rand)); - - hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, - sizeof(cp), &cp); - } - } else { + if (!data) { struct hci_cp_remote_oob_data_neg_reply cp; bacpy(&cp.bdaddr, &ev->bdaddr); hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), &cp); + goto unlock; + } + + if (bredr_sc_enabled(hdev)) { + struct hci_cp_remote_oob_ext_data_reply cp; + + bacpy(&cp.bdaddr, &ev->bdaddr); + if (test_bit(HCI_SC_ONLY, &hdev->dev_flags)) { + memset(cp.hash192, 0, sizeof(cp.hash192)); + memset(cp.rand192, 0, sizeof(cp.rand192)); + } else { + memcpy(cp.hash192, data->hash192, sizeof(cp.hash192)); + memcpy(cp.rand192, data->rand192, sizeof(cp.rand192)); + } + memcpy(cp.hash256, data->hash256, sizeof(cp.hash256)); + memcpy(cp.rand256, data->rand256, sizeof(cp.rand256)); + + hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY, + sizeof(cp), &cp); + } else { + struct hci_cp_remote_oob_data_reply cp; + + bacpy(&cp.bdaddr, &ev->bdaddr); + memcpy(cp.hash, data->hash192, sizeof(cp.hash)); + memcpy(cp.rand, data->rand192, sizeof(cp.rand)); + + hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, + sizeof(cp), &cp); } unlock: From a83ed81ef5881445d96120bea2032f72884fe038 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 27 Jan 2015 16:04:32 -0800 Subject: [PATCH 15/53] Bluetooth: Use helper function to determine BR/EDR OOB data present When replying to the IO capability request for Secure Simple Pairing and Secure Connections, the OOB data present fields needs to set. Instead of making the calculation inline, split this into a separate helper function. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0850cad8c368..8ed8516b18c7 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3855,6 +3855,21 @@ static u8 hci_get_auth_req(struct hci_conn *conn) return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01); } +static u8 bredr_oob_data_present(struct hci_conn *conn) +{ + struct hci_dev *hdev = conn->hdev; + struct oob_data *data; + + data = hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR); + if (!data) + return 0x00; + + if (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) + return 0x01; + + return 0x00; +} + static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_io_capa_request *ev = (void *) skb->data; @@ -3906,12 +3921,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) conn->auth_type &= HCI_AT_NO_BONDING_MITM; cp.authentication = conn->auth_type; - - if (hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR) && - (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) - cp.oob_data = 0x01; - else - cp.oob_data = 0x00; + cp.oob_data = bredr_oob_data_present(conn); hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY, sizeof(cp), &cp); From aa5b03456500b57ab30313affa822d4cd90e2ab2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 27 Jan 2015 16:04:33 -0800 Subject: [PATCH 16/53] Bluetooth: Check for P-256 OOB values in Secure Connections Only mode If Secure Connections Only mode has been enabled, the it is important to check that OOB data for P-256 values is provided. In case it is not, then tell the remote side that no OOB data is present. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8ed8516b18c7..00c160634e7b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -36,6 +36,9 @@ #include "amp.h" #include "smp.h" +#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \ + "\x00\x00\x00\x00\x00\x00\x00\x00" + /* Handle HCI Event packets */ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) @@ -3864,6 +3867,16 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) if (!data) return 0x00; + /* When Secure Connections Only mode is enabled, then the P-256 + * values are required. If they are not available, then do not + * declare that OOB data is present. + */ + if (bredr_sc_enabled(hdev) && + test_bit(HCI_SC_ONLY, &hdev->dev_flags) && + (!memcmp(data->rand256, ZERO_KEY, 16) || + !memcmp(data->hash256, ZERO_KEY, 16))) + return 0x00; + if (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) return 0x01; From ce6bb9297c1bab350811d5003526704b9cd79c47 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Jan 2015 01:58:40 -0800 Subject: [PATCH 17/53] Bluetooth: btusb: Handle out of order firmware loading complete event When loading the Intel firmware it can happen that the firmware loading complete vendor event arrives before the command complete event for the last firmware fragment. < HCI Command: Vendor (0x3f|0x0009) plen 7 01 02 fc 03 00 00 00 > HCI Event: Vendor (0xff) plen 5 06 00 00 00 00 > HCI Event: Command Complete (0x0e) plen 4 Vendor (0x3f|0x0009) ncmd 31 Status: Success (0x00) This is mainly caused by the fact that the vendor command and its command complete event are transported over the bulk endpoints. The firmware loading complete event however is send over the interrupt endpoint. So with just bad timing one event arrives before the other. Currently the code does not account for it. There are precautions for receiving firmware loading complete event quickly, but not for receiving it before the command complete. Introduce an extra flag that tracks when the firmware sending has completed from the driver point of view and track the completion of the firmware loading procedure with a different flag. That way the wakeup can be handled properly. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4fac6927ee11..25ca93d13209 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -280,8 +280,9 @@ static const struct usb_device_id blacklist_table[] = { #define BTUSB_DID_ISO_RESUME 4 #define BTUSB_BOOTLOADER 5 #define BTUSB_DOWNLOADING 6 -#define BTUSB_BOOTING 7 +#define BTUSB_FIRMWARE_LOADED 7 #define BTUSB_FIRMWARE_FAILED 8 +#define BTUSB_BOOTING 9 struct btusb_data { struct hci_dev *hdev; @@ -1788,7 +1789,9 @@ static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) if (skb->data[3] != 0x00) test_bit(BTUSB_FIRMWARE_FAILED, &data->flags); - if (test_and_clear_bit(BTUSB_DOWNLOADING, &data->flags)) + if (test_and_clear_bit(BTUSB_DOWNLOADING, + &data->flags) && + test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) wake_up_interruptible(&hdev->req_wait_q); } @@ -2151,6 +2154,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) fw_ptr += cmd_len; } + set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); + /* Before switching the device into operational mode and with that * booting the loaded firmware, wait for the bootloader notification * that all fragments have been successfully received. From 838f66e3ab5fcaa05fbf33acf189541078352685 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 28 Jan 2015 19:55:59 +0200 Subject: [PATCH 18/53] Bluetooth: btusb: Remove redundant call to btusb_free_frags() The btusb_disconnect() callback calls hci_unregister_dev() which in turn calls btusb_close() if the HCI device is powered. The btusb_close() function in turn will call btusb_free_frags(). It's therefore unnecessary to have another call to btusb_free_frags() in the btusb_disconnect() function. Besides the redundancy the second call seems to also cause some strange stability issues which this patch then also fixes. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 25ca93d13209..70513b8d4d4a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2767,7 +2767,6 @@ static void btusb_disconnect(struct usb_interface *intf) else if (data->isoc) usb_driver_release_interface(&btusb_driver, data->isoc); - btusb_free_frags(data); hci_free_dev(hdev); } From 592002863a03bd172a19d04854c5ed415693911f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 28 Jan 2015 19:56:00 +0200 Subject: [PATCH 19/53] Bluetooth: Fix check for SSP when enabling SC There's a check in set_secure_conn() that's supposed to ensure that SSP is enabled before we try to request the controller to enable SC (since SSP is a pre-requisite for it). However, this check only makes sense for controllers actually supporting BR/EDR SC. If we have a 4.0 controller we're only interested in the LE part of SC and should therefore not be requiring SSP to be enabled. This patch adds an additional condition to check for lmp_sc_capable(hdev) before requiring SSP to be enabled. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8417ab387d1a..78939e0ed1f4 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4818,6 +4818,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, MGMT_STATUS_NOT_SUPPORTED); if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && + lmp_sc_capable(hdev) && !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, MGMT_STATUS_REJECTED); From 39c5d970d4d1302d3407e0471c55520dd5537069 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 28 Jan 2015 19:56:01 +0200 Subject: [PATCH 20/53] Bluetooth: Fix notifying discovery state upon reset When HCI_Reset is issued the discovery state is assumed to be stopped. The hci_cc_reset() handler was trying to set the state but it was doing it without using the hci_discovery_set_state() function. Because of this e.g. the mgmt Discovering event could go without being sent. This patch fixes the code to use the hci_discovery_set_state() function instead of just blindly setting the state value. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 00c160634e7b..4175470ff48e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -200,7 +200,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) /* Reset all non-persistent flags */ hdev->dev_flags &= ~HCI_PERSISTENT_MASK; - hdev->discovery.state = DISCOVERY_STOPPED; + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + hdev->inq_tx_power = HCI_TX_POWER_INVALID; hdev->adv_tx_power = HCI_TX_POWER_INVALID; From 8f502f847a67d00412382aeda0a2fa412b04e2a7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 28 Jan 2015 19:56:02 +0200 Subject: [PATCH 21/53] Bluetooth: Fix notifying discovery state when powering off The discovery state should be set to stopped when the HCI device is powered off. This patch adds the appropriate call to the hci_discovery_set_state() function from hci_dev_do_close() which is responsible for the power-off procedure. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index bb831d678868..46aa702c189d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1628,6 +1628,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) hci_dev_lock(hdev); + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { if (hdev->dev_type == HCI_BREDR) mgmt_powered(hdev, 0); From 5c912495b7a8ab6adae877979abfffba4340e06c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Jan 2015 11:53:05 -0800 Subject: [PATCH 22/53] Bluetooth: Introduce hci_dev_do_reset helper function Split the hci_dev_reset ioctl handling into using hci_dev_do_reset helper function. Similar to what has been done with hci_dev_do_open and hci_dev_do_close. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 57 ++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 46aa702c189d..d4c9152474a9 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1719,32 +1719,14 @@ done: return err; } -int hci_dev_reset(__u16 dev) +static int hci_dev_do_reset(struct hci_dev *hdev) { - struct hci_dev *hdev; - int ret = 0; + int ret; - hdev = hci_dev_get(dev); - if (!hdev) - return -ENODEV; + BT_DBG("%s %p", hdev->name, hdev); hci_req_lock(hdev); - if (!test_bit(HCI_UP, &hdev->flags)) { - ret = -ENETDOWN; - goto done; - } - - if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { - ret = -EBUSY; - goto done; - } - - if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { - ret = -EOPNOTSUPP; - goto done; - } - /* Drop queues */ skb_queue_purge(&hdev->rx_q); skb_queue_purge(&hdev->cmd_q); @@ -1767,12 +1749,41 @@ int hci_dev_reset(__u16 dev) ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); -done: hci_req_unlock(hdev); - hci_dev_put(hdev); return ret; } +int hci_dev_reset(__u16 dev) +{ + struct hci_dev *hdev; + int err; + + hdev = hci_dev_get(dev); + if (!hdev) + return -ENODEV; + + if (!test_bit(HCI_UP, &hdev->flags)) { + err = -ENETDOWN; + goto done; + } + + if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + err = -EBUSY; + goto done; + } + + if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { + err = -EOPNOTSUPP; + goto done; + } + + err = hci_dev_do_reset(hdev); + +done: + hci_dev_put(hdev); + return err; +} + int hci_dev_reset_stat(__u16 dev) { struct hci_dev *hdev; From c7741d16a57cbf97eebe53f27e8216b1ff20e20c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Jan 2015 11:09:55 -0800 Subject: [PATCH 23/53] Bluetooth: Perform a power cycle when receiving hardware error event When receiving a HCI Hardware Error event, the controller should be assumed to be non-functional until issuing a HCI Reset command. The Bluetooth hardware errors are vendor specific and so add a new hdev->hw_error callback that drivers can provide to run extra code to handle the hardware error. After completing the vendor specific error handling perform a full reset of the Bluetooth stack by closing and re-opening the transport. Based-on-patch-by: Johan Hedberg Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 3 +++ net/bluetooth/hci_core.c | 21 +++++++++++++++++++++ net/bluetooth/hci_event.c | 4 +++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 0f5e59f1e3cb..1780f1681ecf 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -232,6 +232,7 @@ struct hci_dev { __u16 conn_info_min_age; __u16 conn_info_max_age; __u8 ssp_debug_mode; + __u8 hw_error_code; __u32 clock; __u16 devid_source; @@ -293,6 +294,7 @@ struct hci_dev { struct work_struct power_on; struct delayed_work power_off; + struct work_struct error_reset; __u16 discov_timeout; struct delayed_work discov_off; @@ -369,6 +371,7 @@ struct hci_dev { int (*setup)(struct hci_dev *hdev); int (*send)(struct hci_dev *hdev, struct sk_buff *skb); void (*notify)(struct hci_dev *hdev, unsigned int evt); + void (*hw_error)(struct hci_dev *hdev, u8 code); int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr); }; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d4c9152474a9..79693a9ef4eb 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2151,6 +2151,26 @@ static void hci_power_off(struct work_struct *work) smp_unregister(hdev); } +static void hci_error_reset(struct work_struct *work) +{ + struct hci_dev *hdev = container_of(work, struct hci_dev, error_reset); + + BT_DBG("%s", hdev->name); + + if (hdev->hw_error) + hdev->hw_error(hdev, hdev->hw_error_code); + else + BT_ERR("%s hardware error 0x%2.2x", hdev->name, + hdev->hw_error_code); + + if (hci_dev_do_close(hdev)) + return; + + smp_unregister(hdev); + + hci_dev_do_open(hdev); +} + static void hci_discov_off(struct work_struct *work) { struct hci_dev *hdev; @@ -2943,6 +2963,7 @@ struct hci_dev *hci_alloc_dev(void) INIT_WORK(&hdev->cmd_work, hci_cmd_work); INIT_WORK(&hdev->tx_work, hci_tx_work); INIT_WORK(&hdev->power_on, hci_power_on); + INIT_WORK(&hdev->error_reset, hci_error_reset); INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4175470ff48e..a72a5f50728d 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3100,7 +3100,9 @@ static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_hardware_error *ev = (void *) skb->data; - BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code); + hdev->hw_error_code = ev->code; + + queue_work(hdev->req_workqueue, &hdev->error_reset); } static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) From 385a768c3be1b4235ed57d707581c74b0d0efd63 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Jan 2015 11:09:56 -0800 Subject: [PATCH 24/53] Bluetooth: btusb: Provide hardware error handler for Intel devices The Intel Bluetooth controllers can provide an additional exception info string when a hardware error event occurs. The core will now call hdev->hw_error to let the driver read out this information. This change will cause a reset of the hardware to bring it back into functional state and then read the Intel exception info string and print it along with the error information. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 70513b8d4d4a..b2753d79edcf 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2266,6 +2266,46 @@ done: return 0; } +static void btusb_hw_error_intel(struct hci_dev *hdev, u8 code) +{ + struct sk_buff *skb; + u8 type = 0x00; + + BT_ERR("%s: Hardware error 0x%2.2x", hdev->name, code); + + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("%s: Reset after hardware error failed (%ld)", + hdev->name, PTR_ERR(skb)); + return; + } + kfree_skb(skb); + + skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("%s: Retrieving Intel exception info failed (%ld)", + hdev->name, PTR_ERR(skb)); + return; + } + + if (skb->len != 13) { + BT_ERR("%s: Exception info size mismatch", hdev->name); + kfree_skb(skb); + return; + } + + if (skb->data[0] != 0x00) { + BT_ERR("%s: Exception info command failure (%02x)", + hdev->name, skb->data[0]); + kfree_skb(skb); + return; + } + + BT_ERR("%s: Exception info %s", hdev->name, (char *)(skb->data + 1)); + + kfree_skb(skb); +} + static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr) { struct sk_buff *skb; @@ -2649,12 +2689,14 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_INTEL) { hdev->setup = btusb_setup_intel; + hdev->hw_error = btusb_hw_error_intel; hdev->set_bdaddr = btusb_set_bdaddr_intel; } if (id->driver_info & BTUSB_INTEL_NEW) { hdev->send = btusb_send_frame_intel; hdev->setup = btusb_setup_intel_new; + hdev->hw_error = btusb_hw_error_intel; hdev->set_bdaddr = btusb_set_bdaddr_intel; } From 64dae967cac7e5e9a685aa79eee470b77a80acd0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Jan 2015 14:10:28 -0800 Subject: [PATCH 25/53] Bluetooth: Move smp_unregister() into hci_dev_do_close() function The smp_unregister() function needs to be called every time the controller is powered down. There are multiple entry points when this can happen. One is "hciconfig hci0 reset" which will throw a WARN_ON when LE support has been enabled. [ 78.564620] WARNING: CPU: 0 PID: 148 at net/bluetooth/smp.c:3075 smp_register+0xf1/0x170() [ 78.564622] Modules linked in: [ 78.564628] CPU: 0 PID: 148 Comm: kworker/u3:1 Not tainted 3.19.0-rc4-devel+ #404 [ 78.564629] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS [ 78.564635] Workqueue: hci0 hci_rx_work [ 78.564638] ffffffff81b4a7a2 ffff88001cb2fb38 ffffffff8161d881 0000000080000000 [ 78.564642] 0000000000000000 ffff88001cb2fb78 ffffffff8103b870 696e55206e6f6f6d [ 78.564645] ffff88001d965000 0000000000000000 0000000000000000 ffff88001d965000 [ 78.564648] Call Trace: [ 78.564655] [] dump_stack+0x4f/0x7b [ 78.564662] [] warn_slowpath_common+0x80/0xc0 [ 78.564667] [] ? add_uuid+0x1f0/0x1f0 [ 78.564671] [] warn_slowpath_null+0x15/0x20 [ 78.564674] [] smp_register+0xf1/0x170 [ 78.564680] [] ? lock_timer_base.isra.30+0x26/0x50 [ 78.564683] [] powered_complete+0xf0/0x120 [ 78.564688] [] hci_req_cmd_complete+0x82/0x260 [ 78.564692] [] hci_cmd_complete_evt+0x6cf/0x2e20 [ 78.564697] [] ? _raw_spin_unlock_irqrestore+0x13/0x30 [ 78.564701] [] ? __wake_up_sync_key+0x4f/0x60 [ 78.564705] [] hci_event_packet+0xbcb/0x2e70 [ 78.564709] [] ? skb_release_all+0x23/0x30 [ 78.564711] [] ? kfree_skb+0x29/0x40 [ 78.564715] [] hci_rx_work+0x1c8/0x3f0 [ 78.564719] [] ? get_parent_ip+0x11/0x50 [ 78.564722] [] ? preempt_count_add+0x55/0xb0 [ 78.564727] [] process_one_work+0x12f/0x360 [ 78.564731] [] worker_thread+0x6b/0x4b0 [ 78.564735] [] ? cancel_delayed_work_sync+0x10/0x10 [ 78.564738] [] kthread+0xea/0x100 [ 78.564742] [] ? __schedule+0x3e0/0x980 [ 78.564745] [] ? kthread_create_on_node+0x180/0x180 [ 78.564749] [] ret_from_fork+0x7c/0xb0 [ 78.564752] [] ? kthread_create_on_node+0x180/0x180 [ 78.564755] ---[ end trace 8b0d943af76d3736 ]--- This warning is not critical and has only been placed in the code to actually catch this exact situation. To avoid triggering it move the smp_unregister() into hci_dev_do_close() which will now also take care of remove the SMP channel. It is safe to call this function since it only remove the channel if it has been previously registered. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 79693a9ef4eb..5d4ac3fbbc08 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1640,6 +1640,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) hci_conn_hash_flush(hdev); hci_dev_unlock(hdev); + smp_unregister(hdev); + hci_notify(hdev, HCI_DEV_DOWN); if (hdev->flush) @@ -2147,8 +2149,6 @@ static void hci_power_off(struct work_struct *work) BT_DBG("%s", hdev->name); hci_dev_do_close(hdev); - - smp_unregister(hdev); } static void hci_error_reset(struct work_struct *work) @@ -2166,8 +2166,6 @@ static void hci_error_reset(struct work_struct *work) if (hci_dev_do_close(hdev)) return; - smp_unregister(hdev); - hci_dev_do_open(hdev); } @@ -3137,8 +3135,6 @@ void hci_unregister_dev(struct hci_dev *hdev) rfkill_destroy(hdev->rfkill); } - smp_unregister(hdev); - device_del(&hdev->dev); debugfs_remove_recursive(hdev->debugfs); From cb1ee89f95ce8d5294bde33447d6ccab582c1999 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Jan 2015 19:41:42 -0800 Subject: [PATCH 26/53] Bluetooth: btusb: Sort USB_DEVICE entries for Marvell by vendor id New entries to the USB blacklist/quirk device table should be sorted by USB vendor id. Fix the recent entry fro Marvell devices. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b2753d79edcf..4f5b93568ecc 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -259,14 +259,15 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC }, + /* Marvell Bluetooth devices */ + { USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL }, + { USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL }, + /* Intel Bluetooth device */ { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW }, - /* Marvell device */ - { USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL }, - { USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL }, { } /* Terminating entry */ }; From d0ac9eb72b6dceae318c15ee82ef2aaee233666d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Jan 2015 19:41:43 -0800 Subject: [PATCH 27/53] Bluetooth: btusb: Ignore unknown Intel devices with generic descriptor The Intel Bluetooth devices use the generic USB device/interface class descriptors that are assigned to Bluetooth H:2 conforming transports. T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 2.01 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 However newer chips have a bootloader stage and require firmware to be loaded before they are functional. To avoid any confusion for the users, just ignore unknown Intel Bluetooth devices. All the released Intel Bluetooth devices have an entry in the device table identifying their setup and support requirements. The advantage here is that older kernel can be booted with newer devices without causing any disturbance. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4f5b93568ecc..9d2d059a7540 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -263,11 +263,14 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL }, { USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL }, - /* Intel Bluetooth device */ + /* Intel Bluetooth devices */ { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW }, + /* Other Intel Bluetooth devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01), + .driver_info = BTUSB_IGNORE }, { } /* Terminating entry */ }; From 893ba5440a25ebe3376f0b2ee5a74e0a6423f00e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Jan 2015 20:27:34 -0800 Subject: [PATCH 28/53] Bluetooth: btusb: Add support for USB based AMP controllers The Bluetooth HCI transport specification for USB device defines on how a standard AMP controller is identified and operated. This patch adds the needed handling to hook it up to the Bluetooth stack. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9d2d059a7540..d114786490b1 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -51,11 +51,15 @@ static struct usb_driver btusb_driver; #define BTUSB_MARVELL 0x800 #define BTUSB_SWAVE 0x1000 #define BTUSB_INTEL_NEW 0x2000 +#define BTUSB_AMP 0x4000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Generic Bluetooth AMP device */ + { USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP }, + /* Apple-specific (Broadcom) devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, @@ -320,6 +324,7 @@ struct btusb_data { struct usb_endpoint_descriptor *isoc_rx_ep; __u8 cmdreq_type; + __u8 cmdreq; unsigned int sco_num; int isoc_altsetting; @@ -973,7 +978,7 @@ static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb) } dr->bRequestType = data->cmdreq_type; - dr->bRequest = 0; + dr->bRequest = data->cmdreq; dr->wIndex = 0; dr->wValue = 0; dr->wLength = __cpu_to_le16(skb->len); @@ -2640,7 +2645,13 @@ static int btusb_probe(struct usb_interface *intf, if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) return -ENODEV; - data->cmdreq_type = USB_TYPE_CLASS; + if (id->driver_info & BTUSB_AMP) { + data->cmdreq_type = USB_TYPE_CLASS | 0x01; + data->cmdreq = 0x2b; + } else { + data->cmdreq_type = USB_TYPE_CLASS; + data->cmdreq = 0x00; + } data->udev = interface_to_usbdev(intf); data->intf = intf; @@ -2672,6 +2683,11 @@ static int btusb_probe(struct usb_interface *intf, hdev->bus = HCI_USB; hci_set_drvdata(hdev, data); + if (id->driver_info & BTUSB_AMP) + hdev->dev_type = HCI_AMP; + else + hdev->dev_type = HCI_BREDR; + data->hdev = hdev; SET_HCIDEV_DEV(hdev, &intf->dev); @@ -2718,8 +2734,13 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_ATH3012) hdev->set_bdaddr = btusb_set_bdaddr_ath3012; - /* Interface numbers are hardcoded in the specification */ - data->isoc = usb_ifnum_to_if(data->udev, 1); + if (id->driver_info & BTUSB_AMP) { + /* AMP controllers do not support SCO packets */ + data->isoc = NULL; + } else { + /* Interface numbers are hardcoded in the specification */ + data->isoc = usb_ifnum_to_if(data->udev, 1); + } if (!reset) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); From ac363cf9eb0b0378165ebfcf41ffbf78295a817e Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 29 Jan 2015 16:36:59 +0100 Subject: [PATCH 29/53] Bluetooth: Fix sending Read Remote Extended Features command This command should only be used if remote device reports that it supports extended features. Otherwise command will fail and connection will be dropped. Some devices support SSP but don't support extended features so current check for SSP support is not enought. Instead of checking for SSP support just check if both ends support Extended Feature. < HCI Command: Create Connection (0x01|0x0005) plen 13 Address: D0:9C:30:00:19:6F (Foster Electric Company, Limited) Packet type: 0xcc18 DM1 may be used DH1 may be used DM3 may be used DH3 may be used DM5 may be used DH5 may be used Page scan repetition mode: R1 (0x01) Page scan mode: Mandatory (0x00) Clock offset: 0x94c8 Role switch: Allow slave (0x01) > HCI Event: Command Status (0x0f) plen 4 Create Connection (0x01|0x0005) ncmd 1 Status: Success (0x00) > HCI Event: Connect Complete (0x03) plen 11 Status: Success (0x00) Handle: 5 Address: D0:9C:30:00:19:6F (Foster Electric Company, Limited) Link type: ACL (0x01) Encryption: Disabled (0x00) < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 Handle: 5 > HCI Event: Command Status (0x0f) plen 4 Read Remote Supported Features (0x01|0x001b) ncmd 1 Status: Success (0x00) > HCI Event: Page Scan Repetition Mode Change (0x20) plen 7 Address: D0:9C:30:00:19:6F (Foster Electric Company, Limited) Page scan repetition mode: R1 (0x01) > HCI Event: Read Remote Supported Features (0x0b) plen 11 Status: Success (0x00) Handle: 5 Features: 0xff 0xff 0x8f 0xfe 0xdb 0xff 0x5b 0x07 3 slot packets 5 slot packets Encryption Slot offset Timing accuracy Role switch Hold mode Sniff mode Park state Power control requests Channel quality driven data rate (CQDDR) SCO link HV2 packets HV3 packets u-law log synchronous data A-law log synchronous data CVSD synchronous data Paging parameter negotiation Power control Transparent synchronous data Broadcast Encryption Enhanced Data Rate ACL 2 Mbps mode Enhanced Data Rate ACL 3 Mbps mode Enhanced inquiry scan Interlaced inquiry scan Interlaced page scan RSSI with inquiry results Extended SCO link (EV3 packets) EV4 packets EV5 packets AFH capable slave AFH classification slave LE Supported (Controller) 3-slot Enhanced Data Rate ACL packets 5-slot Enhanced Data Rate ACL packets Sniff subrating Pause encryption AFH capable master AFH classification master Enhanced Data Rate eSCO 2 Mbps mode Enhanced Data Rate eSCO 3 Mbps mode 3-slot Enhanced Data Rate eSCO packets Extended Inquiry Response Simultaneous LE and BR/EDR (Controller) Secure Simple Pairing Encapsulated PDU Non-flushable Packet Boundary Flag Link Supervision Timeout Changed Event Inquiry TX Power Level Enhanced Power Control < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 Handle: 5 Page: 1 > HCI Event: Command Status (0x0f) plen 4 Read Remote Extended Features (0x01|0x001c) ncmd 1 Status: Command Disallowed (0x0c) < HCI Command: Read Clock Offset (0x01|0x001f) plen 2 Handle: 5 > HCI Event: Command Status (0x0f) plen 4 Read Clock Offset (0x01|0x001f) ncmd 1 Status: Success (0x00) < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 5 Reason: Remote User Terminated Connection (0x13) Signed-off-by: Szymon Janc Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a72a5f50728d..055625b7368f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2671,7 +2671,8 @@ static void hci_remote_features_evt(struct hci_dev *hdev, if (conn->state != BT_CONFIG) goto unlock; - if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { + if (!ev->status && lmp_ext_feat_capable(hdev) && + lmp_ext_feat_capable(conn)) { struct hci_cp_read_remote_ext_features cp; cp.handle = ev->handle; cp.page = 0x01; From c561a5753dd631920c4459a067d22679b3d110d6 Mon Sep 17 00:00:00 2001 From: Adam Lee Date: Wed, 28 Jan 2015 15:30:27 -0500 Subject: [PATCH 30/53] Bluetooth: ath3k: workaround the compatibility issue with xHCI controller BugLink: https://bugs.launchpad.net/bugs/1400215 ath3k devices fail to load firmwares on xHCI buses, but work well on EHCI, this might be a compatibility issue between xHCI and ath3k chips. As my testing result, those chips will work on xHCI buses again with this patch. This workaround is from Qualcomm, they also did some workarounds in Windows driver. Signed-off-by: Adam Lee Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 13a64d0c69e2..de4c8499cbac 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -176,6 +176,8 @@ static const struct usb_device_id ath3k_blist_tbl[] = { #define USB_REQ_DFU_DNLOAD 1 #define BULK_SIZE 4096 #define FW_HDR_SIZE 20 +#define TIMEGAP_USEC_MIN 50 +#define TIMEGAP_USEC_MAX 100 static int ath3k_load_firmware(struct usb_device *udev, const struct firmware *firmware) @@ -207,6 +209,9 @@ static int ath3k_load_firmware(struct usb_device *udev, pipe = usb_sndbulkpipe(udev, 0x02); while (count) { + /* workaround the compatibility issue with xHCI controller*/ + usleep_range(TIMEGAP_USEC_MIN, TIMEGAP_USEC_MAX); + size = min_t(uint, count, BULK_SIZE); memcpy(send_buf, firmware->data + sent, size); @@ -304,6 +309,9 @@ static int ath3k_load_fwfile(struct usb_device *udev, pipe = usb_sndbulkpipe(udev, 0x02); while (count) { + /* workaround the compatibility issue with xHCI controller*/ + usleep_range(TIMEGAP_USEC_MIN, TIMEGAP_USEC_MAX); + size = min_t(uint, count, BULK_SIZE); memcpy(send_buf, firmware->data + sent, size); From 79f0c87d9f852940f285dff636a154971027b46e Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Thu, 29 Jan 2015 10:38:34 -0800 Subject: [PATCH 31/53] Bluetooth: Set HCI_QUIRK_STRICT_DUPLICATE_FILTER for BTUSB_ATH3012 The Bluetooth controllers from Atheros use a strict scanning filter policy that filters based on Bluetooth device addresses and not on RSSI. So tell the core about this. Signed-off-by: Jakub Pawlowski Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d114786490b1..3aa4b3c776b2 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2731,8 +2731,10 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_INTEL_BOOT) set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); - if (id->driver_info & BTUSB_ATH3012) + if (id->driver_info & BTUSB_ATH3012) { hdev->set_bdaddr = btusb_set_bdaddr_ath3012; + set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); + } if (id->driver_info & BTUSB_AMP) { /* AMP controllers do not support SCO packets */ From 74d9daafa5e0b4f9183540b41b337d42662f537b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 29 Jan 2015 13:14:00 -0800 Subject: [PATCH 32/53] Bluetooth: btusb: Limit hardware error handling to Intel Snowfield Peak In general all Intel Bluetooth devices support retrieving of additional exception information. However for older generations including Wilkens Peak and Stone Peak it is not as simple. So for now only enable the Intel specific error handling for Snowfield Peak and later devices. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 3aa4b3c776b2..86f3d92de22a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2709,7 +2709,6 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_INTEL) { hdev->setup = btusb_setup_intel; - hdev->hw_error = btusb_hw_error_intel; hdev->set_bdaddr = btusb_set_bdaddr_intel; } From a087a98e0767cf6c4f2480e6de5441497c9ba5b7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 30 Jan 2015 10:58:54 +0200 Subject: [PATCH 33/53] Bluetooth: btusb: Fix race when waiting for BTUSB_DOWNLOADING The test for BTUSB_DOWNLOADING must be after adding to the wait queue and setting the TASK_INTERRUPTIBLE state. Otherwise the flag may get cleared after we test for it and we end up getting a timeout since schedule_timeout() waits for the full duration. This patch uses a wait_on_bit_timeout() + wake_up_bit(). To perform the task both race-free as well as in a much simpler way. Since there's no global wait_on_bit_timeout() helper yet (even though all the building blocks for it are in place) this patch creates a temporary local btusb copy of it until the global one has made it to upstream trees. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 67 ++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 86f3d92de22a..98341a463f30 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -334,6 +334,16 @@ struct btusb_data { int (*recv_bulk)(struct btusb_data *data, void *buffer, int count); }; +static int btusb_wait_on_bit_timeout(void *word, int bit, unsigned long timeout, + unsigned mode) +{ + might_sleep(); + if (!test_bit(bit, word)) + return 0; + return out_of_line_wait_on_bit_timeout(word, bit, bit_wait_timeout, + mode, timeout); +} + static inline void btusb_free_frags(struct btusb_data *data) { unsigned long flags; @@ -1800,8 +1810,10 @@ static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) if (test_and_clear_bit(BTUSB_DOWNLOADING, &data->flags) && - test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) - wake_up_interruptible(&hdev->req_wait_q); + test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) { + smp_mb__after_atomic(); + wake_up_bit(&data->flags, BTUSB_DOWNLOADING); + } } /* When switching to the operational firmware the device @@ -2165,43 +2177,32 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); + BT_INFO("%s: Waiting for firmware download to complete", hdev->name); + /* Before switching the device into operational mode and with that * booting the loaded firmware, wait for the bootloader notification * that all fragments have been successfully received. * - * When the event processing receives the notification, then this - * flag will be cleared. So just in case that happens really quickly, - * check it first before adding the wait queue. + * When the event processing receives the notification, then the + * BTUSB_DOWNLOADING flag will be cleared. + * + * The firmware loading should not take longer than 5 seconds + * and thus just timeout if that happens and fail the setup + * of this device. */ - if (test_bit(BTUSB_DOWNLOADING, &data->flags)) { - DECLARE_WAITQUEUE(wait, current); - signed long timeout; + err = btusb_wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING, + msecs_to_jiffies(5000), + TASK_INTERRUPTIBLE); + if (err == 1) { + BT_ERR("%s: Firmware loading interrupted", hdev->name); + err = -EINTR; + goto done; + } - BT_INFO("%s: Waiting for firmware download to complete", - hdev->name); - - add_wait_queue(&hdev->req_wait_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - /* The firmware loading should not take longer than 5 seconds - * and thus just timeout if that happens and fail the setup - * of this device. - */ - timeout = schedule_timeout(msecs_to_jiffies(5000)); - - remove_wait_queue(&hdev->req_wait_q, &wait); - - if (signal_pending(current)) { - BT_ERR("%s: Firmware loading interrupted", hdev->name); - err = -EINTR; - goto done; - } - - if (!timeout) { - BT_ERR("%s: Firmware loading timeout", hdev->name); - err = -ETIMEDOUT; - goto done; - } + if (err) { + BT_ERR("%s: Firmware loading timeout", hdev->name); + err = -ETIMEDOUT; + goto done; } if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) { From fad7097228496c2ce0c6bef2fec87f8b74d5f6dd Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 30 Jan 2015 10:58:55 +0200 Subject: [PATCH 34/53] Bluetooth: btusb: Use wait_on_bit_timeout() for BTUSB_BOOTING The wait_on_bit_timeout() is a simpler and race-free way of waiting for a bit to be cleared than the current code in btusb.c. This patch updates the code to use the helper function (its btusb copy - to be later updated to use a global one). Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 44 +++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 98341a463f30..a3a47c50f6bc 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1822,8 +1822,10 @@ static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) */ if (skb->len == 9 && hdr->evt == 0xff && hdr->plen == 0x07 && skb->data[2] == 0x02) { - if (test_and_clear_bit(BTUSB_BOOTING, &data->flags)) - wake_up_interruptible(&hdev->req_wait_q); + if (test_and_clear_bit(BTUSB_BOOTING, &data->flags)) { + smp_mb__after_atomic(); + wake_up_bit(&data->flags, BTUSB_BOOTING); + } } } @@ -2236,33 +2238,25 @@ done: /* The bootloader will not indicate when the device is ready. This * is done by the operational firmware sending bootup notification. + * + * Booting into operational firmware should not take longer than + * 1 second. However if that happens, then just fail the setup + * since something went wrong. */ - if (test_bit(BTUSB_BOOTING, &data->flags)) { - DECLARE_WAITQUEUE(wait, current); - signed long timeout; + BT_INFO("%s: Waiting for device to boot", hdev->name); - BT_INFO("%s: Waiting for device to boot", hdev->name); + err = btusb_wait_on_bit_timeout(&data->flags, BTUSB_BOOTING, + msecs_to_jiffies(1000), + TASK_INTERRUPTIBLE); - add_wait_queue(&hdev->req_wait_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); + if (err == 1) { + BT_ERR("%s: Device boot interrupted", hdev->name); + return -EINTR; + } - /* Booting into operational firmware should not take - * longer than 1 second. However if that happens, then - * just fail the setup since something went wrong. - */ - timeout = schedule_timeout(msecs_to_jiffies(1000)); - - remove_wait_queue(&hdev->req_wait_q, &wait); - - if (signal_pending(current)) { - BT_ERR("%s: Device boot interrupted", hdev->name); - return -EINTR; - } - - if (!timeout) { - BT_ERR("%s: Device boot timeout", hdev->name); - return -ETIMEDOUT; - } + if (err) { + BT_ERR("%s: Device boot timeout", hdev->name); + return -ETIMEDOUT; } rettime = ktime_get(); From c33fb9b4ef6c8e2472405606f3f9850415980c96 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Fri, 30 Jan 2015 18:55:58 -0800 Subject: [PATCH 35/53] Bluetooth: Set HCI_QUIRK_STRICT_DUPLICATE_FILTER for BTUSB_INTEL The Bluetooth controllers from Intel use a strict scanning filter policy that filters based on Bluetooth device addresses and not on RSSI. So tell the core about this. Signed-off-by: Jakub Pawlowski Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a3a47c50f6bc..d084856cc350 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2705,6 +2705,7 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_INTEL) { hdev->setup = btusb_setup_intel; hdev->set_bdaddr = btusb_set_bdaddr_intel; + set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); } if (id->driver_info & BTUSB_INTEL_NEW) { From f7697b1602d13ef80779caf23d13fa1511193144 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 30 Jan 2015 23:20:55 -0800 Subject: [PATCH 36/53] Bluetooth: Store OOB data present value for each set of remote OOB data Instead of doing complex calculation every time the OOB data is used, just calculate the OOB data present value and store it with the OOB data raw values. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_core.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 1780f1681ecf..a37e10f4e2b3 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -145,6 +145,7 @@ struct oob_data { struct list_head list; bdaddr_t bdaddr; u8 bdaddr_type; + u8 present; u8 hash192[16]; u8 rand192[16]; u8 hash256[16]; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5d4ac3fbbc08..f045c062f8f0 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2581,9 +2581,15 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, if (hash192 && rand192) { memcpy(data->hash192, hash192, sizeof(data->hash192)); memcpy(data->rand192, rand192, sizeof(data->rand192)); + if (hash256 && rand256) + data->present = 0x03; } else { memset(data->hash192, 0, sizeof(data->hash192)); memset(data->rand192, 0, sizeof(data->rand192)); + if (hash256 && rand256) + data->present = 0x02; + else + data->present = 0x00; } if (hash256 && rand256) { @@ -2592,6 +2598,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, } else { memset(data->hash256, 0, sizeof(data->hash256)); memset(data->rand256, 0, sizeof(data->rand256)); + if (hash192 && rand192) + data->present = 0x01; } BT_DBG("%s for %pMR", hdev->name, bdaddr); From 659c7fb08463b3dcf6aebb4daa0c5463289ccb97 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 30 Jan 2015 23:20:56 -0800 Subject: [PATCH 37/53] Bluetooth: Fix OOB data present value for BR/EDR Secure Connections When BR/EDR Secure Connections has been enabled, the OOB data present value can take 2 additional values. The host has to clearly provide details about if P-192 OOB data, P-256 OOB data or a combination of P-192 and P-256 OOB data is present. In case BR/EDR Secure Connections is not enabled or not supported, then check that P-192 OOB data is actually present and return the correct value based on that. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 055625b7368f..af181f455f6f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3881,8 +3881,25 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) !memcmp(data->hash256, ZERO_KEY, 16))) return 0x00; - if (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) + if (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) { + /* When Secure Connections has been enabled, then just + * return the present value stored with the OOB data. It + * will contain the right information about which data + * is present. + */ + if (bredr_sc_enabled(hdev)) + return data->present; + + /* When Secure Connections is not enabled or actually + * not supported by the hardware, then check that if + * P-192 data values are present. + */ + if (!memcmp(data->rand192, ZERO_KEY, 16) || + !memcmp(data->hash192, ZERO_KEY, 16)) + return 0x00; + return 0x01; + } return 0x00; } From 4775a4ea14d3e15645336e4b0f1355e526c57956 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 31 Jan 2015 00:15:52 -0800 Subject: [PATCH 38/53] Bluetooth: Fix OOB data present value for SMP pairing Before setting the OOB data present flag with SMP pairing, check the newly introduced present tracking that actual OOB data values have been provided. The existence of remote OOB data structure does not actually mean that the correct data values are available. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 37d9180bfe1c..c09a821f381d 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -620,7 +620,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, oob_data = hci_find_remote_oob_data(hdev, &hcon->dst, bdaddr_type); - if (oob_data) { + if (oob_data && oob_data->present) { set_bit(SMP_FLAG_OOB, &smp->flags); oob_flag = SMP_OOB_PRESENT; memcpy(smp->rr, oob_data->rand256, 16); From 41bcfd50d52c83d43fe75fba7938a592dcb6589b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 31 Jan 2015 00:37:02 -0800 Subject: [PATCH 39/53] Bluetooth: Allow remote OOB data to only provide P-192 or P-256 values In case the remote only provided P-192 or P-256 data for OOB pairing, then make sure that the data value pointers are correctly set. That way the core can provide correct information when remote OOB data present information have to be communicated. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 78939e0ed1f4..ba3b4a5820b1 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3672,7 +3672,7 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, status, &cp->addr, sizeof(cp->addr)); } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) { struct mgmt_cp_add_remote_oob_ext_data *cp = data; - u8 *rand192, *hash192; + u8 *rand192, *hash192, *rand256, *hash256; u8 status; if (bdaddr_type_is_le(cp->addr.type)) { @@ -3691,13 +3691,34 @@ static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, rand192 = NULL; hash192 = NULL; } else { - rand192 = cp->rand192; - hash192 = cp->hash192; + /* In case one of the P-192 values is set to zero, + * then just disable OOB data for P-192. + */ + if (!memcmp(cp->rand192, ZERO_KEY, 16) || + !memcmp(cp->hash192, ZERO_KEY, 16)) { + rand192 = NULL; + hash192 = NULL; + } else { + rand192 = cp->rand192; + hash192 = cp->hash192; + } + } + + /* In case one of the P-256 values is set to zero, then just + * disable OOB data for P-256. + */ + if (!memcmp(cp->rand256, ZERO_KEY, 16) || + !memcmp(cp->hash256, ZERO_KEY, 16)) { + rand256 = NULL; + hash256 = NULL; + } else { + rand256 = cp->rand256; + hash256 = cp->hash256; } err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type, hash192, rand192, - cp->hash256, cp->rand256); + hash256, rand256); if (err < 0) status = MGMT_STATUS_FAILED; else From 6e07231a80de33a3721c971e560316d04db16de8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 31 Jan 2015 15:07:51 -0800 Subject: [PATCH 40/53] Bluetooth: Expose Secure Simple Pairing debug mode setting in debugfs The value of the ssp_debug_mode should be accessible via debugfs to be able to determine if a BR/EDR controller generates debugs keys or not. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_debugfs.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index ead89a5ad9ce..51a424cfa94a 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c @@ -354,6 +354,24 @@ static int voice_setting_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get, NULL, "0x%4.4llx\n"); +static ssize_t ssp_debug_mode_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct hci_dev *hdev = file->private_data; + char buf[3]; + + buf[0] = hdev->ssp_debug_mode ? 'Y': 'N'; + buf[1] = '\n'; + buf[2] = '\0'; + return simple_read_from_buffer(user_buf, count, ppos, buf, 2); +} + +static const struct file_operations ssp_debug_mode_fops = { + .open = simple_open, + .read = ssp_debug_mode_read, + .llseek = default_llseek, +}; + static int auto_accept_delay_set(void *data, u64 val) { struct hci_dev *hdev = data; @@ -474,9 +492,12 @@ void hci_debugfs_create_bredr(struct hci_dev *hdev) debugfs_create_file("voice_setting", 0444, hdev->debugfs, hdev, &voice_setting_fops); - if (lmp_ssp_capable(hdev)) + if (lmp_ssp_capable(hdev)) { + debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs, + hdev, &ssp_debug_mode_fops); debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, hdev, &auto_accept_delay_fops); + } if (lmp_sniff_capable(hdev)) { debugfs_create_file("idle_timeout", 0644, hdev->debugfs, From c50b33c80e6d6fe833aa42ff6ad9156b5d5e92b2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 31 Jan 2015 15:07:52 -0800 Subject: [PATCH 41/53] Bluetooth: Track changes from HCI Write Simple Pairing Debug Mode command When the HCI Write Simple Pairing Debug Mode command has been issued, the result needs to be tracked and stored. The hdev->ssp_debug_mode variable is already present, but was never updated when the mode in the controller was actually changed. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index af181f455f6f..2f2abd986997 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1489,6 +1489,21 @@ unlock: hci_dev_unlock(hdev); } +static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb) +{ + u8 status = *((u8 *) skb->data); + u8 *mode; + + BT_DBG("%s status 0x%2.2x", hdev->name, status); + + if (status) + return; + + mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE); + if (mode) + hdev->ssp_debug_mode = *mode; +} + static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) { BT_DBG("%s status 0x%2.2x", hdev->name, status); @@ -2983,6 +2998,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cc_read_tx_power(hdev, skb); break; + case HCI_OP_WRITE_SSP_DEBUG_MODE: + hci_cc_write_ssp_debug_mode(hdev, skb); + break; + default: BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); break; From 0886aea6acd27006888c36bad1fa5f80dac1e171 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 31 Jan 2015 15:12:06 -0800 Subject: [PATCH 42/53] Bluetooth: Expose debug keys usage setting via debugfs To allow easier debugging when debug keys are generated, provide debugfs entry for checking the setting of debug keys usage. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_debugfs.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index 51a424cfa94a..2272384755d5 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c @@ -212,6 +212,24 @@ static int conn_info_max_age_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(conn_info_max_age_fops, conn_info_max_age_get, conn_info_max_age_set, "%llu\n"); +static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct hci_dev *hdev = file->private_data; + char buf[3]; + + buf[0] = test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags) ? 'Y': 'N'; + buf[1] = '\n'; + buf[2] = '\0'; + return simple_read_from_buffer(user_buf, count, ppos, buf, 2); +} + +static const struct file_operations use_debug_keys_fops = { + .open = simple_open, + .read = use_debug_keys_read, + .llseek = default_llseek, +}; + static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -249,6 +267,10 @@ void hci_debugfs_create_common(struct hci_dev *hdev) debugfs_create_file("conn_info_max_age", 0644, hdev->debugfs, hdev, &conn_info_max_age_fops); + if (lmp_ssp_capable(hdev) || lmp_le_capable(hdev)) + debugfs_create_file("use_debug_keys", 0444, hdev->debugfs, + hdev, &use_debug_keys_fops); + if (lmp_sc_capable(hdev) || lmp_le_capable(hdev)) debugfs_create_file("sc_only_mode", 0444, hdev->debugfs, hdev, &sc_only_mode_fops); From 5789f37cbc560aff45ff4d00673705eac92d3b4d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 31 Jan 2015 19:54:39 -0800 Subject: [PATCH 43/53] Bluetooth: Expose hardware error code as debugfs entry When the Hardware Error event is send by the controller, the Bluetooth core stores the error code. Expose it via debugfs so it can be retrieved later on. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_debugfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index 2272384755d5..5353f6ec8d68 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c @@ -256,6 +256,9 @@ void hci_debugfs_create_common(struct hci_dev *hdev) &hdev->manufacturer); debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver); debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); + debugfs_create_u8("hardware_error", 0444, hdev->debugfs, + &hdev->hw_error_code); + debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, &device_list_fops); debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, From 6858bcd073c9ff36f5d341dc6da011a53954fa9a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 31 Jan 2015 21:01:07 -0800 Subject: [PATCH 44/53] Bluetooth: Expose remote OOB information as debugfs entry For debugging purposes it is good to know which OOB data is actually currently loaded for each controller. So expose that list via debugfs. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_debugfs.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index 5353f6ec8d68..65261e5d4b84 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c @@ -156,6 +156,35 @@ static const struct file_operations uuids_fops = { .release = single_release, }; +static int remote_oob_show(struct seq_file *f, void *ptr) +{ + struct hci_dev *hdev = f->private; + struct oob_data *data; + + hci_dev_lock(hdev); + list_for_each_entry(data, &hdev->remote_oob_data, list) { + seq_printf(f, "%pMR (type %u) %u %*phN %*phN %*phN %*phN\n", + &data->bdaddr, data->bdaddr_type, data->present, + 16, data->hash192, 16, data->rand192, + 16, data->hash256, 19, data->rand256); + } + hci_dev_unlock(hdev); + + return 0; +} + +static int remote_oob_open(struct inode *inode, struct file *file) +{ + return single_open(file, remote_oob_show, inode->i_private); +} + +static const struct file_operations remote_oob_fops = { + .open = remote_oob_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int conn_info_min_age_set(void *data, u64 val) { struct hci_dev *hdev = data; @@ -264,6 +293,8 @@ void hci_debugfs_create_common(struct hci_dev *hdev) debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, &blacklist_fops); debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); + debugfs_create_file("remote_oob", 0400, hdev->debugfs, hdev, + &remote_oob_fops); debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev, &conn_info_min_age_fops); From bf21d7931a5d33ef79b805074e3d23d3009bff98 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 31 Jan 2015 13:20:27 -0800 Subject: [PATCH 45/53] Bluetooth: Fix OOB data present for BR/EDR Secure Connections Only mode When using Secure Connections Only mode, then only P-256 OOB data is valid and should be provided. In case userspace provides P-192 and P-256 OOB data, then the P-192 values will be set to zero. However the present value of the IO capability exchange still mentioned that both values would be available. Fix this by telling the controller clearly that only the P-256 OOB data is present. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2f2abd986997..a3fb094822b6 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3890,24 +3890,28 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) if (!data) return 0x00; - /* When Secure Connections Only mode is enabled, then the P-256 - * values are required. If they are not available, then do not - * declare that OOB data is present. - */ - if (bredr_sc_enabled(hdev) && - test_bit(HCI_SC_ONLY, &hdev->dev_flags) && - (!memcmp(data->rand256, ZERO_KEY, 16) || - !memcmp(data->hash256, ZERO_KEY, 16))) - return 0x00; - if (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)) { - /* When Secure Connections has been enabled, then just - * return the present value stored with the OOB data. It - * will contain the right information about which data - * is present. - */ - if (bredr_sc_enabled(hdev)) - return data->present; + if (bredr_sc_enabled(hdev)) { + /* When Secure Connections is enabled, then just + * return the present value stored with the OOB + * data. The stored value contains the right present + * information. However it can only be trusted when + * not in Secure Connection Only mode. + */ + if (!test_bit(HCI_SC_ONLY, &hdev->dev_flags)) + return data->present; + + /* When Secure Connections Only mode is enabled, then + * the P-256 values are required. If they are not + * available, then do not declare that OOB data is + * present. + */ + if (!memcmp(data->rand256, ZERO_KEY, 16) || + !memcmp(data->hash256, ZERO_KEY, 16)) + return 0x00; + + return 0x02; + } /* When Secure Connections is not enabled or actually * not supported by the hardware, then check that if From 908edc5461565597bfc083c68088b780888e55b0 Mon Sep 17 00:00:00 2001 From: Mohammad Jamal Date: Fri, 23 Jan 2015 19:28:29 +0530 Subject: [PATCH 46/53] ieee802154: cc2520: Replace shift operations by BIT macro This patch replaces the shifting operations by BIT macro Signed-off-by: Mohammad Jamal Acked-by: Varka Bhadram Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/cc2520.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index a43c8acb7268..b38656732ff7 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c @@ -44,9 +44,9 @@ #define CC2520_FREG_MASK 0x3F /* status byte values */ -#define CC2520_STATUS_XOSC32M_STABLE (1 << 7) -#define CC2520_STATUS_RSSI_VALID (1 << 6) -#define CC2520_STATUS_TX_UNDERFLOW (1 << 3) +#define CC2520_STATUS_XOSC32M_STABLE BIT(7) +#define CC2520_STATUS_RSSI_VALID BIT(6) +#define CC2520_STATUS_TX_UNDERFLOW BIT(3) /* IEEE-802.15.4 defined constants (2.4 GHz logical channels) */ #define CC2520_MINCHANNEL 11 From 3251ca334bcc379b4685bf6850bf38db365cbe6f Mon Sep 17 00:00:00 2001 From: Mohammad Jamal Date: Fri, 23 Jan 2015 19:25:27 +0530 Subject: [PATCH 47/53] ieee802154: cc2520: Fix space before , coding style issue This patch removes the warnings (space before , ) shown by checkpatch.pl Signed-off-by: Mohammad Jamal Acked-by: Varka Bhadram Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/cc2520.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index b38656732ff7..181b349b060e 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c @@ -549,14 +549,14 @@ cc2520_ed(struct ieee802154_hw *hw, u8 *level) u8 rssi; int ret; - ret = cc2520_read_register(priv , CC2520_RSSISTAT, &status); + ret = cc2520_read_register(priv, CC2520_RSSISTAT, &status); if (ret) return ret; if (status != RSSI_VALID) return -EINVAL; - ret = cc2520_read_register(priv , CC2520_RSSI, &rssi); + ret = cc2520_read_register(priv, CC2520_RSSI, &rssi); if (ret) return ret; From 2d28cfe7aada495f87bb439151e9bcc86998fb6d Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Sun, 1 Feb 2015 23:07:54 -0800 Subject: [PATCH 48/53] Bluetooth: Add le_scan_restart work for LE scan restarting Currently there is no way to restart le scan, and it's needed in service scan method. The way it work: it disable, and then enable le scan on controller. During the restart, we must remember when the scan was started, and it's duration, to later re-schedule the le_scan_disable work, that was stopped during the stop scan phase. Signed-off-by: Jakub Pawlowski Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 5 +++ net/bluetooth/hci_core.c | 74 ++++++++++++++++++++++++++++++++ net/bluetooth/mgmt.c | 19 +++++++- 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index a37e10f4e2b3..d3a232be9d9b 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -79,6 +79,8 @@ struct discovery_state { s8 rssi; u16 uuid_count; u8 (*uuids)[16]; + unsigned long scan_start; + unsigned long scan_duration; }; struct hci_conn_hash { @@ -354,6 +356,7 @@ struct hci_dev { unsigned long dev_flags; struct delayed_work le_scan_disable; + struct delayed_work le_scan_restart; __s8 adv_tx_power; __u8 adv_data[HCI_MAX_AD_LENGTH]; @@ -531,6 +534,8 @@ static inline void hci_discovery_filter_clear(struct hci_dev *hdev) hdev->discovery.uuid_count = 0; kfree(hdev->discovery.uuids); hdev->discovery.uuids = NULL; + hdev->discovery.scan_start = 0; + hdev->discovery.scan_duration = 0; } bool hci_discovery_active(struct hci_dev *hdev); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f045c062f8f0..3322d3f4c85a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1617,6 +1617,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) cancel_delayed_work(&hdev->service_cache); cancel_delayed_work_sync(&hdev->le_scan_disable); + cancel_delayed_work_sync(&hdev->le_scan_restart); if (test_bit(HCI_MGMT, &hdev->dev_flags)) cancel_delayed_work_sync(&hdev->rpa_expired); @@ -2830,6 +2831,8 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status, return; } + hdev->discovery.scan_start = 0; + switch (hdev->discovery.type) { case DISCOV_TYPE_LE: hci_dev_lock(hdev); @@ -2869,6 +2872,8 @@ static void le_scan_disable_work(struct work_struct *work) BT_DBG("%s", hdev->name); + cancel_delayed_work_sync(&hdev->le_scan_restart); + hci_req_init(&req, hdev); hci_req_add_le_scan_disable(&req); @@ -2878,6 +2883,74 @@ static void le_scan_disable_work(struct work_struct *work) BT_ERR("Disable LE scanning request failed: err %d", err); } +static void le_scan_restart_work_complete(struct hci_dev *hdev, u8 status, + u16 opcode) +{ + unsigned long timeout, duration, scan_start, now; + + BT_DBG("%s", hdev->name); + + if (status) { + BT_ERR("Failed to restart LE scan: status %d", status); + return; + } + + if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || + !hdev->discovery.scan_start) + return; + + /* When the scan was started, hdev->le_scan_disable has been queued + * after duration from scan_start. During scan restart this job + * has been canceled, and we need to queue it again after proper + * timeout, to make sure that scan does not run indefinitely. + */ + duration = hdev->discovery.scan_duration; + scan_start = hdev->discovery.scan_start; + now = jiffies; + if (now - scan_start <= duration) { + int elapsed; + + if (now >= scan_start) + elapsed = now - scan_start; + else + elapsed = ULONG_MAX - scan_start + now; + + timeout = duration - elapsed; + } else { + timeout = 0; + } + queue_delayed_work(hdev->workqueue, + &hdev->le_scan_disable, timeout); +} + +static void le_scan_restart_work(struct work_struct *work) +{ + struct hci_dev *hdev = container_of(work, struct hci_dev, + le_scan_restart.work); + struct hci_request req; + struct hci_cp_le_set_scan_enable cp; + int err; + + BT_DBG("%s", hdev->name); + + /* If controller is not scanning we are done. */ + if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) + return; + + hci_req_init(&req, hdev); + + hci_req_add_le_scan_disable(&req); + + memset(&cp, 0, sizeof(cp)); + cp.enable = LE_SCAN_ENABLE; + cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; + hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); + + err = hci_req_run(&req, le_scan_restart_work_complete); + if (err) + BT_ERR("Restart LE scan request failed: err %d", err); +} + /* Copy the Identity Address of the controller. * * If the controller has a public BD_ADDR, then by default use that one. @@ -2974,6 +3047,7 @@ struct hci_dev *hci_alloc_dev(void) INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off); INIT_DELAYED_WORK(&hdev->le_scan_disable, le_scan_disable_work); + INIT_DELAYED_WORK(&hdev->le_scan_restart, le_scan_restart_work); skb_queue_head_init(&hdev->rx_q); skb_queue_head_init(&hdev->cmd_q); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ba3b4a5820b1..8c2520a7f386 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3896,6 +3896,9 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status, hci_discovery_set_state(hdev, DISCOVERY_FINDING); + /* If the scan involves LE scan, pick proper timeout to schedule + * hdev->le_scan_disable that will stop it. + */ switch (hdev->discovery.type) { case DISCOV_TYPE_LE: timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT); @@ -3912,9 +3915,23 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status, break; } - if (timeout) + if (timeout) { + /* When service discovery is used and the controller has + * a strict duplicate filter, it is important to remember + * the start and duration of the scan. This is required + * for restarting scanning during the discovery phase. + */ + if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, + &hdev->quirks) && + (hdev->discovery.uuid_count > 0 || + hdev->discovery.rssi != HCI_RSSI_INVALID)) { + hdev->discovery.scan_start = jiffies; + hdev->discovery.scan_duration = timeout; + } + queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout); + } unlock: hci_dev_unlock(hdev); From 4b0e0ceddf085a89173805cace44cd3c4c9d9d77 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Sun, 1 Feb 2015 23:07:55 -0800 Subject: [PATCH 49/53] Bluetooth: Add restarting to service discovery When using LE_SCAN_FILTER_DUP_ENABLE, some controllers would send advertising report from each LE device only once. That means that we don't get any updates on RSSI value, and makes Service Discovery very slow. This patch adds restarting scan when in Service Discovery, and device with filtered uuid is found, but it's not in RSSI range to send event yet. This way if device moves into range, we will quickly get RSSI update. Signed-off-by: Jakub Pawlowski Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/mgmt.c | 53 +++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index d3a232be9d9b..52863c3e0b13 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1334,6 +1334,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); #define DISCOV_INTERLEAVED_TIMEOUT 5120 /* msec */ #define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04 #define DISCOV_BREDR_INQUIRY_LEN 0x08 +#define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); int mgmt_new_settings(struct hci_dev *hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8c2520a7f386..9e50b5c09b02 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -7262,6 +7262,21 @@ static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16]) return false; } +static void restart_le_scan(struct hci_dev *hdev) +{ + /* If controller is not scanning we are done. */ + if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) + return; + + if (time_after(jiffies + DISCOV_LE_RESTART_DELAY, + hdev->discovery.scan_start + + hdev->discovery.scan_duration)) + return; + + queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart, + DISCOV_LE_RESTART_DELAY); +} + void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 *dev_class, s8 rssi, u32 flags, u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len) @@ -7284,14 +7299,18 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, /* When using service discovery with a RSSI threshold, then check * if such a RSSI threshold is specified. If a RSSI threshold has - * been specified, then all results with a RSSI smaller than the - * RSSI threshold will be dropped. + * been specified, and HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, + * then all results with a RSSI smaller than the RSSI threshold will be + * dropped. If the quirk is set, let it through for further processing, + * as we might need to restart the scan. * * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry, * the results are also dropped. */ if (hdev->discovery.rssi != HCI_RSSI_INVALID && - (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID)) + (rssi == HCI_RSSI_INVALID || + (rssi < hdev->discovery.rssi && + !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)))) return; /* Make sure that the buffer is big enough. The 5 extra bytes @@ -7326,12 +7345,20 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, * kept and checking possible scan response data * will be skipped. */ - if (hdev->discovery.uuid_count > 0) + if (hdev->discovery.uuid_count > 0) { match = eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count, hdev->discovery.uuids); - else + /* If duplicate filtering does not report RSSI changes, + * then restart scanning to ensure updated result with + * updated RSSI values. + */ + if (match && test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, + &hdev->quirks)) + restart_le_scan(hdev); + } else { match = true; + } if (!match && !scan_rsp_len) return; @@ -7364,6 +7391,14 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, hdev->discovery.uuid_count, hdev->discovery.uuids)) return; + + /* If duplicate filtering does not report RSSI changes, + * then restart scanning to ensure updated result with + * updated RSSI values. + */ + if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, + &hdev->quirks)) + restart_le_scan(hdev); } /* Append scan response data to event */ @@ -7377,6 +7412,14 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, return; } + /* Validate the reported RSSI value against the RSSI threshold once more + * incase HCI_QUIRK_STRICT_DUPLICATE_FILTER forced a restart of LE + * scanning. + */ + if (hdev->discovery.rssi != HCI_RSSI_INVALID && + rssi < hdev->discovery.rssi) + return; + ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len); ev_size = sizeof(*ev) + eir_len + scan_rsp_len; From b970c5ba9d8bbaed019c15115d605deaee18bcfd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 1 Feb 2015 23:57:18 -0800 Subject: [PATCH 50/53] Bluetooth: Set HCI_QUIRK_STRICT_DUPLICATE_FILTER for BTUSB_INTEL_NEW The Intel Snowfield Peak Bluetooth controllers use a strict scanning filter policy that filters based on Bluetooth device addresses and not on RSSI. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d084856cc350..067a11c6829c 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2713,6 +2713,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->setup = btusb_setup_intel_new; hdev->hw_error = btusb_hw_error_intel; hdev->set_bdaddr = btusb_set_bdaddr_intel; + set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); } if (id->driver_info & BTUSB_MARVELL) From 66f096f79166bcd56fe3c3607a51fb6aeff857b1 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 2 Feb 2015 13:23:42 +0200 Subject: [PATCH 51/53] Bluetooth: Remove mgmt_rp_read_local_oob_ext_data struct This extended return parameters struct conflicts with the new Read Local OOB Extended Data command definition. To avoid the conflict simply rename the old "extended" version to the normal one and update the code appropriately to take into account the two possible response PDU sizes. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- include/net/bluetooth/mgmt.h | 4 ---- net/bluetooth/mgmt.c | 27 ++++++++++----------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 95c34d5180fa..e218a30f2061 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -301,10 +301,6 @@ struct mgmt_cp_user_passkey_neg_reply { #define MGMT_OP_READ_LOCAL_OOB_DATA 0x0020 #define MGMT_READ_LOCAL_OOB_DATA_SIZE 0 struct mgmt_rp_read_local_oob_data { - __u8 hash[16]; - __u8 rand[16]; -} __packed; -struct mgmt_rp_read_local_oob_ext_data { __u8 hash192[16]; __u8 rand192[16]; __u8 hash256[16]; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9e50b5c09b02..9ec5390c85eb 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -7168,28 +7168,21 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192, cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, mgmt_status(status)); } else { + struct mgmt_rp_read_local_oob_data rp; + size_t rp_size = sizeof(rp); + + memcpy(rp.hash192, hash192, sizeof(rp.hash192)); + memcpy(rp.rand192, rand192, sizeof(rp.rand192)); + if (bredr_sc_enabled(hdev) && hash256 && rand256) { - struct mgmt_rp_read_local_oob_ext_data rp; - - memcpy(rp.hash192, hash192, sizeof(rp.hash192)); - memcpy(rp.rand192, rand192, sizeof(rp.rand192)); - memcpy(rp.hash256, hash256, sizeof(rp.hash256)); memcpy(rp.rand256, rand256, sizeof(rp.rand256)); - - cmd_complete(cmd->sk, hdev->id, - MGMT_OP_READ_LOCAL_OOB_DATA, 0, - &rp, sizeof(rp)); } else { - struct mgmt_rp_read_local_oob_data rp; - - memcpy(rp.hash, hash192, sizeof(rp.hash)); - memcpy(rp.rand, rand192, sizeof(rp.rand)); - - cmd_complete(cmd->sk, hdev->id, - MGMT_OP_READ_LOCAL_OOB_DATA, 0, - &rp, sizeof(rp)); + rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256); } + + cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, 0, + &rp, rp_size); } mgmt_pending_remove(cmd); From 8f0c304c693c5a9759ed6ae50d07d4590dad5ae7 Mon Sep 17 00:00:00 2001 From: Matej Dubovy Date: Mon, 2 Feb 2015 18:50:14 +0100 Subject: [PATCH 52/53] Bluetooth: btusb: Add support for Lite-On (04ca) Broadcom based, BCM43142 Please add support for sub BT chip on the combo card Broadcom 43142A0 (in Lenovo E145), 04ca:2007 /sys/kernel/debug/usb/devices T: Bus=05 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=04ca ProdID=2007 Rev= 1.12 S: Manufacturer=Broadcom Corp S: Product=BCM43142A0 S: SerialNumber=28E347EC73BD C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr= 0mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=84(I) Atr=02(Bulk) MxPS= 32 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 32 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Firmware for 04ca:2007 can be extracted from the latest Lenovo E145 Bluetooth driver for Windows (driver is however described as BCM20702 but contains also firwmare for BCM43142). Search for BCM43142A0_001.001.011.0122.0153.hex within hex files, then it must be converted using hex2hcd utility. Rename file to BCM43142A0-04ca-2007.hcd, then move to /lib/firmware/brcm/. Signed-off-by: Matej Dubovy Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org --- drivers/bluetooth/btusb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 067a11c6829c..b87688881143 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -122,6 +122,10 @@ static const struct usb_device_id btusb_table[] = { { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM }, + /* Lite-On Technology - Broadcom based */ + { USB_VENDOR_AND_INTERFACE_INFO(0x04ca, 0xff, 0x01, 0x01), + .driver_info = BTUSB_BCM_PATCHRAM }, + /* Broadcom devices with vendor specific id */ { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM }, From 88d9077c27d0c1a7c022d9dc987640beecf23560 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 3 Feb 2015 10:01:13 +0200 Subject: [PATCH 53/53] Bluetooth: Fix potential NULL dereference The bnep_get_device function may be triggered by an ioctl just after a connection has gone down. In such a case the respective L2CAP chan->conn pointer will get set to NULL (by l2cap_chan_del). This patch adds a missing NULL check for this case in the bnep_get_device() function. Reported-by: Patrik Flykt Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/bnep/core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index ce82722d049b..05f57e491ccb 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -511,13 +511,12 @@ static int bnep_session(void *arg) static struct device *bnep_get_device(struct bnep_session *session) { - struct hci_conn *conn; + struct l2cap_conn *conn = l2cap_pi(session->sock->sk)->chan->conn; - conn = l2cap_pi(session->sock->sk)->chan->conn->hcon; - if (!conn) + if (!conn || !conn->hcon) return NULL; - return &conn->dev; + return &conn->hcon->dev; } static struct device_type bnep_type = {