aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-02-15 02:08:47 -0500
committerJohan Hedberg <johan.hedberg@intel.com>2015-02-15 03:16:39 -0500
commit18835dfa3ac526b25f74af3a61829f02fe92a317 (patch)
tree4ce63201ca71ea5d41b47ad35b68e26618a40072 /drivers/bluetooth
parent87e2a020cac29fba4a35e681392ba0d1f7e21ba9 (diff)
Bluetooth: btusb: Use matching names for Broadcom firmware files
The Broadcom firmware files are named with firmware version information encoded into lmp_subver field. So BCM20702B0_002.001.014.0527.0607.hex would be represented by 0x410e. To allow for an easier decoding of the actual firmware names, provide an internal table that does the mapping and request the firmware file by name. Bluetooth: hci0: BCM20702B0 (002.001.014) build 0607 Now the complicated encoding of lmp_subver will be decoded and turned into the name and firmware version information from the firmware files. The previous attempt of using udev->product failed badly since it never contains any matching entry to the actual hardware or firmware files distributed by Broadcom in their Windows drivers. It is even worse since it can change depending on if the internal bootstrapping happened before the USB bus enumeration or after. This caused many race conditions. 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.c75
1 files changed, 53 insertions, 22 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 0f4c43652d71..3ca2e1bf7bfa 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2366,6 +2366,23 @@ static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
2366 return 0; 2366 return 0;
2367} 2367}
2368 2368
2369static const struct {
2370 u16 subver;
2371 const char *name;
2372} bcm_subver_table[] = {
2373 { 0x210b, "BCM43142A0" }, /* 001.001.011 */
2374 { 0x2112, "BCM4314A0" }, /* 001.001.018 */
2375 { 0x2118, "BCM20702A0" }, /* 001.001.024 */
2376 { 0x2126, "BCM4335A0" }, /* 001.001.038 */
2377 { 0x220e, "BCM20702A1" }, /* 001.002.014 */
2378 { 0x230f, "BCM4354A2" }, /* 001.003.015 */
2379 { 0x4106, "BCM4335B0" }, /* 002.001.006 */
2380 { 0x410e, "BCM20702B0" }, /* 002.001.014 */
2381 { 0x6109, "BCM4335C0" }, /* 003.001.009 */
2382 { 0x610c, "BCM4354" }, /* 003.001.012 */
2383 { }
2384};
2385
2369#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) 2386#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
2370 2387
2371static int btusb_setup_bcm_patchram(struct hci_dev *hdev) 2388static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
@@ -2378,29 +2395,20 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
2378 size_t fw_size; 2395 size_t fw_size;
2379 const struct hci_command_hdr *cmd; 2396 const struct hci_command_hdr *cmd;
2380 const u8 *cmd_param; 2397 const u8 *cmd_param;
2381 u16 opcode; 2398 u16 opcode, subver, rev;
2399 const char *hw_name = NULL;
2382 struct sk_buff *skb; 2400 struct sk_buff *skb;
2383 struct hci_rp_read_local_version *ver; 2401 struct hci_rp_read_local_version *ver;
2384 struct hci_rp_read_bd_addr *bda; 2402 struct hci_rp_read_bd_addr *bda;
2385 long ret; 2403 long ret;
2386 2404 int i;
2387 snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd",
2388 udev->product ? udev->product : "BCM",
2389 le16_to_cpu(udev->descriptor.idVendor),
2390 le16_to_cpu(udev->descriptor.idProduct));
2391
2392 ret = request_firmware(&fw, fw_name, &hdev->dev);
2393 if (ret < 0) {
2394 BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name);
2395 return 0;
2396 }
2397 2405
2398 /* Reset */ 2406 /* Reset */
2399 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); 2407 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
2400 if (IS_ERR(skb)) { 2408 if (IS_ERR(skb)) {
2401 ret = PTR_ERR(skb); 2409 ret = PTR_ERR(skb);
2402 BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret); 2410 BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
2403 goto done; 2411 return ret;
2404 } 2412 }
2405 kfree_skb(skb); 2413 kfree_skb(skb);
2406 2414
@@ -2411,23 +2419,43 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
2411 ret = PTR_ERR(skb); 2419 ret = PTR_ERR(skb);
2412 BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)", 2420 BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
2413 hdev->name, ret); 2421 hdev->name, ret);
2414 goto done; 2422 return ret;
2415 } 2423 }
2416 2424
2417 if (skb->len != sizeof(*ver)) { 2425 if (skb->len != sizeof(*ver)) {
2418 BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch", 2426 BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
2419 hdev->name); 2427 hdev->name);
2420 kfree_skb(skb); 2428 kfree_skb(skb);
2421 ret = -EIO; 2429 return -EIO;
2422 goto done;
2423 } 2430 }
2424 2431
2425 ver = (struct hci_rp_read_local_version *)skb->data; 2432 ver = (struct hci_rp_read_local_version *)skb->data;
2426 BT_INFO("%s: BCM: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x " 2433 rev = le16_to_cpu(ver->hci_rev);
2427 "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev, 2434 subver = le16_to_cpu(ver->lmp_subver);
2428 ver->lmp_ver, ver->lmp_subver);
2429 kfree_skb(skb); 2435 kfree_skb(skb);
2430 2436
2437 for (i = 0; bcm_subver_table[i].name; i++) {
2438 if (subver == bcm_subver_table[i].subver) {
2439 hw_name = bcm_subver_table[i].name;
2440 break;
2441 }
2442 }
2443
2444 BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
2445 hw_name ? : "BCM", (subver & 0x7000) >> 13,
2446 (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
2447
2448 snprintf(fw_name, sizeof(fw_name), "brcm/%s-%4.4x-%4.4x.hcd",
2449 hw_name ? : "BCM",
2450 le16_to_cpu(udev->descriptor.idVendor),
2451 le16_to_cpu(udev->descriptor.idProduct));
2452
2453 ret = request_firmware(&fw, fw_name, &hdev->dev);
2454 if (ret < 0) {
2455 BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name);
2456 return 0;
2457 }
2458
2431 /* Start Download */ 2459 /* Start Download */
2432 skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT); 2460 skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
2433 if (IS_ERR(skb)) { 2461 if (IS_ERR(skb)) {
@@ -2505,11 +2533,14 @@ reset_fw:
2505 } 2533 }
2506 2534
2507 ver = (struct hci_rp_read_local_version *)skb->data; 2535 ver = (struct hci_rp_read_local_version *)skb->data;
2508 BT_INFO("%s: BCM: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x " 2536 rev = le16_to_cpu(ver->hci_rev);
2509 "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev, 2537 subver = le16_to_cpu(ver->lmp_subver);
2510 ver->lmp_ver, ver->lmp_subver);
2511 kfree_skb(skb); 2538 kfree_skb(skb);
2512 2539
2540 BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name,
2541 hw_name ? : "BCM", (subver & 0x7000) >> 13,
2542 (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
2543
2513 /* Read BD Address */ 2544 /* Read BD Address */
2514 skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, 2545 skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
2515 HCI_INIT_TIMEOUT); 2546 HCI_INIT_TIMEOUT);