@@ -482,6 +482,57 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
}
EXPORT_SYMBOL_GPL(btintel_read_version);
+int btintel_read_version_tlv(struct hci_dev *hdev, bool *is_tlv_format,
+ struct sk_buff **skb_out)
+{
+ u8 param;
+ u8 status;
+ u8 tlv_check_octet;
+ u8 *data;
+ struct sk_buff *skb;
+
+ param = 0xFF;
+ skb_out = NULL;
+
+ skb = __hci_cmd_sync(hdev, 0xfc05, 1, ¶m, HCI_CMD_TIMEOUT);
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Intel read version command failed (%ld)",
+ PTR_ERR(skb));
+ return PTR_ERR(skb);
+ }
+
+ /* Check status */
+ data = skb->data;
+ status = *data;
+ if (status) {
+ bt_dev_err(hdev, "Intel Read Version failed (%02x)",
+ status);
+ kfree_skb(skb);
+ return -bt_to_errno(status);
+ }
+
+ /* There are two variants of HCI_Intel_Read_Version_Command_Complete
+ * depending on SKU type (legacy and TLV format).If the skb->len
+ * parameter is equal to INTEL_VERSION_LEN and the first octet
+ * after the status parameter is 0x37 then it's the legacy format,
+ * otherwise it's TLV format
+ */
+
+ /* Fetch the octet after status */
+ tlv_check_octet = *(data + 1);
+
+ if (skb->len == INTEL_VERSION_LEN && tlv_check_octet == 0x37) {
+ bt_dev_dbg(hdev, "Using Legacy Intel Version command");
+ *is_tlv_format = false;
+ } else {
+ bt_dev_dbg(hdev, "Using TLV format Version command");
+ *is_tlv_format = true;
+ }
+ *skb_out = skb;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_read_version_tlv);
+
/* ------- REGMAP IBT SUPPORT ------- */
#define IBT_REG_MODE_8BIT 0x00
@@ -6,6 +6,9 @@
* Copyright (C) 2015 Intel Corporation
*/
+/* Length of intel_version structure*/
+#define INTEL_VERSION_LEN 10
+
struct intel_version {
u8 status;
u8 hw_platform;