From c127a871357b8d59cda9c8b96cb65c2e24a72c46 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Thu, 8 Jun 2017 22:58:45 +0200 Subject: [PATCH 01/10] Bluetooth: hci_ll: Add compatible values for more WL chips Add compatible values for WiLink chips from 128x and 180x series. Also the DT binding already contained compatible values for the 127x series, but the driver did not. This brings the list on par with the list from wlcore (the wifi driver). Signed-off-by: Sebastian Reichel Reviewed-by: Rob Herring Signed-off-by: Marcel Holtmann --- Documentation/devicetree/bindings/net/ti,wilink-st.txt | 6 ++++++ drivers/bluetooth/hci_ll.c | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/net/ti,wilink-st.txt b/Documentation/devicetree/bindings/net/ti,wilink-st.txt index cbad73a84ac4..b1a421e2fde3 100644 --- a/Documentation/devicetree/bindings/net/ti,wilink-st.txt +++ b/Documentation/devicetree/bindings/net/ti,wilink-st.txt @@ -14,6 +14,12 @@ Required properties: - compatible: should be one of the following: "ti,wl1271-st" "ti,wl1273-st" + "ti,wl1281-st" + "ti,wl1283-st" + "ti,wl1285-st" + "ti,wl1801-st" + "ti,wl1805-st" + "ti,wl1807-st" "ti,wl1831-st" "ti,wl1835-st" "ti,wl1837-st" diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 200288c87fc4..1b0487310117 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -741,6 +741,14 @@ static void hci_ti_remove(struct serdev_device *serdev) } static const struct of_device_id hci_ti_of_match[] = { + { .compatible = "ti,wl1271-st" }, + { .compatible = "ti,wl1273-st" }, + { .compatible = "ti,wl1281-st" }, + { .compatible = "ti,wl1283-st" }, + { .compatible = "ti,wl1285-st" }, + { .compatible = "ti,wl1801-st" }, + { .compatible = "ti,wl1805-st" }, + { .compatible = "ti,wl1807-st" }, { .compatible = "ti,wl1831-st" }, { .compatible = "ti,wl1835-st" }, { .compatible = "ti,wl1837-st" }, From 3c8e42a7935f720c403612abf896d962a7aa1495 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 7 Jun 2017 11:08:20 +0200 Subject: [PATCH 02/10] dt-bindings: net: Add binding for the external clock for TI WiLink The external clock is provided to the TI WiLink combo chip and it's needed for any of the transport interfaces. However let's make it optional to avoid breaking existing platforms that yet doesn't specify the clock. Fixes: ea452678734e ("arm64: dts: hikey: Fix WiFi support") Signed-off-by: Ulf Hansson Tested-by: John Stultz Signed-off-by: Marcel Holtmann --- Documentation/devicetree/bindings/net/ti,wilink-st.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/net/ti,wilink-st.txt b/Documentation/devicetree/bindings/net/ti,wilink-st.txt index b1a421e2fde3..1649c1f66b07 100644 --- a/Documentation/devicetree/bindings/net/ti,wilink-st.txt +++ b/Documentation/devicetree/bindings/net/ti,wilink-st.txt @@ -28,6 +28,10 @@ Optional properties: - enable-gpios : GPIO signal controlling enabling of BT. Active high. - vio-supply : Vio input supply (1.8V) - vbat-supply : Vbat input supply (2.9-4.8V) + - clocks : Must contain an entry, for each entry in clock-names. + See ../clocks/clock-bindings.txt for details. + - clock-names : Must include the following entry: + "ext_clock" (External clock provided to the TI combo chip). Example: @@ -37,5 +41,7 @@ Example: bluetooth { compatible = "ti,wl1835-st"; enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + clocks = <&clk32k_wl18xx>; + clock-names = "ext_clock"; }; }; From 43d3d092c7cbd1685e1c8ff25ae0b89b5b729388 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 7 Jun 2017 11:08:21 +0200 Subject: [PATCH 03/10] Bluetooth: hci_ll: Add support for the external clock Add support to manage the external clock provided to the WiLink combo chip as it's needed for any of the transport interfaces. To avoid breaking platforms not yet specifying the external clock, we make it optional. In case the clock is successfully fetched during ->probe(), let's manage it via the ->open|close() callbacks, to make sure the device get properly powered on/off. Fixes: ea452678734e ("arm64: dts: hikey: Fix WiFi support") Signed-off-by: Ulf Hansson Tested-by: John Stultz Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ll.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 1b0487310117..2b16d48d82ee 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -84,6 +85,7 @@ struct ll_device { struct hci_uart hu; struct serdev_device *serdev; struct gpio_desc *enable_gpio; + struct clk *ext_clk; }; struct ll_struct { @@ -146,8 +148,12 @@ static int ll_open(struct hci_uart *hu) hu->priv = ll; - if (hu->serdev) + if (hu->serdev) { + struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev); serdev_device_open(hu->serdev); + if (!IS_ERR(lldev->ext_clk)) + clk_prepare_enable(lldev->ext_clk); + } return 0; } @@ -181,6 +187,8 @@ static int ll_close(struct hci_uart *hu) struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev); gpiod_set_value_cansleep(lldev->enable_gpio, 0); + clk_disable_unprepare(lldev->ext_clk); + serdev_device_close(hu->serdev); } @@ -721,6 +729,10 @@ static int hci_ti_probe(struct serdev_device *serdev) if (IS_ERR(lldev->enable_gpio)) return PTR_ERR(lldev->enable_gpio); + lldev->ext_clk = devm_clk_get(&serdev->dev, "ext_clock"); + if (IS_ERR(lldev->ext_clk) && PTR_ERR(lldev->ext_clk) != -ENOENT) + return PTR_ERR(lldev->ext_clk); + of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed); hci_uart_set_speeds(hu, 115200, max_speed); From b73f22695f4445114bd354df19ef84201ead22fe Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 7 Jun 2017 11:08:22 +0200 Subject: [PATCH 04/10] arm64: dts: hikey: Add external clock to the Bluetooth node To make the TI WiLink chip work again for Bluetooth, let's add the missing external clock to the Bluetooth node, such the driver can deal properly with it during power on/off. Fixes: ea452678734e ("arm64: dts: hikey: Fix WiFi support") Cc: Wei Xu Signed-off-by: Ulf Hansson Tested-by: John Stultz Signed-off-by: Marcel Holtmann --- arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 49f6a6242cf9..5cdfe732df38 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -141,6 +141,8 @@ uart1: uart@f7111000 { bluetooth { compatible = "ti,wl1835-st"; enable-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; + clocks = <&pmic>; + clock-names = "ext_clock"; }; }; From fda7057f4b5356d40d321f339f4ac6b3f94076ec Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 6 Jun 2017 17:47:17 +0300 Subject: [PATCH 05/10] Bluetooth: hci_bcm: Switch to devm_acpi_dev_add_driver_gpios() Switch to use managed variant of acpi_dev_add_driver_gpios() to simplify error path and fix potentially wrong assingment if ->probe() fails. Signed-off-by: Andy Shevchenko Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_bcm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index f87bfdfee4ff..e2096c7803b3 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -762,8 +762,7 @@ static int bcm_acpi_probe(struct bcm_device *dev) if (id) gpio_mapping = (const struct acpi_gpio_mapping *) id->driver_data; - ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev), - gpio_mapping); + ret = devm_acpi_dev_add_driver_gpios(&pdev->dev, gpio_mapping); if (ret) return ret; @@ -834,8 +833,6 @@ static int bcm_remove(struct platform_device *pdev) list_del(&dev->list); mutex_unlock(&bcm_device_lock); - acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev)); - dev_info(&pdev->dev, "%s device unregistered.\n", dev->name); return 0; From 4a59d433c98bcd9e1032009abbd43415405cd763 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 6 Jun 2017 17:47:18 +0300 Subject: [PATCH 06/10] Bluetooth: hci_intel: Add GPIO ACPI mapping table In order to make GPIO ACPI library stricter prepare users of gpiod_get_index() to correctly behave when there no mapping is provided by firmware. Here we add explicit mapping between _CRS GpioIo() resources and their names used in the driver. Signed-off-by: Andy Shevchenko Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_intel.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index fa5099986f1b..851bee82df2a 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -1205,9 +1205,19 @@ static const struct dev_pm_ops intel_pm_ops = { SET_RUNTIME_PM_OPS(intel_suspend_device, intel_resume_device, NULL) }; +static const struct acpi_gpio_params reset_gpios = { 0, 0, false }; +static const struct acpi_gpio_params host_wake_gpios = { 1, 0, false }; + +static const struct acpi_gpio_mapping acpi_hci_intel_gpios[] = { + { "reset-gpios", &reset_gpios, 1 }, + { "host-wake-gpios", &host_wake_gpios, 1 }, + { }, +}; + static int intel_probe(struct platform_device *pdev) { struct intel_device *idev; + int ret; idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL); if (!idev) @@ -1217,6 +1227,10 @@ static int intel_probe(struct platform_device *pdev) idev->pdev = pdev; + ret = devm_acpi_dev_add_driver_gpios(&pdev->dev, acpi_hci_intel_gpios); + if (ret) + dev_dbg(&pdev->dev, "Unable to add GPIO mapping table\n"); + idev->reset = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(idev->reset)) { dev_err(&pdev->dev, "Unable to retrieve gpio\n"); From 329d82309824ff1082dc4a91a5bbed8c3bec1580 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 10 Jun 2017 04:59:11 +0200 Subject: [PATCH 07/10] Bluetooth: use constant time memory comparison for secret values This file is filled with complex cryptography. Thus, the comparisons of MACs and secret keys and curve points and so forth should not add timing attacks, which could either result in a direct forgery, or, given the complexity, some other type of attack. Signed-off-by: Jason A. Donenfeld Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org --- net/bluetooth/smp.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 14585edc9439..a0ef89772c36 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -523,7 +524,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16], if (err) return false; - return !memcmp(bdaddr->b, hash, 3); + return !crypto_memneq(bdaddr->b, hash, 3); } int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa) @@ -579,7 +580,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16]) /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ - if (memcmp(smp->local_sk, debug_sk, 32)) + if (crypto_memneq(smp->local_sk, debug_sk, 32)) break; } smp->debug_key = false; @@ -993,7 +994,7 @@ static u8 smp_random(struct smp_chan *smp) if (ret) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { + if (crypto_memneq(smp->pcnf, confirm, sizeof(smp->pcnf))) { BT_ERR("Pairing failed (confirmation values mismatch)"); return SMP_CONFIRM_FAILED; } @@ -1512,7 +1513,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op) smp->rrnd, r, cfm)) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, cfm, 16)) + if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; smp->passkey_round++; @@ -1908,7 +1909,7 @@ static u8 sc_send_public_key(struct smp_chan *smp) /* This is unlikely, but we need to check that * we didn't accidentially generate a debug key. */ - if (memcmp(smp->local_sk, debug_sk, 32)) + if (crypto_memneq(smp->local_sk, debug_sk, 32)) break; } } @@ -2176,7 +2177,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(smp->pcnf, cfm, 16)) + if (crypto_memneq(smp->pcnf, cfm, 16)) return SMP_CONFIRM_FAILED; } else { smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), @@ -2660,7 +2661,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(cfm.confirm_val, smp->pcnf, 16)) + if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16)) return SMP_CONFIRM_FAILED; } @@ -2693,7 +2694,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) else hcon->pending_sec_level = BT_SECURITY_FIPS; - if (!memcmp(debug_pk, smp->remote_pk, 64)) + if (!crypto_memneq(debug_pk, smp->remote_pk, 64)) set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags); if (smp->method == DSP_PASSKEY) { @@ -2792,7 +2793,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb) if (err) return SMP_UNSPECIFIED; - if (memcmp(check->e, e, 16)) + if (crypto_memneq(check->e, e, 16)) return SMP_DHKEY_CHECK_FAILED; if (!hcon->out) { @@ -3506,10 +3507,10 @@ static int __init test_debug_key(void) if (!generate_ecdh_keys(pk, sk)) return -EINVAL; - if (memcmp(sk, debug_sk, 32)) + if (crypto_memneq(sk, debug_sk, 32)) return -EINVAL; - if (memcmp(pk, debug_pk, 64)) + if (crypto_memneq(pk, debug_pk, 64)) return -EINVAL; return 0; @@ -3529,7 +3530,7 @@ static int __init test_ah(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 3)) + if (crypto_memneq(res, exp, 3)) return -EINVAL; return 0; @@ -3559,7 +3560,7 @@ static int __init test_c1(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3584,7 +3585,7 @@ static int __init test_s1(struct crypto_cipher *tfm_aes) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3616,7 +3617,7 @@ static int __init test_f4(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3650,10 +3651,10 @@ static int __init test_f5(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(mackey, exp_mackey, 16)) + if (crypto_memneq(mackey, exp_mackey, 16)) return -EINVAL; - if (memcmp(ltk, exp_ltk, 16)) + if (crypto_memneq(ltk, exp_ltk, 16)) return -EINVAL; return 0; @@ -3686,7 +3687,7 @@ static int __init test_f6(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; @@ -3740,7 +3741,7 @@ static int __init test_h6(struct crypto_shash *tfm_cmac) if (err) return err; - if (memcmp(res, exp, 16)) + if (crypto_memneq(res, exp, 16)) return -EINVAL; return 0; From 313f6888c8fbb1bc8b36c9012ce4e1de848df696 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 9 Jun 2017 18:43:56 +0200 Subject: [PATCH 08/10] Bluetooth: Send HCI Set Event Mask Page 2 command only when needed The Broadcom BCM20702 Bluetooth controller in ThinkPad-T530 devices report support for the Set Event Mask Page 2 command, but actually do return an error when trying to use it. < HCI Command: Read Local Supported Commands (0x04|0x0002) plen 0 > HCI Event: Command Complete (0x0e) plen 68 Read Local Supported Commands (0x04|0x0002) ncmd 1 Status: Success (0x00) Commands: 162 entries ... Set Event Mask Page 2 (Octet 22 - Bit 2) ... < HCI Command: Set Event Mask Page 2 (0x03|0x0063) plen 8 Mask: 0x0000000000000000 > HCI Event: Command Complete (0x0e) plen 4 Set Event Mask Page 2 (0x03|0x0063) ncmd 1 Status: Unknown HCI Command (0x01) Since these controllers do not support any feature that would require the event mask page 2 to be modified, it is safe to not send this command at all. The default value is all bits set to zero. T: Bus=01 Lev=02 Prnt=02 Port=03 Cnt=03 Dev#= 9 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0a5c ProdID=21e6 Rev= 1.12 S: Manufacturer=Broadcom Corp S: Product=BCM20702A0 S: SerialNumber=F82FA8E8CFC0 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=btusb 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) Signed-off-by: Marcel Holtmann Reported-by: Sedat Dilek Tested-by: Sedat Dilek Signed-off-by: Szymon Janc --- net/bluetooth/hci_core.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 7655b4005dfb..93806b959039 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -548,6 +548,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req) { struct hci_dev *hdev = req->hdev; u8 events[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + bool changed = false; /* If Connectionless Slave Broadcast master role is supported * enable all necessary events for it. @@ -557,6 +558,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req) events[1] |= 0x80; /* Synchronization Train Complete */ events[2] |= 0x10; /* Slave Page Response Timeout */ events[2] |= 0x20; /* CSB Channel Map Change */ + changed = true; } /* If Connectionless Slave Broadcast slave role is supported @@ -567,13 +569,24 @@ static void hci_set_event_mask_page_2(struct hci_request *req) events[2] |= 0x02; /* CSB Receive */ events[2] |= 0x04; /* CSB Timeout */ events[2] |= 0x08; /* Truncated Page Complete */ + changed = true; } /* Enable Authenticated Payload Timeout Expired event if supported */ - if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) + if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) { events[2] |= 0x80; + changed = true; + } - hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); + /* Some Broadcom based controllers indicate support for Set Event + * Mask Page 2 command, but then actually do not support it. Since + * the default value is all bits set to zero, the command is only + * required if the event mask has to be changed. In case no change + * to the event mask is needed, skip this command. + */ + if (changed) + hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, + sizeof(events), events); } static int hci_init3_req(struct hci_request *req, unsigned long opt) From 4284ecbeda81083f4c7a3ce325b4a9d675657e61 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 10 Jun 2017 14:33:16 +0200 Subject: [PATCH 09/10] Bluetooth: btbcm: Read controller features during configuration Read the Broadcom specific controller features during configuration and print them for informational purposes. < HCI Command: Broadcom Read Controller Features (0x3f|0x006e) plen 0 > HCI Event: Command Complete (0x0e) plen 12 Broadcom Read Controller Features (0x3f|0x006e) ncmd 1 Status: Success (0x00) Features: 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Multi-AV transport bandwidth reducer WBS SBC FW LC-PLC Signed-off-by: Marcel Holtmann Signed-off-by: Szymon Janc --- drivers/bluetooth/btbcm.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index ba3dd2eafc09..24f8c4e93f4e 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -246,6 +246,27 @@ static struct sk_buff *btbcm_read_verbose_config(struct hci_dev *hdev) return skb; } +static struct sk_buff *btbcm_read_controller_features(struct hci_dev *hdev) +{ + struct sk_buff *skb; + + skb = __hci_cmd_sync(hdev, 0xfc6e, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("%s: BCM: Read controller features failed (%ld)", + hdev->name, PTR_ERR(skb)); + return skb; + } + + if (skb->len != 9) { + BT_ERR("%s: BCM: Controller features length mismatch", + hdev->name); + kfree_skb(skb); + return ERR_PTR(-EIO); + } + + return skb; +} + static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev) { struct sk_buff *skb; @@ -417,6 +438,14 @@ int btbcm_setup_patchram(struct hci_dev *hdev) BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); kfree_skb(skb); + /* Read Controller Features */ + skb = btbcm_read_controller_features(hdev); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]); + kfree_skb(skb); + /* Read Local Name */ skb = btbcm_read_local_name(hdev); if (IS_ERR(skb)) @@ -540,6 +569,13 @@ int btbcm_setup_apple(struct hci_dev *hdev) kfree_skb(skb); } + /* Read Controller Features */ + skb = btbcm_read_controller_features(hdev); + if (!IS_ERR(skb)) { + BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]); + kfree_skb(skb); + } + /* Read Local Name */ skb = btbcm_read_local_name(hdev); if (!IS_ERR(skb)) { From 06e41d8a36689f465006f017bbcd8a73edb98109 Mon Sep 17 00:00:00 2001 From: "Shih-Yuan Lee (FourDollars)" Date: Wed, 14 Jun 2017 14:42:00 +0800 Subject: [PATCH 10/10] Bluetooth: btusb: Add support for 0489:e0a2 QCA_ROME device T: Bus=01 Lev=01 Prnt=01 Port=06 Cnt=03 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0489 ProdID=e0a2 Rev=00.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 I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb Signed-off-by: Shih-Yuan Lee (FourDollars) Suggested-by: Owen Lin 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 278e81186150..bfd5f4bdec80 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -266,6 +266,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME }, + { USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME }, { USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME }, /* Broadcom BCM2035 */