diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-01-08 13:44:29 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-01-08 13:44:29 -0500 |
commit | 300e5fd160114920079dd3ec132e5c01d00e4a1d (patch) | |
tree | 6032c96747aeae7544be71e4f3b7e2866a21bb1c /drivers/bluetooth/btusb.c | |
parent | 6e08d757b72f280c45cfec61e63216adb419e2dd (diff) | |
parent | e825eb1d7e06f616003c17e2e8e421c2e5e44142 (diff) | |
download | op-kernel-dev-300e5fd160114920079dd3ec132e5c01d00e4a1d.zip op-kernel-dev-300e5fd160114920079dd3ec132e5c01d00e4a1d.tar.gz |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r-- | drivers/bluetooth/btusb.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9f7e539..baeaaed 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -965,6 +965,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev) return 0; } +static int btusb_setup_csr(struct hci_dev *hdev) +{ + struct hci_rp_read_local_version *rp; + struct sk_buff *skb; + int ret; + + BT_DBG("%s", hdev->name); + + skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb)); + return -PTR_ERR(skb); + } + + rp = (struct hci_rp_read_local_version *) skb->data; + + if (!rp->status) { + if (le16_to_cpu(rp->manufacturer) != 10) { + /* 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); + + /* These fake CSR controllers have all a broken + * stored link key handling and so just disable it. + */ + set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, + &hdev->quirks); + } + } + + ret = -bt_to_errno(rp->status); + + kfree_skb(skb); + + return ret; +} + struct intel_version { u8 status; u8 hw_platform; @@ -1465,10 +1504,15 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_CSR) { struct usb_device *udev = data->udev; + u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice); /* Old firmware would otherwise execute USB reset */ - if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117) + if (bcdDevice < 0x117) set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); + + /* Fake CSR devices with broken commands */ + if (bcdDevice <= 0x100) + hdev->setup = btusb_setup_csr; } if (id->driver_info & BTUSB_SNIFFER) { |