diff options
Diffstat (limited to 'drivers/bluetooth/btqca.c')
-rw-r--r-- | drivers/bluetooth/btqca.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index f85a55add9be..25114f0d1319 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -94,6 +94,53 @@ out: } EXPORT_SYMBOL_GPL(qca_read_soc_version); +static int qca_read_fw_build_info(struct hci_dev *hdev) +{ + struct sk_buff *skb; + struct edl_event_hdr *edl; + char cmd, build_label[QCA_FW_BUILD_VER_LEN]; + int build_lbl_len, err = 0; + + bt_dev_dbg(hdev, "QCA read fw build info"); + + cmd = EDL_GET_BUILD_INFO_CMD; + skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN, + &cmd, 0, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "Reading QCA fw build info failed (%d)", + err); + return err; + } + + edl = (struct edl_event_hdr *)(skb->data); + if (!edl) { + bt_dev_err(hdev, "QCA read fw build info with no header"); + err = -EILSEQ; + goto out; + } + + if (edl->cresp != EDL_CMD_REQ_RES_EVT || + edl->rtype != EDL_GET_BUILD_INFO_CMD) { + bt_dev_err(hdev, "QCA Wrong packet received %d %d", edl->cresp, + edl->rtype); + err = -EIO; + goto out; + } + + build_lbl_len = edl->data[0]; + if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1) { + memcpy(build_label, edl->data + 1, build_lbl_len); + *(build_label + build_lbl_len) = '\0'; + } + + hci_set_fw_info(hdev, "%s", build_label); + +out: + kfree_skb(skb); + return err; +} + static int qca_send_reset(struct hci_dev *hdev) { struct sk_buff *skb; @@ -517,6 +564,19 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, return err; } + /* WCN399x supports the Microsoft vendor extension with 0xFD70 as the + * VsMsftOpCode. + */ + switch (soc_type) { + case QCA_WCN3990: + case QCA_WCN3991: + case QCA_WCN3998: + hci_set_msft_opcode(hdev, 0xFD70); + break; + default: + break; + } + /* Perform HCI reset */ err = qca_send_reset(hdev); if (err < 0) { @@ -524,6 +584,13 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, return err; } + if (soc_type == QCA_WCN3991) { + /* get fw build info */ + err = qca_read_fw_build_info(hdev); + if (err < 0) + return err; + } + bt_dev_info(hdev, "QCA setup on UART is completed"); return 0; |