static void qca_tlv_check_data()

in btqca.c [230:345]


static void qca_tlv_check_data(struct hci_dev *hdev,
			       struct qca_fw_config *config,
		u8 *fw_data, enum qca_btsoc_type soc_type)
{
	const u8 *data;
	u32 type_len;
	u16 tag_id, tag_len;
	int idx, length;
	struct tlv_type_hdr *tlv;
	struct tlv_type_patch *tlv_patch;
	struct tlv_type_nvm *tlv_nvm;
	uint8_t nvm_baud_rate = config->user_baud_rate;

	config->dnld_mode = QCA_SKIP_EVT_NONE;
	config->dnld_type = QCA_SKIP_EVT_NONE;

	switch (config->type) {
	case ELF_TYPE_PATCH:
		config->dnld_mode = QCA_SKIP_EVT_VSE_CC;
		config->dnld_type = QCA_SKIP_EVT_VSE_CC;

		bt_dev_dbg(hdev, "File Class        : 0x%x", fw_data[4]);
		bt_dev_dbg(hdev, "Data Encoding     : 0x%x", fw_data[5]);
		bt_dev_dbg(hdev, "File version      : 0x%x", fw_data[6]);
		break;
	case TLV_TYPE_PATCH:
		tlv = (struct tlv_type_hdr *)fw_data;
		type_len = le32_to_cpu(tlv->type_len);
		tlv_patch = (struct tlv_type_patch *)tlv->data;

		/* For Rome version 1.1 to 3.1, all segment commands
		 * are acked by a vendor specific event (VSE).
		 * For Rome >= 3.2, the download mode field indicates
		 * if VSE is skipped by the controller.
		 * In case VSE is skipped, only the last segment is acked.
		 */
		config->dnld_mode = tlv_patch->download_mode;
		config->dnld_type = config->dnld_mode;

		BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff);
		BT_DBG("Total Length           : %d bytes",
		       le32_to_cpu(tlv_patch->total_size));
		BT_DBG("Patch Data Length      : %d bytes",
		       le32_to_cpu(tlv_patch->data_length));
		BT_DBG("Signing Format Version : 0x%x",
		       tlv_patch->format_version);
		BT_DBG("Signature Algorithm    : 0x%x",
		       tlv_patch->signature);
		BT_DBG("Download mode          : 0x%x",
		       tlv_patch->download_mode);
		BT_DBG("Reserved               : 0x%x",
		       tlv_patch->reserved1);
		BT_DBG("Product ID             : 0x%04x",
		       le16_to_cpu(tlv_patch->product_id));
		BT_DBG("Rom Build Version      : 0x%04x",
		       le16_to_cpu(tlv_patch->rom_build));
		BT_DBG("Patch Version          : 0x%04x",
		       le16_to_cpu(tlv_patch->patch_version));
		BT_DBG("Reserved               : 0x%x",
		       le16_to_cpu(tlv_patch->reserved2));
		BT_DBG("Patch Entry Address    : 0x%x",
		       le32_to_cpu(tlv_patch->entry));
		break;

	case TLV_TYPE_NVM:
		tlv = (struct tlv_type_hdr *)fw_data;

		type_len = le32_to_cpu(tlv->type_len);
		length = (type_len >> 8) & 0x00ffffff;

		BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff);
		BT_DBG("Length\t\t : %d bytes", length);

		idx = 0;
		data = tlv->data;
		while (idx < length) {
			tlv_nvm = (struct tlv_type_nvm *)(data + idx);

			tag_id = le16_to_cpu(tlv_nvm->tag_id);
			tag_len = le16_to_cpu(tlv_nvm->tag_len);

			/* Update NVM tags as needed */
			switch (tag_id) {
			case EDL_TAG_ID_HCI:
				/* HCI transport layer parameters
				 * enabling software inband sleep
				 * onto controller side.
				 */
				tlv_nvm->data[0] |= 0x80;

				/* UART Baud Rate */
				if (soc_type >= QCA_WCN3991)
					tlv_nvm->data[1] = nvm_baud_rate;
				else
					tlv_nvm->data[2] = nvm_baud_rate;

				break;

			case EDL_TAG_ID_DEEP_SLEEP:
				/* Sleep enable mask
				 * enabling deep sleep feature on controller.
				 */
				tlv_nvm->data[0] |= 0x01;

				break;
			}

			idx += (sizeof(u16) + sizeof(u16) + 8 + tag_len);
		}
		break;

	default:
		BT_ERR("Unknown TLV type %d", config->type);
		break;
	}
}