int btbcm_initialize()

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;
}