Hi, Please check the attached patch proposal for drivers/bluetooth/btusb.c 0.8.1 (for 5.3-rc6/rc8 kernels). I haven't tested it thoroughly but I can get sound with these changes on my "Cambridge Silicon Radio, Ltd Bluetooth Dongle" adapters (ATTRS{idVendor}=="0a12", ATTRS{idProduct}=="0001", ATTRS{bcdDevice}=="8891"). Also, the added kernel module parameters should allow easier testing of the available fixups allowing them to be turned on/off via modprobe (and keep traditional behavior wen not used). * Changes: Patching for Cambridge Silicon Radio, Ltd Bluetooth Dongle(HCI mode) * Adapting patches for HCI_QUIRK_BROKEN_STORED_LINK_KEY * based on patch by Szymon Janc <szymon.janc@xxxxxxxxxxx> * https://pastebin.com/dHepfTmR * Adding patch for CSR bcdDevice == 0x8891 by Sergey Kondakov from * https://bugzilla.kernel.org/show_bug.cgi?id=60824#c37 * Minor Changes allowing some fixups/quirks to be tested and * enabled/disabled via kernel module options: * debug; * disable_csrfix, force_csrfix; * disable_fakecsr, force_fakecsr; * disable_npsetup, force_npsetup; * disable_sniffer, force_sniffer; * disable_intelboot, force_intelboot; * disable_scofix, force_scofix; * disable_slkfix, force_slkfix; * disable_rocfix, force_rocfix; * disable_noisoc, force_noisoc; * disable_ath3012, force_ath3012; * disable_digianswer, force_digianswer; * disable_intel, force_intel; * disable_intelnew, force_intelnew; * disable_marvel, force_marvel; * disable_mediatek, force_mediatek; * disable_qcarome, force_qcarome; * disable_bcm92035, force_bcm92035; * disable_swave, force_swave; Regards. # Fernando Pires de Carvalho # pires.carvalho@xxxxxxxxx
diff -rubi a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c --- a/drivers/bluetooth/btusb.c 2019-09-11 18:34:41.605987497 +0100 +++ b/drivers/bluetooth/btusb.c 2019-09-07 11:51:45.963518104 +0100 @@ -6,6 +6,38 @@ * Copyright (C) 2005-2008 Marcel Holtmann <marcel@xxxxxxxxxxxx> */ +/* Version: 0.8.1 + * Date: 2019-09-01 + * Author: Fernando Carvalho <pires carvalho mail com> + * Changes: Patching for Cambridge Silicon Radio, Ltd Bluetooth Dongle(HCI mode) + * Adapting patches for HCI_QUIRK_BROKEN_STORED_LINK_KEY + * based on patch by Szymon Janc <szymon.janc@xxxxxxxxxxx> + * https://pastebin.com/dHepfTmR + * Adding patch for CSR bcdDevice == 0x8891 by Sergey Kondakov from + * https://bugzilla.kernel.org/show_bug.cgi?id=60824#c37 + * Minor Changes allowing some fixups/quirks to be tested and + * enabled/disabled via kernel module options: + * debug; + * disable_csrfix, force_csrfix; + * disable_fakecsr, force_fakecsr; + * disable_npsetup, force_npsetup; + * disable_sniffer, force_sniffer; + * disable_intelboot, force_intelboot; + * disable_scofix, force_scofix; + * disable_slkfix, force_slkfix; + * disable_rocfix, force_rocfix; + * disable_noisoc, force_noisoc; + * disable_ath3012, force_ath3012; + * disable_digianswer, force_digianswer; + * disable_intel, force_intel; + * disable_intelnew, force_intelnew; + * disable_marvel, force_marvel; + * disable_mediatek, force_mediatek; + * disable_qcarome, force_qcarome; + * disable_bcm92035, force_bcm92035; + * disable_swave, force_swave; +*/ + #include <linux/dmi.h> #include <linux/module.h> #include <linux/usb.h> @@ -25,10 +57,28 @@ #include "btbcm.h" #include "btrtl.h" -#define VERSION "0.8" +#define VERSION "0.8.1" + +static int debug; +static bool disable_csrfix, force_csrfix; +static bool disable_fakecsr, force_fakecsr; +static bool disable_npsetup, force_npsetup; +static bool disable_sniffer, force_sniffer; +static bool disable_intelboot, force_intelboot; +static bool disable_scofix, force_scofix; +static bool disable_slkfix, force_slkfix; +static bool disable_rocfix, force_rocfix; +static bool disable_noisoc, force_noisoc; +static bool disable_ath3012, force_ath3012; +static bool disable_digianswer, force_digianswer; +static bool disable_intel, force_intel; +static bool disable_intelnew, force_intelnew; +static bool disable_marvel, force_marvel; +static bool disable_mediatek, force_mediatek; +static bool disable_qcarome, force_qcarome; +static bool disable_bcm92035, force_bcm92035; +static bool disable_swave, force_swave; -static bool disable_scofix; -static bool force_scofix; static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND); static bool reset = true; @@ -53,10 +103,13 @@ #define BTUSB_QCA_ROME 0x8000 #define BTUSB_BCM_APPLE 0x10000 #define BTUSB_REALTEK 0x20000 -#define BTUSB_BCM2045 0x40000 +// #define BTUSB_BCM2045 0x40000 /* replaced by BTUSB_BROKEN_SLK */ #define BTUSB_IFNUM_2 0x80000 -#define BTUSB_CW6622 0x100000 +// #define BTUSB_CW6622 0x100000 /* replaced by BTUSB_BROKEN_SLK */ #define BTUSB_MEDIATEK 0x200000 +#define BTUSB_BROKEN_SLK 0x400000 /* HCI_QUIRK_BROKEN_STORED_LINK_KEY */ +#define BTUSB_NPSETUP 0x800000 + static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -171,14 +224,15 @@ MODULE_DEVICE_TABLE(usb, btusb_table); static const struct usb_device_id blacklist_table[] = { - /* CSR BlueCore devices */ + /* ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) BlueCore devices */ + // Needs Testing: { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR | BTUSB_BROKEN_SLK }, { USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR }, /* Broadcom BCM2033 without firmware */ { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE }, /* Broadcom BCM2045 devices */ - { USB_DEVICE(0x0a5c, 0x2045), .driver_info = BTUSB_BCM2045 }, + { USB_DEVICE(0x0a5c, 0x2045), .driver_info = BTUSB_BROKEN_SLK }, /* Atheros 3011 with sflash firmware */ { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, @@ -295,7 +349,7 @@ /* Belkin F8T012 and F8T013 devices */ { USB_DEVICE(0x050d, 0x0012), .driver_info = BTUSB_WRONG_SCO_MTU }, - { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_WRONG_SCO_MTU }, + { USB_DEVICE(0x050d, 0x0013), .driver_info = BTUSB_WRONG_SCO_MTU | BTUSB_BROKEN_SLK}, /* Asus WL-BTD202 device */ { USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU }, @@ -309,7 +363,7 @@ /* CONWISE Technology based adapters with buggy SCO support */ { USB_DEVICE(0x0e5e, 0x6622), - .driver_info = BTUSB_BROKEN_ISOC | BTUSB_CW6622}, + .driver_info = BTUSB_BROKEN_ISOC | BTUSB_BROKEN_SLK}, /* Roper Class 1 Bluetooth Dongle (Silicon Wave based) */ { USB_DEVICE(0x1310, 0x0001), .driver_info = BTUSB_SWAVE }, @@ -1600,6 +1654,7 @@ /* Detect controllers which aren't real CSR ones. */ if (le16_to_cpu(rp->manufacturer) != 10 || + le16_to_cpu(rp->lmp_subver) == 0x0811 || le16_to_cpu(rp->lmp_subver) == 0x0c5c) { /* Clear the reset quirk since this is not an actual * early Bluetooth 1.1 device from CSR. @@ -1609,8 +1664,11 @@ /* These fake CSR controllers have all a broken * stored link key handling and so just disable it. */ + if(!disable_slkfix) + { set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); } + } kfree_skb(skb); @@ -3561,7 +3619,8 @@ if (id->driver_info == BTUSB_IGNORE) return -ENODEV; - if (id->driver_info & BTUSB_ATH3012) { + if (force_ath3012 || id->driver_info & BTUSB_ATH3012) { + if(!disable_ath3012) { struct usb_device *udev = interface_to_usbdev(intf); /* Old firmware would otherwise let ath3k driver load @@ -3571,6 +3630,7 @@ !btusb_qca_need_patch(udev)) return -ENODEV; } + } data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -3674,13 +3734,12 @@ goto out_free_dev; } #endif - if (id->driver_info & BTUSB_CW6622) - set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); - if (id->driver_info & BTUSB_BCM2045) + if (!disable_slkfix && (force_slkfix || id->driver_info & BTUSB_BROKEN_SLK)) { set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); + } - if (id->driver_info & BTUSB_BCM92035) + if (!disable_bcm92035 && (force_bcm92035 || id->driver_info & BTUSB_BCM92035)) hdev->setup = btusb_setup_bcm92035; #ifdef CONFIG_BT_HCIBTUSB_BCM @@ -3704,7 +3763,7 @@ } #endif - if (id->driver_info & BTUSB_INTEL) { + if (!disable_intel && (force_intel || id->driver_info & BTUSB_INTEL)) { hdev->manufacturer = 2; hdev->setup = btusb_setup_intel; hdev->shutdown = btusb_shutdown_intel; @@ -3716,7 +3775,7 @@ set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); } - if (id->driver_info & BTUSB_INTEL_NEW) { + if (!disable_intelnew && (force_intelnew || id->driver_info & BTUSB_INTEL_NEW)) { hdev->manufacturer = 2; hdev->send = btusb_send_frame_intel; hdev->setup = btusb_setup_intel_new; @@ -3730,11 +3789,11 @@ set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); } - if (id->driver_info & BTUSB_MARVELL) + if (!disable_marvel && (force_marvel || id->driver_info & BTUSB_MARVELL)) hdev->set_bdaddr = btusb_set_bdaddr_marvell; #ifdef CONFIG_BT_HCIBTUSB_MTK - if (id->driver_info & BTUSB_MEDIATEK) { + if (!disable_mediatek && (force_mediatek || id->driver_info & BTUSB_MEDIATEK)) { hdev->setup = btusb_mtk_setup; hdev->shutdown = btusb_mtk_shutdown; hdev->manufacturer = 70; @@ -3742,24 +3801,28 @@ } #endif - if (id->driver_info & BTUSB_SWAVE) { + if (!disable_npsetup && (force_npsetup || id->driver_info & BTUSB_NPSETUP)) { + set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + } + + if (!disable_swave && (force_swave || id->driver_info & BTUSB_SWAVE)) { set_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks); set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks); } - if (id->driver_info & BTUSB_INTEL_BOOT) { + if (!disable_intelboot && (force_intelboot || id->driver_info & BTUSB_INTEL_BOOT)) { hdev->manufacturer = 2; set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); } - if (id->driver_info & BTUSB_ATH3012) { + if (!disable_ath3012 && (force_ath3012 || id->driver_info & BTUSB_ATH3012)) { data->setup_on_usb = btusb_setup_qca; hdev->set_bdaddr = btusb_set_bdaddr_ath3012; set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); } - if (id->driver_info & BTUSB_QCA_ROME) { + if (!disable_qcarome && (force_qcarome || id->driver_info & BTUSB_QCA_ROME)) { data->setup_on_usb = btusb_setup_qca; hdev->set_bdaddr = btusb_set_bdaddr_ath3012; set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); @@ -3788,55 +3851,131 @@ data->isoc_ifnum = ifnum_base + 1; } - if (!reset) + // TODO: Check logic + if (!disable_rocfix && (force_rocfix || !reset)) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) { - if (!disable_scofix) + if (!disable_scofix) { + if (debug > 10 && force_scofix) + printk("btusb: Forcing SCO fix as per module parameters."); set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); } + else if(debug > 10) + { + printk("btusb: Disabling SCO fix as per module parameters."); + } + } + + if (force_slkfix || id->driver_info & BTUSB_BROKEN_SLK) { + if (!disable_slkfix) { + if (debug > 10 && force_slkfix) + printk("btusb: Forcing Stored Link Key fix as per module parameters."); + set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); + } + else if(debug > 10) + { + printk("btusb: Disabling Stored Link Key fix as per module parameters."); + } + } - if (id->driver_info & BTUSB_BROKEN_ISOC) + if (force_noisoc || id->driver_info & BTUSB_BROKEN_ISOC) { + if(!disable_noisoc) { + if (debug > 10 && force_noisoc) + printk("btusb: Forcing broken ISOC fix as per module parameters."); data->isoc = NULL; + } + else if(debug > 10) + { + printk("btusb: Disabling broken ISOC fix as per module parameters."); + } + } - if (id->driver_info & BTUSB_DIGIANSWER) { + if (!disable_digianswer && (force_digianswer || id->driver_info & BTUSB_DIGIANSWER)) { data->cmdreq_type = USB_TYPE_VENDOR; + if(!disable_digianswer) { set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); } + } - if (id->driver_info & BTUSB_CSR) { + if (force_csrfix || id->driver_info & BTUSB_CSR) { + if(!disable_csrfix) { struct usb_device *udev = data->udev; u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice); + if(debug > 10 && force_csrfix) + printk("btusb: Forcing CSR fix as per module parameters."); + + /* Old firmware would otherwise execute USB reset */ if (bcdDevice < 0x117) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); /* Fake CSR devices with broken commands */ - if (bcdDevice <= 0x100 || bcdDevice == 0x134) + if (!disable_fakecsr && (force_fakecsr || + bcdDevice <= 0x100 || + bcdDevice == 0x134 || + bcdDevice == 0x8891) + ) { + if(debug > 10) + { + if(force_fakecsr) + printk("btusb: Forcing Fake CSR fix as per module parameters."); + else + printk("btusb: Forcing Fake CSR fix by bcdDevice (0x%04x).", bcdDevice); + } hdev->setup = btusb_setup_csr; + } + else if(disable_fakecsr && debug > 10) + { + printk("btusb: Disabling Fake CSR fix as per module parameters."); + } set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); } + else if(debug > 10) + { + printk("btusb: Disabling CSR fix as per module parameters."); + } + } - if (id->driver_info & BTUSB_SNIFFER) { + if (force_sniffer || id->driver_info & BTUSB_SNIFFER) { + if(!disable_sniffer) { struct usb_device *udev = data->udev; + if(debug > 10 && force_sniffer) { + printk("btusb: Forcing Sniffer fix as per module parameters."); + } /* New sniffer firmware has crippled HCI interface */ if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); } + else if(debug > 10) + { + printk("btusb: Disabling Sniffer fix as per module parameters."); + } + } - if (id->driver_info & BTUSB_INTEL_BOOT) { + if (force_intelboot || id->driver_info & BTUSB_INTEL_BOOT) { /* A bug in the bootloader causes that interrupt interface is * only enabled after receiving SetInterface(0, AltSetting=0). */ + if(!disable_intelboot) + { + if(debug > 10 && force_intelboot) { + printk("btusb: Disabling Intel Boot fix as per module parameters."); + } err = usb_set_interface(data->udev, 0, 0); if (err < 0) { BT_ERR("failed to set interface 0, alt 0 %d", err); goto out_free_dev; } } + else if(debug > 10) + { + printk("btusb: Disabling Intel Boot fix as per module parameters."); + } + } if (data->isoc) { err = usb_driver_claim_interface(&btusb_driver, @@ -4061,12 +4200,117 @@ module_usb_driver(btusb_driver); +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level. Set to 99 for full debug."); + +module_param(disable_csrfix, bool, 0644); +MODULE_PARM_DESC(disable_csrfix, "Disable fixup for CSR"); + +module_param(force_csrfix, bool, 0644); +MODULE_PARM_DESC(force_csrfix, "Force fixup for CSR"); + +module_param(disable_fakecsr, bool, 0644); +MODULE_PARM_DESC(disable_fakecsr, "Disable fixup for Fake CSR"); + +module_param(force_fakecsr, bool, 0644); +MODULE_PARM_DESC(force_fakecsr, "Force fixup for Fake CSR"); + +module_param(disable_npsetup, bool, 0644); +MODULE_PARM_DESC(disable_npsetup, "Disable Non Persistent Setup fixup"); + +module_param(force_npsetup, bool, 0644); +MODULE_PARM_DESC(force_npsetup, "Force Non Persistent Setup fixup"); + +module_param(disable_sniffer, bool, 0644); +MODULE_PARM_DESC(disable_sniffer, "Disable Sniffer fixup"); + +module_param(force_sniffer, bool, 0644); +MODULE_PARM_DESC(force_sniffer, "Force Sniffer fixup"); + +module_param(disable_intelboot, bool, 0644); +MODULE_PARM_DESC(disable_intelboot, "Disable Intel boot fixup"); + +module_param(force_intelboot, bool, 0644); +MODULE_PARM_DESC(force_intelboot, "Force Intel boot fixup"); + module_param(disable_scofix, bool, 0644); MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size"); module_param(force_scofix, bool, 0644); MODULE_PARM_DESC(force_scofix, "Force fixup of wrong SCO buffers size"); +module_param(disable_slkfix, bool, 0644); +MODULE_PARM_DESC(disable_slkfix, "Disable fixup of broken Stored Link Key"); + +module_param(force_slkfix, bool, 0644); +MODULE_PARM_DESC(force_slkfix, "Force fixup of broken Stored Link Key"); + +module_param(disable_rocfix, bool, 0644); +MODULE_PARM_DESC(disable_rocfix, "Disable reset on close fixup"); + +module_param(force_rocfix, bool, 0644); +MODULE_PARM_DESC(force_rocfix, "Force reset on close fixup"); + +module_param(disable_noisoc, bool, 0644); +MODULE_PARM_DESC(disable_noisoc, "Disable broken ISOC fixup"); + +module_param(force_noisoc, bool, 0644); +MODULE_PARM_DESC(force_noisoc, "Force broken ISOC fixup"); + +module_param(disable_ath3012, bool, 0644); +MODULE_PARM_DESC(disable_ath3012, "Disable ATH3012 fixup"); + +module_param(force_ath3012, bool, 0644); +MODULE_PARM_DESC(force_ath3012, "Force ATH3012 fixup"); + +module_param(disable_bcm92035, bool, 0644); +MODULE_PARM_DESC(disable_bcm92035, "Disable BCM92035 fixup"); + +module_param(force_bcm92035, bool, 0644); +MODULE_PARM_DESC(force_bcm92035, "Force BCM92035 fixup"); + +module_param(disable_digianswer, bool, 0644); +MODULE_PARM_DESC(disable_digianswer, "Disable Digianswer fixup"); + +module_param(force_digianswer, bool, 0644); +MODULE_PARM_DESC(force_digianswer, "Force Digianswer fixup"); + +module_param(disable_intel, bool, 0644); +MODULE_PARM_DESC(disable_intel, "Disable Intel fixup"); + +module_param(force_intel, bool, 0644); +MODULE_PARM_DESC(force_intel, "Force Intel fixup"); + +module_param(disable_intelnew, bool, 0644); +MODULE_PARM_DESC(disable_intelnew, "Disable Intel new fixup"); + +module_param(force_intelnew, bool, 0644); +MODULE_PARM_DESC(force_intelnew, "Force Intel new fixup"); + +module_param(disable_marvel, bool, 0644); +MODULE_PARM_DESC(disable_marvel, "Disable Marvel fixup"); + +module_param(force_marvel, bool, 0644); +MODULE_PARM_DESC(force_marvel, "Force Marvel fixup"); + +module_param(disable_mediatek, bool, 0644); +MODULE_PARM_DESC(disable_mediatek, "Disable Mediatek fixup"); + +module_param(force_mediatek, bool, 0644); +MODULE_PARM_DESC(force_mediatek, "Force Mediatek fixup"); + +module_param(disable_qcarome, bool, 0644); +MODULE_PARM_DESC(disable_qcarome, "Disable QCA Rome fixup"); + +module_param(force_qcarome, bool, 0644); +MODULE_PARM_DESC(force_qcarome, "Force QCA Rome fixup"); + +module_param(disable_swave, bool, 0644); +MODULE_PARM_DESC(disable_swave, "Disable Swave fixup"); + +module_param(force_swave, bool, 0644); +MODULE_PARM_DESC(force_swave, "Force sWave fixup"); + module_param(enable_autosuspend, bool, 0644); MODULE_PARM_DESC(enable_autosuspend, "Enable USB autosuspend by default");