in btbcm.c [479:585]
int btbcm_initialize(struct hci_dev *hdev, bool *fw_load_done)
{
u16 subver, rev, pid, vid;
struct sk_buff *skb;
struct hci_rp_read_local_version *ver;
const struct bcm_subver_table *bcm_subver_table;
const char *hw_name = NULL;
char postfix[16] = "";
int fw_name_count = 0;
bcm_fw_name *fw_name;
const struct firmware *fw;
int i, err;
/* Reset */
err = btbcm_reset(hdev);
if (err)
return err;
/* Read Local Version Info */
skb = btbcm_read_local_version(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
ver = (struct hci_rp_read_local_version *)skb->data;
rev = le16_to_cpu(ver->hci_rev);
subver = le16_to_cpu(ver->lmp_subver);
kfree_skb(skb);
/* Read controller information */
if (!(*fw_load_done)) {
err = btbcm_read_info(hdev);
if (err)
return err;
}
err = btbcm_print_local_name(hdev);
if (err)
return err;
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;
}
}
bt_dev_info(hdev, "%s (%3.3u.%3.3u.%3.3u) build %4.4u",
hw_name ? hw_name : "BCM", (subver & 0xe000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
if (*fw_load_done)
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(postfix, sizeof(postfix), "-%4.4x-%4.4x", vid, pid);
}
fw_name = kmalloc(BCM_FW_NAME_COUNT_MAX * BCM_FW_NAME_LEN, GFP_KERNEL);
if (!fw_name)
return -ENOMEM;
if (hw_name) {
snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
"brcm/%s%s.hcd", hw_name, postfix);
fw_name_count++;
}
snprintf(fw_name[fw_name_count], BCM_FW_NAME_LEN,
"brcm/BCM%s.hcd", postfix);
fw_name_count++;
for (i = 0; i < fw_name_count; i++) {
err = firmware_request_nowarn(&fw, fw_name[i], &hdev->dev);
if (err == 0) {
bt_dev_info(hdev, "%s '%s' Patch",
hw_name ? hw_name : "BCM", fw_name[i]);
*fw_load_done = true;
break;
}
}
if (*fw_load_done) {
err = btbcm_patchram(hdev, fw);
if (err)
bt_dev_info(hdev, "BCM: Patch failed (%d)", err);
release_firmware(fw);
} else {
bt_dev_err(hdev, "BCM: firmware Patch file not found, tried:");
for (i = 0; i < fw_name_count; i++)
bt_dev_err(hdev, "BCM: '%s'", fw_name[i]);
}
kfree(fw_name);
return 0;
}