2019-05-27 14:55:05 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2007-10-20 20:12:34 +08:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Generic Bluetooth USB driver
|
|
|
|
*
|
2008-08-18 19:23:52 +08:00
|
|
|
* Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
|
2007-10-20 20:12:34 +08:00
|
|
|
*/
|
|
|
|
|
2018-02-20 16:06:18 +08:00
|
|
|
#include <linux/dmi.h>
|
2007-10-20 20:12:34 +08:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/usb.h>
|
2018-01-08 17:44:16 +08:00
|
|
|
#include <linux/usb/quirks.h>
|
2013-04-20 00:57:43 +08:00
|
|
|
#include <linux/firmware.h>
|
2019-06-02 08:02:48 +08:00
|
|
|
#include <linux/iopoll.h>
|
2017-02-02 06:24:09 +08:00
|
|
|
#include <linux/of_device.h>
|
|
|
|
#include <linux/of_irq.h>
|
2017-02-24 14:24:29 +08:00
|
|
|
#include <linux/suspend.h>
|
2019-01-25 07:28:14 +08:00
|
|
|
#include <linux/gpio/consumer.h>
|
2021-12-04 06:38:13 +08:00
|
|
|
#include <linux/debugfs.h>
|
2024-10-02 03:35:57 +08:00
|
|
|
#include <linux/unaligned.h>
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
#include <net/bluetooth/bluetooth.h>
|
|
|
|
#include <net/bluetooth/hci_core.h>
|
|
|
|
|
2015-04-06 15:52:12 +08:00
|
|
|
#include "btintel.h"
|
2015-04-06 13:52:11 +08:00
|
|
|
#include "btbcm.h"
|
2015-05-14 16:49:09 +08:00
|
|
|
#include "btrtl.h"
|
2021-10-19 05:30:12 +08:00
|
|
|
#include "btmtk.h"
|
2015-04-06 13:52:11 +08:00
|
|
|
|
2015-04-06 13:52:16 +08:00
|
|
|
#define VERSION "0.8"
|
2008-08-08 04:26:56 +08:00
|
|
|
|
2012-01-13 07:02:20 +08:00
|
|
|
static bool disable_scofix;
|
|
|
|
static bool force_scofix;
|
2017-11-13 21:44:16 +08:00
|
|
|
static bool enable_autosuspend = IS_ENABLED(CONFIG_BT_HCIBTUSB_AUTOSUSPEND);
|
2022-10-26 05:12:57 +08:00
|
|
|
static bool enable_poll_sync = IS_ENABLED(CONFIG_BT_HCIBTUSB_POLL_SYNC);
|
2015-05-26 02:23:40 +08:00
|
|
|
static bool reset = true;
|
2008-08-08 04:26:56 +08:00
|
|
|
|
|
|
|
static struct usb_driver btusb_driver;
|
|
|
|
|
2022-03-04 06:17:07 +08:00
|
|
|
#define BTUSB_IGNORE BIT(0)
|
|
|
|
#define BTUSB_DIGIANSWER BIT(1)
|
|
|
|
#define BTUSB_CSR BIT(2)
|
|
|
|
#define BTUSB_SNIFFER BIT(3)
|
|
|
|
#define BTUSB_BCM92035 BIT(4)
|
|
|
|
#define BTUSB_BROKEN_ISOC BIT(5)
|
|
|
|
#define BTUSB_WRONG_SCO_MTU BIT(6)
|
|
|
|
#define BTUSB_ATH3012 BIT(7)
|
|
|
|
#define BTUSB_INTEL_COMBINED BIT(8)
|
|
|
|
#define BTUSB_INTEL_BOOT BIT(9)
|
|
|
|
#define BTUSB_BCM_PATCHRAM BIT(10)
|
|
|
|
#define BTUSB_MARVELL BIT(11)
|
|
|
|
#define BTUSB_SWAVE BIT(12)
|
|
|
|
#define BTUSB_AMP BIT(13)
|
|
|
|
#define BTUSB_QCA_ROME BIT(14)
|
|
|
|
#define BTUSB_BCM_APPLE BIT(15)
|
|
|
|
#define BTUSB_REALTEK BIT(16)
|
|
|
|
#define BTUSB_BCM2045 BIT(17)
|
|
|
|
#define BTUSB_IFNUM_2 BIT(18)
|
|
|
|
#define BTUSB_CW6622 BIT(19)
|
|
|
|
#define BTUSB_MEDIATEK BIT(20)
|
|
|
|
#define BTUSB_WIDEBAND_SPEECH BIT(21)
|
2024-08-12 23:01:15 +08:00
|
|
|
#define BTUSB_INVALID_LE_STATES BIT(22)
|
2022-03-04 06:17:07 +08:00
|
|
|
#define BTUSB_QCA_WCN6855 BIT(23)
|
|
|
|
#define BTUSB_INTEL_BROKEN_SHUTDOWN_LED BIT(24)
|
|
|
|
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25)
|
|
|
|
#define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26)
|
2022-12-17 04:12:47 +08:00
|
|
|
#define BTUSB_ACTIONS_SEMI BIT(27)
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2013-10-11 22:46:18 +08:00
|
|
|
static const struct usb_device_id btusb_table[] = {
|
2007-10-20 20:12:34 +08:00
|
|
|
/* Generic Bluetooth USB device */
|
|
|
|
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
|
|
|
|
|
2015-01-29 12:27:34 +08:00
|
|
|
/* Generic Bluetooth AMP device */
|
|
|
|
{ USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP },
|
|
|
|
|
2015-07-18 01:12:25 +08:00
|
|
|
/* Generic Bluetooth USB interface */
|
|
|
|
{ USB_INTERFACE_INFO(0xe0, 0x01, 0x01) },
|
|
|
|
|
2012-08-26 01:28:06 +08:00
|
|
|
/* Apple-specific (Broadcom) devices */
|
2015-03-22 22:52:38 +08:00
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01),
|
2015-10-20 06:53:33 +08:00
|
|
|
.driver_info = BTUSB_BCM_APPLE | BTUSB_IFNUM_2 },
|
2012-08-26 01:28:06 +08:00
|
|
|
|
2013-06-04 21:40:26 +08:00
|
|
|
/* MediaTek MT76x0E */
|
|
|
|
{ USB_DEVICE(0x0e8d, 0x763f) },
|
|
|
|
|
2011-09-21 17:41:45 +08:00
|
|
|
/* Broadcom SoftSailing reporting vendor specific */
|
2012-03-29 04:41:11 +08:00
|
|
|
{ USB_DEVICE(0x0a5c, 0x21e1) },
|
2011-09-21 17:41:45 +08:00
|
|
|
|
2010-08-20 15:24:07 +08:00
|
|
|
/* Apple MacBookPro 7,1 */
|
|
|
|
{ USB_DEVICE(0x05ac, 0x8213) },
|
|
|
|
|
2010-07-14 14:29:27 +08:00
|
|
|
/* Apple iMac11,1 */
|
|
|
|
{ USB_DEVICE(0x05ac, 0x8215) },
|
|
|
|
|
2010-08-20 15:24:06 +08:00
|
|
|
/* Apple MacBookPro6,2 */
|
|
|
|
{ USB_DEVICE(0x05ac, 0x8218) },
|
|
|
|
|
2010-11-04 15:04:33 +08:00
|
|
|
/* Apple MacBookAir3,1, MacBookAir3,2 */
|
|
|
|
{ USB_DEVICE(0x05ac, 0x821b) },
|
|
|
|
|
2011-09-07 14:28:10 +08:00
|
|
|
/* Apple MacBookAir4,1 */
|
|
|
|
{ USB_DEVICE(0x05ac, 0x821f) },
|
|
|
|
|
2011-03-25 01:51:21 +08:00
|
|
|
/* Apple MacBookPro8,2 */
|
|
|
|
{ USB_DEVICE(0x05ac, 0x821a) },
|
|
|
|
|
2011-09-05 00:01:42 +08:00
|
|
|
/* Apple MacMini5,1 */
|
|
|
|
{ USB_DEVICE(0x05ac, 0x8281) },
|
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
/* AVM BlueFRITZ! USB v2.0 */
|
2015-01-02 09:34:37 +08:00
|
|
|
{ USB_DEVICE(0x057c, 0x3800), .driver_info = BTUSB_SWAVE },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
|
|
|
/* Bluetooth Ultraport Module from IBM */
|
|
|
|
{ USB_DEVICE(0x04bf, 0x030a) },
|
|
|
|
|
|
|
|
/* ALPS Modules with non-standard id */
|
|
|
|
{ USB_DEVICE(0x044e, 0x3001) },
|
|
|
|
{ USB_DEVICE(0x044e, 0x3002) },
|
|
|
|
|
|
|
|
/* Ericsson with non-standard id */
|
|
|
|
{ USB_DEVICE(0x0bdb, 0x1002) },
|
|
|
|
|
|
|
|
/* Canyon CN-BTU1 with HID interfaces */
|
2008-11-30 19:17:26 +08:00
|
|
|
{ USB_DEVICE(0x0c10, 0x0000) },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
2015-01-27 12:35:32 +08:00
|
|
|
/* Broadcom BCM20702B0 (Dynex/Insignia) */
|
|
|
|
{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
|
|
|
|
|
Bluetooth: btusb: Add support for Foxconn/Lenovo BCM43142A0 (105b:e065)
Recently salvaged this 'BCM43142A0' WiFi/Bluetooth module from a Lenovo laptop
and noticed it doesn't work automatically, because the USB IDs are missing
from btusb.c.
Plugging in the adapter on Linux 4.1 (dmesg):
usb 3-3.3.3: new full-speed USB device number 90 using xhci_hcd
usb 3-3.3.3: New USB device found, idVendor=105b, idProduct=e065
usb 3-3.3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-3.3.3: Product: BCM43142A0
usb 3-3.3.3: Manufacturer: Broadcom Corp
usb 3-3.3.3: SerialNumber: 0090A286559E
/sys/kernel/debug/usb/devices:
T: Bus=03 Lev=03 Prnt=22 Port=02 Cnt=02 Dev#= 90 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=105b ProdID=e065 Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM43142A0
S: SerialNumber=0090A286559E
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)
Support for the chipset was added in commit 88f9b65 and a similar BCM43142
based device was added in commit 8f0c304.
To work around the issue, I got the firmware
(BCM43142A0_001.001.011.0122.0153) off a Windows installation of Broadcom
bluetooth driver and converted it to a .hcd -file via. hex2hcd and placed it
in /lib/firmware/brcm/BCM.hcd. After that:
$ echo "105b e065 0 19ff 0239" > /sys/bus/usb/drivers/btusb/new_id
...(plug in the adapter)
usb 3-3.3.3: new full-speed USB device number 91 using xhci_hcd
usb 3-3.3.3: New USB device found, idVendor=105b, idProduct=e065
usb 3-3.3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-3.3.3: Product: BCM43142A0
usb 3-3.3.3: Manufacturer: Broadcom Corp
usb 3-3.3.3: SerialNumber: 0090A286559E
Bluetooth: hci0: BCM: chip id 70
Bluetooth: hci0: BCM (001.001.011) build 0000
bluetooth hci0: firmware: direct-loading firmware brcm/BCM.hcd
Bluetooth: hci0: BCM (001.001.011) build 0154
Bam, now it works for me!
/sys/kernel/debug/usb/devices:
T: Bus=03 Lev=03 Prnt=22 Port=02 Cnt=02 Dev#= 92 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=105b ProdID=e065 Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM43142A0
S: SerialNumber=0090A286559E
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)
Signed-off-by: Santtu Rekilä <sare@r00t3d.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-10-05 20:45:27 +08:00
|
|
|
/* Broadcom BCM43142A0 (Foxconn/Lenovo) */
|
2017-07-06 19:41:13 +08:00
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x105b, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
Bluetooth: btusb: Add support for Foxconn/Lenovo BCM43142A0 (105b:e065)
Recently salvaged this 'BCM43142A0' WiFi/Bluetooth module from a Lenovo laptop
and noticed it doesn't work automatically, because the USB IDs are missing
from btusb.c.
Plugging in the adapter on Linux 4.1 (dmesg):
usb 3-3.3.3: new full-speed USB device number 90 using xhci_hcd
usb 3-3.3.3: New USB device found, idVendor=105b, idProduct=e065
usb 3-3.3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-3.3.3: Product: BCM43142A0
usb 3-3.3.3: Manufacturer: Broadcom Corp
usb 3-3.3.3: SerialNumber: 0090A286559E
/sys/kernel/debug/usb/devices:
T: Bus=03 Lev=03 Prnt=22 Port=02 Cnt=02 Dev#= 90 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=105b ProdID=e065 Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM43142A0
S: SerialNumber=0090A286559E
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)
Support for the chipset was added in commit 88f9b65 and a similar BCM43142
based device was added in commit 8f0c304.
To work around the issue, I got the firmware
(BCM43142A0_001.001.011.0122.0153) off a Windows installation of Broadcom
bluetooth driver and converted it to a .hcd -file via. hex2hcd and placed it
in /lib/firmware/brcm/BCM.hcd. After that:
$ echo "105b e065 0 19ff 0239" > /sys/bus/usb/drivers/btusb/new_id
...(plug in the adapter)
usb 3-3.3.3: new full-speed USB device number 91 using xhci_hcd
usb 3-3.3.3: New USB device found, idVendor=105b, idProduct=e065
usb 3-3.3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-3.3.3: Product: BCM43142A0
usb 3-3.3.3: Manufacturer: Broadcom Corp
usb 3-3.3.3: SerialNumber: 0090A286559E
Bluetooth: hci0: BCM: chip id 70
Bluetooth: hci0: BCM (001.001.011) build 0000
bluetooth hci0: firmware: direct-loading firmware brcm/BCM.hcd
Bluetooth: hci0: BCM (001.001.011) build 0154
Bam, now it works for me!
/sys/kernel/debug/usb/devices:
T: Bus=03 Lev=03 Prnt=22 Port=02 Cnt=02 Dev#= 92 Spd=12 MxCh= 0
D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=105b ProdID=e065 Rev= 1.12
S: Manufacturer=Broadcom Corp
S: Product=BCM43142A0
S: SerialNumber=0090A286559E
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)
Signed-off-by: Santtu Rekilä <sare@r00t3d.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-10-05 20:45:27 +08:00
|
|
|
|
2017-02-10 21:02:45 +08:00
|
|
|
/* Broadcom BCM920703 (HTC Vive) */
|
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bb4, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
|
|
|
|
2012-04-14 02:45:55 +08:00
|
|
|
/* Foxconn - Hon Hai */
|
2014-12-04 02:32:22 +08:00
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
2012-04-14 02:45:55 +08:00
|
|
|
|
2015-02-03 01:50:14 +08:00
|
|
|
/* Lite-On Technology - Broadcom based */
|
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x04ca, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
|
|
|
|
2014-02-19 00:26:19 +08:00
|
|
|
/* Broadcom devices with vendor specific id */
|
2014-05-09 06:50:01 +08:00
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
2012-08-07 02:36:49 +08:00
|
|
|
|
2014-07-21 20:02:33 +08:00
|
|
|
/* ASUSTek Computer - Broadcom based */
|
2015-01-17 12:29:12 +08:00
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
2014-07-21 20:02:33 +08:00
|
|
|
|
2013-09-22 02:14:43 +08:00
|
|
|
/* Belkin F8065bf - Broadcom based */
|
2015-03-28 06:11:41 +08:00
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
2013-09-22 02:14:43 +08:00
|
|
|
|
2014-02-15 19:01:09 +08:00
|
|
|
/* IMC Networks - Broadcom based */
|
2015-03-28 06:11:41 +08:00
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
2014-02-15 19:01:09 +08:00
|
|
|
|
2017-01-10 15:41:13 +08:00
|
|
|
/* Dell Computer - Broadcom based */
|
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x413c, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
|
|
|
|
2015-12-05 19:09:36 +08:00
|
|
|
/* Toshiba Corp - Broadcom based */
|
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_BCM_PATCHRAM },
|
|
|
|
|
2014-07-06 19:29:58 +08:00
|
|
|
/* Intel Bluetooth USB Bootloader (RAM module) */
|
2014-07-06 20:53:55 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0a5a),
|
|
|
|
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
|
2014-07-06 19:29:58 +08:00
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
{ } /* Terminating entry */
|
|
|
|
};
|
|
|
|
|
|
|
|
MODULE_DEVICE_TABLE(usb, btusb_table);
|
|
|
|
|
2023-08-22 18:20:24 +08:00
|
|
|
static const struct usb_device_id quirks_table[] = {
|
2008-08-08 04:26:56 +08:00
|
|
|
/* CSR BlueCore devices */
|
|
|
|
{ USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
|
|
|
|
|
|
|
|
/* Broadcom BCM2033 without firmware */
|
|
|
|
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
|
|
|
|
|
2015-10-17 20:39:27 +08:00
|
|
|
/* Broadcom BCM2045 devices */
|
|
|
|
{ USB_DEVICE(0x0a5c, 0x2045), .driver_info = BTUSB_BCM2045 },
|
|
|
|
|
2010-11-26 20:05:46 +08:00
|
|
|
/* Atheros 3011 with sflash firmware */
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
|
2015-02-14 03:05:11 +08:00
|
|
|
{ USB_DEVICE(0x04f2, 0xaff1), .driver_info = BTUSB_IGNORE },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
|
2010-11-26 20:05:46 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
|
2012-06-08 20:32:50 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
|
2011-05-10 07:11:16 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
|
2010-11-26 20:05:46 +08:00
|
|
|
|
2011-01-26 17:10:59 +08:00
|
|
|
/* Atheros AR9285 Malbec with sflash firmware */
|
|
|
|
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
|
|
|
|
|
2011-02-11 18:08:53 +08:00
|
|
|
/* Atheros 3012 with sflash firmware */
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
2015-06-07 01:25:40 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
|
2014-10-06 19:01:49 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
|
2016-02-10 05:49:11 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
2014-04-18 02:37:13 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
|
2015-06-19 01:41:51 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
|
2015-05-02 18:36:58 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
|
2014-12-09 13:44:51 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
|
2016-02-28 16:04:06 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
|
2017-01-05 18:19:53 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3018), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
2015-10-06 00:29:33 +08:00
|
|
|
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
2014-08-08 19:33:56 +08:00
|
|
|
{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:20 +08:00
|
|
|
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
|
2013-03-15 11:00:39 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
2018-04-26 20:18:19 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
2013-03-12 03:41:58 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
2012-03-15 04:01:21 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
2014-01-16 22:37:11 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
|
2014-01-16 23:02:58 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
2013-03-18 23:45:11 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
2015-10-16 16:45:26 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x817b), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
2012-04-19 14:53:45 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
2013-08-30 17:41:40 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
2015-05-13 11:39:24 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0xe006), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
2012-12-11 11:41:20 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
2016-02-10 20:33:17 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
|
2013-07-15 11:59:03 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
2014-11-26 01:19:52 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
2015-01-18 05:16:51 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
|
2014-07-08 21:55:08 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
2016-03-04 06:32:19 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
|
2015-06-07 01:29:25 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
|
2016-05-10 04:36:11 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 },
|
2016-07-12 06:35:18 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3490), .driver_info = BTUSB_ATH3012 },
|
2011-02-11 18:08:53 +08:00
|
|
|
|
2011-02-15 10:20:07 +08:00
|
|
|
/* Atheros AR5BBU12 with sflash firmware */
|
|
|
|
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
|
|
|
|
2012-05-03 04:33:40 +08:00
|
|
|
/* Atheros AR5BBU12 with sflash firmware */
|
2012-08-07 22:18:10 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
|
2012-05-03 04:33:40 +08:00
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
/* QCA ROME chipset */
|
2020-09-17 21:09:23 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0x535b), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-05-19 01:25:46 +08:00
|
|
|
{ USB_DEVICE(0x0cf3, 0xe500), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2020-09-17 21:09:23 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x301a), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x04ca, 0x3021), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3491), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2015-02-16 07:07:33 +08:00
|
|
|
|
2020-09-29 12:23:51 +08:00
|
|
|
/* QCA WCN6855 chipset */
|
|
|
|
{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-11-16 19:02:16 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0cc), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-11-16 19:02:16 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0d6), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-12-03 18:01:37 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0e3), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-12-09 14:34:01 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9309), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-12-09 14:34:01 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9409), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-01-07 11:59:09 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0d0), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9108), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9109), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9208), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9209), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9308), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9408), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9508), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9509), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9608), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9609), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x10ab, 0x9f09), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3022), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0c7), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0c9), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0ca), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0cb), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0ce), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0de), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0df), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0e1), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0ea), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0ec), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3023), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3024), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3a22), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3a24), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3a26), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-10-30 01:22:54 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3a27), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2020-09-29 12:23:51 +08:00
|
|
|
|
2022-04-25 23:01:29 +08:00
|
|
|
/* QCA WCN785x chipset */
|
|
|
|
{ USB_DEVICE(0x0cf3, 0xe700), .driver_info = BTUSB_QCA_WCN6855 |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-04-25 23:01:29 +08:00
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
/* Broadcom BCM2035 */
|
2008-11-30 19:17:26 +08:00
|
|
|
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
|
2014-02-19 00:26:19 +08:00
|
|
|
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
|
|
|
|
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
|
|
|
/* Broadcom BCM2045 */
|
2008-11-30 19:17:26 +08:00
|
|
|
{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
|
|
|
|
{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_WRONG_SCO_MTU },
|
2008-09-23 06:16:35 +08:00
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
/* IBM/Lenovo ThinkPad with Broadcom chip */
|
2008-11-30 19:17:26 +08:00
|
|
|
{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_WRONG_SCO_MTU },
|
|
|
|
{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_WRONG_SCO_MTU },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
|
|
|
/* HP laptop with Broadcom chip */
|
2008-11-30 19:17:26 +08:00
|
|
|
{ USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_WRONG_SCO_MTU },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
|
|
|
/* Dell laptop with Broadcom chip */
|
2008-11-30 19:17:26 +08:00
|
|
|
{ USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_WRONG_SCO_MTU },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
2008-11-30 19:17:27 +08:00
|
|
|
/* Dell Wireless 370 and 410 devices */
|
2008-11-30 19:17:26 +08:00
|
|
|
{ USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_WRONG_SCO_MTU },
|
2008-11-30 19:17:27 +08:00
|
|
|
{ USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_WRONG_SCO_MTU },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
2008-11-30 19:17:26 +08:00
|
|
|
/* 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 },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
2008-11-30 19:17:27 +08:00
|
|
|
/* Asus WL-BTD202 device */
|
|
|
|
{ USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU },
|
|
|
|
|
|
|
|
/* Kensington Bluetooth USB adapter */
|
|
|
|
{ USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_WRONG_SCO_MTU },
|
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
/* RTX Telecom based adapters with buggy SCO support */
|
|
|
|
{ USB_DEVICE(0x0400, 0x0807), .driver_info = BTUSB_BROKEN_ISOC },
|
|
|
|
{ USB_DEVICE(0x0400, 0x080a), .driver_info = BTUSB_BROKEN_ISOC },
|
|
|
|
|
|
|
|
/* CONWISE Technology based adapters with buggy SCO support */
|
2016-09-01 23:22:37 +08:00
|
|
|
{ USB_DEVICE(0x0e5e, 0x6622),
|
|
|
|
.driver_info = BTUSB_BROKEN_ISOC | BTUSB_CW6622},
|
2008-08-08 04:26:56 +08:00
|
|
|
|
2015-01-02 09:34:37 +08:00
|
|
|
/* Roper Class 1 Bluetooth Dongle (Silicon Wave based) */
|
2015-06-08 17:02:10 +08:00
|
|
|
{ USB_DEVICE(0x1310, 0x0001), .driver_info = BTUSB_SWAVE },
|
2015-01-02 09:34:37 +08:00
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
/* Digianswer devices */
|
|
|
|
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
|
|
|
|
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
|
|
|
|
|
|
|
|
/* CSR BlueCore Bluetooth Sniffer */
|
2014-07-07 06:12:04 +08:00
|
|
|
{ USB_DEVICE(0x0a12, 0x0002),
|
|
|
|
.driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
|
|
|
/* Frontline ComProbe Bluetooth Sniffer */
|
2014-07-07 06:12:04 +08:00
|
|
|
{ USB_DEVICE(0x16d3, 0x0002),
|
|
|
|
.driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
|
2008-08-08 04:26:56 +08:00
|
|
|
|
2015-01-29 11:41:42 +08:00
|
|
|
/* Marvell Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
|
|
|
|
{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
|
2016-09-28 18:48:35 +08:00
|
|
|
{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
|
2015-01-29 11:41:42 +08:00
|
|
|
|
2015-01-29 11:41:43 +08:00
|
|
|
/* Intel Bluetooth devices */
|
2021-08-05 08:32:16 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_COMBINED },
|
|
|
|
{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_COMBINED },
|
|
|
|
{ USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_COMBINED },
|
|
|
|
{ USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_COMBINED },
|
|
|
|
{ USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED },
|
2022-02-01 00:32:35 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0035), .driver_info = BTUSB_INTEL_COMBINED },
|
2023-07-04 16:16:51 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0036), .driver_info = BTUSB_INTEL_COMBINED },
|
2024-05-02 13:23:56 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0037), .driver_info = BTUSB_INTEL_COMBINED },
|
2023-09-07 17:15:50 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0038), .driver_info = BTUSB_INTEL_COMBINED },
|
2024-07-05 18:29:23 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0039), .driver_info = BTUSB_INTEL_COMBINED },
|
2015-02-23 07:41:18 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
|
2021-08-05 08:32:12 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
|
2022-01-21 03:44:18 +08:00
|
|
|
BTUSB_INTEL_NO_WBS_SUPPORT |
|
2022-01-07 08:34:54 +08:00
|
|
|
BTUSB_INTEL_BROKEN_INITIAL_NCMD |
|
|
|
|
BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
|
|
|
|
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED |
|
2022-01-21 03:44:18 +08:00
|
|
|
BTUSB_INTEL_NO_WBS_SUPPORT |
|
2022-01-07 08:34:54 +08:00
|
|
|
BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
|
2021-08-05 08:32:16 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED },
|
2022-01-07 08:34:54 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED |
|
|
|
|
BTUSB_INTEL_BROKEN_SHUTDOWN_LED },
|
2021-08-05 08:32:16 +08:00
|
|
|
{ USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_COMBINED },
|
2013-04-20 00:57:43 +08:00
|
|
|
|
2015-01-29 11:41:43 +08:00
|
|
|
/* Other Intel Bluetooth devices */
|
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_IGNORE },
|
2014-07-19 05:47:06 +08:00
|
|
|
|
2022-12-26 03:07:13 +08:00
|
|
|
/* Realtek 8821CE Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3529), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
|
2020-07-13 15:45:29 +08:00
|
|
|
/* Realtek 8822CE Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK |
|
2021-06-02 03:04:18 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0bda, 0xc822), .driver_info = BTUSB_REALTEK |
|
2020-07-13 15:45:29 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
|
2022-12-01 17:43:53 +08:00
|
|
|
/* Realtek 8822CU Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3549), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
|
2020-11-10 11:38:37 +08:00
|
|
|
/* Realtek 8852AE Bluetooth devices */
|
2022-01-20 04:18:37 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2020-11-10 11:38:37 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0xc852), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-11-22 00:51:48 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0x385a), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-09-29 02:45:20 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0x4852), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-09-01 15:48:45 +08:00
|
|
|
{ USB_DEVICE(0x04c5, 0x165c), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-09-29 02:45:20 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x4006), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-08-17 05:35:22 +08:00
|
|
|
{ USB_DEVICE(0x0cb8, 0xc549), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2020-11-10 11:38:37 +08:00
|
|
|
|
2022-07-14 19:25:19 +08:00
|
|
|
/* Realtek 8852CE Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x04ca, 0x4007), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-07-14 19:25:20 +08:00
|
|
|
{ USB_DEVICE(0x04c5, 0x1675), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-07-14 19:25:21 +08:00
|
|
|
{ USB_DEVICE(0x0cb8, 0xc558), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-07-14 19:25:22 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3587), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-07-14 19:25:23 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3586), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-08-29 19:45:07 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-08-16 16:58:22 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-07-14 19:25:19 +08:00
|
|
|
|
2022-11-23 16:10:05 +08:00
|
|
|
/* Realtek 8852BE Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-03-29 10:34:39 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-03-23 08:52:02 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-10-12 19:21:17 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-09-24 19:16:55 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-03-23 08:52:03 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-12-20 01:35:47 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3572), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-06-22 12:09:59 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3591), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-06-17 17:05:18 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-11-23 16:10:05 +08:00
|
|
|
|
2023-12-26 19:45:17 +08:00
|
|
|
/* Realtek 8852BT/8852BE-VT Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x0bda, 0x8520), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-08-20 14:28:29 +08:00
|
|
|
|
|
|
|
/* Realtek 8922AE Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x0bda, 0x8922), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3617), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3616), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe130), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
|
2015-04-17 04:09:55 +08:00
|
|
|
/* Realtek Bluetooth devices */
|
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
|
|
|
|
.driver_info = BTUSB_REALTEK },
|
|
|
|
|
2019-06-02 08:02:48 +08:00
|
|
|
/* MediaTek Bluetooth devices */
|
|
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01),
|
2021-03-29 01:18:33 +08:00
|
|
|
.driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2019-06-02 08:02:48 +08:00
|
|
|
|
2020-11-10 11:40:10 +08:00
|
|
|
/* Additional MediaTek MT7615E Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
|
|
|
|
|
2022-02-11 17:31:03 +08:00
|
|
|
/* Additional MediaTek MT7663 Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x043e, 0x310c), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-02-28 13:55:17 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3801), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-02-11 17:31:03 +08:00
|
|
|
|
2021-07-12 15:32:20 +08:00
|
|
|
/* Additional MediaTek MT7668 Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x043e, 0x3109), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-07-12 15:32:20 +08:00
|
|
|
|
2021-04-12 23:06:27 +08:00
|
|
|
/* Additional MediaTek MT7921 Bluetooth devices */
|
2022-04-28 02:38:39 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-07-25 02:25:02 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0e0), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-12-15 10:18:54 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-04-12 23:06:27 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x0e8d, 0x0608), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-07-08 04:00:59 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-09-01 19:30:15 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-02-23 07:55:59 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3567), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-08-30 06:55:58 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3578), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-08-31 12:53:28 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3583), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:56 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3606), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-04-12 23:06:27 +08:00
|
|
|
|
2024-03-15 15:48:08 +08:00
|
|
|
/* MediaTek MT7922 Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3585), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-03-15 15:48:08 +08:00
|
|
|
|
2021-12-17 17:51:50 +08:00
|
|
|
/* MediaTek MT7922A Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x0489, 0xe0d8), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-12-17 17:51:50 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-06-25 17:03:57 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0e2), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-03-06 09:44:59 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0e4), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-07-13 05:36:02 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0f1), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-11-28 15:49:57 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-07-03 05:01:38 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-06-30 21:32:30 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe0f6), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-07-07 14:29:58 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-07-07 14:29:59 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3605), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3607), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3614), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3615), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:57 +08:00
|
|
|
{ USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-01-13 15:27:38 +08:00
|
|
|
|
|
|
|
/* Additional MediaTek MT7925 Bluetooth devices */
|
2024-04-23 14:51:56 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe113), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-09-01 12:28:47 +08:00
|
|
|
{ USB_DEVICE(0x0489, 0xe118), .driver_info = BTUSB_MEDIATEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe11e), .driver_info = BTUSB_MEDIATEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-01-13 15:27:38 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3602), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-04-23 14:51:56 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3603), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-07-31 06:08:25 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3604), .driver_info = BTUSB_MEDIATEK |
|
2024-08-12 23:01:15 +08:00
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2024-08-21 19:08:56 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3608), .driver_info = BTUSB_MEDIATEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-12-17 17:51:50 +08:00
|
|
|
|
2015-04-17 04:09:55 +08:00
|
|
|
/* Additional Realtek 8723AE Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK },
|
|
|
|
|
|
|
|
/* Additional Realtek 8723BE Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x0489, 0xe085), .driver_info = BTUSB_REALTEK },
|
|
|
|
{ USB_DEVICE(0x0489, 0xe08b), .driver_info = BTUSB_REALTEK },
|
2022-03-08 22:57:31 +08:00
|
|
|
{ USB_DEVICE(0x04f2, 0xb49f), .driver_info = BTUSB_REALTEK },
|
2015-04-17 04:09:55 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
|
2017-08-08 19:09:02 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
|
2015-04-17 04:09:55 +08:00
|
|
|
|
2018-03-21 02:41:10 +08:00
|
|
|
/* Additional Realtek 8723BU Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
|
|
|
|
|
2018-05-21 18:09:20 +08:00
|
|
|
/* Additional Realtek 8723DE Bluetooth devices */
|
2018-05-25 17:54:52 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
|
2018-05-21 18:09:20 +08:00
|
|
|
{ USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK },
|
|
|
|
|
2022-08-26 06:42:07 +08:00
|
|
|
/* Additional Realtek 8761BUV Bluetooth devices */
|
2021-09-30 16:22:39 +08:00
|
|
|
{ USB_DEVICE(0x2357, 0x0604), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-05-28 23:26:45 +08:00
|
|
|
{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-02-26 23:22:56 +08:00
|
|
|
{ USB_DEVICE(0x2550, 0x8761), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-04-27 20:59:48 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0x8771), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2023-05-10 03:45:24 +08:00
|
|
|
{ USB_DEVICE(0x6655, 0x8771), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-08-26 06:42:08 +08:00
|
|
|
{ USB_DEVICE(0x7392, 0xc611), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-11-08 20:54:13 +08:00
|
|
|
{ USB_DEVICE(0x2b89, 0x8761), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2022-04-27 20:59:48 +08:00
|
|
|
|
2015-04-17 04:09:55 +08:00
|
|
|
/* Additional Realtek 8821AE Bluetooth devices */
|
|
|
|
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3458), .driver_info = BTUSB_REALTEK },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
|
|
|
|
|
2018-02-12 02:24:32 +08:00
|
|
|
/* Additional Realtek 8822BE Bluetooth devices */
|
2018-05-30 16:23:00 +08:00
|
|
|
{ USB_DEVICE(0x13d3, 0x3526), .driver_info = BTUSB_REALTEK },
|
2018-02-12 02:24:32 +08:00
|
|
|
{ USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
|
|
|
|
|
2019-09-03 17:10:42 +08:00
|
|
|
/* Additional Realtek 8822CE Bluetooth devices */
|
2020-11-05 18:54:48 +08:00
|
|
|
{ USB_DEVICE(0x04ca, 0x4005), .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 |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3548), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3549), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3553), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x13d3, 0x3555), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
|
|
|
{ USB_DEVICE(0x2ff8, 0x3051), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2020-11-10 00:47:22 +08:00
|
|
|
{ USB_DEVICE(0x1358, 0xc123), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2020-11-19 13:16:25 +08:00
|
|
|
{ USB_DEVICE(0x0bda, 0xc123), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2021-02-18 19:11:24 +08:00
|
|
|
{ USB_DEVICE(0x0cb5, 0xc547), .driver_info = BTUSB_REALTEK |
|
|
|
|
BTUSB_WIDEBAND_SPEECH },
|
2019-09-03 17:10:42 +08:00
|
|
|
|
2022-12-17 04:12:47 +08:00
|
|
|
/* Actions Semiconductor ATS2851 based devices */
|
|
|
|
{ USB_DEVICE(0x10d7, 0xb012), .driver_info = BTUSB_ACTIONS_SEMI },
|
|
|
|
|
2015-08-16 02:47:09 +08:00
|
|
|
/* Silicon Wave based devices */
|
|
|
|
{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
{ } /* Terminating entry */
|
|
|
|
};
|
|
|
|
|
2018-02-20 16:06:18 +08:00
|
|
|
/* The Bluetooth USB module build into some devices needs to be reset on resume,
|
|
|
|
* this is a problem with the platform (likely shutting off all power) not with
|
|
|
|
* the module itself. So we use a DMI list to match known broken platforms.
|
|
|
|
*/
|
|
|
|
static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
|
|
|
|
{
|
2018-03-01 13:42:52 +08:00
|
|
|
/* Dell OptiPlex 3060 (QCA ROME device 0cf3:e007) */
|
2018-02-20 16:06:18 +08:00
|
|
|
.matches = {
|
2018-03-01 13:42:52 +08:00
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 3060"),
|
2018-02-20 16:06:18 +08:00
|
|
|
},
|
|
|
|
},
|
2018-04-27 02:52:06 +08:00
|
|
|
{
|
|
|
|
/* Dell XPS 9360 (QCA ROME device 0cf3:e300) */
|
|
|
|
.matches = {
|
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"),
|
|
|
|
},
|
|
|
|
},
|
2018-05-22 15:34:10 +08:00
|
|
|
{
|
|
|
|
/* Dell Inspiron 5565 (QCA ROME device 0cf3:e009) */
|
|
|
|
.matches = {
|
|
|
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5565"),
|
|
|
|
},
|
|
|
|
},
|
2018-02-20 16:06:18 +08:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2023-04-19 11:38:05 +08:00
|
|
|
struct qca_dump_info {
|
|
|
|
/* fields for dump collection */
|
|
|
|
u16 id_vendor;
|
|
|
|
u16 id_product;
|
|
|
|
u32 fw_version;
|
|
|
|
u32 controller_id;
|
|
|
|
u32 ram_dump_size;
|
|
|
|
u16 ram_dump_seqno;
|
|
|
|
};
|
|
|
|
|
2008-08-18 19:23:52 +08:00
|
|
|
#define BTUSB_MAX_ISOC_FRAMES 10
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
#define BTUSB_INTR_RUNNING 0
|
|
|
|
#define BTUSB_BULK_RUNNING 1
|
2008-08-18 19:23:52 +08:00
|
|
|
#define BTUSB_ISOC_RUNNING 2
|
2009-08-25 05:44:59 +08:00
|
|
|
#define BTUSB_SUSPENDING 3
|
2010-07-17 04:20:33 +08:00
|
|
|
#define BTUSB_DID_ISO_RESUME 4
|
2015-01-27 13:33:48 +08:00
|
|
|
#define BTUSB_BOOTLOADER 5
|
|
|
|
#define BTUSB_DOWNLOADING 6
|
2015-01-28 17:58:40 +08:00
|
|
|
#define BTUSB_FIRMWARE_LOADED 7
|
2015-01-27 13:33:48 +08:00
|
|
|
#define BTUSB_FIRMWARE_FAILED 8
|
2015-01-28 17:58:40 +08:00
|
|
|
#define BTUSB_BOOTING 9
|
2018-01-08 17:44:16 +08:00
|
|
|
#define BTUSB_DIAG_RUNNING 10
|
|
|
|
#define BTUSB_OOB_WAKE_ENABLED 11
|
2019-01-25 07:28:14 +08:00
|
|
|
#define BTUSB_HW_RESET_ACTIVE 12
|
2019-06-02 08:02:48 +08:00
|
|
|
#define BTUSB_TX_WAIT_VND_EVT 13
|
2021-08-17 11:03:12 +08:00
|
|
|
#define BTUSB_WAKEUP_AUTOSUSPEND 14
|
2021-07-27 02:02:06 +08:00
|
|
|
#define BTUSB_USE_ALT3_FOR_WBS 15
|
2022-10-05 16:43:31 +08:00
|
|
|
#define BTUSB_ALT6_CONTINUOUS_TX 16
|
2023-04-19 11:38:05 +08:00
|
|
|
#define BTUSB_HW_SSR_ACTIVE 17
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
struct btusb_data {
|
|
|
|
struct hci_dev *hdev;
|
|
|
|
struct usb_device *udev;
|
2008-09-23 06:16:36 +08:00
|
|
|
struct usb_interface *intf;
|
2008-08-18 19:23:52 +08:00
|
|
|
struct usb_interface *isoc;
|
2015-10-09 02:23:08 +08:00
|
|
|
struct usb_interface *diag;
|
2017-10-25 01:42:45 +08:00
|
|
|
unsigned isoc_ifnum;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
bool poll_sync;
|
|
|
|
int intr_interval;
|
|
|
|
struct work_struct work;
|
|
|
|
struct work_struct waker;
|
|
|
|
struct delayed_work rx_work;
|
|
|
|
|
|
|
|
struct sk_buff_head acl_q;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-16 14:00:29 +08:00
|
|
|
struct usb_anchor deferred;
|
2007-10-20 20:12:34 +08:00
|
|
|
struct usb_anchor tx_anchor;
|
2014-09-16 14:00:29 +08:00
|
|
|
int tx_in_flight;
|
|
|
|
spinlock_t txlock;
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
struct usb_anchor intr_anchor;
|
|
|
|
struct usb_anchor bulk_anchor;
|
2008-08-18 19:23:52 +08:00
|
|
|
struct usb_anchor isoc_anchor;
|
2015-10-09 02:23:08 +08:00
|
|
|
struct usb_anchor diag_anchor;
|
2019-06-02 08:02:48 +08:00
|
|
|
struct usb_anchor ctrl_anchor;
|
2014-09-16 14:00:29 +08:00
|
|
|
spinlock_t rxlock;
|
|
|
|
|
|
|
|
struct sk_buff *evt_skb;
|
|
|
|
struct sk_buff *acl_skb;
|
|
|
|
struct sk_buff *sco_skb;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
struct usb_endpoint_descriptor *intr_ep;
|
|
|
|
struct usb_endpoint_descriptor *bulk_tx_ep;
|
|
|
|
struct usb_endpoint_descriptor *bulk_rx_ep;
|
2008-08-18 19:23:52 +08:00
|
|
|
struct usb_endpoint_descriptor *isoc_tx_ep;
|
|
|
|
struct usb_endpoint_descriptor *isoc_rx_ep;
|
2015-10-09 02:23:08 +08:00
|
|
|
struct usb_endpoint_descriptor *diag_tx_ep;
|
|
|
|
struct usb_endpoint_descriptor *diag_rx_ep;
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2019-01-25 07:28:14 +08:00
|
|
|
struct gpio_desc *reset_gpio;
|
|
|
|
|
2008-11-30 19:17:26 +08:00
|
|
|
__u8 cmdreq_type;
|
2015-01-29 12:27:34 +08:00
|
|
|
__u8 cmdreq;
|
2008-11-30 19:17:26 +08:00
|
|
|
|
2009-02-05 00:41:38 +08:00
|
|
|
unsigned int sco_num;
|
2020-04-04 03:43:59 +08:00
|
|
|
unsigned int air_mode;
|
|
|
|
bool usb_alt6_packet_flow;
|
2008-08-18 19:23:52 +08:00
|
|
|
int isoc_altsetting;
|
2008-11-30 19:17:14 +08:00
|
|
|
int suspend_count;
|
2014-11-03 12:16:07 +08:00
|
|
|
|
2015-01-13 05:51:10 +08:00
|
|
|
int (*recv_event)(struct hci_dev *hdev, struct sk_buff *skb);
|
2021-08-04 17:03:15 +08:00
|
|
|
int (*recv_acl)(struct hci_dev *hdev, struct sk_buff *skb);
|
2014-11-03 12:16:07 +08:00
|
|
|
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
|
2015-02-16 07:06:14 +08:00
|
|
|
|
|
|
|
int (*setup_on_usb)(struct hci_dev *hdev);
|
2017-02-02 06:24:09 +08:00
|
|
|
|
2024-07-04 14:01:12 +08:00
|
|
|
int (*suspend)(struct hci_dev *hdev);
|
|
|
|
int (*resume)(struct hci_dev *hdev);
|
|
|
|
|
2017-02-02 06:24:09 +08:00
|
|
|
int oob_wake_irq; /* irq for out-of-band wake-on-bt */
|
2019-01-25 07:28:14 +08:00
|
|
|
unsigned cmd_timeout_cnt;
|
2023-04-19 11:38:05 +08:00
|
|
|
|
|
|
|
struct qca_dump_info qca_dump;
|
2007-10-20 20:12:34 +08:00
|
|
|
};
|
|
|
|
|
2022-10-06 17:09:31 +08:00
|
|
|
static void btusb_reset(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (hdev->reset) {
|
|
|
|
hdev->reset(hdev);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = hci_get_drvdata(hdev);
|
|
|
|
/* This is not an unbalanced PM reference since the device will reset */
|
|
|
|
err = usb_autopm_get_interface(data->intf);
|
|
|
|
if (err) {
|
|
|
|
bt_dev_err(hdev, "Failed usb_autopm_get_interface: %d", err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_dev_err(hdev, "Resetting usb device.");
|
|
|
|
usb_queue_reset_device(data->intf);
|
|
|
|
}
|
|
|
|
|
2019-01-25 07:28:14 +08:00
|
|
|
static void btusb_intel_cmd_timeout(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct gpio_desc *reset_gpio = data->reset_gpio;
|
2023-06-11 14:43:42 +08:00
|
|
|
struct btintel_data *intel_data = hci_get_priv(hdev);
|
2019-01-25 07:28:14 +08:00
|
|
|
|
|
|
|
if (++data->cmd_timeout_cnt < 5)
|
|
|
|
return;
|
|
|
|
|
2023-06-11 14:43:42 +08:00
|
|
|
if (intel_data->acpi_reset_method) {
|
|
|
|
if (test_and_set_bit(INTEL_ACPI_RESET_ACTIVE, intel_data->flags)) {
|
|
|
|
bt_dev_err(hdev, "acpi: last reset failed ? Not resetting again");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_dev_err(hdev, "Initiating acpi reset method");
|
|
|
|
/* If ACPI reset method fails, lets try with legacy GPIO
|
|
|
|
* toggling
|
|
|
|
*/
|
|
|
|
if (!intel_data->acpi_reset_method(hdev)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-25 07:28:14 +08:00
|
|
|
if (!reset_gpio) {
|
2022-10-06 17:09:31 +08:00
|
|
|
btusb_reset(hdev);
|
2019-01-25 07:28:14 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Toggle the hard reset line if the platform provides one. The reset
|
|
|
|
* is going to yank the device off the USB and then replug. So doing
|
|
|
|
* once is enough. The cleanup is handled correctly on the way out
|
|
|
|
* (standard USB disconnect), and the new device is detected cleanly
|
|
|
|
* and bound to the driver again like it should be.
|
|
|
|
*/
|
|
|
|
if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
|
|
|
|
bt_dev_err(hdev, "last reset failed? Not resetting again");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_dev_err(hdev, "Initiating HW reset via gpio");
|
2019-01-29 07:08:09 +08:00
|
|
|
gpiod_set_value_cansleep(reset_gpio, 1);
|
|
|
|
msleep(100);
|
|
|
|
gpiod_set_value_cansleep(reset_gpio, 0);
|
2019-01-25 07:28:14 +08:00
|
|
|
}
|
|
|
|
|
2023-04-27 11:27:55 +08:00
|
|
|
#define RTK_DEVCOREDUMP_CODE_MEMDUMP 0x01
|
|
|
|
#define RTK_DEVCOREDUMP_CODE_HW_ERR 0x02
|
|
|
|
#define RTK_DEVCOREDUMP_CODE_CMD_TIMEOUT 0x03
|
|
|
|
|
|
|
|
#define RTK_SUB_EVENT_CODE_COREDUMP 0x34
|
|
|
|
|
|
|
|
struct rtk_dev_coredump_hdr {
|
|
|
|
u8 type;
|
|
|
|
u8 code;
|
|
|
|
u8 reserved[2];
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
static inline void btusb_rtl_alloc_devcoredump(struct hci_dev *hdev,
|
|
|
|
struct rtk_dev_coredump_hdr *hdr, u8 *buf, u32 len)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
skb = alloc_skb(len + sizeof(*hdr), GFP_ATOMIC);
|
|
|
|
if (!skb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
skb_put_data(skb, hdr, sizeof(*hdr));
|
|
|
|
if (len)
|
|
|
|
skb_put_data(skb, buf, len);
|
|
|
|
|
|
|
|
if (!hci_devcd_init(hdev, skb->len)) {
|
|
|
|
hci_devcd_append(hdev, skb);
|
|
|
|
hci_devcd_complete(hdev);
|
|
|
|
} else {
|
|
|
|
bt_dev_err(hdev, "RTL: Failed to generate devcoredump");
|
|
|
|
kfree_skb(skb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-05 10:36:31 +08:00
|
|
|
static void btusb_rtl_cmd_timeout(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct gpio_desc *reset_gpio = data->reset_gpio;
|
2023-04-27 11:27:55 +08:00
|
|
|
struct rtk_dev_coredump_hdr hdr = {
|
|
|
|
.type = RTK_DEVCOREDUMP_CODE_CMD_TIMEOUT,
|
|
|
|
};
|
|
|
|
|
|
|
|
btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0);
|
2019-09-05 10:36:31 +08:00
|
|
|
|
|
|
|
if (++data->cmd_timeout_cnt < 5)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!reset_gpio) {
|
2022-10-06 17:09:31 +08:00
|
|
|
btusb_reset(hdev);
|
2019-09-05 10:36:31 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Toggle the hard reset line. The Realtek device is going to
|
|
|
|
* yank itself off the USB and then replug. The cleanup is handled
|
|
|
|
* correctly on the way out (standard USB disconnect), and the new
|
|
|
|
* device is detected cleanly and bound to the driver again like
|
|
|
|
* it should be.
|
|
|
|
*/
|
|
|
|
if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
|
|
|
|
bt_dev_err(hdev, "last reset failed? Not resetting again");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_dev_err(hdev, "Reset Realtek device via gpio");
|
|
|
|
gpiod_set_value_cansleep(reset_gpio, 1);
|
2019-11-27 11:01:07 +08:00
|
|
|
msleep(200);
|
|
|
|
gpiod_set_value_cansleep(reset_gpio, 0);
|
2019-09-05 10:36:31 +08:00
|
|
|
}
|
|
|
|
|
2023-04-27 11:27:55 +08:00
|
|
|
static void btusb_rtl_hw_error(struct hci_dev *hdev, u8 code)
|
|
|
|
{
|
|
|
|
struct rtk_dev_coredump_hdr hdr = {
|
|
|
|
.type = RTK_DEVCOREDUMP_CODE_HW_ERR,
|
|
|
|
.code = code,
|
|
|
|
};
|
|
|
|
|
|
|
|
bt_dev_err(hdev, "RTL: hw err, trigger devcoredump (%d)", code);
|
|
|
|
|
|
|
|
btusb_rtl_alloc_devcoredump(hdev, &hdr, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2020-06-25 02:11:44 +08:00
|
|
|
static void btusb_qca_cmd_timeout(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2021-09-16 16:41:06 +08:00
|
|
|
struct gpio_desc *reset_gpio = data->reset_gpio;
|
2020-06-25 02:11:44 +08:00
|
|
|
|
2023-04-19 11:38:05 +08:00
|
|
|
if (test_bit(BTUSB_HW_SSR_ACTIVE, &data->flags)) {
|
|
|
|
bt_dev_info(hdev, "Ramdump in progress, defer cmd_timeout");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-25 02:11:44 +08:00
|
|
|
if (++data->cmd_timeout_cnt < 5)
|
|
|
|
return;
|
|
|
|
|
2021-09-16 16:41:06 +08:00
|
|
|
if (reset_gpio) {
|
|
|
|
bt_dev_err(hdev, "Reset qca device via bt_en gpio");
|
|
|
|
|
|
|
|
/* Toggle the hard reset line. The qca bt device is going to
|
|
|
|
* yank itself off the USB and then replug. The cleanup is handled
|
|
|
|
* correctly on the way out (standard USB disconnect), and the new
|
|
|
|
* device is detected cleanly and bound to the driver again like
|
|
|
|
* it should be.
|
|
|
|
*/
|
|
|
|
if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) {
|
|
|
|
bt_dev_err(hdev, "last reset failed? Not resetting again");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gpiod_set_value_cansleep(reset_gpio, 0);
|
|
|
|
msleep(200);
|
|
|
|
gpiod_set_value_cansleep(reset_gpio, 1);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-06 17:09:31 +08:00
|
|
|
btusb_reset(hdev);
|
2020-06-25 02:11:44 +08:00
|
|
|
}
|
|
|
|
|
2014-09-16 14:00:29 +08:00
|
|
|
static inline void btusb_free_frags(struct btusb_data *data)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data->rxlock, flags);
|
|
|
|
|
2022-12-06 20:59:10 +08:00
|
|
|
dev_kfree_skb_irq(data->evt_skb);
|
2014-09-16 14:00:29 +08:00
|
|
|
data->evt_skb = NULL;
|
|
|
|
|
2022-12-06 20:59:10 +08:00
|
|
|
dev_kfree_skb_irq(data->acl_skb);
|
2014-09-16 14:00:29 +08:00
|
|
|
data->acl_skb = NULL;
|
|
|
|
|
2022-12-06 20:59:10 +08:00
|
|
|
dev_kfree_skb_irq(data->sco_skb);
|
2014-09-16 14:00:29 +08:00
|
|
|
data->sco_skb = NULL;
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&data->rxlock, flags);
|
|
|
|
}
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
static int btusb_recv_event(struct btusb_data *data, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
if (data->intr_interval) {
|
|
|
|
/* Trigger dequeue immediatelly if an event is received */
|
|
|
|
schedule_delayed_work(&data->rx_work, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return data->recv_event(data->hdev, skb);
|
|
|
|
}
|
|
|
|
|
2014-09-16 11:33:33 +08:00
|
|
|
static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
|
|
|
|
{
|
2014-09-16 14:00:29 +08:00
|
|
|
struct sk_buff *skb;
|
2018-06-20 05:56:57 +08:00
|
|
|
unsigned long flags;
|
2014-09-16 14:00:29 +08:00
|
|
|
int err = 0;
|
|
|
|
|
2018-06-20 05:56:57 +08:00
|
|
|
spin_lock_irqsave(&data->rxlock, flags);
|
2014-09-16 14:00:29 +08:00
|
|
|
skb = data->evt_skb;
|
|
|
|
|
|
|
|
while (count) {
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!skb) {
|
|
|
|
skb = bt_skb_alloc(HCI_MAX_EVENT_SIZE, GFP_ATOMIC);
|
|
|
|
if (!skb) {
|
|
|
|
err = -ENOMEM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
|
|
|
|
hci_skb_expect(skb) = HCI_EVENT_HDR_SIZE;
|
2014-09-16 14:00:29 +08:00
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
len = min_t(uint, hci_skb_expect(skb), count);
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:20 +08:00
|
|
|
skb_put_data(skb, buffer, len);
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
count -= len;
|
|
|
|
buffer += len;
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_expect(skb) -= len;
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
if (skb->len == HCI_EVENT_HDR_SIZE) {
|
|
|
|
/* Complete event header */
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_expect(skb) = hci_event_hdr(skb)->plen;
|
2014-09-16 14:00:29 +08:00
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
|
2014-09-16 14:00:29 +08:00
|
|
|
kfree_skb(skb);
|
|
|
|
skb = NULL;
|
|
|
|
|
|
|
|
err = -EILSEQ;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
if (!hci_skb_expect(skb)) {
|
2014-09-16 14:00:29 +08:00
|
|
|
/* Complete frame */
|
2021-12-04 06:38:13 +08:00
|
|
|
btusb_recv_event(data, skb);
|
2014-09-16 14:00:29 +08:00
|
|
|
skb = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data->evt_skb = skb;
|
2018-06-20 05:56:57 +08:00
|
|
|
spin_unlock_irqrestore(&data->rxlock, flags);
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
return err;
|
2014-09-16 11:33:33 +08:00
|
|
|
}
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
static int btusb_recv_acl(struct btusb_data *data, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
/* Only queue ACL packet if intr_interval is set as it means
|
|
|
|
* force_poll_sync has been enabled.
|
|
|
|
*/
|
|
|
|
if (!data->intr_interval)
|
|
|
|
return data->recv_acl(data->hdev, skb);
|
|
|
|
|
|
|
|
skb_queue_tail(&data->acl_q, skb);
|
|
|
|
schedule_delayed_work(&data->rx_work, data->intr_interval);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-16 11:33:33 +08:00
|
|
|
static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
|
|
|
|
{
|
2014-09-16 14:00:29 +08:00
|
|
|
struct sk_buff *skb;
|
2018-06-20 05:56:57 +08:00
|
|
|
unsigned long flags;
|
2014-09-16 14:00:29 +08:00
|
|
|
int err = 0;
|
|
|
|
|
2018-06-20 05:56:57 +08:00
|
|
|
spin_lock_irqsave(&data->rxlock, flags);
|
2014-09-16 14:00:29 +08:00
|
|
|
skb = data->acl_skb;
|
|
|
|
|
|
|
|
while (count) {
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!skb) {
|
|
|
|
skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
|
|
|
if (!skb) {
|
|
|
|
err = -ENOMEM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
|
|
|
|
hci_skb_expect(skb) = HCI_ACL_HDR_SIZE;
|
2014-09-16 14:00:29 +08:00
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
len = min_t(uint, hci_skb_expect(skb), count);
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:20 +08:00
|
|
|
skb_put_data(skb, buffer, len);
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
count -= len;
|
|
|
|
buffer += len;
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_expect(skb) -= len;
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
if (skb->len == HCI_ACL_HDR_SIZE) {
|
|
|
|
__le16 dlen = hci_acl_hdr(skb)->dlen;
|
|
|
|
|
|
|
|
/* Complete ACL header */
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_expect(skb) = __le16_to_cpu(dlen);
|
2014-09-16 14:00:29 +08:00
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
|
2014-09-16 14:00:29 +08:00
|
|
|
kfree_skb(skb);
|
|
|
|
skb = NULL;
|
|
|
|
|
|
|
|
err = -EILSEQ;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
if (!hci_skb_expect(skb)) {
|
2014-09-16 14:00:29 +08:00
|
|
|
/* Complete frame */
|
2021-12-04 06:38:13 +08:00
|
|
|
btusb_recv_acl(data, skb);
|
2014-09-16 14:00:29 +08:00
|
|
|
skb = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data->acl_skb = skb;
|
2018-06-20 05:56:57 +08:00
|
|
|
spin_unlock_irqrestore(&data->rxlock, flags);
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
return err;
|
2014-09-16 11:33:33 +08:00
|
|
|
}
|
|
|
|
|
2022-10-05 23:06:21 +08:00
|
|
|
static bool btusb_validate_sco_handle(struct hci_dev *hdev,
|
|
|
|
struct hci_sco_hdr *hdr)
|
|
|
|
{
|
|
|
|
__u16 handle;
|
|
|
|
|
|
|
|
if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL))
|
|
|
|
// Can't validate, userspace controls everything.
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* USB isochronous transfers are not designed to be reliable and may
|
|
|
|
* lose fragments. When this happens, the next first fragment
|
|
|
|
* encountered might actually be a continuation fragment.
|
|
|
|
* Validate the handle to detect it and drop it, or else the upper
|
|
|
|
* layer will get garbage for a while.
|
|
|
|
*/
|
|
|
|
|
|
|
|
handle = hci_handle(__le16_to_cpu(hdr->handle));
|
|
|
|
|
|
|
|
switch (hci_conn_lookup_type(hdev, handle)) {
|
|
|
|
case SCO_LINK:
|
|
|
|
case ESCO_LINK:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-16 11:33:33 +08:00
|
|
|
static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
|
|
|
|
{
|
2014-09-16 14:00:29 +08:00
|
|
|
struct sk_buff *skb;
|
2018-06-20 05:56:57 +08:00
|
|
|
unsigned long flags;
|
2014-09-16 14:00:29 +08:00
|
|
|
int err = 0;
|
|
|
|
|
2018-06-20 05:56:57 +08:00
|
|
|
spin_lock_irqsave(&data->rxlock, flags);
|
2014-09-16 14:00:29 +08:00
|
|
|
skb = data->sco_skb;
|
|
|
|
|
|
|
|
while (count) {
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!skb) {
|
|
|
|
skb = bt_skb_alloc(HCI_MAX_SCO_SIZE, GFP_ATOMIC);
|
|
|
|
if (!skb) {
|
|
|
|
err = -ENOMEM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_pkt_type(skb) = HCI_SCODATA_PKT;
|
|
|
|
hci_skb_expect(skb) = HCI_SCO_HDR_SIZE;
|
2014-09-16 14:00:29 +08:00
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
len = min_t(uint, hci_skb_expect(skb), count);
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:20 +08:00
|
|
|
skb_put_data(skb, buffer, len);
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
count -= len;
|
|
|
|
buffer += len;
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_expect(skb) -= len;
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
if (skb->len == HCI_SCO_HDR_SIZE) {
|
|
|
|
/* Complete SCO header */
|
2022-10-05 23:06:21 +08:00
|
|
|
struct hci_sco_hdr *hdr = hci_sco_hdr(skb);
|
2014-09-16 14:00:29 +08:00
|
|
|
|
2022-10-05 23:06:21 +08:00
|
|
|
hci_skb_expect(skb) = hdr->dlen;
|
|
|
|
|
|
|
|
if (skb_tailroom(skb) < hci_skb_expect(skb) ||
|
|
|
|
!btusb_validate_sco_handle(data->hdev, hdr)) {
|
2014-09-16 14:00:29 +08:00
|
|
|
kfree_skb(skb);
|
|
|
|
skb = NULL;
|
|
|
|
|
|
|
|
err = -EILSEQ;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
if (!hci_skb_expect(skb)) {
|
2014-09-16 14:00:29 +08:00
|
|
|
/* Complete frame */
|
|
|
|
hci_recv_frame(data->hdev, skb);
|
|
|
|
skb = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data->sco_skb = skb;
|
2018-06-20 05:56:57 +08:00
|
|
|
spin_unlock_irqrestore(&data->rxlock, flags);
|
2014-09-16 14:00:29 +08:00
|
|
|
|
|
|
|
return err;
|
2014-09-16 11:33:33 +08:00
|
|
|
}
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
static void btusb_intr_complete(struct urb *urb)
|
|
|
|
{
|
|
|
|
struct hci_dev *hdev = urb->context;
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
int err;
|
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
|
|
|
|
urb->actual_length);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (urb->status == 0) {
|
2008-08-18 19:23:52 +08:00
|
|
|
hdev->stat.byte_rx += urb->actual_length;
|
|
|
|
|
2014-09-16 11:33:33 +08:00
|
|
|
if (btusb_recv_intr(data, urb->transfer_buffer,
|
|
|
|
urb->actual_length) < 0) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "corrupted event packet");
|
2007-10-20 20:12:34 +08:00
|
|
|
hdev->stat.err_rx++;
|
|
|
|
}
|
2014-09-07 03:06:08 +08:00
|
|
|
} else if (urb->status == -ENOENT) {
|
|
|
|
/* Avoid suspend failed when usb_kill_urb */
|
|
|
|
return;
|
2007-10-20 20:12:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
|
|
|
|
return;
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
usb_mark_last_busy(data->udev);
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_anchor_urb(urb, &data->intr_anchor);
|
|
|
|
|
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
|
if (err < 0) {
|
2011-08-09 23:16:28 +08:00
|
|
|
/* -EPERM: urb is being killed;
|
2017-07-22 09:47:07 +08:00
|
|
|
* -ENODEV: device got disconnected
|
|
|
|
*/
|
2011-08-09 23:16:28 +08:00
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
|
|
|
|
urb, -err);
|
2021-12-03 22:59:02 +08:00
|
|
|
if (err != -EPERM)
|
|
|
|
hci_cmd_sync_cancel(hdev, -err);
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
2007-10-20 20:12:34 +08:00
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
struct urb *urb;
|
|
|
|
unsigned char *buf;
|
|
|
|
unsigned int pipe;
|
|
|
|
int err, size;
|
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
2008-08-18 19:23:52 +08:00
|
|
|
if (!data->intr_ep)
|
|
|
|
return -ENODEV;
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
urb = usb_alloc_urb(0, mem_flags);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (!urb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2024-10-16 23:47:00 +08:00
|
|
|
if (le16_to_cpu(data->udev->descriptor.idVendor) == 0x0a12 &&
|
|
|
|
le16_to_cpu(data->udev->descriptor.idProduct) == 0x0001)
|
|
|
|
/* Fake CSR devices don't seem to support sort-transter */
|
|
|
|
size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
|
|
|
|
else
|
|
|
|
/* Use maximum HCI Event size so the USB stack handles
|
|
|
|
* ZPL/short-transfer automatically.
|
|
|
|
*/
|
|
|
|
size = HCI_MAX_EVENT_SIZE;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
buf = kmalloc(size, mem_flags);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (!buf) {
|
|
|
|
usb_free_urb(urb);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipe = usb_rcvintpipe(data->udev, data->intr_ep->bEndpointAddress);
|
|
|
|
|
|
|
|
usb_fill_int_urb(urb, data->udev, pipe, buf, size,
|
2014-09-16 10:44:50 +08:00
|
|
|
btusb_intr_complete, hdev, data->intr_ep->bInterval);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
urb->transfer_flags |= URB_FREE_BUFFER;
|
|
|
|
|
|
|
|
usb_anchor_urb(urb, &data->intr_anchor);
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
err = usb_submit_urb(urb, mem_flags);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (err < 0) {
|
2011-10-09 18:12:22 +08:00
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p submission failed (%d)",
|
|
|
|
urb, -err);
|
2021-12-03 22:59:02 +08:00
|
|
|
if (err != -EPERM)
|
|
|
|
hci_cmd_sync_cancel(hdev, -err);
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
}
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
/* Only initialize intr_interval if URB poll sync is enabled */
|
|
|
|
if (!data->poll_sync)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
/* The units are frames (milliseconds) for full and low speed devices,
|
|
|
|
* and microframes (1/8 millisecond) for highspeed and SuperSpeed
|
|
|
|
* devices.
|
|
|
|
*
|
|
|
|
* This is done once on open/resume so it shouldn't change even if
|
|
|
|
* force_poll_sync changes.
|
|
|
|
*/
|
|
|
|
switch (urb->dev->speed) {
|
|
|
|
case USB_SPEED_SUPER_PLUS:
|
|
|
|
case USB_SPEED_SUPER: /* units are 125us */
|
|
|
|
data->intr_interval = usecs_to_jiffies(urb->interval * 125);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
data->intr_interval = msecs_to_jiffies(urb->interval);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_free_urb(urb);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void btusb_bulk_complete(struct urb *urb)
|
|
|
|
{
|
|
|
|
struct hci_dev *hdev = urb->context;
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
int err;
|
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
|
|
|
|
urb->actual_length);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (urb->status == 0) {
|
2008-08-18 19:23:52 +08:00
|
|
|
hdev->stat.byte_rx += urb->actual_length;
|
|
|
|
|
2014-11-03 12:16:07 +08:00
|
|
|
if (data->recv_bulk(data, urb->transfer_buffer,
|
2014-09-16 11:33:33 +08:00
|
|
|
urb->actual_length) < 0) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "corrupted ACL packet");
|
2007-10-20 20:12:34 +08:00
|
|
|
hdev->stat.err_rx++;
|
|
|
|
}
|
2014-09-07 03:06:08 +08:00
|
|
|
} else if (urb->status == -ENOENT) {
|
|
|
|
/* Avoid suspend failed when usb_kill_urb */
|
|
|
|
return;
|
2007-10-20 20:12:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!test_bit(BTUSB_BULK_RUNNING, &data->flags))
|
|
|
|
return;
|
|
|
|
|
|
|
|
usb_anchor_urb(urb, &data->bulk_anchor);
|
2009-12-17 02:23:43 +08:00
|
|
|
usb_mark_last_busy(data->udev);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
|
if (err < 0) {
|
2011-08-09 23:16:28 +08:00
|
|
|
/* -EPERM: urb is being killed;
|
2017-07-22 09:47:07 +08:00
|
|
|
* -ENODEV: device got disconnected
|
|
|
|
*/
|
2011-08-09 23:16:28 +08:00
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
|
|
|
|
urb, -err);
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
2007-10-20 20:12:34 +08:00
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
struct urb *urb;
|
|
|
|
unsigned char *buf;
|
|
|
|
unsigned int pipe;
|
2009-07-02 17:01:59 +08:00
|
|
|
int err, size = HCI_MAX_FRAME_SIZE;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
2008-08-18 19:23:52 +08:00
|
|
|
if (!data->bulk_rx_ep)
|
|
|
|
return -ENODEV;
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
urb = usb_alloc_urb(0, mem_flags);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (!urb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
buf = kmalloc(size, mem_flags);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (!buf) {
|
|
|
|
usb_free_urb(urb);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
|
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
|
|
|
|
btusb_bulk_complete, hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
urb->transfer_flags |= URB_FREE_BUFFER;
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
usb_mark_last_busy(data->udev);
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_anchor_urb(urb, &data->bulk_anchor);
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
err = usb_submit_urb(urb, mem_flags);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (err < 0) {
|
2011-10-09 18:12:22 +08:00
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p submission failed (%d)",
|
|
|
|
urb, -err);
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
}
|
|
|
|
|
|
|
|
usb_free_urb(urb);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2008-08-18 19:23:52 +08:00
|
|
|
static void btusb_isoc_complete(struct urb *urb)
|
|
|
|
{
|
|
|
|
struct hci_dev *hdev = urb->context;
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2008-08-18 19:23:52 +08:00
|
|
|
int i, err;
|
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
|
|
|
|
urb->actual_length);
|
2008-08-18 19:23:52 +08:00
|
|
|
|
|
|
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (urb->status == 0) {
|
|
|
|
for (i = 0; i < urb->number_of_packets; i++) {
|
|
|
|
unsigned int offset = urb->iso_frame_desc[i].offset;
|
|
|
|
unsigned int length = urb->iso_frame_desc[i].actual_length;
|
|
|
|
|
|
|
|
if (urb->iso_frame_desc[i].status)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
hdev->stat.byte_rx += length;
|
|
|
|
|
2014-09-16 11:33:33 +08:00
|
|
|
if (btusb_recv_isoc(data, urb->transfer_buffer + offset,
|
|
|
|
length) < 0) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "corrupted SCO packet");
|
2008-08-18 19:23:52 +08:00
|
|
|
hdev->stat.err_rx++;
|
|
|
|
}
|
|
|
|
}
|
2014-09-07 03:06:08 +08:00
|
|
|
} else if (urb->status == -ENOENT) {
|
|
|
|
/* Avoid suspend failed when usb_kill_urb */
|
|
|
|
return;
|
2008-08-18 19:23:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags))
|
|
|
|
return;
|
|
|
|
|
|
|
|
usb_anchor_urb(urb, &data->isoc_anchor);
|
|
|
|
|
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
|
if (err < 0) {
|
2011-08-09 23:16:28 +08:00
|
|
|
/* -EPERM: urb is being killed;
|
2017-07-22 09:47:07 +08:00
|
|
|
* -ENODEV: device got disconnected
|
|
|
|
*/
|
2011-08-09 23:16:28 +08:00
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
|
|
|
|
urb, -err);
|
2008-08-18 19:23:52 +08:00
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-04 03:43:59 +08:00
|
|
|
static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len,
|
|
|
|
int mtu, struct btusb_data *data)
|
|
|
|
{
|
2022-10-05 16:43:31 +08:00
|
|
|
int i = 0, offset = 0;
|
2020-04-04 03:43:59 +08:00
|
|
|
unsigned int interval;
|
|
|
|
|
|
|
|
BT_DBG("len %d mtu %d", len, mtu);
|
|
|
|
|
2022-10-05 16:43:31 +08:00
|
|
|
/* For mSBC ALT 6 settings some chips need to transmit the data
|
|
|
|
* continuously without the zero length of USB packets.
|
|
|
|
*/
|
|
|
|
if (test_bit(BTUSB_ALT6_CONTINUOUS_TX, &data->flags))
|
|
|
|
goto ignore_usb_alt6_packet_flow;
|
|
|
|
|
2020-04-04 03:43:59 +08:00
|
|
|
/* For mSBC ALT 6 setting the host will send the packet at continuous
|
|
|
|
* flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
|
|
|
|
* 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
|
|
|
|
* To maintain the rate we send 63bytes of usb packets alternatively for
|
|
|
|
* 7ms and 8ms to maintain the rate as 7.5ms.
|
|
|
|
*/
|
|
|
|
if (data->usb_alt6_packet_flow) {
|
|
|
|
interval = 7;
|
|
|
|
data->usb_alt6_packet_flow = false;
|
|
|
|
} else {
|
|
|
|
interval = 6;
|
|
|
|
data->usb_alt6_packet_flow = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < interval; i++) {
|
|
|
|
urb->iso_frame_desc[i].offset = offset;
|
|
|
|
urb->iso_frame_desc[i].length = offset;
|
|
|
|
}
|
|
|
|
|
2022-10-05 16:43:31 +08:00
|
|
|
ignore_usb_alt6_packet_flow:
|
2020-04-04 03:43:59 +08:00
|
|
|
if (len && i < BTUSB_MAX_ISOC_FRAMES) {
|
|
|
|
urb->iso_frame_desc[i].offset = offset;
|
|
|
|
urb->iso_frame_desc[i].length = len;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
urb->number_of_packets = i;
|
|
|
|
}
|
|
|
|
|
2011-01-17 07:09:38 +08:00
|
|
|
static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
|
2008-08-18 19:23:52 +08:00
|
|
|
{
|
|
|
|
int i, offset = 0;
|
|
|
|
|
|
|
|
BT_DBG("len %d mtu %d", len, mtu);
|
|
|
|
|
|
|
|
for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu;
|
|
|
|
i++, offset += mtu, len -= mtu) {
|
|
|
|
urb->iso_frame_desc[i].offset = offset;
|
|
|
|
urb->iso_frame_desc[i].length = mtu;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len && i < BTUSB_MAX_ISOC_FRAMES) {
|
|
|
|
urb->iso_frame_desc[i].offset = offset;
|
|
|
|
urb->iso_frame_desc[i].length = len;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
urb->number_of_packets = i;
|
|
|
|
}
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
2008-08-18 19:23:52 +08:00
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2008-08-18 19:23:52 +08:00
|
|
|
struct urb *urb;
|
|
|
|
unsigned char *buf;
|
|
|
|
unsigned int pipe;
|
|
|
|
int err, size;
|
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
|
|
|
if (!data->isoc_rx_ep)
|
|
|
|
return -ENODEV;
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, mem_flags);
|
2008-08-18 19:23:52 +08:00
|
|
|
if (!urb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) *
|
|
|
|
BTUSB_MAX_ISOC_FRAMES;
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
buf = kmalloc(size, mem_flags);
|
2008-08-18 19:23:52 +08:00
|
|
|
if (!buf) {
|
|
|
|
usb_free_urb(urb);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
|
|
|
|
|
2011-12-21 10:19:00 +08:00
|
|
|
usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
|
2014-09-16 10:44:50 +08:00
|
|
|
hdev, data->isoc_rx_ep->bInterval);
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
|
2008-08-18 19:23:52 +08:00
|
|
|
|
|
|
|
__fill_isoc_descriptor(urb, size,
|
2014-09-16 10:44:50 +08:00
|
|
|
le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
|
2008-08-18 19:23:52 +08:00
|
|
|
|
|
|
|
usb_anchor_urb(urb, &data->isoc_anchor);
|
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
err = usb_submit_urb(urb, mem_flags);
|
2008-08-18 19:23:52 +08:00
|
|
|
if (err < 0) {
|
2011-10-09 18:12:22 +08:00
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p submission failed (%d)",
|
|
|
|
urb, -err);
|
2008-08-18 19:23:52 +08:00
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
}
|
|
|
|
|
|
|
|
usb_free_urb(urb);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2015-10-09 02:23:08 +08:00
|
|
|
static void btusb_diag_complete(struct urb *urb)
|
|
|
|
{
|
|
|
|
struct hci_dev *hdev = urb->context;
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
|
|
|
|
urb->actual_length);
|
|
|
|
|
|
|
|
if (urb->status == 0) {
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
skb = bt_skb_alloc(urb->actual_length, GFP_ATOMIC);
|
|
|
|
if (skb) {
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:20 +08:00
|
|
|
skb_put_data(skb, urb->transfer_buffer,
|
|
|
|
urb->actual_length);
|
2015-10-09 02:23:08 +08:00
|
|
|
hci_recv_diag(hdev, skb);
|
|
|
|
}
|
|
|
|
} else if (urb->status == -ENOENT) {
|
|
|
|
/* Avoid suspend failed when usb_kill_urb */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!test_bit(BTUSB_DIAG_RUNNING, &data->flags))
|
|
|
|
return;
|
|
|
|
|
|
|
|
usb_anchor_urb(urb, &data->diag_anchor);
|
|
|
|
usb_mark_last_busy(data->udev);
|
|
|
|
|
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
|
|
|
if (err < 0) {
|
|
|
|
/* -EPERM: urb is being killed;
|
2017-07-22 09:47:07 +08:00
|
|
|
* -ENODEV: device got disconnected
|
|
|
|
*/
|
2015-10-09 02:23:08 +08:00
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p failed to resubmit (%d)",
|
|
|
|
urb, -err);
|
2015-10-09 02:23:08 +08:00
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_submit_diag_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct urb *urb;
|
|
|
|
unsigned char *buf;
|
|
|
|
unsigned int pipe;
|
|
|
|
int err, size = HCI_MAX_FRAME_SIZE;
|
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
|
|
|
if (!data->diag_rx_ep)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
urb = usb_alloc_urb(0, mem_flags);
|
|
|
|
if (!urb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
buf = kmalloc(size, mem_flags);
|
|
|
|
if (!buf) {
|
|
|
|
usb_free_urb(urb);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipe = usb_rcvbulkpipe(data->udev, data->diag_rx_ep->bEndpointAddress);
|
|
|
|
|
|
|
|
usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
|
|
|
|
btusb_diag_complete, hdev);
|
|
|
|
|
|
|
|
urb->transfer_flags |= URB_FREE_BUFFER;
|
|
|
|
|
|
|
|
usb_mark_last_busy(data->udev);
|
|
|
|
usb_anchor_urb(urb, &data->diag_anchor);
|
|
|
|
|
|
|
|
err = usb_submit_urb(urb, mem_flags);
|
|
|
|
if (err < 0) {
|
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p submission failed (%d)",
|
|
|
|
urb, -err);
|
2015-10-09 02:23:08 +08:00
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
}
|
|
|
|
|
|
|
|
usb_free_urb(urb);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
static void btusb_tx_complete(struct urb *urb)
|
2009-08-25 05:44:59 +08:00
|
|
|
{
|
|
|
|
struct sk_buff *skb = urb->context;
|
2014-09-16 10:44:50 +08:00
|
|
|
struct hci_dev *hdev = (struct hci_dev *)skb->dev;
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2018-06-20 05:56:57 +08:00
|
|
|
unsigned long flags;
|
2009-08-25 05:44:59 +08:00
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
|
|
|
|
urb->actual_length);
|
2009-08-25 05:44:59 +08:00
|
|
|
|
|
|
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
|
|
|
goto done;
|
|
|
|
|
2021-12-03 22:59:02 +08:00
|
|
|
if (!urb->status) {
|
2009-08-25 05:44:59 +08:00
|
|
|
hdev->stat.byte_tx += urb->transfer_buffer_length;
|
2021-12-03 22:59:02 +08:00
|
|
|
} else {
|
|
|
|
if (hci_skb_pkt_type(skb) == HCI_COMMAND_PKT)
|
|
|
|
hci_cmd_sync_cancel(hdev, -urb->status);
|
2009-08-25 05:44:59 +08:00
|
|
|
hdev->stat.err_tx++;
|
2021-12-03 22:59:02 +08:00
|
|
|
}
|
2009-08-25 05:44:59 +08:00
|
|
|
|
|
|
|
done:
|
2018-06-20 05:56:57 +08:00
|
|
|
spin_lock_irqsave(&data->txlock, flags);
|
2009-08-25 05:44:59 +08:00
|
|
|
data->tx_in_flight--;
|
2018-06-20 05:56:57 +08:00
|
|
|
spin_unlock_irqrestore(&data->txlock, flags);
|
2009-08-25 05:44:59 +08:00
|
|
|
|
|
|
|
kfree(urb->setup_packet);
|
|
|
|
|
|
|
|
kfree_skb(skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void btusb_isoc_tx_complete(struct urb *urb)
|
2007-10-20 20:12:34 +08:00
|
|
|
{
|
|
|
|
struct sk_buff *skb = urb->context;
|
2014-09-16 10:44:50 +08:00
|
|
|
struct hci_dev *hdev = (struct hci_dev *)skb->dev;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status,
|
|
|
|
urb->actual_length);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
if (!urb->status)
|
|
|
|
hdev->stat.byte_tx += urb->transfer_buffer_length;
|
|
|
|
else
|
|
|
|
hdev->stat.err_tx++;
|
|
|
|
|
|
|
|
done:
|
|
|
|
kfree(urb->setup_packet);
|
|
|
|
|
|
|
|
kfree_skb(skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_open(struct hci_dev *hdev)
|
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
int err;
|
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
2016-10-07 12:06:42 +08:00
|
|
|
err = usb_autopm_get_interface(data->intf);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2015-02-16 07:06:14 +08:00
|
|
|
/* Patching USB firmware files prior to starting any URBs of HCI path
|
|
|
|
* It is more safe to use USB bulk channel for downloading USB patch
|
|
|
|
*/
|
|
|
|
if (data->setup_on_usb) {
|
|
|
|
err = data->setup_on_usb(hdev);
|
2015-04-17 05:15:50 +08:00
|
|
|
if (err < 0)
|
2019-11-14 23:01:18 +08:00
|
|
|
goto setup_fail;
|
2015-02-16 07:06:14 +08:00
|
|
|
}
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
data->intf->needs_remote_wakeup = 1;
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
|
2009-08-25 05:44:59 +08:00
|
|
|
goto done;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2008-11-30 19:17:10 +08:00
|
|
|
err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
|
2009-02-05 00:41:38 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
err = btusb_submit_bulk_urb(hdev, GFP_KERNEL);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (err < 0) {
|
2009-02-05 00:41:38 +08:00
|
|
|
usb_kill_anchored_urbs(&data->intr_anchor);
|
|
|
|
goto failed;
|
2007-10-20 20:12:34 +08:00
|
|
|
}
|
|
|
|
|
2009-02-05 00:41:38 +08:00
|
|
|
set_bit(BTUSB_BULK_RUNNING, &data->flags);
|
|
|
|
btusb_submit_bulk_urb(hdev, GFP_KERNEL);
|
|
|
|
|
2015-10-09 02:23:08 +08:00
|
|
|
if (data->diag) {
|
|
|
|
if (!btusb_submit_diag_urb(hdev, GFP_KERNEL))
|
|
|
|
set_bit(BTUSB_DIAG_RUNNING, &data->flags);
|
|
|
|
}
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
done:
|
|
|
|
usb_autopm_put_interface(data->intf);
|
2009-02-05 00:41:38 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
failed:
|
|
|
|
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
2019-11-14 23:01:18 +08:00
|
|
|
setup_fail:
|
2009-08-25 05:44:59 +08:00
|
|
|
usb_autopm_put_interface(data->intf);
|
2007-10-20 20:12:34 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
static void btusb_stop_traffic(struct btusb_data *data)
|
|
|
|
{
|
|
|
|
usb_kill_anchored_urbs(&data->intr_anchor);
|
|
|
|
usb_kill_anchored_urbs(&data->bulk_anchor);
|
|
|
|
usb_kill_anchored_urbs(&data->isoc_anchor);
|
2015-10-09 02:23:08 +08:00
|
|
|
usb_kill_anchored_urbs(&data->diag_anchor);
|
2019-06-02 08:02:48 +08:00
|
|
|
usb_kill_anchored_urbs(&data->ctrl_anchor);
|
2009-08-25 05:44:59 +08:00
|
|
|
}
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
static int btusb_close(struct hci_dev *hdev)
|
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2009-08-25 05:44:59 +08:00
|
|
|
int err;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
cancel_delayed_work(&data->rx_work);
|
2008-09-23 06:16:36 +08:00
|
|
|
cancel_work_sync(&data->work);
|
2009-11-12 05:32:29 +08:00
|
|
|
cancel_work_sync(&data->waker);
|
2008-09-23 06:16:36 +08:00
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
skb_queue_purge(&data->acl_q);
|
|
|
|
|
2008-08-18 19:23:52 +08:00
|
|
|
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
2007-10-20 20:12:34 +08:00
|
|
|
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
|
|
|
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
2015-10-09 02:23:08 +08:00
|
|
|
clear_bit(BTUSB_DIAG_RUNNING, &data->flags);
|
2009-08-25 05:44:59 +08:00
|
|
|
|
|
|
|
btusb_stop_traffic(data);
|
2014-09-16 14:00:29 +08:00
|
|
|
btusb_free_frags(data);
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
err = usb_autopm_get_interface(data->intf);
|
|
|
|
if (err < 0)
|
2009-11-13 21:26:23 +08:00
|
|
|
goto failed;
|
2009-08-25 05:44:59 +08:00
|
|
|
|
|
|
|
data->intf->needs_remote_wakeup = 0;
|
2019-08-14 20:02:52 +08:00
|
|
|
|
|
|
|
/* Enable remote wake up for auto-suspend */
|
2021-08-17 11:03:12 +08:00
|
|
|
if (test_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags))
|
2019-08-14 20:02:52 +08:00
|
|
|
data->intf->needs_remote_wakeup = 1;
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
usb_autopm_put_interface(data->intf);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2009-11-13 21:26:23 +08:00
|
|
|
failed:
|
|
|
|
usb_scuttle_anchored_urbs(&data->deferred);
|
2007-10-20 20:12:34 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_flush(struct hci_dev *hdev)
|
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
cancel_delayed_work(&data->rx_work);
|
|
|
|
|
|
|
|
skb_queue_purge(&data->acl_q);
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_kill_anchored_urbs(&data->tx_anchor);
|
2014-09-16 14:00:29 +08:00
|
|
|
btusb_free_frags(data);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb)
|
2007-10-20 20:12:34 +08:00
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
struct usb_ctrlrequest *dr;
|
|
|
|
struct urb *urb;
|
|
|
|
unsigned int pipe;
|
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
urb = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
|
if (!urb)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
dr = kmalloc(sizeof(*dr), GFP_KERNEL);
|
|
|
|
if (!dr) {
|
|
|
|
usb_free_urb(urb);
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
}
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
dr->bRequestType = data->cmdreq_type;
|
2015-01-29 12:27:34 +08:00
|
|
|
dr->bRequest = data->cmdreq;
|
2014-09-14 15:11:06 +08:00
|
|
|
dr->wIndex = 0;
|
|
|
|
dr->wValue = 0;
|
|
|
|
dr->wLength = __cpu_to_le16(skb->len);
|
2013-10-11 21:19:18 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
pipe = usb_sndctrlpipe(data->udev, 0x00);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
|
2014-09-14 15:11:06 +08:00
|
|
|
skb->data, skb->len, btusb_tx_complete, skb);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
skb->dev = (void *)hdev;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
return urb;
|
|
|
|
}
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct urb *urb;
|
|
|
|
unsigned int pipe;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
if (!data->bulk_tx_ep)
|
|
|
|
return ERR_PTR(-ENODEV);
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
urb = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
|
if (!urb)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
usb_fill_bulk_urb(urb, data->udev, pipe,
|
|
|
|
skb->data, skb->len, btusb_tx_complete, skb);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-16 10:44:50 +08:00
|
|
|
skb->dev = (void *)hdev;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
return urb;
|
|
|
|
}
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct urb *urb;
|
|
|
|
unsigned int pipe;
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
if (!data->isoc_tx_ep)
|
|
|
|
return ERR_PTR(-ENODEV);
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
|
|
|
|
if (!urb)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress);
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
usb_fill_int_urb(urb, data->udev, pipe,
|
|
|
|
skb->data, skb->len, btusb_isoc_tx_complete,
|
|
|
|
skb, data->isoc_tx_ep->bInterval);
|
2008-08-18 19:23:52 +08:00
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
urb->transfer_flags = URB_ISO_ASAP;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2020-04-04 03:43:59 +08:00
|
|
|
if (data->isoc_altsetting == 6)
|
|
|
|
__fill_isoc_descriptor_msbc(urb, skb->len,
|
|
|
|
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize),
|
|
|
|
data);
|
|
|
|
else
|
|
|
|
__fill_isoc_descriptor(urb, skb->len,
|
|
|
|
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
|
2014-09-16 10:44:50 +08:00
|
|
|
skb->dev = (void *)hdev;
|
2014-09-14 15:11:06 +08:00
|
|
|
|
|
|
|
return urb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
int err;
|
2009-08-25 05:44:59 +08:00
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
usb_anchor_urb(urb, &data->tx_anchor);
|
|
|
|
|
2014-09-14 13:49:34 +08:00
|
|
|
err = usb_submit_urb(urb, GFP_KERNEL);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (err < 0) {
|
2011-10-09 18:12:16 +08:00
|
|
|
if (err != -EPERM && err != -ENODEV)
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "urb %p submission failed (%d)",
|
|
|
|
urb, -err);
|
2007-10-20 20:12:34 +08:00
|
|
|
kfree(urb->setup_packet);
|
|
|
|
usb_unanchor_urb(urb);
|
2009-08-25 05:44:59 +08:00
|
|
|
} else {
|
|
|
|
usb_mark_last_busy(data->udev);
|
2007-10-20 20:12:34 +08:00
|
|
|
}
|
|
|
|
|
2011-11-22 09:32:57 +08:00
|
|
|
usb_free_urb(urb);
|
2007-10-20 20:12:34 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2014-09-14 15:11:06 +08:00
|
|
|
static int submit_or_queue_tx_urb(struct hci_dev *hdev, struct urb *urb)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
unsigned long flags;
|
|
|
|
bool suspending;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&data->txlock, flags);
|
|
|
|
suspending = test_bit(BTUSB_SUSPENDING, &data->flags);
|
|
|
|
if (!suspending)
|
|
|
|
data->tx_in_flight++;
|
|
|
|
spin_unlock_irqrestore(&data->txlock, flags);
|
|
|
|
|
|
|
|
if (!suspending)
|
|
|
|
return submit_tx_urb(hdev, urb);
|
|
|
|
|
|
|
|
usb_anchor_urb(urb, &data->deferred);
|
|
|
|
schedule_work(&data->waker);
|
|
|
|
|
|
|
|
usb_free_urb(urb);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct urb *urb;
|
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
switch (hci_skb_pkt_type(skb)) {
|
2014-09-14 15:11:06 +08:00
|
|
|
case HCI_COMMAND_PKT:
|
|
|
|
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);
|
2019-10-28 23:09:09 +08:00
|
|
|
|
|
|
|
case HCI_ISODATA_PKT:
|
|
|
|
urb = alloc_bulk_urb(hdev, skb);
|
|
|
|
if (IS_ERR(urb))
|
|
|
|
return PTR_ERR(urb);
|
|
|
|
|
|
|
|
return submit_or_queue_tx_urb(hdev, urb);
|
2014-09-14 15:11:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return -EILSEQ;
|
|
|
|
}
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
|
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
BT_DBG("%s evt %d", hdev->name, evt);
|
|
|
|
|
2013-10-11 00:47:55 +08:00
|
|
|
if (hci_conn_num(hdev, SCO_LINK) != data->sco_num) {
|
|
|
|
data->sco_num = hci_conn_num(hdev, SCO_LINK);
|
2020-04-04 03:43:59 +08:00
|
|
|
data->air_mode = evt;
|
2009-02-05 00:41:38 +08:00
|
|
|
schedule_work(&data->work);
|
2008-11-30 19:17:12 +08:00
|
|
|
}
|
2007-10-20 20:12:34 +08:00
|
|
|
}
|
|
|
|
|
2011-01-17 07:09:38 +08:00
|
|
|
static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
|
2008-08-18 19:23:52 +08:00
|
|
|
{
|
2012-02-10 04:58:32 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2008-08-18 19:23:52 +08:00
|
|
|
struct usb_interface *intf = data->isoc;
|
|
|
|
struct usb_endpoint_descriptor *ep_desc;
|
|
|
|
int i, err;
|
|
|
|
|
|
|
|
if (!data->isoc)
|
|
|
|
return -ENODEV;
|
|
|
|
|
2017-10-25 01:42:45 +08:00
|
|
|
err = usb_set_interface(data->udev, data->isoc_ifnum, altsetting);
|
2008-08-18 19:23:52 +08:00
|
|
|
if (err < 0) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "setting interface failed (%d)", -err);
|
2008-08-18 19:23:52 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->isoc_altsetting = altsetting;
|
|
|
|
|
|
|
|
data->isoc_tx_ep = NULL;
|
|
|
|
data->isoc_rx_ep = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
|
|
|
|
ep_desc = &intf->cur_altsetting->endpoint[i].desc;
|
|
|
|
|
|
|
|
if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
|
|
|
|
data->isoc_tx_ep = ep_desc;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
|
|
|
|
data->isoc_rx_ep = ep_desc;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "invalid SCO descriptors");
|
2008-08-18 19:23:52 +08:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-04-04 03:43:59 +08:00
|
|
|
static int btusb_switch_alt_setting(struct hci_dev *hdev, int new_alts)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (data->isoc_altsetting != new_alts) {
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
|
|
|
usb_kill_anchored_urbs(&data->isoc_anchor);
|
|
|
|
|
|
|
|
/* When isochronous alternate setting needs to be
|
|
|
|
* changed, because SCO connection has been added
|
|
|
|
* or removed, a packet fragment may be left in the
|
|
|
|
* reassembling state. This could lead to wrongly
|
|
|
|
* assembled fragments.
|
|
|
|
*
|
|
|
|
* Clear outstanding fragment when selecting a new
|
|
|
|
* alternate setting.
|
|
|
|
*/
|
|
|
|
spin_lock_irqsave(&data->rxlock, flags);
|
2023-08-23 11:46:37 +08:00
|
|
|
dev_kfree_skb_irq(data->sco_skb);
|
2020-04-04 03:43:59 +08:00
|
|
|
data->sco_skb = NULL;
|
|
|
|
spin_unlock_irqrestore(&data->rxlock, flags);
|
|
|
|
|
|
|
|
err = __set_isoc_interface(hdev, new_alts);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
|
|
|
|
if (btusb_submit_isoc_urb(hdev, GFP_KERNEL) < 0)
|
|
|
|
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
|
|
|
else
|
|
|
|
btusb_submit_isoc_urb(hdev, GFP_KERNEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct usb_host_interface *btusb_find_altsetting(struct btusb_data *data,
|
|
|
|
int alt)
|
|
|
|
{
|
|
|
|
struct usb_interface *intf = data->isoc;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
BT_DBG("Looking for Alt no :%d", alt);
|
|
|
|
|
2020-04-08 13:27:03 +08:00
|
|
|
if (!intf)
|
|
|
|
return NULL;
|
|
|
|
|
2020-04-04 03:43:59 +08:00
|
|
|
for (i = 0; i < intf->num_altsetting; i++) {
|
|
|
|
if (intf->altsetting[i].desc.bAlternateSetting == alt)
|
|
|
|
return &intf->altsetting[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
static void btusb_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = container_of(work, struct btusb_data, work);
|
|
|
|
struct hci_dev *hdev = data->hdev;
|
2020-04-04 03:43:59 +08:00
|
|
|
int new_alts = 0;
|
2009-08-25 05:44:59 +08:00
|
|
|
int err;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2013-10-11 00:47:55 +08:00
|
|
|
if (data->sco_num > 0) {
|
2010-07-17 04:20:33 +08:00
|
|
|
if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
|
2011-02-11 20:00:06 +08:00
|
|
|
err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf);
|
2009-08-25 05:44:59 +08:00
|
|
|
if (err < 0) {
|
|
|
|
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
|
|
|
usb_kill_anchored_urbs(&data->isoc_anchor);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-07-17 04:20:33 +08:00
|
|
|
set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
|
2009-08-25 05:44:59 +08:00
|
|
|
}
|
2012-04-11 14:48:51 +08:00
|
|
|
|
2020-04-04 03:43:59 +08:00
|
|
|
if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) {
|
|
|
|
if (hdev->voice_setting & 0x0020) {
|
|
|
|
static const int alts[3] = { 2, 4, 5 };
|
2012-04-11 14:48:51 +08:00
|
|
|
|
2020-04-04 03:43:59 +08:00
|
|
|
new_alts = alts[data->sco_num - 1];
|
|
|
|
} else {
|
|
|
|
new_alts = data->sco_num;
|
|
|
|
}
|
|
|
|
} else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) {
|
Bluetooth: btusb: Always fallback to alt 1 for WBS
When alt mode 6 is not available, fallback to the kernel <= 5.7 behavior
of always using alt mode 1.
Prior to kernel 5.8, btusb would always use alt mode 1 for WBS (Wide
Band Speech aka mSBC aka transparent SCO). In commit baac6276c0a9
("Bluetooth: btusb: handle mSBC audio over USB Endpoints") this
was changed to use alt mode 6, which is the recommended mode in the
Bluetooth spec (Specifications of the Bluetooth System, v5.0, Vol 4.B
§2.2.1). However, many if not most BT USB adapters do not support alt
mode 6. In fact, I have been unable to find any which do.
In kernel 5.8, this was changed to use alt mode 6, and if not available,
use alt mode 0. But mode 0 has a zero byte max packet length and can
not possibly work. It is just there as a zero-bandwidth dummy mode to
work around a USB flaw that would prevent device enumeration if
insufficient bandwidth were available for the lowest isoc mode
supported.
In effect, WBS was broken for all USB-BT adapters that do not support
alt 6, which appears to nearly all of them.
Then in commit 461f95f04f19 ("Bluetooth: btusb: USB alternate setting 1 for
WBS") the 5.7 behavior was restored, but only for Realtek adapters.
I've tested a Broadcom BRCM20702A and CSR 8510 adapter, both work with
the 5.7 behavior and do not with the 5.8.
So get rid of the Realtek specific flag and use the 5.7 behavior for all
adapters as a fallback when alt 6 is not available. This was the
kernel's behavior prior to 5.8 and I can find no adapters for which it
is not correct. And even if there is an adapter for which this does not
work, the current behavior would be to fall back to alt 0, which can not
possibly work either, and so is no better.
Signed-off-by: Trent Piepho <tpiepho@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-12-10 09:20:03 +08:00
|
|
|
/* 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
|
2021-07-27 02:02:06 +08:00
|
|
|
* 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.
|
Bluetooth: btusb: Always fallback to alt 1 for WBS
When alt mode 6 is not available, fallback to the kernel <= 5.7 behavior
of always using alt mode 1.
Prior to kernel 5.8, btusb would always use alt mode 1 for WBS (Wide
Band Speech aka mSBC aka transparent SCO). In commit baac6276c0a9
("Bluetooth: btusb: handle mSBC audio over USB Endpoints") this
was changed to use alt mode 6, which is the recommended mode in the
Bluetooth spec (Specifications of the Bluetooth System, v5.0, Vol 4.B
§2.2.1). However, many if not most BT USB adapters do not support alt
mode 6. In fact, I have been unable to find any which do.
In kernel 5.8, this was changed to use alt mode 6, and if not available,
use alt mode 0. But mode 0 has a zero byte max packet length and can
not possibly work. It is just there as a zero-bandwidth dummy mode to
work around a USB flaw that would prevent device enumeration if
insufficient bandwidth were available for the lowest isoc mode
supported.
In effect, WBS was broken for all USB-BT adapters that do not support
alt 6, which appears to nearly all of them.
Then in commit 461f95f04f19 ("Bluetooth: btusb: USB alternate setting 1 for
WBS") the 5.7 behavior was restored, but only for Realtek adapters.
I've tested a Broadcom BRCM20702A and CSR 8510 adapter, both work with
the 5.7 behavior and do not with the 5.8.
So get rid of the Realtek specific flag and use the 5.7 behavior for all
adapters as a fallback when alt 6 is not available. This was the
kernel's behavior prior to 5.8 and I can find no adapters for which it
is not correct. And even if there is an adapter for which this does not
work, the current behavior would be to fall back to alt 0, which can not
possibly work either, and so is no better.
Signed-off-by: Trent Piepho <tpiepho@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-12-10 09:20:03 +08:00
|
|
|
*/
|
2021-07-27 02:02:06 +08:00
|
|
|
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))
|
2021-05-14 11:19:01 +08:00
|
|
|
new_alts = 3;
|
2021-07-27 02:02:06 +08:00
|
|
|
else
|
|
|
|
new_alts = 1;
|
2008-08-18 19:23:52 +08:00
|
|
|
}
|
2020-04-04 03:43:59 +08:00
|
|
|
|
|
|
|
if (btusb_switch_alt_setting(hdev, new_alts) < 0)
|
|
|
|
bt_dev_err(hdev, "set USB alt:(%d) failed!", new_alts);
|
2008-08-18 19:23:52 +08:00
|
|
|
} else {
|
|
|
|
usb_kill_anchored_urbs(&data->isoc_anchor);
|
|
|
|
|
2022-10-03 14:48:36 +08:00
|
|
|
if (test_and_clear_bit(BTUSB_ISOC_RUNNING, &data->flags))
|
|
|
|
__set_isoc_interface(hdev, 0);
|
|
|
|
|
2010-07-17 04:20:33 +08:00
|
|
|
if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
|
2011-02-11 20:00:06 +08:00
|
|
|
usb_autopm_put_interface(data->isoc ? data->isoc : data->intf);
|
2007-10-20 20:12:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
static void btusb_waker(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = container_of(work, struct btusb_data, waker);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = usb_autopm_get_interface(data->intf);
|
|
|
|
if (err < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
usb_autopm_put_interface(data->intf);
|
|
|
|
}
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
static void btusb_rx_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = container_of(work, struct btusb_data,
|
|
|
|
rx_work.work);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
/* Dequeue ACL data received during the interval */
|
|
|
|
while ((skb = skb_dequeue(&data->acl_q)))
|
|
|
|
data->recv_acl(data->hdev, skb);
|
|
|
|
}
|
|
|
|
|
2013-04-10 23:11:35 +08:00
|
|
|
static int btusb_setup_bcm92035(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
u8 val = 0x00;
|
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
|
|
|
skb = __hci_cmd_sync(hdev, 0xfc3b, 1, &val, HCI_INIT_TIMEOUT);
|
|
|
|
if (IS_ERR(skb))
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "BCM92035 command failed (%ld)", PTR_ERR(skb));
|
2013-04-10 23:11:35 +08:00
|
|
|
else
|
|
|
|
kfree_skb(skb);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-03 19:02:36 +08:00
|
|
|
static int btusb_setup_csr(struct hci_dev *hdev)
|
|
|
|
{
|
2020-12-05 23:02:00 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
u16 bcdDevice = le16_to_cpu(data->udev->descriptor.bcdDevice);
|
2014-01-03 19:02:36 +08:00
|
|
|
struct hci_rp_read_local_version *rp;
|
|
|
|
struct sk_buff *skb;
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
bool is_fake = false;
|
Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers
With the recent btusb change to detect and deal with more fake CSR
controllers, I decided to see if fake CSR controllers with Barrot
8041a02 chips would now work.
After much experimentation I came to the conclusion that it works, if I
have autosuspend enabled initially and then disable it after the device
has suspended at least once. Yes this is very weird, but I've tried many
things, like manually clearing the remote-wakeup feature. Doing a
runtime-resume + runtime suspend is the only way to get the receiver
to actually report received data (and/or pairing info) through its
bulk rx endpoint.
But the funkyness of the bulk-endpoint does not stop there, I mainly
found out about this problem, because with autosuspend enabled
(which usually ensures the suspend at least once condition is met),
the receiver stops reporting received data through its bulk rx endpoint
as soon as autosuspend kicks in. So I initially just disabled
autosuspend, but then the receiver does not work at all.
This was with a fake CSR receiver with a Barrot 8041a02 chip with a
bcdDevice value of 0x8891, a lmp_subver of 0x1012, a hci_rev of 0x0810
and a hci_ver of BLUETOOTH_VER_4_0.
Summarizing this specific fake CSR receiver has the following 2 issues:
1. The bulk rx endpoint will never report any data unless
the device was suspended at least once.
2. They will not wakeup when autosuspended and receiving data on their
bulk rx endpoint from e.g. a keyboard or mouse (IOW remote-wakeup support
is broken for the bulk endpoint).
Add a workaround for 1. which enables runtime-suspend, force-suspends
the hci and then wakes-it up by disabling runtime-suspend again.
Add a workaround for 2. which clears the hci's can_wake flag, this way
the hci will still be autosuspended when it is not open.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-12-05 23:02:01 +08:00
|
|
|
int ret;
|
2014-01-03 19:02:36 +08:00
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
2015-06-07 16:01:02 +08:00
|
|
|
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
|
|
|
|
HCI_INIT_TIMEOUT);
|
|
|
|
if (IS_ERR(skb)) {
|
|
|
|
int err = PTR_ERR(skb);
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "CSR: Local version failed (%d)", err);
|
2015-06-07 16:01:02 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2022-12-06 01:49:15 +08:00
|
|
|
rp = skb_pull_data(skb, sizeof(*rp));
|
|
|
|
if (!rp) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "CSR: Local version length mismatch");
|
2015-06-07 16:01:02 +08:00
|
|
|
kfree_skb(skb);
|
|
|
|
return -EIO;
|
|
|
|
}
|
2014-01-03 19:02:36 +08:00
|
|
|
|
2022-12-06 01:49:15 +08:00
|
|
|
bt_dev_info(hdev, "CSR: Setting up dongle with HCI ver=%u rev=%04x",
|
|
|
|
rp->hci_ver, le16_to_cpu(rp->hci_rev));
|
2014-01-03 19:02:36 +08:00
|
|
|
|
2022-12-06 01:49:15 +08:00
|
|
|
bt_dev_info(hdev, "LMP ver=%u subver=%04x; manufacturer=%u",
|
|
|
|
rp->lmp_ver, le16_to_cpu(rp->lmp_subver),
|
|
|
|
le16_to_cpu(rp->manufacturer));
|
2022-10-30 04:24:53 +08:00
|
|
|
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
/* Detect a wide host of Chinese controllers that aren't CSR.
|
|
|
|
*
|
|
|
|
* Known fake bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
|
|
|
|
*
|
|
|
|
* The main thing they have in common is that these are really popular low-cost
|
|
|
|
* options that support newer Bluetooth versions but rely on heavy VID/PID
|
|
|
|
* squatting of this poor old Bluetooth 1.1 device. Even sold as such.
|
|
|
|
*
|
|
|
|
* We detect actual CSR devices by checking that the HCI manufacturer code
|
|
|
|
* is Cambridge Silicon Radio (10) and ensuring that LMP sub-version and
|
|
|
|
* HCI rev values always match. As they both store the firmware number.
|
|
|
|
*/
|
2015-08-31 02:47:21 +08:00
|
|
|
if (le16_to_cpu(rp->manufacturer) != 10 ||
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
le16_to_cpu(rp->hci_rev) != le16_to_cpu(rp->lmp_subver))
|
|
|
|
is_fake = true;
|
|
|
|
|
|
|
|
/* Known legit CSR firmware build numbers and their supported BT versions:
|
|
|
|
* - 1.1 (0x1) -> 0x0073, 0x020d, 0x033c, 0x034e
|
|
|
|
* - 1.2 (0x2) -> 0x04d9, 0x0529
|
|
|
|
* - 2.0 (0x3) -> 0x07a6, 0x07ad, 0x0c5c
|
|
|
|
* - 2.1 (0x4) -> 0x149c, 0x1735, 0x1899 (0x1899 is a BlueCore4-External)
|
|
|
|
* - 4.0 (0x6) -> 0x1d86, 0x2031, 0x22bb
|
|
|
|
*
|
|
|
|
* e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
|
|
|
|
* support BT 1.1 only; so it's a dead giveaway when some
|
|
|
|
* third-party BT 4.0 dongle reuses it.
|
|
|
|
*/
|
|
|
|
else if (le16_to_cpu(rp->lmp_subver) <= 0x034e &&
|
2022-12-06 01:49:15 +08:00
|
|
|
rp->hci_ver > BLUETOOTH_VER_1_1)
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
is_fake = true;
|
|
|
|
|
|
|
|
else if (le16_to_cpu(rp->lmp_subver) <= 0x0529 &&
|
2022-12-06 01:49:15 +08:00
|
|
|
rp->hci_ver > BLUETOOTH_VER_1_2)
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
is_fake = true;
|
|
|
|
|
|
|
|
else if (le16_to_cpu(rp->lmp_subver) <= 0x0c5c &&
|
2022-12-06 01:49:15 +08:00
|
|
|
rp->hci_ver > BLUETOOTH_VER_2_0)
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
is_fake = true;
|
|
|
|
|
|
|
|
else if (le16_to_cpu(rp->lmp_subver) <= 0x1899 &&
|
2022-12-06 01:49:15 +08:00
|
|
|
rp->hci_ver > BLUETOOTH_VER_2_1)
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
is_fake = true;
|
|
|
|
|
|
|
|
else if (le16_to_cpu(rp->lmp_subver) <= 0x22bb &&
|
2022-12-06 01:49:15 +08:00
|
|
|
rp->hci_ver > BLUETOOTH_VER_4_0)
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
is_fake = true;
|
|
|
|
|
2020-12-05 23:02:00 +08:00
|
|
|
/* Other clones which beat all the above checks */
|
|
|
|
else if (bcdDevice == 0x0134 &&
|
|
|
|
le16_to_cpu(rp->lmp_subver) == 0x0c5c &&
|
2022-12-06 01:49:15 +08:00
|
|
|
rp->hci_ver == BLUETOOTH_VER_2_0)
|
2020-12-05 23:02:00 +08:00
|
|
|
is_fake = true;
|
|
|
|
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
if (is_fake) {
|
2021-07-17 07:21:43 +08:00
|
|
|
bt_dev_warn(hdev, "CSR: Unbranded CSR clone detected; adding workarounds and force-suspending once...");
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
|
|
|
|
/* Generally these clones have big discrepancies between
|
|
|
|
* advertised features and what's actually supported.
|
|
|
|
* Probably will need to be expanded in the future;
|
|
|
|
* without these the controller will lock up.
|
|
|
|
*/
|
|
|
|
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
|
2022-10-30 04:24:52 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
|
Bluetooth: btusb: Use quirk to skip HCI_FLT_CLEAR_ALL on fake CSR controllers
Another subset of the more recent batch of Chinese clones aren't
specs-compliant and seem to lock up whenever they receive a
HCI_OP_SET_EVENT_FLT with flt_type set to zero/HCI_FLT_CLEAR_ALL,
which on Linux (until the recent HCI state-machine refactor) happened
right at BR/EDR setup. As there are other less-straightforward ways
of reaching those operations, this patch is still relevant.
So, while all the previous efforts to wrangle the herd of fake CSRs
seem to be paying off (and these also get detected as such) we
still need to take care of this quirk; testers seem to agree
that these dongles tend to work well enough afterwards.
From some cursory USB packet capture on Windows it seems like
that driver doesn't appear to use this clear-all functionality at all.
This patch was tested on some really popular AliExpress-style
dongles, in my case marked as "V5.0". Chip markings: UG8413,
the backside of the PCB says "USB Dangel" (sic).
Here is the `hciconfig -a` output; for completeness:
hci0: Type: Primary Bus: USB
BD Address: 00:1A:7D:DA:7X:XX ACL MTU: 679:8 SCO MTU: 48:16
UP RUNNING PSCAN ISCAN
Features: 0xbf 0x3e 0x4d 0xfa 0xdb 0x3d 0x7b 0xc7
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH SNIFF
Link mode: PERIPHERAL ACCEPT
Name: 'CSR8510 A10.'
Class: 0x7c0104
Service Classes: Rendering, Capturing, Object Transfer, Audio, Telephony
Device Class: Computer, Desktop workstation
HCI Version: 4.0 (0x6) Revision: 0x3120
LMP Version: 4.0 (0x6) Subversion: 0x22bb
Manufacturer: Cambridge Silicon Radio (10)
As well as the `lsusb -vv -d 0a12:0001`:
ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 224 Wireless
bDeviceSubClass 1 Radio Frequency
bDeviceProtocol 1 Bluetooth
bMaxPacketSize0 64
idVendor 0x0a12 Cambridge Silicon Radio, Ltd
idProduct 0x0001 Bluetooth Dongle (HCI mode)
bcdDevice 88.91
iManufacturer 0
iProduct 2 BT DONGLE10
iSerial 0
bNumConfigurations 1
Also, changed the benign dmesg print that shows up whenever the
generic force-suspend fails from bt_dev_err to bt_dev_warn;
it's okay and done on a best-effort basis, not a problem
if that does not work.
Also, swapped the HCI subver and LMP subver numbers for the Barrot
in the comment, which I copied wrong the last time around.
Fixes: 81cac64ba258a ("Bluetooth: Deal with USB devices that are faking CSR vendor")
Fixes: cde1a8a992875 ("Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers")
Fixes: d74e0ae7e0303 ("Bluetooth: btusb: Fix detection of some fake CSR controllers with a bcdDevice val of 0x0134")
Fixes: 0671c0662383e ("Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers")
Fixes: f4292e2faf522 ("Bluetooth: btusb: Make the CSR clone chip force-suspend workaround more generic")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=60824
Link: https://gist.github.com/nevack/6b36b82d715dc025163d9e9124840a07
Cc: stable@vger.kernel.org
Cc: Hans de Goede <hdegoede@redhat.com>
Tested-by: Gonzalo Tornaría <tornaria@cmat.edu.uy>
Tested-by: Mateus Lemos <lemonsmateus@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2022-03-08 04:04:45 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks);
|
|
|
|
set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks);
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
|
2015-06-07 16:01:01 +08:00
|
|
|
/* Clear the reset quirk since this is not an actual
|
|
|
|
* early Bluetooth 1.1 device from CSR.
|
|
|
|
*/
|
|
|
|
clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
clear_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers
With the recent btusb change to detect and deal with more fake CSR
controllers, I decided to see if fake CSR controllers with Barrot
8041a02 chips would now work.
After much experimentation I came to the conclusion that it works, if I
have autosuspend enabled initially and then disable it after the device
has suspended at least once. Yes this is very weird, but I've tried many
things, like manually clearing the remote-wakeup feature. Doing a
runtime-resume + runtime suspend is the only way to get the receiver
to actually report received data (and/or pairing info) through its
bulk rx endpoint.
But the funkyness of the bulk-endpoint does not stop there, I mainly
found out about this problem, because with autosuspend enabled
(which usually ensures the suspend at least once condition is met),
the receiver stops reporting received data through its bulk rx endpoint
as soon as autosuspend kicks in. So I initially just disabled
autosuspend, but then the receiver does not work at all.
This was with a fake CSR receiver with a Barrot 8041a02 chip with a
bcdDevice value of 0x8891, a lmp_subver of 0x1012, a hci_rev of 0x0810
and a hci_ver of BLUETOOTH_VER_4_0.
Summarizing this specific fake CSR receiver has the following 2 issues:
1. The bulk rx endpoint will never report any data unless
the device was suspended at least once.
2. They will not wakeup when autosuspended and receiving data on their
bulk rx endpoint from e.g. a keyboard or mouse (IOW remote-wakeup support
is broken for the bulk endpoint).
Add a workaround for 1. which enables runtime-suspend, force-suspends
the hci and then wakes-it up by disabling runtime-suspend again.
Add a workaround for 2. which clears the hci's can_wake flag, this way
the hci will still be autosuspended when it is not open.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-12-05 23:02:01 +08:00
|
|
|
|
|
|
|
/*
|
2021-07-17 07:21:43 +08:00
|
|
|
* Special workaround for these BT 4.0 chip clones, and potentially more:
|
|
|
|
*
|
Bluetooth: btusb: Use quirk to skip HCI_FLT_CLEAR_ALL on fake CSR controllers
Another subset of the more recent batch of Chinese clones aren't
specs-compliant and seem to lock up whenever they receive a
HCI_OP_SET_EVENT_FLT with flt_type set to zero/HCI_FLT_CLEAR_ALL,
which on Linux (until the recent HCI state-machine refactor) happened
right at BR/EDR setup. As there are other less-straightforward ways
of reaching those operations, this patch is still relevant.
So, while all the previous efforts to wrangle the herd of fake CSRs
seem to be paying off (and these also get detected as such) we
still need to take care of this quirk; testers seem to agree
that these dongles tend to work well enough afterwards.
From some cursory USB packet capture on Windows it seems like
that driver doesn't appear to use this clear-all functionality at all.
This patch was tested on some really popular AliExpress-style
dongles, in my case marked as "V5.0". Chip markings: UG8413,
the backside of the PCB says "USB Dangel" (sic).
Here is the `hciconfig -a` output; for completeness:
hci0: Type: Primary Bus: USB
BD Address: 00:1A:7D:DA:7X:XX ACL MTU: 679:8 SCO MTU: 48:16
UP RUNNING PSCAN ISCAN
Features: 0xbf 0x3e 0x4d 0xfa 0xdb 0x3d 0x7b 0xc7
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH SNIFF
Link mode: PERIPHERAL ACCEPT
Name: 'CSR8510 A10.'
Class: 0x7c0104
Service Classes: Rendering, Capturing, Object Transfer, Audio, Telephony
Device Class: Computer, Desktop workstation
HCI Version: 4.0 (0x6) Revision: 0x3120
LMP Version: 4.0 (0x6) Subversion: 0x22bb
Manufacturer: Cambridge Silicon Radio (10)
As well as the `lsusb -vv -d 0a12:0001`:
ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 224 Wireless
bDeviceSubClass 1 Radio Frequency
bDeviceProtocol 1 Bluetooth
bMaxPacketSize0 64
idVendor 0x0a12 Cambridge Silicon Radio, Ltd
idProduct 0x0001 Bluetooth Dongle (HCI mode)
bcdDevice 88.91
iManufacturer 0
iProduct 2 BT DONGLE10
iSerial 0
bNumConfigurations 1
Also, changed the benign dmesg print that shows up whenever the
generic force-suspend fails from bt_dev_err to bt_dev_warn;
it's okay and done on a best-effort basis, not a problem
if that does not work.
Also, swapped the HCI subver and LMP subver numbers for the Barrot
in the comment, which I copied wrong the last time around.
Fixes: 81cac64ba258a ("Bluetooth: Deal with USB devices that are faking CSR vendor")
Fixes: cde1a8a992875 ("Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers")
Fixes: d74e0ae7e0303 ("Bluetooth: btusb: Fix detection of some fake CSR controllers with a bcdDevice val of 0x0134")
Fixes: 0671c0662383e ("Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers")
Fixes: f4292e2faf522 ("Bluetooth: btusb: Make the CSR clone chip force-suspend workaround more generic")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=60824
Link: https://gist.github.com/nevack/6b36b82d715dc025163d9e9124840a07
Cc: stable@vger.kernel.org
Cc: Hans de Goede <hdegoede@redhat.com>
Tested-by: Gonzalo Tornaría <tornaria@cmat.edu.uy>
Tested-by: Mateus Lemos <lemonsmateus@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2022-03-08 04:04:45 +08:00
|
|
|
* - 0x0134: a Barrot 8041a02 (HCI rev: 0x0810 sub: 0x1012)
|
2021-07-17 07:21:43 +08:00
|
|
|
* - 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
|
2022-01-18 16:04:19 +08:00
|
|
|
* the device was suspended at least once (yes, really).
|
Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers
With the recent btusb change to detect and deal with more fake CSR
controllers, I decided to see if fake CSR controllers with Barrot
8041a02 chips would now work.
After much experimentation I came to the conclusion that it works, if I
have autosuspend enabled initially and then disable it after the device
has suspended at least once. Yes this is very weird, but I've tried many
things, like manually clearing the remote-wakeup feature. Doing a
runtime-resume + runtime suspend is the only way to get the receiver
to actually report received data (and/or pairing info) through its
bulk rx endpoint.
But the funkyness of the bulk-endpoint does not stop there, I mainly
found out about this problem, because with autosuspend enabled
(which usually ensures the suspend at least once condition is met),
the receiver stops reporting received data through its bulk rx endpoint
as soon as autosuspend kicks in. So I initially just disabled
autosuspend, but then the receiver does not work at all.
This was with a fake CSR receiver with a Barrot 8041a02 chip with a
bcdDevice value of 0x8891, a lmp_subver of 0x1012, a hci_rev of 0x0810
and a hci_ver of BLUETOOTH_VER_4_0.
Summarizing this specific fake CSR receiver has the following 2 issues:
1. The bulk rx endpoint will never report any data unless
the device was suspended at least once.
2. They will not wakeup when autosuspended and receiving data on their
bulk rx endpoint from e.g. a keyboard or mouse (IOW remote-wakeup support
is broken for the bulk endpoint).
Add a workaround for 1. which enables runtime-suspend, force-suspends
the hci and then wakes-it up by disabling runtime-suspend again.
Add a workaround for 2. which clears the hci's can_wake flag, this way
the hci will still be autosuspended when it is not open.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-12-05 23:02:01 +08:00
|
|
|
* 2. They will not wakeup when autosuspended and receiving data
|
2022-01-18 16:04:19 +08:00
|
|
|
* on their bulk RX endpoint from e.g. a keyboard or mouse
|
|
|
|
* (IOW remote-wakeup support is broken for the bulk endpoint).
|
Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers
With the recent btusb change to detect and deal with more fake CSR
controllers, I decided to see if fake CSR controllers with Barrot
8041a02 chips would now work.
After much experimentation I came to the conclusion that it works, if I
have autosuspend enabled initially and then disable it after the device
has suspended at least once. Yes this is very weird, but I've tried many
things, like manually clearing the remote-wakeup feature. Doing a
runtime-resume + runtime suspend is the only way to get the receiver
to actually report received data (and/or pairing info) through its
bulk rx endpoint.
But the funkyness of the bulk-endpoint does not stop there, I mainly
found out about this problem, because with autosuspend enabled
(which usually ensures the suspend at least once condition is met),
the receiver stops reporting received data through its bulk rx endpoint
as soon as autosuspend kicks in. So I initially just disabled
autosuspend, but then the receiver does not work at all.
This was with a fake CSR receiver with a Barrot 8041a02 chip with a
bcdDevice value of 0x8891, a lmp_subver of 0x1012, a hci_rev of 0x0810
and a hci_ver of BLUETOOTH_VER_4_0.
Summarizing this specific fake CSR receiver has the following 2 issues:
1. The bulk rx endpoint will never report any data unless
the device was suspended at least once.
2. They will not wakeup when autosuspended and receiving data on their
bulk rx endpoint from e.g. a keyboard or mouse (IOW remote-wakeup support
is broken for the bulk endpoint).
Add a workaround for 1. which enables runtime-suspend, force-suspends
the hci and then wakes-it up by disabling runtime-suspend again.
Add a workaround for 2. which clears the hci's can_wake flag, this way
the hci will still be autosuspended when it is not open.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-12-05 23:02:01 +08:00
|
|
|
*
|
|
|
|
* To fix 1. enable runtime-suspend, force-suspend the
|
2021-07-17 07:21:43 +08:00
|
|
|
* HCI and then wake-it up by disabling runtime-suspend.
|
Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers
With the recent btusb change to detect and deal with more fake CSR
controllers, I decided to see if fake CSR controllers with Barrot
8041a02 chips would now work.
After much experimentation I came to the conclusion that it works, if I
have autosuspend enabled initially and then disable it after the device
has suspended at least once. Yes this is very weird, but I've tried many
things, like manually clearing the remote-wakeup feature. Doing a
runtime-resume + runtime suspend is the only way to get the receiver
to actually report received data (and/or pairing info) through its
bulk rx endpoint.
But the funkyness of the bulk-endpoint does not stop there, I mainly
found out about this problem, because with autosuspend enabled
(which usually ensures the suspend at least once condition is met),
the receiver stops reporting received data through its bulk rx endpoint
as soon as autosuspend kicks in. So I initially just disabled
autosuspend, but then the receiver does not work at all.
This was with a fake CSR receiver with a Barrot 8041a02 chip with a
bcdDevice value of 0x8891, a lmp_subver of 0x1012, a hci_rev of 0x0810
and a hci_ver of BLUETOOTH_VER_4_0.
Summarizing this specific fake CSR receiver has the following 2 issues:
1. The bulk rx endpoint will never report any data unless
the device was suspended at least once.
2. They will not wakeup when autosuspended and receiving data on their
bulk rx endpoint from e.g. a keyboard or mouse (IOW remote-wakeup support
is broken for the bulk endpoint).
Add a workaround for 1. which enables runtime-suspend, force-suspends
the hci and then wakes-it up by disabling runtime-suspend again.
Add a workaround for 2. which clears the hci's can_wake flag, this way
the hci will still be autosuspended when it is not open.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-12-05 23:02:01 +08:00
|
|
|
*
|
2021-07-17 07:21:43 +08:00
|
|
|
* To fix 2. clear the HCI's can_wake flag, this way the HCI
|
Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers
With the recent btusb change to detect and deal with more fake CSR
controllers, I decided to see if fake CSR controllers with Barrot
8041a02 chips would now work.
After much experimentation I came to the conclusion that it works, if I
have autosuspend enabled initially and then disable it after the device
has suspended at least once. Yes this is very weird, but I've tried many
things, like manually clearing the remote-wakeup feature. Doing a
runtime-resume + runtime suspend is the only way to get the receiver
to actually report received data (and/or pairing info) through its
bulk rx endpoint.
But the funkyness of the bulk-endpoint does not stop there, I mainly
found out about this problem, because with autosuspend enabled
(which usually ensures the suspend at least once condition is met),
the receiver stops reporting received data through its bulk rx endpoint
as soon as autosuspend kicks in. So I initially just disabled
autosuspend, but then the receiver does not work at all.
This was with a fake CSR receiver with a Barrot 8041a02 chip with a
bcdDevice value of 0x8891, a lmp_subver of 0x1012, a hci_rev of 0x0810
and a hci_ver of BLUETOOTH_VER_4_0.
Summarizing this specific fake CSR receiver has the following 2 issues:
1. The bulk rx endpoint will never report any data unless
the device was suspended at least once.
2. They will not wakeup when autosuspended and receiving data on their
bulk rx endpoint from e.g. a keyboard or mouse (IOW remote-wakeup support
is broken for the bulk endpoint).
Add a workaround for 1. which enables runtime-suspend, force-suspends
the hci and then wakes-it up by disabling runtime-suspend again.
Add a workaround for 2. which clears the hci's can_wake flag, this way
the hci will still be autosuspended when it is not open.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-12-05 23:02:01 +08:00
|
|
|
* will still be autosuspended when it is not open.
|
2021-07-17 07:21:43 +08:00
|
|
|
*
|
|
|
|
* --
|
|
|
|
*
|
|
|
|
* 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.
|
Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers
With the recent btusb change to detect and deal with more fake CSR
controllers, I decided to see if fake CSR controllers with Barrot
8041a02 chips would now work.
After much experimentation I came to the conclusion that it works, if I
have autosuspend enabled initially and then disable it after the device
has suspended at least once. Yes this is very weird, but I've tried many
things, like manually clearing the remote-wakeup feature. Doing a
runtime-resume + runtime suspend is the only way to get the receiver
to actually report received data (and/or pairing info) through its
bulk rx endpoint.
But the funkyness of the bulk-endpoint does not stop there, I mainly
found out about this problem, because with autosuspend enabled
(which usually ensures the suspend at least once condition is met),
the receiver stops reporting received data through its bulk rx endpoint
as soon as autosuspend kicks in. So I initially just disabled
autosuspend, but then the receiver does not work at all.
This was with a fake CSR receiver with a Barrot 8041a02 chip with a
bcdDevice value of 0x8891, a lmp_subver of 0x1012, a hci_rev of 0x0810
and a hci_ver of BLUETOOTH_VER_4_0.
Summarizing this specific fake CSR receiver has the following 2 issues:
1. The bulk rx endpoint will never report any data unless
the device was suspended at least once.
2. They will not wakeup when autosuspended and receiving data on their
bulk rx endpoint from e.g. a keyboard or mouse (IOW remote-wakeup support
is broken for the bulk endpoint).
Add a workaround for 1. which enables runtime-suspend, force-suspends
the hci and then wakes-it up by disabling runtime-suspend again.
Add a workaround for 2. which clears the hci's can_wake flag, this way
the hci will still be autosuspended when it is not open.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-12-05 23:02:01 +08:00
|
|
|
*/
|
2021-07-17 07:21:43 +08:00
|
|
|
pm_runtime_allow(&data->udev->dev);
|
|
|
|
|
|
|
|
ret = pm_runtime_suspend(&data->udev->dev);
|
|
|
|
if (ret >= 0)
|
|
|
|
msleep(200);
|
|
|
|
else
|
Bluetooth: btusb: Use quirk to skip HCI_FLT_CLEAR_ALL on fake CSR controllers
Another subset of the more recent batch of Chinese clones aren't
specs-compliant and seem to lock up whenever they receive a
HCI_OP_SET_EVENT_FLT with flt_type set to zero/HCI_FLT_CLEAR_ALL,
which on Linux (until the recent HCI state-machine refactor) happened
right at BR/EDR setup. As there are other less-straightforward ways
of reaching those operations, this patch is still relevant.
So, while all the previous efforts to wrangle the herd of fake CSRs
seem to be paying off (and these also get detected as such) we
still need to take care of this quirk; testers seem to agree
that these dongles tend to work well enough afterwards.
From some cursory USB packet capture on Windows it seems like
that driver doesn't appear to use this clear-all functionality at all.
This patch was tested on some really popular AliExpress-style
dongles, in my case marked as "V5.0". Chip markings: UG8413,
the backside of the PCB says "USB Dangel" (sic).
Here is the `hciconfig -a` output; for completeness:
hci0: Type: Primary Bus: USB
BD Address: 00:1A:7D:DA:7X:XX ACL MTU: 679:8 SCO MTU: 48:16
UP RUNNING PSCAN ISCAN
Features: 0xbf 0x3e 0x4d 0xfa 0xdb 0x3d 0x7b 0xc7
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH SNIFF
Link mode: PERIPHERAL ACCEPT
Name: 'CSR8510 A10.'
Class: 0x7c0104
Service Classes: Rendering, Capturing, Object Transfer, Audio, Telephony
Device Class: Computer, Desktop workstation
HCI Version: 4.0 (0x6) Revision: 0x3120
LMP Version: 4.0 (0x6) Subversion: 0x22bb
Manufacturer: Cambridge Silicon Radio (10)
As well as the `lsusb -vv -d 0a12:0001`:
ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 224 Wireless
bDeviceSubClass 1 Radio Frequency
bDeviceProtocol 1 Bluetooth
bMaxPacketSize0 64
idVendor 0x0a12 Cambridge Silicon Radio, Ltd
idProduct 0x0001 Bluetooth Dongle (HCI mode)
bcdDevice 88.91
iManufacturer 0
iProduct 2 BT DONGLE10
iSerial 0
bNumConfigurations 1
Also, changed the benign dmesg print that shows up whenever the
generic force-suspend fails from bt_dev_err to bt_dev_warn;
it's okay and done on a best-effort basis, not a problem
if that does not work.
Also, swapped the HCI subver and LMP subver numbers for the Barrot
in the comment, which I copied wrong the last time around.
Fixes: 81cac64ba258a ("Bluetooth: Deal with USB devices that are faking CSR vendor")
Fixes: cde1a8a992875 ("Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers")
Fixes: d74e0ae7e0303 ("Bluetooth: btusb: Fix detection of some fake CSR controllers with a bcdDevice val of 0x0134")
Fixes: 0671c0662383e ("Bluetooth: btusb: Add workaround for remote-wakeup issues with Barrot 8041a02 fake CSR controllers")
Fixes: f4292e2faf522 ("Bluetooth: btusb: Make the CSR clone chip force-suspend workaround more generic")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=60824
Link: https://gist.github.com/nevack/6b36b82d715dc025163d9e9124840a07
Cc: stable@vger.kernel.org
Cc: Hans de Goede <hdegoede@redhat.com>
Tested-by: Gonzalo Tornaría <tornaria@cmat.edu.uy>
Tested-by: Mateus Lemos <lemonsmateus@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2022-03-08 04:04:45 +08:00
|
|
|
bt_dev_warn(hdev, "CSR: Couldn't suspend the device for our Barrot 8041a02 receive-issue workaround");
|
2021-07-17 07:21:43 +08:00
|
|
|
|
|
|
|
pm_runtime_forbid(&data->udev->dev);
|
|
|
|
|
|
|
|
device_set_wakeup_capable(&data->udev->dev, false);
|
|
|
|
|
|
|
|
/* Re-enable autosuspend if this was requested */
|
|
|
|
if (enable_autosuspend)
|
|
|
|
usb_enable_autosuspend(data->udev);
|
2015-06-07 16:01:01 +08:00
|
|
|
}
|
2014-01-03 19:02:36 +08:00
|
|
|
|
|
|
|
kfree_skb(skb);
|
|
|
|
|
2015-06-07 16:01:01 +08:00
|
|
|
return 0;
|
2014-01-03 19:02:36 +08:00
|
|
|
}
|
|
|
|
|
2015-01-27 13:33:48 +08:00
|
|
|
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;
|
|
|
|
|
2018-07-23 11:38:51 +08:00
|
|
|
skb = bt_skb_alloc(sizeof(*hdr) + sizeof(*evt) + 1, GFP_KERNEL);
|
2015-01-27 13:33:48 +08:00
|
|
|
if (!skb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
networking: make skb_put & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions (skb_put, __skb_put and pskb_put) return void *
and remove all the casts across the tree, adding a (u8 *) cast only
where the unsigned char pointer was used directly, all done with the
following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_put, __skb_put };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_put, __skb_put };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
which actually doesn't cover pskb_put since there are only three
users overall.
A handful of stragglers were converted manually, notably a macro in
drivers/isdn/i4l/isdn_bsdcomp.c and, oddly enough, one of the many
instances in net/bluetooth/hci_sock.c. In the former file, I also
had to fix one whitespace problem spatch introduced.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:21 +08:00
|
|
|
hdr = skb_put(skb, sizeof(*hdr));
|
2015-01-27 13:33:48 +08:00
|
|
|
hdr->evt = HCI_EV_CMD_COMPLETE;
|
|
|
|
hdr->plen = sizeof(*evt) + 1;
|
|
|
|
|
networking: make skb_put & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions (skb_put, __skb_put and pskb_put) return void *
and remove all the casts across the tree, adding a (u8 *) cast only
where the unsigned char pointer was used directly, all done with the
following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_put, __skb_put };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_put, __skb_put };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
which actually doesn't cover pskb_put since there are only three
users overall.
A handful of stragglers were converted manually, notably a macro in
drivers/isdn/i4l/isdn_bsdcomp.c and, oddly enough, one of the many
instances in net/bluetooth/hci_sock.c. In the former file, I also
had to fix one whitespace problem spatch introduced.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:21 +08:00
|
|
|
evt = skb_put(skb, sizeof(*evt));
|
2015-01-27 13:33:48 +08:00
|
|
|
evt->ncmd = 0x01;
|
|
|
|
evt->opcode = cpu_to_le16(opcode);
|
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:24 +08:00
|
|
|
skb_put_u8(skb, 0x00);
|
2015-01-27 13:33:48 +08:00
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
|
2015-01-27 13:33:48 +08:00
|
|
|
|
|
|
|
return hci_recv_frame(hdev, skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer,
|
|
|
|
int count)
|
|
|
|
{
|
2021-08-05 08:32:15 +08:00
|
|
|
struct hci_dev *hdev = data->hdev;
|
|
|
|
|
2015-01-27 13:33:48 +08:00
|
|
|
/* 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.
|
|
|
|
*/
|
2021-08-05 08:32:15 +08:00
|
|
|
if (btintel_test_flag(hdev, INTEL_BOOTLOADER))
|
2015-01-27 13:33:48 +08:00
|
|
|
return btusb_recv_intr(data, buffer, count);
|
|
|
|
|
|
|
|
return btusb_recv_bulk(data, buffer, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct urb *urb;
|
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
2015-11-05 14:33:56 +08:00
|
|
|
switch (hci_skb_pkt_type(skb)) {
|
2015-01-27 13:33:48 +08:00
|
|
|
case HCI_COMMAND_PKT:
|
2021-08-05 08:32:15 +08:00
|
|
|
if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
|
2015-01-27 13:33:48 +08:00
|
|
|
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);
|
2019-10-28 23:09:09 +08:00
|
|
|
|
|
|
|
case HCI_ISODATA_PKT:
|
|
|
|
urb = alloc_bulk_urb(hdev, skb);
|
|
|
|
if (IS_ERR(urb))
|
|
|
|
return PTR_ERR(urb);
|
|
|
|
|
|
|
|
return submit_or_queue_tx_urb(hdev, urb);
|
2015-01-27 13:33:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return -EILSEQ;
|
|
|
|
}
|
|
|
|
|
2022-10-05 16:43:31 +08:00
|
|
|
static int btusb_setup_realtek(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = btrtl_setup_realtek(hdev);
|
|
|
|
|
|
|
|
if (btrealtek_test_flag(data->hdev, REALTEK_ALT6_CONTINUOUS_TX_CHIP))
|
|
|
|
set_bit(BTUSB_ALT6_CONTINUOUS_TX, &data->flags);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-04-27 11:27:55 +08:00
|
|
|
static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
|
|
|
|
struct rtk_dev_coredump_hdr hdr = {
|
|
|
|
.code = RTK_DEVCOREDUMP_CODE_MEMDUMP,
|
|
|
|
};
|
|
|
|
|
|
|
|
bt_dev_dbg(hdev, "RTL: received coredump vendor evt, len %u",
|
|
|
|
skb->len);
|
|
|
|
|
|
|
|
btusb_rtl_alloc_devcoredump(hdev, &hdr, skb->data, skb->len);
|
|
|
|
kfree_skb(skb);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hci_recv_frame(hdev, skb);
|
|
|
|
}
|
|
|
|
|
2024-07-04 14:01:16 +08:00
|
|
|
static void btusb_mtk_claim_iso_intf(struct btusb_data *data)
|
|
|
|
{
|
|
|
|
struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = usb_driver_claim_interface(&btusb_driver,
|
|
|
|
btmtk_data->isopkt_intf, data);
|
|
|
|
if (err < 0) {
|
|
|
|
btmtk_data->isopkt_intf = NULL;
|
|
|
|
bt_dev_err(data->hdev, "Failed to claim iso interface");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void btusb_mtk_release_iso_intf(struct btusb_data *data)
|
|
|
|
{
|
|
|
|
struct btmtk_data *btmtk_data = hci_get_priv(data->hdev);
|
|
|
|
|
|
|
|
if (btmtk_data->isopkt_intf) {
|
|
|
|
usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor);
|
|
|
|
clear_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags);
|
|
|
|
|
|
|
|
dev_kfree_skb_irq(btmtk_data->isopkt_skb);
|
|
|
|
btmtk_data->isopkt_skb = NULL;
|
|
|
|
usb_set_intfdata(btmtk_data->isopkt_intf, NULL);
|
|
|
|
usb_driver_release_interface(&btusb_driver,
|
|
|
|
btmtk_data->isopkt_intf);
|
|
|
|
}
|
|
|
|
|
|
|
|
clear_bit(BTMTK_ISOPKT_OVER_INTR, &btmtk_data->flags);
|
|
|
|
}
|
|
|
|
|
2024-05-16 07:15:19 +08:00
|
|
|
static int btusb_mtk_reset(struct hci_dev *hdev, void *rst_data)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2024-07-04 14:01:11 +08:00
|
|
|
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
2024-05-16 07:15:19 +08:00
|
|
|
int err;
|
|
|
|
|
|
|
|
/* It's MediaTek specific bluetooth reset mechanism via USB */
|
2024-07-04 14:01:14 +08:00
|
|
|
if (test_and_set_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags)) {
|
2024-05-16 07:15:19 +08:00
|
|
|
bt_dev_err(hdev, "last reset failed? Not resetting again");
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
2023-06-29 06:54:56 +08:00
|
|
|
|
2024-05-16 07:15:19 +08:00
|
|
|
err = usb_autopm_get_interface(data->intf);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2024-07-04 14:01:16 +08:00
|
|
|
if (test_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags))
|
|
|
|
btusb_mtk_release_iso_intf(data);
|
|
|
|
|
2024-05-16 07:15:19 +08:00
|
|
|
btusb_stop_traffic(data);
|
|
|
|
usb_kill_anchored_urbs(&data->tx_anchor);
|
|
|
|
|
2024-07-04 14:01:14 +08:00
|
|
|
err = btmtk_usb_subsys_reset(hdev, btmtk_data->dev_id);
|
2024-05-16 07:15:19 +08:00
|
|
|
|
|
|
|
usb_queue_reset_device(data->intf);
|
2024-07-04 14:01:14 +08:00
|
|
|
clear_bit(BTMTK_HW_RESET_ACTIVE, &btmtk_data->flags);
|
2023-06-29 06:54:56 +08:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2024-07-04 14:01:16 +08:00
|
|
|
static int btusb_send_frame_mtk(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct urb *urb;
|
|
|
|
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
|
|
|
|
if (hci_skb_pkt_type(skb) == HCI_ISODATA_PKT) {
|
|
|
|
urb = alloc_mtk_intr_urb(hdev, skb, btusb_tx_complete);
|
|
|
|
if (IS_ERR(urb))
|
|
|
|
return PTR_ERR(urb);
|
|
|
|
|
|
|
|
return submit_or_queue_tx_urb(hdev, urb);
|
|
|
|
} else {
|
|
|
|
return btusb_send_frame(hdev, skb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-02 08:02:48 +08:00
|
|
|
static int btusb_mtk_setup(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
2024-07-04 14:01:14 +08:00
|
|
|
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
2019-06-02 08:02:48 +08:00
|
|
|
|
2024-07-04 14:01:14 +08:00
|
|
|
/* MediaTek WMT vendor cmd requiring below USB resources to
|
|
|
|
* complete the handshake.
|
|
|
|
*/
|
|
|
|
btmtk_data->drv_name = btusb_driver.name;
|
|
|
|
btmtk_data->intf = data->intf;
|
|
|
|
btmtk_data->udev = data->udev;
|
|
|
|
btmtk_data->ctrl_anchor = &data->ctrl_anchor;
|
|
|
|
btmtk_data->reset_sync = btusb_mtk_reset;
|
2019-06-02 08:02:48 +08:00
|
|
|
|
2024-07-04 14:01:16 +08:00
|
|
|
/* Claim ISO data interface and endpoint */
|
|
|
|
btmtk_data->isopkt_intf = usb_ifnum_to_if(data->udev, MTK_ISO_IFNUM);
|
|
|
|
if (btmtk_data->isopkt_intf)
|
|
|
|
btusb_mtk_claim_iso_intf(data);
|
|
|
|
|
2024-07-04 14:01:14 +08:00
|
|
|
return btmtk_usb_setup(hdev);
|
2019-06-02 08:02:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_mtk_shutdown(struct hci_dev *hdev)
|
|
|
|
{
|
2024-07-04 14:01:16 +08:00
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
|
|
|
|
|
|
|
if (test_bit(BTMTK_ISOPKT_RUNNING, &btmtk_data->flags))
|
|
|
|
btusb_mtk_release_iso_intf(data);
|
|
|
|
|
2024-07-04 14:01:14 +08:00
|
|
|
return btmtk_usb_shutdown(hdev);
|
2019-06-02 08:02:48 +08:00
|
|
|
}
|
|
|
|
|
2017-02-02 06:24:10 +08:00
|
|
|
#ifdef CONFIG_PM
|
|
|
|
/* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
|
|
|
|
static int marvell_config_oob_wake(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct device *dev = &data->udev->dev;
|
|
|
|
u16 pin, gap, opcode;
|
|
|
|
int ret;
|
|
|
|
u8 cmd[5];
|
|
|
|
|
|
|
|
/* Move on if no wakeup pin specified */
|
|
|
|
if (of_property_read_u16(dev->of_node, "marvell,wakeup-pin", &pin) ||
|
|
|
|
of_property_read_u16(dev->of_node, "marvell,wakeup-gap-ms", &gap))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Vendor specific command to configure a GPIO as wake-up pin */
|
|
|
|
opcode = hci_opcode_pack(0x3F, 0x59);
|
|
|
|
cmd[0] = opcode & 0xFF;
|
|
|
|
cmd[1] = opcode >> 8;
|
|
|
|
cmd[2] = 2; /* length of parameters that follow */
|
|
|
|
cmd[3] = pin;
|
|
|
|
cmd[4] = gap; /* time in ms, for which wakeup pin should be asserted */
|
|
|
|
|
|
|
|
skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
|
|
|
|
if (!skb) {
|
2020-12-22 18:31:49 +08:00
|
|
|
bt_dev_err(hdev, "%s: No memory", __func__);
|
2017-02-02 06:24:10 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:20 +08:00
|
|
|
skb_put_data(skb, cmd, sizeof(cmd));
|
2017-02-02 06:24:10 +08:00
|
|
|
hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
|
|
|
|
|
|
|
|
ret = btusb_send_frame(hdev, skb);
|
|
|
|
if (ret) {
|
2020-12-22 18:31:49 +08:00
|
|
|
bt_dev_err(hdev, "%s: configuration failed", __func__);
|
2017-02-02 06:24:10 +08:00
|
|
|
kfree_skb(skb);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-07-19 05:47:06 +08:00
|
|
|
static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
|
|
|
|
const bdaddr_t *bdaddr)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
u8 buf[8];
|
|
|
|
long ret;
|
|
|
|
|
|
|
|
buf[0] = 0xfe;
|
|
|
|
buf[1] = sizeof(bdaddr_t);
|
|
|
|
memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
|
|
|
|
|
|
|
|
skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT);
|
|
|
|
if (IS_ERR(skb)) {
|
|
|
|
ret = PTR_ERR(skb);
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "changing Marvell device address failed (%ld)",
|
|
|
|
ret);
|
2014-07-19 05:47:06 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
kfree_skb(skb);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-13 02:58:05 +08:00
|
|
|
static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
|
|
|
|
const bdaddr_t *bdaddr)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
u8 buf[10];
|
|
|
|
long ret;
|
|
|
|
|
|
|
|
buf[0] = 0x01;
|
|
|
|
buf[1] = 0x01;
|
|
|
|
buf[2] = 0x00;
|
|
|
|
buf[3] = sizeof(bdaddr_t);
|
|
|
|
memcpy(buf + 4, bdaddr, sizeof(bdaddr_t));
|
|
|
|
|
|
|
|
skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT);
|
|
|
|
if (IS_ERR(skb)) {
|
|
|
|
ret = PTR_ERR(skb);
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "Change address command failed (%ld)", ret);
|
2014-12-13 02:58:05 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
kfree_skb(skb);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-09-29 12:23:51 +08:00
|
|
|
static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
|
|
|
|
const bdaddr_t *bdaddr)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
u8 buf[6];
|
|
|
|
long ret;
|
|
|
|
|
|
|
|
memcpy(buf, bdaddr, sizeof(bdaddr_t));
|
|
|
|
|
|
|
|
skb = __hci_cmd_sync_ev(hdev, 0xfc14, sizeof(buf), buf,
|
|
|
|
HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
|
|
|
|
if (IS_ERR(skb)) {
|
|
|
|
ret = PTR_ERR(skb);
|
|
|
|
bt_dev_err(hdev, "Change address command failed (%ld)", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
kfree_skb(skb);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-04-19 11:38:05 +08:00
|
|
|
#define QCA_MEMDUMP_ACL_HANDLE 0x2EDD
|
|
|
|
#define QCA_MEMDUMP_SIZE_MAX 0x100000
|
|
|
|
#define QCA_MEMDUMP_VSE_CLASS 0x01
|
|
|
|
#define QCA_MEMDUMP_MSG_TYPE 0x08
|
|
|
|
#define QCA_MEMDUMP_PKT_SIZE 248
|
|
|
|
#define QCA_LAST_SEQUENCE_NUM 0xffff
|
|
|
|
|
|
|
|
struct qca_dump_hdr {
|
|
|
|
u8 vse_class;
|
|
|
|
u8 msg_type;
|
|
|
|
__le16 seqno;
|
|
|
|
u8 reserved;
|
|
|
|
union {
|
|
|
|
u8 data[0];
|
|
|
|
struct {
|
|
|
|
__le32 ram_dump_size;
|
|
|
|
u8 data0[0];
|
|
|
|
} __packed;
|
|
|
|
};
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
|
|
|
|
static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
char buf[128];
|
|
|
|
struct btusb_data *btdata = hci_get_drvdata(hdev);
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "Controller Name: 0x%x\n",
|
|
|
|
btdata->qca_dump.controller_id);
|
|
|
|
skb_put_data(skb, buf, strlen(buf));
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "Firmware Version: 0x%x\n",
|
|
|
|
btdata->qca_dump.fw_version);
|
|
|
|
skb_put_data(skb, buf, strlen(buf));
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "Driver: %s\nVendor: qca\n",
|
|
|
|
btusb_driver.name);
|
|
|
|
skb_put_data(skb, buf, strlen(buf));
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "VID: 0x%x\nPID:0x%x\n",
|
|
|
|
btdata->qca_dump.id_vendor, btdata->qca_dump.id_product);
|
|
|
|
skb_put_data(skb, buf, strlen(buf));
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "Lmp Subversion: 0x%x\n",
|
|
|
|
hdev->lmp_subver);
|
|
|
|
skb_put_data(skb, buf, strlen(buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void btusb_coredump_qca(struct hci_dev *hdev)
|
|
|
|
{
|
2024-03-25 16:11:49 +08:00
|
|
|
int err;
|
2023-04-19 11:38:05 +08:00
|
|
|
static const u8 param[] = { 0x26 };
|
|
|
|
|
2024-03-25 16:11:49 +08:00
|
|
|
err = __hci_cmd_send(hdev, 0xfc0c, 1, param);
|
|
|
|
if (err < 0)
|
|
|
|
bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err);
|
2023-04-19 11:38:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ==0: not a dump pkt.
|
|
|
|
* < 0: fails to handle a dump pkt
|
|
|
|
* > 0: otherwise.
|
|
|
|
*/
|
|
|
|
static int handle_dump_pkt_qca(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
|
|
|
u8 pkt_type;
|
|
|
|
u8 *sk_ptr;
|
|
|
|
unsigned int sk_len;
|
|
|
|
u16 seqno;
|
|
|
|
u32 dump_size;
|
|
|
|
|
|
|
|
struct hci_event_hdr *event_hdr;
|
|
|
|
struct hci_acl_hdr *acl_hdr;
|
|
|
|
struct qca_dump_hdr *dump_hdr;
|
|
|
|
struct btusb_data *btdata = hci_get_drvdata(hdev);
|
|
|
|
struct usb_device *udev = btdata->udev;
|
|
|
|
|
|
|
|
pkt_type = hci_skb_pkt_type(skb);
|
|
|
|
sk_ptr = skb->data;
|
|
|
|
sk_len = skb->len;
|
|
|
|
|
|
|
|
if (pkt_type == HCI_ACLDATA_PKT) {
|
|
|
|
acl_hdr = hci_acl_hdr(skb);
|
|
|
|
if (le16_to_cpu(acl_hdr->handle) != QCA_MEMDUMP_ACL_HANDLE)
|
|
|
|
return 0;
|
|
|
|
sk_ptr += HCI_ACL_HDR_SIZE;
|
|
|
|
sk_len -= HCI_ACL_HDR_SIZE;
|
|
|
|
event_hdr = (struct hci_event_hdr *)sk_ptr;
|
|
|
|
} else {
|
|
|
|
event_hdr = hci_event_hdr(skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((event_hdr->evt != HCI_VENDOR_PKT)
|
|
|
|
|| (event_hdr->plen != (sk_len - HCI_EVENT_HDR_SIZE)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sk_ptr += HCI_EVENT_HDR_SIZE;
|
|
|
|
sk_len -= HCI_EVENT_HDR_SIZE;
|
|
|
|
|
|
|
|
dump_hdr = (struct qca_dump_hdr *)sk_ptr;
|
|
|
|
if ((sk_len < offsetof(struct qca_dump_hdr, data))
|
|
|
|
|| (dump_hdr->vse_class != QCA_MEMDUMP_VSE_CLASS)
|
|
|
|
|| (dump_hdr->msg_type != QCA_MEMDUMP_MSG_TYPE))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*it is dump pkt now*/
|
|
|
|
seqno = le16_to_cpu(dump_hdr->seqno);
|
|
|
|
if (seqno == 0) {
|
|
|
|
set_bit(BTUSB_HW_SSR_ACTIVE, &btdata->flags);
|
|
|
|
dump_size = le32_to_cpu(dump_hdr->ram_dump_size);
|
|
|
|
if (!dump_size || (dump_size > QCA_MEMDUMP_SIZE_MAX)) {
|
|
|
|
ret = -EILSEQ;
|
|
|
|
bt_dev_err(hdev, "Invalid memdump size(%u)",
|
|
|
|
dump_size);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = hci_devcd_init(hdev, dump_size);
|
|
|
|
if (ret < 0) {
|
|
|
|
bt_dev_err(hdev, "memdump init error(%d)", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
btdata->qca_dump.ram_dump_size = dump_size;
|
|
|
|
btdata->qca_dump.ram_dump_seqno = 0;
|
|
|
|
sk_ptr += offsetof(struct qca_dump_hdr, data0);
|
|
|
|
sk_len -= offsetof(struct qca_dump_hdr, data0);
|
|
|
|
|
|
|
|
usb_disable_autosuspend(udev);
|
|
|
|
bt_dev_info(hdev, "%s memdump size(%u)\n",
|
|
|
|
(pkt_type == HCI_ACLDATA_PKT) ? "ACL" : "event",
|
|
|
|
dump_size);
|
|
|
|
} else {
|
|
|
|
sk_ptr += offsetof(struct qca_dump_hdr, data);
|
|
|
|
sk_len -= offsetof(struct qca_dump_hdr, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!btdata->qca_dump.ram_dump_size) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
bt_dev_err(hdev, "memdump is not active");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((seqno > btdata->qca_dump.ram_dump_seqno + 1) && (seqno != QCA_LAST_SEQUENCE_NUM)) {
|
|
|
|
dump_size = QCA_MEMDUMP_PKT_SIZE * (seqno - btdata->qca_dump.ram_dump_seqno - 1);
|
|
|
|
hci_devcd_append_pattern(hdev, 0x0, dump_size);
|
|
|
|
bt_dev_err(hdev,
|
|
|
|
"expected memdump seqno(%u) is not received(%u)\n",
|
|
|
|
btdata->qca_dump.ram_dump_seqno, seqno);
|
|
|
|
btdata->qca_dump.ram_dump_seqno = seqno;
|
|
|
|
kfree_skb(skb);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb_pull(skb, skb->len - sk_len);
|
|
|
|
hci_devcd_append(hdev, skb);
|
|
|
|
btdata->qca_dump.ram_dump_seqno++;
|
|
|
|
if (seqno == QCA_LAST_SEQUENCE_NUM) {
|
|
|
|
bt_dev_info(hdev,
|
|
|
|
"memdump done: pkts(%u), total(%u)\n",
|
|
|
|
btdata->qca_dump.ram_dump_seqno, btdata->qca_dump.ram_dump_size);
|
|
|
|
|
|
|
|
hci_devcd_complete(hdev);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (btdata->qca_dump.ram_dump_size)
|
|
|
|
usb_enable_autosuspend(udev);
|
|
|
|
btdata->qca_dump.ram_dump_size = 0;
|
|
|
|
btdata->qca_dump.ram_dump_seqno = 0;
|
|
|
|
clear_bit(BTUSB_HW_SSR_ACTIVE, &btdata->flags);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
kfree_skb(skb);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_recv_acl_qca(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
if (handle_dump_pkt_qca(hdev, skb))
|
|
|
|
return 0;
|
|
|
|
return hci_recv_frame(hdev, skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_recv_evt_qca(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
if (handle_dump_pkt_qca(hdev, skb))
|
|
|
|
return 0;
|
|
|
|
return hci_recv_frame(hdev, skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
#define QCA_DFU_PACKET_LEN 4096
|
|
|
|
|
|
|
|
#define QCA_GET_TARGET_VERSION 0x09
|
|
|
|
#define QCA_CHECK_STATUS 0x05
|
|
|
|
#define QCA_DFU_DOWNLOAD 0x01
|
|
|
|
|
|
|
|
#define QCA_SYSCFG_UPDATED 0x40
|
|
|
|
#define QCA_PATCH_UPDATED 0x80
|
|
|
|
#define QCA_DFU_TIMEOUT 3000
|
2020-12-03 12:57:14 +08:00
|
|
|
#define QCA_FLAG_MULTI_NVM 0x80
|
2022-02-14 18:43:39 +08:00
|
|
|
#define QCA_BT_RESET_WAIT_MS 100
|
2015-02-16 07:07:33 +08:00
|
|
|
|
2021-10-29 11:21:21 +08:00
|
|
|
#define WCN6855_2_0_RAM_VERSION_GF 0x400c1200
|
|
|
|
#define WCN6855_2_1_RAM_VERSION_GF 0x400c1211
|
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
struct qca_version {
|
|
|
|
__le32 rom_version;
|
|
|
|
__le32 patch_version;
|
|
|
|
__le32 ram_version;
|
2021-11-16 12:48:49 +08:00
|
|
|
__u8 chip_id;
|
|
|
|
__u8 platform_id;
|
2020-12-03 12:57:14 +08:00
|
|
|
__le16 flag;
|
2015-02-16 07:07:33 +08:00
|
|
|
__u8 reserved[4];
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
struct qca_rampatch_version {
|
2020-09-29 12:23:51 +08:00
|
|
|
__le16 rom_version_high;
|
|
|
|
__le16 rom_version_low;
|
2015-02-16 07:07:33 +08:00
|
|
|
__le16 patch_version;
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
struct qca_device_info {
|
2015-03-11 07:34:58 +08:00
|
|
|
u32 rom_version;
|
|
|
|
u8 rampatch_hdr; /* length of header in rampatch */
|
|
|
|
u8 nvm_hdr; /* length of header in NVM */
|
|
|
|
u8 ver_offset; /* offset of version structure in rampatch */
|
2015-02-16 07:07:33 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct qca_device_info qca_devices_table[] = {
|
2020-09-29 12:23:51 +08:00
|
|
|
{ 0x00000100, 20, 4, 8 }, /* Rome 1.0 */
|
|
|
|
{ 0x00000101, 20, 4, 8 }, /* Rome 1.1 */
|
|
|
|
{ 0x00000200, 28, 4, 16 }, /* Rome 2.0 */
|
|
|
|
{ 0x00000201, 28, 4, 16 }, /* Rome 2.1 */
|
|
|
|
{ 0x00000300, 28, 4, 16 }, /* Rome 3.0 */
|
|
|
|
{ 0x00000302, 28, 4, 16 }, /* Rome 3.2 */
|
|
|
|
{ 0x00130100, 40, 4, 16 }, /* WCN6855 1.0 */
|
|
|
|
{ 0x00130200, 40, 4, 16 }, /* WCN6855 2.0 */
|
2021-10-29 11:21:21 +08:00
|
|
|
{ 0x00130201, 40, 4, 16 }, /* WCN6855 2.1 */
|
2022-04-25 23:01:29 +08:00
|
|
|
{ 0x00190200, 40, 4, 16 }, /* WCN785x 2.0 */
|
2015-02-16 07:07:33 +08:00
|
|
|
};
|
|
|
|
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
|
2015-02-16 07:07:33 +08:00
|
|
|
void *data, u16 size)
|
|
|
|
{
|
|
|
|
int pipe, err;
|
|
|
|
u8 *buf;
|
|
|
|
|
|
|
|
buf = kmalloc(size, GFP_KERNEL);
|
|
|
|
if (!buf)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
/* Found some of USB hosts have IOT issues with ours so that we should
|
|
|
|
* not wait until HCI layer is ready.
|
|
|
|
*/
|
|
|
|
pipe = usb_rcvctrlpipe(udev, 0);
|
|
|
|
err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN,
|
2024-04-22 22:57:10 +08:00
|
|
|
0, 0, buf, size, USB_CTRL_GET_TIMEOUT);
|
2015-02-16 07:07:33 +08:00
|
|
|
if (err < 0) {
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
dev_err(&udev->dev, "Failed to access otp area (%d)", err);
|
2015-02-16 07:07:33 +08:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(data, buf, size);
|
|
|
|
|
|
|
|
done:
|
|
|
|
kfree(buf);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_setup_qca_download_fw(struct hci_dev *hdev,
|
|
|
|
const struct firmware *firmware,
|
|
|
|
size_t hdr_size)
|
|
|
|
{
|
|
|
|
struct btusb_data *btdata = hci_get_drvdata(hdev);
|
|
|
|
struct usb_device *udev = btdata->udev;
|
|
|
|
size_t count, size, sent = 0;
|
|
|
|
int pipe, len, err;
|
|
|
|
u8 *buf;
|
|
|
|
|
|
|
|
buf = kmalloc(QCA_DFU_PACKET_LEN, GFP_KERNEL);
|
|
|
|
if (!buf)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
count = firmware->size;
|
|
|
|
|
|
|
|
size = min_t(size_t, count, hdr_size);
|
|
|
|
memcpy(buf, firmware->data, size);
|
|
|
|
|
|
|
|
/* USB patches should go down to controller through USB path
|
|
|
|
* because binary format fits to go down through USB channel.
|
|
|
|
* USB control path is for patching headers and USB bulk is for
|
|
|
|
* patch body.
|
|
|
|
*/
|
|
|
|
pipe = usb_sndctrlpipe(udev, 0);
|
|
|
|
err = usb_control_msg(udev, pipe, QCA_DFU_DOWNLOAD, USB_TYPE_VENDOR,
|
|
|
|
0, 0, buf, size, USB_CTRL_SET_TIMEOUT);
|
|
|
|
if (err < 0) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "Failed to send headers (%d)", err);
|
2015-02-16 07:07:33 +08:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
sent += size;
|
|
|
|
count -= size;
|
|
|
|
|
2021-06-01 17:57:10 +08:00
|
|
|
/* ep2 need time to switch from function acl to function dfu,
|
|
|
|
* so we add 20ms delay here.
|
|
|
|
*/
|
|
|
|
msleep(20);
|
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
while (count) {
|
|
|
|
size = min_t(size_t, count, QCA_DFU_PACKET_LEN);
|
|
|
|
|
|
|
|
memcpy(buf, firmware->data + sent, size);
|
|
|
|
|
|
|
|
pipe = usb_sndbulkpipe(udev, 0x02);
|
|
|
|
err = usb_bulk_msg(udev, pipe, buf, size, &len,
|
|
|
|
QCA_DFU_TIMEOUT);
|
|
|
|
if (err < 0) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "Failed to send body at %zd of %zd (%d)",
|
|
|
|
sent, firmware->size, err);
|
2015-02-16 07:07:33 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size != len) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "Failed to get bulk buffer");
|
2015-02-16 07:07:33 +08:00
|
|
|
err = -EILSEQ;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sent += size;
|
|
|
|
count -= size;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
kfree(buf);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
|
|
|
|
struct qca_version *ver,
|
|
|
|
const struct qca_device_info *info)
|
|
|
|
{
|
|
|
|
struct qca_rampatch_version *rver;
|
|
|
|
const struct firmware *fw;
|
2020-09-29 12:23:51 +08:00
|
|
|
u32 ver_rom, ver_patch, rver_rom;
|
|
|
|
u16 rver_rom_low, rver_rom_high, rver_patch;
|
2015-02-16 07:07:33 +08:00
|
|
|
char fwname[64];
|
|
|
|
int err;
|
|
|
|
|
2015-03-11 07:34:58 +08:00
|
|
|
ver_rom = le32_to_cpu(ver->rom_version);
|
|
|
|
ver_patch = le32_to_cpu(ver->patch_version);
|
|
|
|
|
|
|
|
snprintf(fwname, sizeof(fwname), "qca/rampatch_usb_%08x.bin", ver_rom);
|
2015-02-16 07:07:33 +08:00
|
|
|
|
|
|
|
err = request_firmware(&fw, fwname, &hdev->dev);
|
|
|
|
if (err) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "failed to request rampatch file: %s (%d)",
|
|
|
|
fwname, err);
|
2015-02-16 07:07:33 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_info(hdev, "using rampatch file: %s", fwname);
|
2015-03-11 07:34:58 +08:00
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
|
2020-09-29 12:23:51 +08:00
|
|
|
rver_rom_low = le16_to_cpu(rver->rom_version_low);
|
2015-03-11 07:34:58 +08:00
|
|
|
rver_patch = le16_to_cpu(rver->patch_version);
|
|
|
|
|
2020-09-29 12:23:51 +08:00
|
|
|
if (ver_rom & ~0xffffU) {
|
|
|
|
rver_rom_high = le16_to_cpu(rver->rom_version_high);
|
2022-12-06 01:58:43 +08:00
|
|
|
rver_rom = rver_rom_high << 16 | rver_rom_low;
|
2020-09-29 12:23:51 +08:00
|
|
|
} else {
|
|
|
|
rver_rom = rver_rom_low;
|
|
|
|
}
|
|
|
|
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
|
|
|
|
"firmware rome 0x%x build 0x%x",
|
|
|
|
rver_rom, rver_patch, ver_rom, ver_patch);
|
2015-02-16 07:07:33 +08:00
|
|
|
|
2015-03-11 07:34:58 +08:00
|
|
|
if (rver_rom != ver_rom || rver_patch <= ver_patch) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "rampatch file version did not match with firmware");
|
2015-02-16 07:07:33 +08:00
|
|
|
err = -EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = btusb_setup_qca_download_fw(hdev, fw, info->rampatch_hdr);
|
|
|
|
|
|
|
|
done:
|
|
|
|
release_firmware(fw);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2021-10-29 11:21:21 +08:00
|
|
|
static void btusb_generate_qca_nvm_name(char *fwname, size_t max_size,
|
|
|
|
const struct qca_version *ver)
|
|
|
|
{
|
|
|
|
u32 rom_version = le32_to_cpu(ver->rom_version);
|
|
|
|
u16 flag = le16_to_cpu(ver->flag);
|
|
|
|
|
|
|
|
if (((flag >> 8) & 0xff) == QCA_FLAG_MULTI_NVM) {
|
2021-11-16 12:48:49 +08:00
|
|
|
/* The board_id should be split into two bytes
|
|
|
|
* The 1st byte is chip ID, and the 2nd byte is platform ID
|
|
|
|
* For example, board ID 0x010A, 0x01 is platform ID. 0x0A is chip ID
|
2021-11-16 19:02:16 +08:00
|
|
|
* we have several platforms, and platform IDs are continuously added
|
2021-11-16 12:48:49 +08:00
|
|
|
* Platform ID:
|
|
|
|
* 0x00 is for Mobile
|
|
|
|
* 0x01 is for X86
|
|
|
|
* 0x02 is for Automotive
|
|
|
|
* 0x03 is for Consumer electronic
|
|
|
|
*/
|
|
|
|
u16 board_id = (ver->chip_id << 8) + ver->platform_id;
|
2021-10-29 11:21:21 +08:00
|
|
|
const char *variant;
|
|
|
|
|
|
|
|
switch (le32_to_cpu(ver->ram_version)) {
|
|
|
|
case WCN6855_2_0_RAM_VERSION_GF:
|
|
|
|
case WCN6855_2_1_RAM_VERSION_GF:
|
|
|
|
variant = "_gf";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
variant = "";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (board_id == 0) {
|
|
|
|
snprintf(fwname, max_size, "qca/nvm_usb_%08x%s.bin",
|
|
|
|
rom_version, variant);
|
|
|
|
} else {
|
|
|
|
snprintf(fwname, max_size, "qca/nvm_usb_%08x%s_%04x.bin",
|
|
|
|
rom_version, variant, board_id);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
snprintf(fwname, max_size, "qca/nvm_usb_%08x.bin",
|
|
|
|
rom_version);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
static int btusb_setup_qca_load_nvm(struct hci_dev *hdev,
|
|
|
|
struct qca_version *ver,
|
|
|
|
const struct qca_device_info *info)
|
|
|
|
{
|
|
|
|
const struct firmware *fw;
|
|
|
|
char fwname[64];
|
|
|
|
int err;
|
|
|
|
|
2021-10-29 11:21:21 +08:00
|
|
|
btusb_generate_qca_nvm_name(fwname, sizeof(fwname), ver);
|
2015-02-16 07:07:33 +08:00
|
|
|
|
|
|
|
err = request_firmware(&fw, fwname, &hdev->dev);
|
|
|
|
if (err) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "failed to request NVM file: %s (%d)",
|
|
|
|
fwname, err);
|
2015-02-16 07:07:33 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_info(hdev, "using NVM file: %s", fwname);
|
2015-02-16 07:07:33 +08:00
|
|
|
|
|
|
|
err = btusb_setup_qca_download_fw(hdev, fw, info->nvm_hdr);
|
|
|
|
|
|
|
|
release_firmware(fw);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
/* identify the ROM version and check whether patches are needed */
|
|
|
|
static bool btusb_qca_need_patch(struct usb_device *udev)
|
|
|
|
{
|
|
|
|
struct qca_version ver;
|
|
|
|
|
|
|
|
if (btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
|
|
|
|
sizeof(ver)) < 0)
|
|
|
|
return false;
|
|
|
|
/* only low ROM versions need patches */
|
|
|
|
return !(le32_to_cpu(ver.rom_version) & ~0xffffU);
|
|
|
|
}
|
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
static int btusb_setup_qca(struct hci_dev *hdev)
|
|
|
|
{
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
struct btusb_data *btdata = hci_get_drvdata(hdev);
|
|
|
|
struct usb_device *udev = btdata->udev;
|
2015-02-16 07:07:33 +08:00
|
|
|
const struct qca_device_info *info = NULL;
|
|
|
|
struct qca_version ver;
|
2015-03-11 07:34:58 +08:00
|
|
|
u32 ver_rom;
|
2015-02-16 07:07:33 +08:00
|
|
|
u8 status;
|
|
|
|
int i, err;
|
|
|
|
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
|
2015-04-17 05:15:50 +08:00
|
|
|
sizeof(ver));
|
2015-02-16 07:07:33 +08:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2015-03-11 07:34:58 +08:00
|
|
|
ver_rom = le32_to_cpu(ver.rom_version);
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
|
2015-03-11 07:34:58 +08:00
|
|
|
if (ver_rom == qca_devices_table[i].rom_version)
|
2015-02-16 07:07:33 +08:00
|
|
|
info = &qca_devices_table[i];
|
|
|
|
}
|
|
|
|
if (!info) {
|
Bluetooth: btusb: Some Qualcomm Bluetooth adapters stop working
This issue starts from linux-5.10-rc1, I reproduced this issue on my
Dell Inspiron 7447 with BT adapter 0cf3:e005, the kernel will print
out: "Bluetooth: hci0: don't support firmware rome 0x31010000", and
someone else also reported the similar issue to bugzilla #211571.
I found this is a regression introduced by 'commit b40f58b97386
("Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support"), the
patch assumed that if high ROM version is not zero, it is an adapter
on WCN6855, but many old adapters don't need to load rampatch or nvm,
and they have non-zero high ROM version.
To fix it, let the driver match the rom_version in the
qca_devices_table first, if there is no entry matched, check the
high ROM version, if it is not zero, we assume this adapter is ready
to work and no need to load rampatch and nvm like previously.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=211571
Fixes: b40f58b97386 ("Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support")
Signed-off-by: Hui Wang <hui.wang@canonical.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-02-08 13:02:37 +08:00
|
|
|
/* If the rom_version is not matched in the qca_devices_table
|
|
|
|
* and the high ROM version is not zero, we assume this chip no
|
|
|
|
* need to load the rampatch and nvm.
|
|
|
|
*/
|
|
|
|
if (ver_rom & ~0xffffU)
|
|
|
|
return 0;
|
|
|
|
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
|
2015-02-16 07:07:33 +08:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
err = btusb_qca_send_vendor_req(udev, QCA_CHECK_STATUS, &status,
|
2015-02-16 07:07:33 +08:00
|
|
|
sizeof(status));
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (!(status & QCA_PATCH_UPDATED)) {
|
|
|
|
err = btusb_setup_qca_load_rampatch(hdev, &ver, info);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-12-03 12:57:14 +08:00
|
|
|
err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
|
|
|
|
sizeof(ver));
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2023-04-19 11:38:05 +08:00
|
|
|
btdata->qca_dump.fw_version = le32_to_cpu(ver.patch_version);
|
|
|
|
btdata->qca_dump.controller_id = le32_to_cpu(ver.rom_version);
|
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
if (!(status & QCA_SYSCFG_UPDATED)) {
|
|
|
|
err = btusb_setup_qca_load_nvm(hdev, &ver, info);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
2022-02-14 18:43:39 +08:00
|
|
|
|
2022-04-25 23:01:29 +08:00
|
|
|
/* WCN6855 2.1 and later will reset to apply firmware downloaded here, so
|
2022-02-14 18:43:39 +08:00
|
|
|
* wait ~100ms for reset Done then go ahead, otherwise, it maybe
|
|
|
|
* cause potential enable failure.
|
|
|
|
*/
|
2022-04-25 23:01:29 +08:00
|
|
|
if (info->rom_version >= 0x00130201)
|
2022-02-14 18:43:39 +08:00
|
|
|
msleep(QCA_BT_RESET_WAIT_MS);
|
2015-02-16 07:07:33 +08:00
|
|
|
}
|
|
|
|
|
2022-04-02 07:38:25 +08:00
|
|
|
/* Mark HCI_OP_ENHANCED_SETUP_SYNC_CONN as broken as it doesn't seem to
|
|
|
|
* work with the likes of HSP/HFP mSBC.
|
|
|
|
*/
|
|
|
|
set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
|
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-10-09 02:23:08 +08:00
|
|
|
static inline int __set_diag_interface(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct usb_interface *intf = data->diag;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!data->diag)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
data->diag_tx_ep = NULL;
|
|
|
|
data->diag_rx_ep = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
|
|
|
|
struct usb_endpoint_descriptor *ep_desc;
|
|
|
|
|
|
|
|
ep_desc = &intf->cur_altsetting->endpoint[i].desc;
|
|
|
|
|
|
|
|
if (!data->diag_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
|
|
|
|
data->diag_tx_ep = ep_desc;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data->diag_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
|
|
|
|
data->diag_rx_ep = ep_desc;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data->diag_tx_ep || !data->diag_rx_ep) {
|
2017-10-30 17:42:59 +08:00
|
|
|
bt_dev_err(hdev, "invalid diagnostic descriptors");
|
2015-10-09 02:23:08 +08:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct urb *alloc_diag_urb(struct hci_dev *hdev, bool enable)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
struct urb *urb;
|
|
|
|
unsigned int pipe;
|
|
|
|
|
|
|
|
if (!data->diag_tx_ep)
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
|
|
|
|
urb = usb_alloc_urb(0, GFP_KERNEL);
|
|
|
|
if (!urb)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
skb = bt_skb_alloc(2, GFP_KERNEL);
|
|
|
|
if (!skb) {
|
|
|
|
usb_free_urb(urb);
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
}
|
|
|
|
|
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 20:29:24 +08:00
|
|
|
skb_put_u8(skb, 0xf0);
|
|
|
|
skb_put_u8(skb, enable);
|
2015-10-09 02:23:08 +08:00
|
|
|
|
|
|
|
pipe = usb_sndbulkpipe(data->udev, data->diag_tx_ep->bEndpointAddress);
|
|
|
|
|
|
|
|
usb_fill_bulk_urb(urb, data->udev, pipe,
|
|
|
|
skb->data, skb->len, btusb_tx_complete, skb);
|
|
|
|
|
|
|
|
skb->dev = (void *)hdev;
|
|
|
|
|
|
|
|
return urb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct urb *urb;
|
|
|
|
|
|
|
|
if (!data->diag)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
|
|
|
return -ENETDOWN;
|
|
|
|
|
|
|
|
urb = alloc_diag_urb(hdev, enable);
|
|
|
|
if (IS_ERR(urb))
|
|
|
|
return PTR_ERR(urb);
|
|
|
|
|
|
|
|
return submit_or_queue_tx_urb(hdev, urb);
|
|
|
|
}
|
|
|
|
|
2017-02-02 06:24:09 +08:00
|
|
|
#ifdef CONFIG_PM
|
|
|
|
static irqreturn_t btusb_oob_wake_handler(int irq, void *priv)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = priv;
|
|
|
|
|
|
|
|
pm_wakeup_event(&data->udev->dev, 0);
|
2017-02-24 14:24:29 +08:00
|
|
|
pm_system_wakeup();
|
2017-02-02 06:24:09 +08:00
|
|
|
|
|
|
|
/* Disable only if not already disabled (keep it balanced) */
|
|
|
|
if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {
|
|
|
|
disable_irq_nosync(irq);
|
|
|
|
disable_irq_wake(irq);
|
|
|
|
}
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct of_device_id btusb_match_table[] = {
|
|
|
|
{ .compatible = "usb1286,204e" },
|
2019-02-23 06:53:43 +08:00
|
|
|
{ .compatible = "usbcf3,e300" }, /* QCA6174A */
|
|
|
|
{ .compatible = "usb4ca,301a" }, /* QCA6174A (Lite-On) */
|
2017-02-02 06:24:09 +08:00
|
|
|
{ }
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(of, btusb_match_table);
|
|
|
|
|
|
|
|
/* Use an oob wakeup pin? */
|
|
|
|
static int btusb_config_oob_wake(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
struct device *dev = &data->udev->dev;
|
|
|
|
int irq, ret;
|
|
|
|
|
|
|
|
clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags);
|
|
|
|
|
|
|
|
if (!of_match_device(btusb_match_table, dev))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Move on if no IRQ specified */
|
|
|
|
irq = of_irq_get_byname(dev->of_node, "wakeup");
|
|
|
|
if (irq <= 0) {
|
|
|
|
bt_dev_dbg(hdev, "%s: no OOB Wakeup IRQ in DT", __func__);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-04-10 02:49:17 +08:00
|
|
|
irq_set_status_flags(irq, IRQ_NOAUTOEN);
|
2017-02-02 06:24:09 +08:00
|
|
|
ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler,
|
|
|
|
0, "OOB Wake-on-BT", data);
|
|
|
|
if (ret) {
|
|
|
|
bt_dev_err(hdev, "%s: IRQ request failed", __func__);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = device_init_wakeup(dev, true);
|
|
|
|
if (ret) {
|
|
|
|
bt_dev_err(hdev, "%s: failed to init_wakeup", __func__);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->oob_wake_irq = irq;
|
|
|
|
bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-04-27 17:26:43 +08:00
|
|
|
static void btusb_check_needs_reset_resume(struct usb_interface *intf)
|
|
|
|
{
|
|
|
|
if (dmi_check_system(btusb_needs_reset_resume_table))
|
|
|
|
interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
|
|
|
|
}
|
|
|
|
|
2021-10-02 04:22:31 +08:00
|
|
|
static bool btusb_wakeup(struct hci_dev *hdev)
|
2020-05-13 10:19:27 +08:00
|
|
|
{
|
|
|
|
struct btusb_data *data = hci_get_drvdata(hdev);
|
|
|
|
|
2021-10-02 04:22:31 +08:00
|
|
|
return device_may_wakeup(&data->udev->dev);
|
2020-05-13 10:19:27 +08:00
|
|
|
}
|
|
|
|
|
2020-12-18 18:12:11 +08:00
|
|
|
static int btusb_shutdown_qca(struct hci_dev *hdev)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
|
|
|
|
if (IS_ERR(skb)) {
|
|
|
|
bt_dev_err(hdev, "HCI reset during shutdown failed");
|
|
|
|
return PTR_ERR(skb);
|
|
|
|
}
|
|
|
|
kfree_skb(skb);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
static ssize_t force_poll_sync_read(struct file *file, char __user *user_buf,
|
|
|
|
size_t count, loff_t *ppos)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = file->private_data;
|
|
|
|
char buf[3];
|
|
|
|
|
|
|
|
buf[0] = data->poll_sync ? 'Y' : 'N';
|
|
|
|
buf[1] = '\n';
|
|
|
|
buf[2] = '\0';
|
|
|
|
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t force_poll_sync_write(struct file *file,
|
|
|
|
const char __user *user_buf,
|
|
|
|
size_t count, loff_t *ppos)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = file->private_data;
|
|
|
|
bool enable;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = kstrtobool_from_user(user_buf, count, &enable);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
/* Only allow changes while the adapter is down */
|
|
|
|
if (test_bit(HCI_UP, &data->hdev->flags))
|
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
if (data->poll_sync == enable)
|
|
|
|
return -EALREADY;
|
|
|
|
|
|
|
|
data->poll_sync = enable;
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations force_poll_sync_fops = {
|
|
|
|
.open = simple_open,
|
|
|
|
.read = force_poll_sync_read,
|
|
|
|
.write = force_poll_sync_write,
|
|
|
|
.llseek = default_llseek,
|
|
|
|
};
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
static int btusb_probe(struct usb_interface *intf,
|
2014-09-16 10:44:50 +08:00
|
|
|
const struct usb_device_id *id)
|
2007-10-20 20:12:34 +08:00
|
|
|
{
|
|
|
|
struct usb_endpoint_descriptor *ep_desc;
|
2019-01-25 07:28:14 +08:00
|
|
|
struct gpio_desc *reset_gpio;
|
2007-10-20 20:12:34 +08:00
|
|
|
struct btusb_data *data;
|
|
|
|
struct hci_dev *hdev;
|
2015-10-20 06:53:33 +08:00
|
|
|
unsigned ifnum_base;
|
2021-08-05 08:32:11 +08:00
|
|
|
int i, err, priv_size;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
BT_DBG("intf %p id %p", intf, id);
|
|
|
|
|
2023-02-07 19:57:41 +08:00
|
|
|
if ((id->driver_info & BTUSB_IFNUM_2) &&
|
2023-07-13 18:25:14 +08:00
|
|
|
(intf->cur_altsetting->desc.bInterfaceNumber != 0) &&
|
2023-02-07 19:57:41 +08:00
|
|
|
(intf->cur_altsetting->desc.bInterfaceNumber != 2))
|
|
|
|
return -ENODEV;
|
2015-10-20 06:53:33 +08:00
|
|
|
|
|
|
|
ifnum_base = intf->cur_altsetting->desc.bInterfaceNumber;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
if (!id->driver_info) {
|
|
|
|
const struct usb_device_id *match;
|
2014-09-16 10:44:50 +08:00
|
|
|
|
2023-08-22 18:20:24 +08:00
|
|
|
match = usb_match_id(intf, quirks_table);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (match)
|
|
|
|
id = match;
|
|
|
|
}
|
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
if (id->driver_info == BTUSB_IGNORE)
|
|
|
|
return -ENODEV;
|
|
|
|
|
2011-07-01 14:02:36 +08:00
|
|
|
if (id->driver_info & BTUSB_ATH3012) {
|
|
|
|
struct usb_device *udev = interface_to_usbdev(intf);
|
|
|
|
|
|
|
|
/* Old firmware would otherwise let ath3k driver load
|
2017-07-22 09:47:07 +08:00
|
|
|
* patch and sysconfig files
|
|
|
|
*/
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001 &&
|
|
|
|
!btusb_qca_need_patch(udev))
|
2011-07-01 14:02:36 +08:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2012-07-27 15:08:39 +08:00
|
|
|
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
|
2007-10-20 20:12:34 +08:00
|
|
|
if (!data)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
|
|
|
|
ep_desc = &intf->cur_altsetting->endpoint[i].desc;
|
|
|
|
|
|
|
|
if (!data->intr_ep && usb_endpoint_is_int_in(ep_desc)) {
|
|
|
|
data->intr_ep = ep_desc;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data->bulk_tx_ep && usb_endpoint_is_bulk_out(ep_desc)) {
|
|
|
|
data->bulk_tx_ep = ep_desc;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data->bulk_rx_ep && usb_endpoint_is_bulk_in(ep_desc)) {
|
|
|
|
data->bulk_rx_ep = ep_desc;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-27 15:08:39 +08:00
|
|
|
if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
|
2007-10-20 20:12:34 +08:00
|
|
|
return -ENODEV;
|
|
|
|
|
2015-01-29 12:27:34 +08:00
|
|
|
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;
|
|
|
|
}
|
2008-11-30 19:17:26 +08:00
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
data->udev = interface_to_usbdev(intf);
|
2008-09-23 06:16:36 +08:00
|
|
|
data->intf = intf;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
INIT_WORK(&data->work, btusb_work);
|
2009-08-25 05:44:59 +08:00
|
|
|
INIT_WORK(&data->waker, btusb_waker);
|
2021-12-04 06:38:13 +08:00
|
|
|
INIT_DELAYED_WORK(&data->rx_work, btusb_rx_work);
|
|
|
|
|
|
|
|
skb_queue_head_init(&data->acl_q);
|
|
|
|
|
2014-09-16 14:00:29 +08:00
|
|
|
init_usb_anchor(&data->deferred);
|
|
|
|
init_usb_anchor(&data->tx_anchor);
|
2009-08-25 05:44:59 +08:00
|
|
|
spin_lock_init(&data->txlock);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
init_usb_anchor(&data->intr_anchor);
|
|
|
|
init_usb_anchor(&data->bulk_anchor);
|
2008-08-18 19:23:52 +08:00
|
|
|
init_usb_anchor(&data->isoc_anchor);
|
2015-10-09 02:23:08 +08:00
|
|
|
init_usb_anchor(&data->diag_anchor);
|
2019-06-02 08:02:48 +08:00
|
|
|
init_usb_anchor(&data->ctrl_anchor);
|
2014-09-16 14:00:29 +08:00
|
|
|
spin_lock_init(&data->rxlock);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2021-08-05 08:32:11 +08:00
|
|
|
priv_size = 0;
|
|
|
|
|
2021-08-05 08:32:15 +08:00
|
|
|
data->recv_event = hci_recv_frame;
|
|
|
|
data->recv_bulk = btusb_recv_bulk;
|
|
|
|
|
2021-08-05 08:32:11 +08:00
|
|
|
if (id->driver_info & BTUSB_INTEL_COMBINED) {
|
|
|
|
/* Allocate extra space for Intel device */
|
|
|
|
priv_size += sizeof(struct btintel_data);
|
|
|
|
|
2021-08-05 08:32:15 +08:00
|
|
|
/* Override the rx handlers */
|
2023-07-21 06:16:32 +08:00
|
|
|
data->recv_event = btintel_recv_event;
|
2015-01-27 13:33:48 +08:00
|
|
|
data->recv_bulk = btusb_recv_bulk_intel;
|
2022-10-05 16:43:30 +08:00
|
|
|
} else if (id->driver_info & BTUSB_REALTEK) {
|
|
|
|
/* Allocate extra space for Realtek device */
|
|
|
|
priv_size += sizeof(struct btrealtek_data);
|
2023-04-27 11:27:55 +08:00
|
|
|
|
|
|
|
data->recv_event = btusb_recv_event_realtek;
|
2023-06-20 16:27:50 +08:00
|
|
|
} else if (id->driver_info & BTUSB_MEDIATEK) {
|
|
|
|
/* Allocate extra space for Mediatek device */
|
2024-07-04 14:01:11 +08:00
|
|
|
priv_size += sizeof(struct btmtk_data);
|
2015-01-27 13:33:48 +08:00
|
|
|
}
|
2014-11-03 12:16:07 +08:00
|
|
|
|
2021-08-04 17:03:15 +08:00
|
|
|
data->recv_acl = hci_recv_frame;
|
|
|
|
|
2021-08-05 08:32:11 +08:00
|
|
|
hdev = hci_alloc_dev_priv(priv_size);
|
2012-07-27 15:08:39 +08:00
|
|
|
if (!hdev)
|
2007-10-20 20:12:34 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2010-02-08 22:27:07 +08:00
|
|
|
hdev->bus = HCI_USB;
|
2012-02-10 04:58:32 +08:00
|
|
|
hci_set_drvdata(hdev, data);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
data->hdev = hdev;
|
|
|
|
|
|
|
|
SET_HCIDEV_DEV(hdev, &intf->dev);
|
|
|
|
|
2019-01-25 07:28:14 +08:00
|
|
|
reset_gpio = gpiod_get_optional(&data->udev->dev, "reset",
|
|
|
|
GPIOD_OUT_LOW);
|
|
|
|
if (IS_ERR(reset_gpio)) {
|
|
|
|
err = PTR_ERR(reset_gpio);
|
|
|
|
goto out_free_dev;
|
|
|
|
} else if (reset_gpio) {
|
|
|
|
data->reset_gpio = reset_gpio;
|
|
|
|
}
|
|
|
|
|
2013-04-10 23:11:35 +08:00
|
|
|
hdev->open = btusb_open;
|
|
|
|
hdev->close = btusb_close;
|
|
|
|
hdev->flush = btusb_flush;
|
|
|
|
hdev->send = btusb_send_frame;
|
|
|
|
hdev->notify = btusb_notify;
|
2021-10-02 04:22:31 +08:00
|
|
|
hdev->wakeup = btusb_wakeup;
|
2013-04-10 23:11:35 +08:00
|
|
|
|
2017-02-02 06:24:09 +08:00
|
|
|
#ifdef CONFIG_PM
|
|
|
|
err = btusb_config_oob_wake(hdev);
|
|
|
|
if (err)
|
|
|
|
goto out_free_dev;
|
2017-02-02 06:24:10 +08:00
|
|
|
|
|
|
|
/* Marvell devices may need a specific chip configuration */
|
|
|
|
if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
|
|
|
|
err = marvell_config_oob_wake(hdev);
|
|
|
|
if (err)
|
|
|
|
goto out_free_dev;
|
|
|
|
}
|
2017-02-02 06:24:09 +08:00
|
|
|
#endif
|
2016-09-01 23:22:37 +08:00
|
|
|
if (id->driver_info & BTUSB_CW6622)
|
|
|
|
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
|
|
|
|
|
2015-10-17 20:39:27 +08:00
|
|
|
if (id->driver_info & BTUSB_BCM2045)
|
|
|
|
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
|
|
|
|
|
2013-04-10 23:11:35 +08:00
|
|
|
if (id->driver_info & BTUSB_BCM92035)
|
|
|
|
hdev->setup = btusb_setup_bcm92035;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2019-09-27 14:48:58 +08:00
|
|
|
if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) &&
|
|
|
|
(id->driver_info & BTUSB_BCM_PATCHRAM)) {
|
2015-10-20 08:30:48 +08:00
|
|
|
hdev->manufacturer = 15;
|
2015-04-06 13:52:14 +08:00
|
|
|
hdev->setup = btbcm_setup_patchram;
|
2015-10-09 02:23:08 +08:00
|
|
|
hdev->set_diag = btusb_bcm_set_diag;
|
2015-04-06 13:52:11 +08:00
|
|
|
hdev->set_bdaddr = btbcm_set_bdaddr;
|
2015-10-09 02:23:08 +08:00
|
|
|
|
|
|
|
/* Broadcom LM_DIAG Interface numbers are hardcoded */
|
2015-10-20 06:53:33 +08:00
|
|
|
data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
|
2014-07-02 06:53:48 +08:00
|
|
|
}
|
2014-05-09 06:50:01 +08:00
|
|
|
|
2019-09-27 14:48:58 +08:00
|
|
|
if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) &&
|
|
|
|
(id->driver_info & BTUSB_BCM_APPLE)) {
|
2015-10-20 08:30:48 +08:00
|
|
|
hdev->manufacturer = 15;
|
2015-04-06 13:52:14 +08:00
|
|
|
hdev->setup = btbcm_setup_apple;
|
2015-10-09 02:23:08 +08:00
|
|
|
hdev->set_diag = btusb_bcm_set_diag;
|
|
|
|
|
|
|
|
/* Broadcom LM_DIAG Interface numbers are hardcoded */
|
2015-10-20 06:53:33 +08:00
|
|
|
data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2);
|
2015-10-09 02:23:08 +08:00
|
|
|
}
|
2015-03-22 22:52:38 +08:00
|
|
|
|
2021-08-05 08:32:10 +08:00
|
|
|
/* Combined Intel Device setup to support multiple setup routine */
|
|
|
|
if (id->driver_info & BTUSB_INTEL_COMBINED) {
|
2023-03-31 00:58:26 +08:00
|
|
|
err = btintel_configure_setup(hdev, btusb_driver.name);
|
2021-08-05 08:32:10 +08:00
|
|
|
if (err)
|
|
|
|
goto out_free_dev;
|
|
|
|
|
|
|
|
/* Transport specific configuration */
|
2021-08-05 08:32:15 +08:00
|
|
|
hdev->send = btusb_send_frame_intel;
|
2019-01-25 07:28:14 +08:00
|
|
|
hdev->cmd_timeout = btusb_intel_cmd_timeout;
|
2021-08-05 08:32:10 +08:00
|
|
|
|
2022-01-21 03:44:18 +08:00
|
|
|
if (id->driver_info & BTUSB_INTEL_NO_WBS_SUPPORT)
|
|
|
|
btintel_set_flag(hdev, INTEL_ROM_LEGACY_NO_WBS_SUPPORT);
|
|
|
|
|
2021-08-05 08:32:12 +08:00
|
|
|
if (id->driver_info & BTUSB_INTEL_BROKEN_INITIAL_NCMD)
|
|
|
|
btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD);
|
2022-01-07 08:34:54 +08:00
|
|
|
|
|
|
|
if (id->driver_info & BTUSB_INTEL_BROKEN_SHUTDOWN_LED)
|
|
|
|
btintel_set_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED);
|
2014-07-02 17:25:25 +08:00
|
|
|
}
|
2013-04-20 00:57:43 +08:00
|
|
|
|
2014-07-19 05:47:06 +08:00
|
|
|
if (id->driver_info & BTUSB_MARVELL)
|
|
|
|
hdev->set_bdaddr = btusb_set_bdaddr_marvell;
|
|
|
|
|
2019-09-27 14:48:58 +08:00
|
|
|
if (IS_ENABLED(CONFIG_BT_HCIBTUSB_MTK) &&
|
|
|
|
(id->driver_info & BTUSB_MEDIATEK)) {
|
2019-06-02 08:02:48 +08:00
|
|
|
hdev->setup = btusb_mtk_setup;
|
|
|
|
hdev->shutdown = btusb_mtk_shutdown;
|
|
|
|
hdev->manufacturer = 70;
|
2023-06-29 06:54:56 +08:00
|
|
|
hdev->cmd_timeout = btmtk_reset_sync;
|
2021-10-19 05:30:12 +08:00
|
|
|
hdev->set_bdaddr = btmtk_set_bdaddr;
|
2024-07-04 14:01:16 +08:00
|
|
|
hdev->send = btusb_send_frame_mtk;
|
2022-07-13 23:29:13 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks);
|
2019-06-02 08:02:48 +08:00
|
|
|
set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
|
2024-07-04 14:01:15 +08:00
|
|
|
data->recv_acl = btmtk_usb_recv_acl;
|
2024-07-04 14:01:16 +08:00
|
|
|
data->suspend = btmtk_usb_suspend;
|
|
|
|
data->resume = btmtk_usb_resume;
|
2019-06-02 08:02:48 +08:00
|
|
|
}
|
|
|
|
|
2015-01-03 15:35:20 +08:00
|
|
|
if (id->driver_info & BTUSB_SWAVE) {
|
|
|
|
set_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks);
|
2014-12-26 11:42:33 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks);
|
2015-01-03 15:35:20 +08:00
|
|
|
}
|
2014-12-26 11:42:33 +08:00
|
|
|
|
2015-10-21 07:31:45 +08:00
|
|
|
if (id->driver_info & BTUSB_INTEL_BOOT) {
|
|
|
|
hdev->manufacturer = 2;
|
2014-07-06 19:29:58 +08:00
|
|
|
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
2015-10-21 07:31:45 +08:00
|
|
|
}
|
2014-07-06 19:29:58 +08:00
|
|
|
|
2015-01-30 02:38:34 +08:00
|
|
|
if (id->driver_info & BTUSB_ATH3012) {
|
Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
In commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros
1525/QCA6174") we tried to address the non-working Atheros BT devices
by changing the quirk from BTUSB_ATH3012 to BTUSB_QCA_ROME. This made
such devices working while it turned out to break other existing chips
with the very same USB ID, hence it was reverted afterwards.
This is another attempt to tackle the issue. The essential point to
use BTUSB_QCA_ROME is to apply the btusb_setup_qca() and do RAM-
patching. And the previous attempt failed because btusb_setup_qca()
returns -ENODEV if the ROM version doesn't match with the expected
ones. For some devices that have already the "correct" ROM versions,
we may just skip the setup procedure and continue the rest.
So, the first fix we'll need is to add a check of the ROM version in
the function to skip the setup if the ROM version looks already sane,
so that it can be applied for all ath devices.
However, the world is a bit more complex than that simple solution.
Since BTUSB_ATH3012 quirk checks the bcdDevice and bails out when it's
0x0001 at the beginning of probing, so the device probe always aborts
here.
In this patch, we add another check of ROM version again, and if the
device needs patching, the probe continues. For that, a slight
refactoring of btusb_qca_send_vendor_req() was required so that the
probe function can pass usb_device pointer directly before allocating
hci_dev stuff.
Fixes: commit f44cb4b19ed4 ("Bluetooth: btusb: Fix quirk for Atheros 1525/QCA6174")
Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1082504
Tested-by: Ivan Levshin <ivan.levshin@microfocus.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-05-22 04:34:52 +08:00
|
|
|
data->setup_on_usb = btusb_setup_qca;
|
2014-12-13 02:58:05 +08:00
|
|
|
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
|
2015-03-18 00:04:15 +08:00
|
|
|
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
2015-01-30 02:38:34 +08:00
|
|
|
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
|
|
|
|
}
|
2014-12-13 02:58:05 +08:00
|
|
|
|
2015-02-16 07:07:33 +08:00
|
|
|
if (id->driver_info & BTUSB_QCA_ROME) {
|
|
|
|
data->setup_on_usb = btusb_setup_qca;
|
2023-08-07 14:46:26 +08:00
|
|
|
hdev->shutdown = btusb_shutdown_qca;
|
2015-02-16 07:07:33 +08:00
|
|
|
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
|
2020-06-25 02:11:44 +08:00
|
|
|
hdev->cmd_timeout = btusb_qca_cmd_timeout;
|
2018-03-28 23:28:47 +08:00
|
|
|
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
2018-04-27 17:26:43 +08:00
|
|
|
btusb_check_needs_reset_resume(intf);
|
2015-02-16 07:07:33 +08:00
|
|
|
}
|
|
|
|
|
2020-09-29 12:23:51 +08:00
|
|
|
if (id->driver_info & BTUSB_QCA_WCN6855) {
|
2023-04-19 11:38:05 +08:00
|
|
|
data->qca_dump.id_vendor = id->idVendor;
|
|
|
|
data->qca_dump.id_product = id->idProduct;
|
|
|
|
data->recv_event = btusb_recv_evt_qca;
|
|
|
|
data->recv_acl = btusb_recv_acl_qca;
|
|
|
|
hci_devcd_register(hdev, btusb_coredump_qca, btusb_dump_hdr_qca, NULL);
|
2020-09-29 12:23:51 +08:00
|
|
|
data->setup_on_usb = btusb_setup_qca;
|
2020-12-18 18:12:11 +08:00
|
|
|
hdev->shutdown = btusb_shutdown_qca;
|
2020-09-29 12:23:51 +08:00
|
|
|
hdev->set_bdaddr = btusb_set_bdaddr_wcn6855;
|
|
|
|
hdev->cmd_timeout = btusb_qca_cmd_timeout;
|
|
|
|
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
2021-07-30 01:10:59 +08:00
|
|
|
hci_set_msft_opcode(hdev, 0xFD70);
|
2020-09-29 12:23:51 +08:00
|
|
|
}
|
|
|
|
|
2020-06-30 21:09:40 +08:00
|
|
|
if (id->driver_info & BTUSB_AMP) {
|
|
|
|
/* AMP controllers do not support SCO packets */
|
|
|
|
data->isoc = NULL;
|
|
|
|
} else {
|
|
|
|
/* Interface orders are hardcoded in the specification */
|
|
|
|
data->isoc = usb_ifnum_to_if(data->udev, ifnum_base + 1);
|
|
|
|
data->isoc_ifnum = ifnum_base + 1;
|
|
|
|
}
|
|
|
|
|
2019-09-19 03:59:02 +08:00
|
|
|
if (IS_ENABLED(CONFIG_BT_HCIBTUSB_RTL) &&
|
|
|
|
(id->driver_info & BTUSB_REALTEK)) {
|
2023-04-27 11:27:55 +08:00
|
|
|
btrtl_set_driver_name(hdev, btusb_driver.name);
|
2022-10-05 16:43:31 +08:00
|
|
|
hdev->setup = btusb_setup_realtek;
|
2019-06-25 16:30:51 +08:00
|
|
|
hdev->shutdown = btrtl_shutdown_realtek;
|
2019-09-05 10:36:31 +08:00
|
|
|
hdev->cmd_timeout = btusb_rtl_cmd_timeout;
|
2023-04-27 11:27:55 +08:00
|
|
|
hdev->hw_error = btusb_rtl_hw_error;
|
2015-05-21 22:23:50 +08:00
|
|
|
|
2021-08-17 11:03:12 +08:00
|
|
|
/* Realtek devices need to set remote wakeup on auto-suspend */
|
|
|
|
set_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags);
|
2021-07-27 02:02:06 +08:00
|
|
|
set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags);
|
2015-05-21 22:23:50 +08:00
|
|
|
}
|
2015-04-17 04:09:55 +08:00
|
|
|
|
2022-12-17 04:12:47 +08:00
|
|
|
if (id->driver_info & BTUSB_ACTIONS_SEMI) {
|
|
|
|
/* Support is advertised, but not implemented */
|
|
|
|
set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks);
|
2023-03-10 23:14:10 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks);
|
2023-03-23 21:45:39 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks);
|
2023-03-10 23:14:10 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
|
2024-02-27 09:43:26 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks);
|
2022-12-17 04:12:47 +08:00
|
|
|
}
|
|
|
|
|
2008-11-30 19:17:26 +08:00
|
|
|
if (!reset)
|
2012-05-23 18:35:46 +08:00
|
|
|
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
2008-08-08 04:26:56 +08:00
|
|
|
|
|
|
|
if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
|
|
|
|
if (!disable_scofix)
|
|
|
|
set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
|
|
|
|
}
|
|
|
|
|
2008-08-18 19:23:52 +08:00
|
|
|
if (id->driver_info & BTUSB_BROKEN_ISOC)
|
|
|
|
data->isoc = NULL;
|
|
|
|
|
2020-02-28 02:29:39 +08:00
|
|
|
if (id->driver_info & BTUSB_WIDEBAND_SPEECH)
|
2020-03-06 00:14:59 +08:00
|
|
|
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
2020-02-28 02:29:39 +08:00
|
|
|
|
2024-08-12 23:01:15 +08:00
|
|
|
if (id->driver_info & BTUSB_INVALID_LE_STATES)
|
2024-08-12 22:43:48 +08:00
|
|
|
set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks);
|
2020-04-23 22:43:31 +08:00
|
|
|
|
2008-11-30 19:17:26 +08:00
|
|
|
if (id->driver_info & BTUSB_DIGIANSWER) {
|
|
|
|
data->cmdreq_type = USB_TYPE_VENDOR;
|
2012-05-23 18:35:46 +08:00
|
|
|
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
2008-11-30 19:17:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (id->driver_info & BTUSB_CSR) {
|
|
|
|
struct usb_device *udev = data->udev;
|
2014-01-03 19:02:36 +08:00
|
|
|
u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
|
2008-11-30 19:17:26 +08:00
|
|
|
|
|
|
|
/* Old firmware would otherwise execute USB reset */
|
2014-01-03 19:02:36 +08:00
|
|
|
if (bcdDevice < 0x117)
|
2012-05-23 18:35:46 +08:00
|
|
|
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
2014-01-03 19:02:36 +08:00
|
|
|
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
/* This must be set first in case we disable it for fakes */
|
|
|
|
set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
|
|
|
|
|
2014-01-03 19:02:36 +08:00
|
|
|
/* Fake CSR devices with broken commands */
|
Bluetooth: btusb: Fix and detect most of the Chinese Bluetooth controllers
For some reason they tend to squat on the very first CSR/
Cambridge Silicon Radio VID/PID instead of paying fees.
This is an extremely common problem; the issue goes as back as 2013
and these devices are only getting more popular, even rebranded by
reputable vendors and sold by retailers everywhere.
So, at this point in time there are hundreds of modern dongles reusing
the ID of what originally was an early Bluetooth 1.1 controller.
Linux is the only place where they don't work due to spotty checks
in our detection code. It only covered a minimum subset.
So what's the big idea? Take advantage of the fact that all CSR
chips report the same internal version as both the LMP sub-version and
HCI revision number. It always matches, couple that with the manufacturer
code, that rarely lies, and we now have a good idea of who is who.
Additionally, by compiling a list of user-reported HCI/lsusb dumps, and
searching around for legit CSR dongles in similar product ranges we can
find what CSR BlueCore firmware supported which Bluetooth versions.
That way we can narrow down ranges of fakes for each of them.
e.g. Real CSR dongles with LMP subversion 0x73 are old enough that
support BT 1.1 only; so it's a dead giveaway when some
third-party BT 4.0 dongle reuses it.
So, to sum things up; there are multiple classes of fake controllers
reusing the same 0A12:0001 VID/PID. This has been broken for a while.
Known 'fake' bcdDevices: 0x0100, 0x0134, 0x1915, 0x2520, 0x7558, 0x8891
IC markings on 0x7558: FR3191AHAL 749H15143 (???)
https://bugzilla.kernel.org/show_bug.cgi?id=60824
Fixes: 81cac64ba258ae (Deal with USB devices that are faking CSR vendor)
Reported-by: Michał Wiśniewski <brylozketrzyn@gmail.com>
Tested-by: Mike Johnson <yuyuyak@gmail.com>
Tested-by: Ricardo Rodrigues <ekatonb@gmail.com>
Tested-by: M.Hanny Sabbagh <mhsabbagh@outlook.com>
Tested-by: Oussama BEN BRAHIM <b.brahim.oussama@gmail.com>
Tested-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Ismael Ferreras Morezuelas <swyterzone@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-07-27 05:12:28 +08:00
|
|
|
if (le16_to_cpu(udev->descriptor.idVendor) == 0x0a12 &&
|
|
|
|
le16_to_cpu(udev->descriptor.idProduct) == 0x0001)
|
2014-01-03 19:02:36 +08:00
|
|
|
hdev->setup = btusb_setup_csr;
|
2008-11-30 19:17:26 +08:00
|
|
|
}
|
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
if (id->driver_info & BTUSB_SNIFFER) {
|
2008-08-18 19:23:52 +08:00
|
|
|
struct usb_device *udev = data->udev;
|
2008-08-08 04:26:56 +08:00
|
|
|
|
2008-11-30 19:17:26 +08:00
|
|
|
/* New sniffer firmware has crippled HCI interface */
|
2008-08-08 04:26:56 +08:00
|
|
|
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
|
|
|
|
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
|
|
|
}
|
|
|
|
|
2014-07-06 20:53:54 +08:00
|
|
|
if (id->driver_info & BTUSB_INTEL_BOOT) {
|
|
|
|
/* A bug in the bootloader causes that interrupt interface is
|
|
|
|
* only enabled after receiving SetInterface(0, AltSetting=0).
|
|
|
|
*/
|
|
|
|
err = usb_set_interface(data->udev, 0, 0);
|
|
|
|
if (err < 0) {
|
|
|
|
BT_ERR("failed to set interface 0, alt 0 %d", err);
|
2017-02-02 06:24:08 +08:00
|
|
|
goto out_free_dev;
|
2014-07-06 20:53:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-18 19:23:52 +08:00
|
|
|
if (data->isoc) {
|
|
|
|
err = usb_driver_claim_interface(&btusb_driver,
|
2014-09-16 10:44:50 +08:00
|
|
|
data->isoc, data);
|
2017-02-02 06:24:08 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto out_free_dev;
|
2008-08-18 19:23:52 +08:00
|
|
|
}
|
|
|
|
|
2019-09-27 14:48:58 +08:00
|
|
|
if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && data->diag) {
|
2015-10-09 02:23:08 +08:00
|
|
|
if (!usb_driver_claim_interface(&btusb_driver,
|
|
|
|
data->diag, data))
|
|
|
|
__set_diag_interface(hdev);
|
|
|
|
else
|
|
|
|
data->diag = NULL;
|
|
|
|
}
|
|
|
|
|
2021-04-09 21:58:50 +08:00
|
|
|
if (enable_autosuspend)
|
|
|
|
usb_enable_autosuspend(data->udev);
|
2017-11-13 21:44:16 +08:00
|
|
|
|
2022-10-26 05:12:57 +08:00
|
|
|
data->poll_sync = enable_poll_sync;
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
err = hci_register_dev(hdev);
|
2017-02-02 06:24:08 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto out_free_dev;
|
2007-10-20 20:12:34 +08:00
|
|
|
|
|
|
|
usb_set_intfdata(intf, data);
|
|
|
|
|
2021-12-04 06:38:13 +08:00
|
|
|
debugfs_create_file("force_poll_sync", 0644, hdev->debugfs, data,
|
|
|
|
&force_poll_sync_fops);
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
return 0;
|
2017-02-02 06:24:08 +08:00
|
|
|
|
|
|
|
out_free_dev:
|
2019-01-25 07:28:14 +08:00
|
|
|
if (data->reset_gpio)
|
|
|
|
gpiod_put(data->reset_gpio);
|
2017-02-02 06:24:08 +08:00
|
|
|
hci_free_dev(hdev);
|
|
|
|
return err;
|
2007-10-20 20:12:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void btusb_disconnect(struct usb_interface *intf)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = usb_get_intfdata(intf);
|
|
|
|
struct hci_dev *hdev;
|
|
|
|
|
|
|
|
BT_DBG("intf %p", intf);
|
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return;
|
|
|
|
|
|
|
|
hdev = data->hdev;
|
2008-09-23 06:16:36 +08:00
|
|
|
usb_set_intfdata(data->intf, NULL);
|
|
|
|
|
|
|
|
if (data->isoc)
|
|
|
|
usb_set_intfdata(data->isoc, NULL);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2015-10-09 02:23:08 +08:00
|
|
|
if (data->diag)
|
|
|
|
usb_set_intfdata(data->diag, NULL);
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
hci_unregister_dev(hdev);
|
|
|
|
|
2015-10-09 02:23:08 +08:00
|
|
|
if (intf == data->intf) {
|
|
|
|
if (data->isoc)
|
|
|
|
usb_driver_release_interface(&btusb_driver, data->isoc);
|
|
|
|
if (data->diag)
|
|
|
|
usb_driver_release_interface(&btusb_driver, data->diag);
|
|
|
|
} else if (intf == data->isoc) {
|
|
|
|
if (data->diag)
|
|
|
|
usb_driver_release_interface(&btusb_driver, data->diag);
|
2008-09-23 06:16:36 +08:00
|
|
|
usb_driver_release_interface(&btusb_driver, data->intf);
|
2015-10-09 02:23:08 +08:00
|
|
|
} else if (intf == data->diag) {
|
|
|
|
usb_driver_release_interface(&btusb_driver, data->intf);
|
|
|
|
if (data->isoc)
|
|
|
|
usb_driver_release_interface(&btusb_driver, data->isoc);
|
|
|
|
}
|
2008-09-23 06:16:36 +08:00
|
|
|
|
2017-02-02 06:24:09 +08:00
|
|
|
if (data->oob_wake_irq)
|
|
|
|
device_init_wakeup(&data->udev->dev, false);
|
|
|
|
|
2019-01-25 07:28:14 +08:00
|
|
|
if (data->reset_gpio)
|
|
|
|
gpiod_put(data->reset_gpio);
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
hci_free_dev(hdev);
|
|
|
|
}
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
#ifdef CONFIG_PM
|
2008-11-30 19:17:14 +08:00
|
|
|
static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = usb_get_intfdata(intf);
|
|
|
|
|
|
|
|
BT_DBG("intf %p", intf);
|
|
|
|
|
2024-10-01 23:21:37 +08:00
|
|
|
/* Don't auto-suspend if there are connections; external suspend calls
|
|
|
|
* shall never fail.
|
|
|
|
*/
|
|
|
|
if (PMSG_IS_AUTO(message) && hci_conn_count(data->hdev))
|
2023-05-03 06:11:59 +08:00
|
|
|
return -EBUSY;
|
|
|
|
|
2008-11-30 19:17:14 +08:00
|
|
|
if (data->suspend_count++)
|
|
|
|
return 0;
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
spin_lock_irq(&data->txlock);
|
2011-08-20 05:49:48 +08:00
|
|
|
if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
|
2009-08-25 05:44:59 +08:00
|
|
|
set_bit(BTUSB_SUSPENDING, &data->flags);
|
|
|
|
spin_unlock_irq(&data->txlock);
|
|
|
|
} else {
|
|
|
|
spin_unlock_irq(&data->txlock);
|
|
|
|
data->suspend_count--;
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
|
2008-11-30 19:17:14 +08:00
|
|
|
cancel_work_sync(&data->work);
|
|
|
|
|
2024-07-04 14:01:12 +08:00
|
|
|
if (data->suspend)
|
|
|
|
data->suspend(data->hdev);
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
btusb_stop_traffic(data);
|
2008-11-30 19:17:14 +08:00
|
|
|
usb_kill_anchored_urbs(&data->tx_anchor);
|
|
|
|
|
2017-02-02 06:24:09 +08:00
|
|
|
if (data->oob_wake_irq && device_may_wakeup(&data->udev->dev)) {
|
|
|
|
set_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags);
|
|
|
|
enable_irq_wake(data->oob_wake_irq);
|
|
|
|
enable_irq(data->oob_wake_irq);
|
|
|
|
}
|
|
|
|
|
2019-08-14 20:02:52 +08:00
|
|
|
/* For global suspend, Realtek devices lose the loaded fw
|
|
|
|
* in them. But for autosuspend, firmware should remain.
|
|
|
|
* Actually, it depends on whether the usb host sends
|
|
|
|
* set feature (enable wakeup) or not.
|
|
|
|
*/
|
2021-08-17 11:03:12 +08:00
|
|
|
if (test_bit(BTUSB_WAKEUP_AUTOSUSPEND, &data->flags)) {
|
2019-08-14 20:02:52 +08:00
|
|
|
if (PMSG_IS_AUTO(message) &&
|
|
|
|
device_can_wakeup(&data->udev->dev))
|
|
|
|
data->udev->do_remote_wakeup = 1;
|
2021-08-17 11:03:12 +08:00
|
|
|
else if (!PMSG_IS_AUTO(message) &&
|
|
|
|
!device_may_wakeup(&data->udev->dev)) {
|
|
|
|
data->udev->do_remote_wakeup = 0;
|
2019-08-14 20:02:52 +08:00
|
|
|
data->udev->reset_resume = 1;
|
2021-08-17 11:03:12 +08:00
|
|
|
}
|
2019-08-14 20:02:52 +08:00
|
|
|
}
|
|
|
|
|
2008-11-30 19:17:14 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
static void play_deferred(struct btusb_data *data)
|
|
|
|
{
|
|
|
|
struct urb *urb;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
while ((urb = usb_get_from_anchor(&data->deferred))) {
|
2017-07-20 18:53:50 +08:00
|
|
|
usb_anchor_urb(urb, &data->tx_anchor);
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
2017-07-20 18:53:50 +08:00
|
|
|
if (err < 0) {
|
|
|
|
if (err != -EPERM && err != -ENODEV)
|
|
|
|
BT_ERR("%s urb %p submission failed (%d)",
|
|
|
|
data->hdev->name, urb, -err);
|
|
|
|
kfree(urb->setup_packet);
|
|
|
|
usb_unanchor_urb(urb);
|
|
|
|
usb_free_urb(urb);
|
2009-08-25 05:44:59 +08:00
|
|
|
break;
|
2017-07-20 18:53:50 +08:00
|
|
|
}
|
2009-08-25 05:44:59 +08:00
|
|
|
|
|
|
|
data->tx_in_flight++;
|
2017-07-20 18:53:50 +08:00
|
|
|
usb_free_urb(urb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup the rest deferred urbs. */
|
|
|
|
while ((urb = usb_get_from_anchor(&data->deferred))) {
|
|
|
|
kfree(urb->setup_packet);
|
|
|
|
usb_free_urb(urb);
|
2009-08-25 05:44:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-30 19:17:14 +08:00
|
|
|
static int btusb_resume(struct usb_interface *intf)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = usb_get_intfdata(intf);
|
|
|
|
struct hci_dev *hdev = data->hdev;
|
2009-08-25 05:44:59 +08:00
|
|
|
int err = 0;
|
2008-11-30 19:17:14 +08:00
|
|
|
|
|
|
|
BT_DBG("intf %p", intf);
|
|
|
|
|
|
|
|
if (--data->suspend_count)
|
|
|
|
return 0;
|
|
|
|
|
2017-02-02 06:24:09 +08:00
|
|
|
/* Disable only if not already disabled (keep it balanced) */
|
|
|
|
if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {
|
|
|
|
disable_irq(data->oob_wake_irq);
|
|
|
|
disable_irq_wake(data->oob_wake_irq);
|
|
|
|
}
|
|
|
|
|
2008-11-30 19:17:14 +08:00
|
|
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
2009-08-25 05:44:59 +08:00
|
|
|
goto done;
|
2008-11-30 19:17:14 +08:00
|
|
|
|
|
|
|
if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
|
|
|
|
err = btusb_submit_intr_urb(hdev, GFP_NOIO);
|
|
|
|
if (err < 0) {
|
|
|
|
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
2009-08-25 05:44:59 +08:00
|
|
|
goto failed;
|
2008-11-30 19:17:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (test_bit(BTUSB_BULK_RUNNING, &data->flags)) {
|
2009-02-05 00:41:38 +08:00
|
|
|
err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
|
|
|
|
if (err < 0) {
|
2008-11-30 19:17:14 +08:00
|
|
|
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
2009-08-25 05:44:59 +08:00
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
|
|
|
|
btusb_submit_bulk_urb(hdev, GFP_NOIO);
|
2008-11-30 19:17:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
|
|
|
|
if (btusb_submit_isoc_urb(hdev, GFP_NOIO) < 0)
|
|
|
|
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
|
|
|
else
|
|
|
|
btusb_submit_isoc_urb(hdev, GFP_NOIO);
|
|
|
|
}
|
|
|
|
|
2024-07-04 14:01:12 +08:00
|
|
|
if (data->resume)
|
|
|
|
data->resume(hdev);
|
|
|
|
|
2009-08-25 05:44:59 +08:00
|
|
|
spin_lock_irq(&data->txlock);
|
|
|
|
play_deferred(data);
|
|
|
|
clear_bit(BTUSB_SUSPENDING, &data->flags);
|
|
|
|
spin_unlock_irq(&data->txlock);
|
|
|
|
schedule_work(&data->work);
|
|
|
|
|
2008-11-30 19:17:14 +08:00
|
|
|
return 0;
|
2009-08-25 05:44:59 +08:00
|
|
|
|
|
|
|
failed:
|
|
|
|
usb_scuttle_anchored_urbs(&data->deferred);
|
|
|
|
done:
|
|
|
|
spin_lock_irq(&data->txlock);
|
|
|
|
clear_bit(BTUSB_SUSPENDING, &data->flags);
|
|
|
|
spin_unlock_irq(&data->txlock);
|
|
|
|
|
|
|
|
return err;
|
2008-11-30 19:17:14 +08:00
|
|
|
}
|
2009-08-25 05:44:59 +08:00
|
|
|
#endif
|
2008-11-30 19:17:14 +08:00
|
|
|
|
2023-03-31 00:58:25 +08:00
|
|
|
#ifdef CONFIG_DEV_COREDUMP
|
|
|
|
static void btusb_coredump(struct device *dev)
|
|
|
|
{
|
|
|
|
struct btusb_data *data = dev_get_drvdata(dev);
|
|
|
|
struct hci_dev *hdev = data->hdev;
|
|
|
|
|
|
|
|
if (hdev->dump.coredump)
|
|
|
|
hdev->dump.coredump(hdev);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
static struct usb_driver btusb_driver = {
|
|
|
|
.name = "btusb",
|
|
|
|
.probe = btusb_probe,
|
|
|
|
.disconnect = btusb_disconnect,
|
2009-08-25 05:44:59 +08:00
|
|
|
#ifdef CONFIG_PM
|
2008-11-30 19:17:14 +08:00
|
|
|
.suspend = btusb_suspend,
|
|
|
|
.resume = btusb_resume,
|
2009-08-25 05:44:59 +08:00
|
|
|
#endif
|
2007-10-20 20:12:34 +08:00
|
|
|
.id_table = btusb_table,
|
2009-08-25 05:44:59 +08:00
|
|
|
.supports_autosuspend = 1,
|
2012-04-24 01:08:51 +08:00
|
|
|
.disable_hub_initiated_lpm = 1,
|
2023-03-31 00:58:25 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_DEV_COREDUMP
|
2024-01-04 11:28:22 +08:00
|
|
|
.driver = {
|
|
|
|
.coredump = btusb_coredump,
|
2023-03-31 00:58:25 +08:00
|
|
|
},
|
|
|
|
#endif
|
2007-10-20 20:12:34 +08:00
|
|
|
};
|
|
|
|
|
2011-11-19 01:47:34 +08:00
|
|
|
module_usb_driver(btusb_driver);
|
2007-10-20 20:12:34 +08:00
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
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");
|
|
|
|
|
2017-11-13 21:44:16 +08:00
|
|
|
module_param(enable_autosuspend, bool, 0644);
|
|
|
|
MODULE_PARM_DESC(enable_autosuspend, "Enable USB autosuspend by default");
|
|
|
|
|
2008-08-08 04:26:56 +08:00
|
|
|
module_param(reset, bool, 0644);
|
|
|
|
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
|
|
|
|
|
2007-10-20 20:12:34 +08:00
|
|
|
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
|
|
|
MODULE_DESCRIPTION("Generic Bluetooth USB driver ver " VERSION);
|
|
|
|
MODULE_VERSION(VERSION);
|
|
|
|
MODULE_LICENSE("GPL");
|