diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2015-03-22 14:52:38 (GMT) |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2015-03-23 00:15:07 (GMT) |
commit | 17b2772b8fe3442b46c99fb91150a480acb7ebc4 (patch) | |
tree | 143108735b2ca4ad88346ca2b26dd780b6907324 /drivers/bluetooth/btusb.c | |
parent | baf880a96859cca79208122e555e7efeabd16e4d (diff) | |
download | linux-17b2772b8fe3442b46c99fb91150a480acb7ebc4.tar.xz |
Bluetooth: Read Broadcom chip info for Apple Bluetooth devices
For the Apple Bluetooth devices that are Broadcom based, it makes sense
to read the chip information. It is a single HCI command and might help
gathering more information about these devices.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r-- | drivers/bluetooth/btusb.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 1521dad..9bf4d6a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/usb.h> #include <linux/firmware.h> +#include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -53,6 +54,7 @@ static struct usb_driver btusb_driver; #define BTUSB_INTEL_NEW 0x2000 #define BTUSB_AMP 0x4000 #define BTUSB_QCA_ROME 0x8000 +#define BTUSB_BCM_APPLE 0x10000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -62,7 +64,8 @@ static const struct usb_device_id btusb_table[] = { { USB_DEVICE_INFO(0xe0, 0x01, 0x04), .driver_info = BTUSB_AMP }, /* Apple-specific (Broadcom) devices */ - { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01), + .driver_info = BTUSB_BCM_APPLE }, /* MediaTek MT76x0E */ { USB_DEVICE(0x0e8d, 0x763f) }, @@ -2634,6 +2637,34 @@ static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr) return 0; } +static int btusb_setup_bcm_apple(struct hci_dev *hdev) +{ + struct sk_buff *skb; + int err; + + /* Read Verbose Config Version Info */ + skb = __hci_cmd_sync(hdev, 0xfc79, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + BT_ERR("%s: BCM: Read Verbose Version failed (%d)", + hdev->name, err); + return err; + } + + if (skb->len != 7) { + BT_ERR("%s: BCM: Read Verbose Version event length mismatch", + hdev->name); + kfree_skb(skb); + return -EIO; + } + + BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1], + get_unaligned_le16(skb->data + 5)); + kfree_skb(skb); + + return 0; +} + static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev, const bdaddr_t *bdaddr) { @@ -3033,6 +3064,11 @@ static int btusb_probe(struct usb_interface *intf, set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); } + if (id->driver_info & BTUSB_BCM_APPLE) { + hdev->setup = btusb_setup_bcm_apple; + set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); + } + if (id->driver_info & BTUSB_INTEL) { hdev->setup = btusb_setup_intel; hdev->shutdown = btusb_shutdown_intel; |