My latest howto and the two patches from bluetooth-next to fix the issue on Debian/stretch AMD64. - Sedat -
ISSUE: A Broadcom BCM20702A0 bluetooth dongle in a ThinkPad-T530 does not really support HCI_Set_Event_Mask_Page_2 command and is not usable. HELP-1: See discussion on linux-bluetooth Mailing-list with the topic HELP-1: "[Linux-4.9.30] Broadcom BCM20702 bluetooth in ThinkPad-T530 not usable" HELP-2: Build-instructions adapted from <https://github.com/neurobin/MT7630E/issues/6> NOTE-1: My system is a Debian/stretch 9.0 with linux-image-4.9.0-3-amd64 (4.9.30-1) package installed. NOTE-2: Debian does not ship a fitting firmware, see <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=801084>. PREREQ: You need a firmware file from <https://github.com/winterheart/broadcom-bt-firmware>. PREREQ: You should have a /lib/firmware/brcm/BCM20702A1-0a5c-21e6.hcd PATCH-1: "[PATCH] Bluetooth: Send HCI Set Event Mask Page 2 command only when needed" PATCH-1: <https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git/patch/?id=313f6888c8fbb1bc8b36c9012ce4e1de848df696> PATCH-1: Backport for Linux v4.9.30 see <http://marc.info/?l=linux-bluetooth&m=149726402220677&w=2> PATCH-2: "[PATCH] Bluetooth: btbcm: Read controller features during configuration" PATCH-2: <https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git/commit/?id=4284ecbeda81083f4c7a3ce325b4a9d675657e61> PATCH-3: "[PATCH] Bluetooth: btusb: set HCI_QUIRK_BROKEN_LOCAL_COMMANDS for 0x0a5c:0x21f3" PATCH-3: Sample patch to demonstrate HCI_QUIRK_BROKEN_LOCAL_COMMANDS usage, see <https://www.spinics.net/lists/linux-bluetooth/msg70436.html> [ CHECK STATUS AND STOP BLUETOOTH SERVICE ] sudo systemctl status bluetooth.service sudo systemctl stop bluetooth.service [ DOWNLOAD DEBIAN-KERNEL HEADERS AND TOOLS ] sudo apt-get install build-essential linux-headers-$(uname -r) sudo apt-get build-dep linux-image-$(uname -r) [ CREATE A BUILD-ENVIRONMENT ] mkdir -p ~/src/linux-kernel cd ~/src/linux-kernel [ DOWNLOAD AND UNPACK DEBIAN-KERNEL SOURCES ] apt-get source linux-image-$(uname -r) -d dpkg-source -x *.dsc [ PREPARE, GENERATE AND COPY BLUETOOTH.KO AND BTBCM.KO KERNEL-MODULES ] KVER="4.9.30" cd linux-$KVER [ PATCH-1 REQUIRES A REBUILD OF BLUETOOTH.KO KERNEL-MODULE ] patch -Np1 -i ../patches/bluetooth-fixes-4.9.30/1-2-Bluetooth-Send-HCI-Set-Event-Mask-Page-2-command-only-when-needed-for-4-9-30.patch [ PATCH-2 REQUIRES A REBUILD OF BTBCM.KO KERNEL-MODULE ] patch -Np1 -i ../patches/bluetooth-fixes-4.9.30/2-2-Bluetooth-btbcm-Read-controller-features-during-configuration.patch cp -av /boot/config-$(uname -r) .config cp -av /usr/src/linux-headers-$(uname -r)/Module.symvers ./ make prepare make modules_prepare make M=scripts/mod make M=net/bluetooth modules make M=drivers/bluetooth modules KPATH_MODULES="/lib/modules/$(uname -r)/kernel" sudo cp -av net/bluetooth/bluetooth.ko $KPATH_MODULES/net/bluetooth/ sudo cp -av drivers/bluetooth/btbcm.ko $KPATH_MODULES/drivers/bluetooth/ sudo chown root:root $KPATH_MODULES/net/bluetooth/bluetooth.ko $KPATH_MODULES/drivers/bluetooth/btbcm.ko ll $KPATH_MODULES/net/bluetooth/bluetooth.ko $KPATH_MODULES/drivers/bluetooth/btbcm.ko [ START BLUETOOTH SERVICE ] sudo systemctl start bluetooth.service [ ALTERNATIVELY MONITOR HCI0 ] [ SESSION #1 ] modprobe -r -v btusb modprobe -v btusb rfkill list bluetooth ( rfkill unblock bluetooth ) hciconfig hci0 up bluetoothctl ( list & show ) [ SESSION #2 ] [ BTMON BTSNOOP-FORMAT ] btmon -w btmom-w_bcm20702-fixed.log [ CONVERT TO ASCII TEXT ] btmod -r btmom-w_bcm20702-fixed.log > btmom-w_bcm20702-fixed.txt [ SUCCESS ] The bluetooth dongle should now work! -dileks // 13-JUN-2017
From 313f6888c8fbb1bc8b36c9012ce4e1de848df696 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann <marcel@xxxxxxxxxxxx> Date: Fri, 9 Jun 2017 18:43:56 +0200 Subject: [4.9.30] 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 <marcel@xxxxxxxxxxxx> Reported-by: Sedat Dilek <sedat.dilek@xxxxxxxxx> Tested-by: Sedat Dilek <sedat.dilek@xxxxxxxxx> Signed-off-by: Szymon Janc <szymon.janc@xxxxxxxxxxx> --- [ Backported to fit Linux v4.9.30. -dileks ] 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 3ac89e9..5049433 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 @@ -570,10 +572,20 @@ static void hci_set_event_mask_page_2(struct hci_request *req) } /* 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 <marcel@xxxxxxxxxxxx> Date: Sat, 10 Jun 2017 14:33:16 +0200 Subject: 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 <marcel@xxxxxxxxxxxx> Signed-off-by: Szymon Janc <szymon.janc@xxxxxxxxxxx> --- drivers/bluetooth/btbcm.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index ba3dd2e..24f8c4e 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)) { -- cgit v1.1