diff options
author | Hans de Goede <hdegoede@redhat.com> | 2018-04-20 14:44:04 +0200 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2018-05-18 06:37:51 +0200 |
commit | fec0de23ea11429478fa2c24ace5cf4cc9cd2191 (patch) | |
tree | 5e852c048b6932c0e4221412ebd69d0b21647dc9 /drivers/bluetooth/btbcm.c | |
parent | f7328381bf64137e958d9fd0e070752d1366e91b (diff) | |
download | linux-fec0de23ea11429478fa2c24ace5cf4cc9cd2191.tar.gz linux-fec0de23ea11429478fa2c24ace5cf4cc9cd2191.tar.bz2 linux-fec0de23ea11429478fa2c24ace5cf4cc9cd2191.zip |
Bluetooth: btbcm: Make btbcm_initialize() also work for USB connected devices
Make btbcm_initialize() also work for USB connected device,
btbcm_initialize() and btbcm_setup_patchram() are quite similar,
this is a preparation patch for making btbcm_setup_patchram() use
btbcm_initialize() to remove the code duplication.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth/btbcm.c')
-rw-r--r-- | drivers/bluetooth/btbcm.c | 72 |
1 files changed, 43 insertions, 29 deletions
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index e3393bceb1a0..dd243afe32de 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -332,12 +332,27 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = { { } }; +static const struct bcm_subver_table bcm_usb_subver_table[] = { + { 0x210b, "BCM43142A0" }, /* 001.001.011 */ + { 0x2112, "BCM4314A0" }, /* 001.001.018 */ + { 0x2118, "BCM20702A0" }, /* 001.001.024 */ + { 0x2126, "BCM4335A0" }, /* 001.001.038 */ + { 0x220e, "BCM20702A1" }, /* 001.002.014 */ + { 0x230f, "BCM4354A2" }, /* 001.003.015 */ + { 0x4106, "BCM4335B0" }, /* 002.001.006 */ + { 0x410e, "BCM20702B0" }, /* 002.001.014 */ + { 0x6109, "BCM4335C0" }, /* 003.001.009 */ + { 0x610c, "BCM4354" }, /* 003.001.012 */ + { } +}; + int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len) { - u16 subver, rev; + u16 subver, rev, pid, vid; const char *hw_name = NULL; struct sk_buff *skb; struct hci_rp_read_local_version *ver; + const struct bcm_subver_table *bcm_subver_table; int i, err; /* Reset */ @@ -360,22 +375,35 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len) if (err) return err; - switch ((rev & 0xf000) >> 12) { - case 0: - case 1: - case 2: - case 3: - for (i = 0; bcm_uart_subver_table[i].name; i++) { - if (subver == bcm_uart_subver_table[i].subver) { - hw_name = bcm_uart_subver_table[i].name; - break; - } + /* Upper nibble of rev should be between 0 and 3? */ + if (((rev & 0xf000) >> 12) > 3) + return 0; + + bcm_subver_table = (hdev->bus == HCI_USB) ? bcm_usb_subver_table : + bcm_uart_subver_table; + + for (i = 0; bcm_subver_table[i].name; i++) { + if (subver == bcm_subver_table[i].subver) { + hw_name = bcm_subver_table[i].name; + break; } + } - snprintf(fw_name, len, "brcm/%s.hcd", hw_name ? : "BCM"); - break; - default: - return 0; + if (hdev->bus == HCI_USB) { + /* Read USB Product Info */ + skb = btbcm_read_usb_product(hdev); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + vid = get_unaligned_le16(skb->data + 1); + pid = get_unaligned_le16(skb->data + 3); + kfree_skb(skb); + + snprintf(fw_name, len, "brcm/%s-%4.4x-%4.4x.hcd", + hw_name ? : "BCM", vid, pid); + } else { + snprintf(fw_name, len, "brcm/%s.hcd", + hw_name ? : "BCM"); } bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u", @@ -420,20 +448,6 @@ int btbcm_finalize(struct hci_dev *hdev) } EXPORT_SYMBOL_GPL(btbcm_finalize); -static const struct bcm_subver_table bcm_usb_subver_table[] = { - { 0x210b, "BCM43142A0" }, /* 001.001.011 */ - { 0x2112, "BCM4314A0" }, /* 001.001.018 */ - { 0x2118, "BCM20702A0" }, /* 001.001.024 */ - { 0x2126, "BCM4335A0" }, /* 001.001.038 */ - { 0x220e, "BCM20702A1" }, /* 001.002.014 */ - { 0x230f, "BCM4354A2" }, /* 001.003.015 */ - { 0x4106, "BCM4335B0" }, /* 002.001.006 */ - { 0x410e, "BCM20702B0" }, /* 002.001.014 */ - { 0x6109, "BCM4335C0" }, /* 003.001.009 */ - { 0x610c, "BCM4354" }, /* 003.001.012 */ - { } -}; - int btbcm_setup_patchram(struct hci_dev *hdev) { char fw_name[64]; |