1/* 2 * 3 * Bluetooth support for Broadcom devices 4 * 5 * Copyright (C) 2015 Intel Corporation 6 * 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24#include <linux/module.h> 25#include <linux/firmware.h> 26#include <asm/unaligned.h> 27 28#include <net/bluetooth/bluetooth.h> 29#include <net/bluetooth/hci_core.h> 30 31#include "btbcm.h" 32 33#define VERSION "0.1" 34 35#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}}) 36 37int btbcm_check_bdaddr(struct hci_dev *hdev) 38{ 39 struct hci_rp_read_bd_addr *bda; 40 struct sk_buff *skb; 41 42 skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, 43 HCI_INIT_TIMEOUT); 44 if (IS_ERR(skb)) { 45 int err = PTR_ERR(skb); 46 BT_ERR("%s: BCM: Reading device address failed (%d)", 47 hdev->name, err); 48 return err; 49 } 50 51 if (skb->len != sizeof(*bda)) { 52 BT_ERR("%s: BCM: Device address length mismatch", hdev->name); 53 kfree_skb(skb); 54 return -EIO; 55 } 56 57 bda = (struct hci_rp_read_bd_addr *)skb->data; 58 if (bda->status) { 59 BT_ERR("%s: BCM: Device address result failed (%02x)", 60 hdev->name, bda->status); 61 kfree_skb(skb); 62 return -bt_to_errno(bda->status); 63 } 64 65 /* The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller 66 * with no configured address. 67 */ 68 if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0)) { 69 BT_INFO("%s: BCM: Using default device address (%pMR)", 70 hdev->name, &bda->bdaddr); 71 set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); 72 } 73 74 kfree_skb(skb); 75 76 return 0; 77} 78EXPORT_SYMBOL_GPL(btbcm_check_bdaddr); 79 80int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) 81{ 82 struct sk_buff *skb; 83 int err; 84 85 skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT); 86 if (IS_ERR(skb)) { 87 err = PTR_ERR(skb); 88 BT_ERR("%s: BCM: Change address command failed (%d)", 89 hdev->name, err); 90 return err; 91 } 92 kfree_skb(skb); 93 94 return 0; 95} 96EXPORT_SYMBOL_GPL(btbcm_set_bdaddr); 97 98int btbcm_patchram(struct hci_dev *hdev, const char *firmware) 99{ 100 const struct hci_command_hdr *cmd; 101 const struct firmware *fw; 102 const u8 *fw_ptr; 103 size_t fw_size; 104 struct sk_buff *skb; 105 u16 opcode; 106 int err; 107 108 err = request_firmware(&fw, firmware, &hdev->dev); 109 if (err < 0) { 110 BT_INFO("%s: BCM: Patch %s not found", hdev->name, firmware); 111 return err; 112 } 113 114 /* Start Download */ 115 skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT); 116 if (IS_ERR(skb)) { 117 err = PTR_ERR(skb); 118 BT_ERR("%s: BCM: Download Minidrv command failed (%d)", 119 hdev->name, err); 120 goto done; 121 } 122 kfree_skb(skb); 123 124 /* 50 msec delay after Download Minidrv completes */ 125 msleep(50); 126 127 fw_ptr = fw->data; 128 fw_size = fw->size; 129 130 while (fw_size >= sizeof(*cmd)) { 131 const u8 *cmd_param; 132 133 cmd = (struct hci_command_hdr *)fw_ptr; 134 fw_ptr += sizeof(*cmd); 135 fw_size -= sizeof(*cmd); 136 137 if (fw_size < cmd->plen) { 138 BT_ERR("%s: BCM: Patch %s is corrupted", hdev->name, 139 firmware); 140 err = -EINVAL; 141 goto done; 142 } 143 144 cmd_param = fw_ptr; 145 fw_ptr += cmd->plen; 146 fw_size -= cmd->plen; 147 148 opcode = le16_to_cpu(cmd->opcode); 149 150 skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param, 151 HCI_INIT_TIMEOUT); 152 if (IS_ERR(skb)) { 153 err = PTR_ERR(skb); 154 BT_ERR("%s: BCM: Patch command %04x failed (%d)", 155 hdev->name, opcode, err); 156 goto done; 157 } 158 kfree_skb(skb); 159 } 160 161 /* 250 msec delay after Launch Ram completes */ 162 msleep(250); 163 164done: 165 release_firmware(fw); 166 return err; 167} 168EXPORT_SYMBOL(btbcm_patchram); 169 170static int btbcm_reset(struct hci_dev *hdev) 171{ 172 struct sk_buff *skb; 173 174 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); 175 if (IS_ERR(skb)) { 176 int err = PTR_ERR(skb); 177 BT_ERR("%s: BCM: Reset failed (%d)", hdev->name, err); 178 return err; 179 } 180 kfree_skb(skb); 181 182 return 0; 183} 184 185static struct sk_buff *btbcm_read_local_version(struct hci_dev *hdev) 186{ 187 struct sk_buff *skb; 188 189 skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL, 190 HCI_INIT_TIMEOUT); 191 if (IS_ERR(skb)) { 192 BT_ERR("%s: BCM: Reading local version info failed (%ld)", 193 hdev->name, PTR_ERR(skb)); 194 return skb; 195 } 196 197 if (skb->len != sizeof(struct hci_rp_read_local_version)) { 198 BT_ERR("%s: BCM: Local version length mismatch", hdev->name); 199 kfree_skb(skb); 200 return ERR_PTR(-EIO); 201 } 202 203 return skb; 204} 205 206static struct sk_buff *btbcm_read_verbose_config(struct hci_dev *hdev) 207{ 208 struct sk_buff *skb; 209 210 skb = __hci_cmd_sync(hdev, 0xfc79, 0, NULL, HCI_INIT_TIMEOUT); 211 if (IS_ERR(skb)) { 212 BT_ERR("%s: BCM: Read verbose config info failed (%ld)", 213 hdev->name, PTR_ERR(skb)); 214 return skb; 215 } 216 217 if (skb->len != 7) { 218 BT_ERR("%s: BCM: Verbose config length mismatch", hdev->name); 219 kfree_skb(skb); 220 return ERR_PTR(-EIO); 221 } 222 223 return skb; 224} 225 226static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev) 227{ 228 struct sk_buff *skb; 229 230 skb = __hci_cmd_sync(hdev, 0xfc5a, 0, NULL, HCI_INIT_TIMEOUT); 231 if (IS_ERR(skb)) { 232 BT_ERR("%s: BCM: Read USB product info failed (%ld)", 233 hdev->name, PTR_ERR(skb)); 234 return skb; 235 } 236 237 if (skb->len != 5) { 238 BT_ERR("%s: BCM: USB product length mismatch", hdev->name); 239 kfree_skb(skb); 240 return ERR_PTR(-EIO); 241 } 242 243 return skb; 244} 245 246static const struct { 247 u16 subver; 248 const char *name; 249} bcm_uart_subver_table[] = { 250 { 0x410e, "BCM43341B0" }, /* 002.001.014 */ 251 { } 252}; 253 254static const struct { 255 u16 subver; 256 const char *name; 257} bcm_usb_subver_table[] = { 258 { 0x210b, "BCM43142A0" }, /* 001.001.011 */ 259 { 0x2112, "BCM4314A0" }, /* 001.001.018 */ 260 { 0x2118, "BCM20702A0" }, /* 001.001.024 */ 261 { 0x2126, "BCM4335A0" }, /* 001.001.038 */ 262 { 0x220e, "BCM20702A1" }, /* 001.002.014 */ 263 { 0x230f, "BCM4354A2" }, /* 001.003.015 */ 264 { 0x4106, "BCM4335B0" }, /* 002.001.006 */ 265 { 0x410e, "BCM20702B0" }, /* 002.001.014 */ 266 { 0x6109, "BCM4335C0" }, /* 003.001.009 */ 267 { 0x610c, "BCM4354" }, /* 003.001.012 */ 268 { } 269}; 270 271int btbcm_setup_patchram(struct hci_dev *hdev) 272{ 273 char fw_name[64]; 274 u16 subver, rev, pid, vid; 275 const char *hw_name = NULL; 276 struct sk_buff *skb; 277 struct hci_rp_read_local_version *ver; 278 int i, err; 279 280 /* Reset */ 281 err = btbcm_reset(hdev); 282 if (err) 283 return err; 284 285 /* Read Local Version Info */ 286 skb = btbcm_read_local_version(hdev); 287 if (IS_ERR(skb)) 288 return PTR_ERR(skb); 289 290 ver = (struct hci_rp_read_local_version *)skb->data; 291 rev = le16_to_cpu(ver->hci_rev); 292 subver = le16_to_cpu(ver->lmp_subver); 293 kfree_skb(skb); 294 295 /* Read Verbose Config Version Info */ 296 skb = btbcm_read_verbose_config(hdev); 297 if (IS_ERR(skb)) 298 return PTR_ERR(skb); 299 300 BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); 301 kfree_skb(skb); 302 303 switch ((rev & 0xf000) >> 12) { 304 case 0: 305 for (i = 0; bcm_uart_subver_table[i].name; i++) { 306 if (subver == bcm_uart_subver_table[i].subver) { 307 hw_name = bcm_uart_subver_table[i].name; 308 break; 309 } 310 } 311 312 snprintf(fw_name, sizeof(fw_name), "brcm/%s.hcd", 313 hw_name ? : "BCM"); 314 break; 315 case 1: 316 case 2: 317 /* Read USB Product Info */ 318 skb = btbcm_read_usb_product(hdev); 319 if (IS_ERR(skb)) 320 return PTR_ERR(skb); 321 322 vid = get_unaligned_le16(skb->data + 1); 323 pid = get_unaligned_le16(skb->data + 3); 324 kfree_skb(skb); 325 326 for (i = 0; bcm_usb_subver_table[i].name; i++) { 327 if (subver == bcm_usb_subver_table[i].subver) { 328 hw_name = bcm_usb_subver_table[i].name; 329 break; 330 } 331 } 332 333 snprintf(fw_name, sizeof(fw_name), "brcm/%s-%4.4x-%4.4x.hcd", 334 hw_name ? : "BCM", vid, pid); 335 break; 336 default: 337 return 0; 338 } 339 340 BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name, 341 hw_name ? : "BCM", (subver & 0x7000) >> 13, 342 (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); 343 344 err = btbcm_patchram(hdev, fw_name); 345 if (err == -ENOENT) 346 return 0; 347 348 /* Reset */ 349 err = btbcm_reset(hdev); 350 if (err) 351 return err; 352 353 /* Read Local Version Info */ 354 skb = btbcm_read_local_version(hdev); 355 if (IS_ERR(skb)) 356 return PTR_ERR(skb); 357 358 ver = (struct hci_rp_read_local_version *)skb->data; 359 rev = le16_to_cpu(ver->hci_rev); 360 subver = le16_to_cpu(ver->lmp_subver); 361 kfree_skb(skb); 362 363 BT_INFO("%s: %s (%3.3u.%3.3u.%3.3u) build %4.4u", hdev->name, 364 hw_name ? : "BCM", (subver & 0x7000) >> 13, 365 (subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff); 366 367 btbcm_check_bdaddr(hdev); 368 369 set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); 370 371 return 0; 372} 373EXPORT_SYMBOL_GPL(btbcm_setup_patchram); 374 375int btbcm_setup_apple(struct hci_dev *hdev) 376{ 377 struct sk_buff *skb; 378 379 /* Read Verbose Config Version Info */ 380 skb = btbcm_read_verbose_config(hdev); 381 if (!IS_ERR(skb)) { 382 BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1], 383 get_unaligned_le16(skb->data + 5)); 384 kfree_skb(skb); 385 } 386 387 set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); 388 389 return 0; 390} 391EXPORT_SYMBOL_GPL(btbcm_setup_apple); 392 393MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 394MODULE_DESCRIPTION("Bluetooth support for Broadcom devices ver " VERSION); 395MODULE_VERSION(VERSION); 396MODULE_LICENSE("GPL"); 397