diff options
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r-- | drivers/bluetooth/btusb.c | 99 |
1 files changed, 58 insertions, 41 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a9855a2dd561..bd37d6fb88c2 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -452,6 +452,10 @@ static const struct usb_device_id blacklist_table[] = { /* Additional Realtek 8822CE Bluetooth devices */ { USB_DEVICE(0x04ca, 0x4005), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + /* Bluetooth component of Realtek 8852AE device */ + { USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x04c5, 0x161f), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0b05, 0x18ef), .driver_info = BTUSB_REALTEK | @@ -525,6 +529,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = { #define BTUSB_HW_RESET_ACTIVE 12 #define BTUSB_TX_WAIT_VND_EVT 13 #define BTUSB_WAKEUP_DISABLE 14 +#define BTUSB_USE_ALT3_FOR_WBS 15 struct btusb_data { struct hci_dev *hdev; @@ -1757,16 +1762,20 @@ static void btusb_work(struct work_struct *work) /* Bluetooth USB spec recommends alt 6 (63 bytes), but * many adapters do not support it. Alt 1 appears to * work for all adapters that do not have alt 6, and - * which work with WBS at all. + * which work with WBS at all. Some devices prefer + * alt 3 (HCI payload >= 60 Bytes let air packet + * data satisfy 60 bytes), requiring + * MTU >= 3 (packets) * 25 (size) - 3 (headers) = 72 + * see also Core spec 5, vol 4, B 2.1.1 & Table 2.1. */ - new_alts = btusb_find_altsetting(data, 6) ? 6 : 1; - /* Because mSBC frames do not need to be aligned to the - * SCO packet boundary. If support the Alt 3, use the - * Alt 3 for HCI payload >= 60 Bytes let air packet - * data satisfy 60 bytes. - */ - if (new_alts == 1 && btusb_find_altsetting(data, 3)) + if (btusb_find_altsetting(data, 6)) + new_alts = 6; + else if (btusb_find_altsetting(data, 3) && + hdev->sco_mtu >= 72 && + test_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags)) new_alts = 3; + else + new_alts = 1; } if (btusb_switch_alt_setting(hdev, new_alts) < 0) @@ -1890,7 +1899,7 @@ static int btusb_setup_csr(struct hci_dev *hdev) is_fake = true; if (is_fake) { - bt_dev_warn(hdev, "CSR: Unbranded CSR clone detected; adding workarounds..."); + bt_dev_warn(hdev, "CSR: Unbranded CSR clone detected; adding workarounds and force-suspending once..."); /* Generally these clones have big discrepancies between * advertised features and what's actually supported. @@ -1907,41 +1916,46 @@ static int btusb_setup_csr(struct hci_dev *hdev) clear_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); /* - * Special workaround for clones with a Barrot 8041a02 chip, - * these clones are really messed-up: - * 1. Their bulk rx endpoint will never report any data unless - * the device was suspended at least once (yes really). + * Special workaround for these BT 4.0 chip clones, and potentially more: + * + * - 0x0134: a Barrot 8041a02 (HCI rev: 0x1012 sub: 0x0810) + * - 0x7558: IC markings FR3191AHAL 749H15143 (HCI rev/sub-version: 0x0709) + * + * These controllers are really messed-up. + * + * 1. Their bulk RX endpoint will never report any data unless + * the device was suspended at least once (yes, really). * 2. They will not wakeup when autosuspended and receiving data - * on their bulk rx endpoint from e.g. a keyboard or mouse + * on their bulk RX endpoint from e.g. a keyboard or mouse * (IOW remote-wakeup support is broken for the bulk endpoint). * * To fix 1. enable runtime-suspend, force-suspend the - * hci and then wake-it up by disabling runtime-suspend. + * HCI and then wake-it up by disabling runtime-suspend. * - * To fix 2. clear the hci's can_wake flag, this way the hci + * To fix 2. clear the HCI's can_wake flag, this way the HCI * will still be autosuspended when it is not open. + * + * -- + * + * Because these are widespread problems we prefer generic solutions; so + * apply this initialization quirk to every controller that gets here, + * it should be harmless. The alternative is to not work at all. */ - if (bcdDevice == 0x8891 && - le16_to_cpu(rp->lmp_subver) == 0x1012 && - le16_to_cpu(rp->hci_rev) == 0x0810 && - le16_to_cpu(rp->hci_ver) == BLUETOOTH_VER_4_0) { - bt_dev_warn(hdev, "CSR: detected a fake CSR dongle using a Barrot 8041a02 chip, this chip is very buggy and may have issues"); + pm_runtime_allow(&data->udev->dev); - pm_runtime_allow(&data->udev->dev); + ret = pm_runtime_suspend(&data->udev->dev); + if (ret >= 0) + msleep(200); + else + bt_dev_err(hdev, "CSR: Failed to suspend the device for our Barrot 8041a02 receive-issue workaround"); - ret = pm_runtime_suspend(&data->udev->dev); - if (ret >= 0) - msleep(200); - else - bt_dev_err(hdev, "Failed to suspend the device for Barrot 8041a02 receive-issue workaround"); + pm_runtime_forbid(&data->udev->dev); - pm_runtime_forbid(&data->udev->dev); + device_set_wakeup_capable(&data->udev->dev, false); - device_set_wakeup_capable(&data->udev->dev, false); - /* Re-enable autosuspend if this was requested */ - if (enable_autosuspend) - usb_enable_autosuspend(data->udev); - } + /* Re-enable autosuspend if this was requested */ + if (enable_autosuspend) + usb_enable_autosuspend(data->udev); } kfree_skb(skb); @@ -2907,10 +2921,11 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) /* Read the Intel supported features and if new exception formats * supported, need to load the additional DDC config to enable. */ - btintel_read_debug_features(hdev, &features); - - /* Set DDC mask for available debug features */ - btintel_set_debug_features(hdev, &features); + err = btintel_read_debug_features(hdev, &features); + if (!err) { + /* Set DDC mask for available debug features */ + btintel_set_debug_features(hdev, &features); + } /* Read the Intel version information after loading the FW */ err = btintel_read_version(hdev, &ver); @@ -3003,10 +3018,11 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev) /* Read the Intel supported features and if new exception formats * supported, need to load the additional DDC config to enable. */ - btintel_read_debug_features(hdev, &features); - - /* Set DDC mask for available debug features */ - btintel_set_debug_features(hdev, &features); + err = btintel_read_debug_features(hdev, &features); + if (!err) { + /* Set DDC mask for available debug features */ + btintel_set_debug_features(hdev, &features); + } /* Read the Intel version information after loading the FW */ err = btintel_read_version_tlv(hdev, &version); @@ -4742,6 +4758,7 @@ static int btusb_probe(struct usb_interface *intf, * (DEVICE_REMOTE_WAKEUP) */ set_bit(BTUSB_WAKEUP_DISABLE, &data->flags); + set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags); } if (!reset) |