aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/btusb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/btusb.c')
-rw-r--r--drivers/bluetooth/btusb.c155
1 files changed, 154 insertions, 1 deletions
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index a7dfbf9a3afb..a1c80b0c7663 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -49,6 +49,7 @@ static struct usb_driver btusb_driver;
49#define BTUSB_WRONG_SCO_MTU 0x40 49#define BTUSB_WRONG_SCO_MTU 0x40
50#define BTUSB_ATH3012 0x80 50#define BTUSB_ATH3012 0x80
51#define BTUSB_INTEL 0x100 51#define BTUSB_INTEL 0x100
52#define BTUSB_BCM_PATCHRAM 0x200
52 53
53static const struct usb_device_id btusb_table[] = { 54static const struct usb_device_id btusb_table[] = {
54 /* Generic Bluetooth USB device */ 55 /* Generic Bluetooth USB device */
@@ -111,7 +112,8 @@ static const struct usb_device_id btusb_table[] = {
111 { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) }, 112 { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
112 113
113 /* Broadcom devices with vendor specific id */ 114 /* Broadcom devices with vendor specific id */
114 { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, 115 { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
116 .driver_info = BTUSB_BCM_PATCHRAM },
115 117
116 /* Belkin F8065bf - Broadcom based */ 118 /* Belkin F8065bf - Broadcom based */
117 { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) }, 119 { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
@@ -1381,6 +1383,154 @@ exit_mfg_deactivate:
1381 return 0; 1383 return 0;
1382} 1384}
1383 1385
1386static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
1387{
1388 struct btusb_data *data = hci_get_drvdata(hdev);
1389 struct usb_device *udev = data->udev;
1390 char fw_name[64];
1391 const struct firmware *fw;
1392 const u8 *fw_ptr;
1393 size_t fw_size;
1394 const struct hci_command_hdr *cmd;
1395 const u8 *cmd_param;
1396 u16 opcode;
1397 struct sk_buff *skb;
1398 struct hci_rp_read_local_version *ver;
1399 long ret;
1400
1401 snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd",
1402 udev->product ? udev->product : "BCM",
1403 le16_to_cpu(udev->descriptor.idVendor),
1404 le16_to_cpu(udev->descriptor.idProduct));
1405
1406 ret = request_firmware(&fw, fw_name, &hdev->dev);
1407 if (ret < 0) {
1408 BT_INFO("%s: BCM: patch %s not found", hdev->name,
1409 fw_name);
1410 return 0;
1411 }
1412
1413 /* Reset */
1414 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
1415 if (IS_ERR(skb)) {
1416 ret = PTR_ERR(skb);
1417 BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
1418 goto done;
1419 }
1420 kfree_skb(skb);
1421
1422 /* Read Local Version Info */
1423 skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
1424 HCI_INIT_TIMEOUT);
1425 if (IS_ERR(skb)) {
1426 ret = PTR_ERR(skb);
1427 BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
1428 hdev->name, ret);
1429 goto done;
1430 }
1431
1432 if (skb->len != sizeof(*ver)) {
1433 BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
1434 hdev->name);
1435 kfree_skb(skb);
1436 ret = -EIO;
1437 goto done;
1438 }
1439
1440 ver = (struct hci_rp_read_local_version *) skb->data;
1441 BT_INFO("%s: BCM: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
1442 "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev,
1443 ver->lmp_ver, ver->lmp_subver);
1444 kfree_skb(skb);
1445
1446 /* Start Download */
1447 skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
1448 if (IS_ERR(skb)) {
1449 ret = PTR_ERR(skb);
1450 BT_ERR("%s: BCM: Download Minidrv command failed (%ld)",
1451 hdev->name, ret);
1452 goto reset_fw;
1453 }
1454 kfree_skb(skb);
1455
1456 /* 50 msec delay after Download Minidrv completes */
1457 msleep(50);
1458
1459 fw_ptr = fw->data;
1460 fw_size = fw->size;
1461
1462 while (fw_size >= sizeof(*cmd)) {
1463 cmd = (struct hci_command_hdr *) fw_ptr;
1464 fw_ptr += sizeof(*cmd);
1465 fw_size -= sizeof(*cmd);
1466
1467 if (fw_size < cmd->plen) {
1468 BT_ERR("%s: BCM: patch %s is corrupted",
1469 hdev->name, fw_name);
1470 ret = -EINVAL;
1471 goto reset_fw;
1472 }
1473
1474 cmd_param = fw_ptr;
1475 fw_ptr += cmd->plen;
1476 fw_size -= cmd->plen;
1477
1478 opcode = le16_to_cpu(cmd->opcode);
1479
1480 skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param,
1481 HCI_INIT_TIMEOUT);
1482 if (IS_ERR(skb)) {
1483 ret = PTR_ERR(skb);
1484 BT_ERR("%s: BCM: patch command %04x failed (%ld)",
1485 hdev->name, opcode, ret);
1486 goto reset_fw;
1487 }
1488 kfree_skb(skb);
1489 }
1490
1491 /* 250 msec delay after Launch Ram completes */
1492 msleep(250);
1493
1494reset_fw:
1495 /* Reset */
1496 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
1497 if (IS_ERR(skb)) {
1498 ret = PTR_ERR(skb);
1499 BT_ERR("%s: HCI_OP_RESET failed (%ld)", hdev->name, ret);
1500 goto done;
1501 }
1502 kfree_skb(skb);
1503
1504 /* Read Local Version Info */
1505 skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
1506 HCI_INIT_TIMEOUT);
1507 if (IS_ERR(skb)) {
1508 ret = PTR_ERR(skb);
1509 BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION failed (%ld)",
1510 hdev->name, ret);
1511 goto done;
1512 }
1513
1514 if (skb->len != sizeof(*ver)) {
1515 BT_ERR("%s: HCI_OP_READ_LOCAL_VERSION event length mismatch",
1516 hdev->name);
1517 kfree_skb(skb);
1518 ret = -EIO;
1519 goto done;
1520 }
1521
1522 ver = (struct hci_rp_read_local_version *) skb->data;
1523 BT_INFO("%s: BCM: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
1524 "lmp_subver=%04x", hdev->name, ver->hci_ver, ver->hci_rev,
1525 ver->lmp_ver, ver->lmp_subver);
1526 kfree_skb(skb);
1527
1528done:
1529 release_firmware(fw);
1530
1531 return ret;
1532}
1533
1384static int btusb_probe(struct usb_interface *intf, 1534static int btusb_probe(struct usb_interface *intf,
1385 const struct usb_device_id *id) 1535 const struct usb_device_id *id)
1386{ 1536{
@@ -1486,6 +1636,9 @@ static int btusb_probe(struct usb_interface *intf,
1486 if (id->driver_info & BTUSB_BCM92035) 1636 if (id->driver_info & BTUSB_BCM92035)
1487 hdev->setup = btusb_setup_bcm92035; 1637 hdev->setup = btusb_setup_bcm92035;
1488 1638
1639 if (id->driver_info & BTUSB_BCM_PATCHRAM)
1640 hdev->setup = btusb_setup_bcm_patchram;
1641
1489 if (id->driver_info & BTUSB_INTEL) 1642 if (id->driver_info & BTUSB_INTEL)
1490 hdev->setup = btusb_setup_intel; 1643 hdev->setup = btusb_setup_intel;
1491 1644