aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-01-03 06:02:36 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2014-01-04 13:11:07 -0500
commit81cac64ba258ae823f52cfaec0cad26ecb31adc3 (patch)
treec12d8bd99ca58115add9c359c4811006ddbe9e83 /drivers/bluetooth
parentf9f462faa02777f497eb25255683a94e0c054de6 (diff)
Bluetooth: Deal with USB devices that are faking CSR vendor
There exists a set of Bluetooth USB devices that show up on the USB bus as 0a12:0001 and identify themselves as devices from CSR. However they are not. When sending Read Local Version command they now have a split personality and say they are from Broadcom. < HCI Command: Read Local Version Information (0x04|0x0001) plen 0 > HCI Event: Command Complete (0x0e) plen 12 Read Local Version Information (0x04|0x0001) ncmd 1 status 0x00 HCI Version: 2.0 (0x3) HCI Revision: 0x3000 LMP Version: 2.0 (0x3) LMP Subversion: 0x420b Manufacturer: Broadcom Corporation (15) The assumption is that they are neither CSR nor Broadcom based devices and that they are designed and manufactured by someone else. For the most parts they follow the Bluetooth HCI specification and can be used as standard Bluetooth devices. However they have the minor problem that the Delete Stored Link Key command is not working as it should. During the Bluetooth controller setup, this command is needed if stored link keys are supported. For these devices it has to be assumed that this is broken and so just set a quirk to clearly indicate the behavior. After that the setup can just proceed. Now the trick part is to detect these faulty devices since we do not want to punish all CSR and all Broadcom devices. The original devices do actually work according to the specification. What is known so far is that these broken devices set the USB bcdDevice revision information to 1.0 or less. T: Bus=02 Lev=01 Prnt=01 Port=08 Cnt=03 Dev#= 9 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0a12 ProdID=0001 Rev= 1.00 S: Manufacturer=Bluetooth v2.0 S: Product=Bluetooth V2.0 Dongle T: Bus=05 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0a12 ProdID=0001 Rev= 0.07 In case of CSR devices, the bcdDevice revision contains the firmware build ID and that is normally a higher value. If the bcdDevice revision is 1.0 or less, then an extra setup stage is checking if Read Local Version returns CSR manufacturer information. If not then it will be assumed that this is a broken device and the Delete Stored Link Key command will be marked as broken. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/btusb.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index bfbcc5a772a6..e7b36beca42c 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -964,6 +964,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev)
964 return 0; 964 return 0;
965} 965}
966 966
967static int btusb_setup_csr(struct hci_dev *hdev)
968{
969 struct hci_rp_read_local_version *rp;
970 struct sk_buff *skb;
971 int ret;
972
973 BT_DBG("%s", hdev->name);
974
975 skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
976 HCI_INIT_TIMEOUT);
977 if (IS_ERR(skb)) {
978 BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb));
979 return -PTR_ERR(skb);
980 }
981
982 rp = (struct hci_rp_read_local_version *) skb->data;
983
984 if (!rp->status) {
985 if (le16_to_cpu(rp->manufacturer) != 10) {
986 /* Clear the reset quirk since this is not an actual
987 * early Bluetooth 1.1 device from CSR.
988 */
989 clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
990
991 /* These fake CSR controllers have all a broken
992 * stored link key handling and so just disable it.
993 */
994 set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY,
995 &hdev->quirks);
996 }
997 }
998
999 ret = -bt_to_errno(rp->status);
1000
1001 kfree_skb(skb);
1002
1003 return ret;
1004}
1005
967struct intel_version { 1006struct intel_version {
968 u8 status; 1007 u8 status;
969 u8 hw_platform; 1008 u8 hw_platform;
@@ -1464,10 +1503,15 @@ static int btusb_probe(struct usb_interface *intf,
1464 1503
1465 if (id->driver_info & BTUSB_CSR) { 1504 if (id->driver_info & BTUSB_CSR) {
1466 struct usb_device *udev = data->udev; 1505 struct usb_device *udev = data->udev;
1506 u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
1467 1507
1468 /* Old firmware would otherwise execute USB reset */ 1508 /* Old firmware would otherwise execute USB reset */
1469 if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117) 1509 if (bcdDevice < 0x117)
1470 set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); 1510 set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
1511
1512 /* Fake CSR devices with broken commands */
1513 if (bcdDevice <= 0x100)
1514 hdev->setup = btusb_setup_csr;
1471 } 1515 }
1472 1516
1473 if (id->driver_info & BTUSB_SNIFFER) { 1517 if (id->driver_info & BTUSB_SNIFFER) {