2020-09-04 06:22:07

by Rocky Liao

[permalink] [raw]
Subject: [PATCH v1] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

This patch add support for WCN6855 i.e. patch and nvm download
support.

Signed-off-by: Rocky Liao <[email protected]>
---
drivers/bluetooth/btusb.c | 42 +++++++++++++++++++++++++++++++++++----
1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index fe80588c7bd3..e51e754ca9b8 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_MEDIATEK 0x200000
#define BTUSB_WIDEBAND_SPEECH 0x400000
#define BTUSB_VALID_LE_STATES 0x800000
+#define BTUSB_QCA_WCN6855 0x1000000

static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -273,6 +274,10 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },

+ /* QCA WCN6855 chipset */
+ { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
+ BTUSB_WIDEBAND_SPEECH },
+
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
return 0;
}

+static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
+ const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ u8 buf[6];
+ long ret;
+
+ memcpy(buf, bdaddr, sizeof(bdaddr_t));
+
+ skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ bt_dev_err(hdev, "Change address command failed (%ld)", ret);
+ return ret;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+
#define QCA_DFU_PACKET_LEN 4096

#define QCA_GET_TARGET_VERSION 0x09
@@ -3428,6 +3453,8 @@ static const struct qca_device_info qca_devices_table[] = {
{ 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
{ 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
+ { 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */
+ { 0x00130200, 40, 4, 18 } /* WCN6855 2.0 */
};

static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
@@ -3530,7 +3557,7 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
struct qca_rampatch_version *rver;
const struct firmware *fw;
u32 ver_rom, ver_patch;
- u16 rver_rom, rver_patch;
+ u32 rver_rom, rver_patch;
char fwname[64];
int err;

@@ -3552,6 +3579,9 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
rver_rom = le16_to_cpu(rver->rom_version);
rver_patch = le16_to_cpu(rver->patch_version);

+ if (ver_rom & ~0xffffU)
+ rver_rom = *(u16 *)(fw->data + 16) << 16 | rver_rom;
+
bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
"firmware rome 0x%x build 0x%x",
rver_rom, rver_patch, ver_rom, ver_patch);
@@ -3625,9 +3655,6 @@ static int btusb_setup_qca(struct hci_dev *hdev)
return err;

ver_rom = le32_to_cpu(ver.rom_version);
- /* Don't care about high ROM versions */
- if (ver_rom & ~0xffffU)
- return 0;

for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
if (ver_rom == qca_devices_table[i].rom_version)
@@ -4063,6 +4090,13 @@ static int btusb_probe(struct usb_interface *intf,
btusb_check_needs_reset_resume(intf);
}

+ if (id->driver_info & BTUSB_QCA_WCN6855) {
+ data->setup_on_usb = btusb_setup_qca;
+ hdev->set_bdaddr = btusb_set_bdaddr_wcn6855;
+ hdev->cmd_timeout = btusb_qca_cmd_timeout;
+ set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
+ }
+
if (id->driver_info & BTUSB_AMP) {
/* AMP controllers do not support SCO packets */
data->isoc = NULL;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project


2020-09-11 06:57:23

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v1] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

Hi Rocky,

> This patch add support for WCN6855 i.e. patch and nvm download
> support.
>
> Signed-off-by: Rocky Liao <[email protected]>
> ---
> drivers/bluetooth/btusb.c | 42 +++++++++++++++++++++++++++++++++++----
> 1 file changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index fe80588c7bd3..e51e754ca9b8 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
> #define BTUSB_MEDIATEK 0x200000
> #define BTUSB_WIDEBAND_SPEECH 0x400000
> #define BTUSB_VALID_LE_STATES 0x800000
> +#define BTUSB_QCA_WCN6855 0x1000000
>
> static const struct usb_device_id btusb_table[] = {
> /* Generic Bluetooth USB device */
> @@ -273,6 +274,10 @@ static const struct usb_device_id blacklist_table[] = {
> { USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
> { USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
>
> + /* QCA WCN6855 chipset */
> + { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
> + BTUSB_WIDEBAND_SPEECH },
> +
> /* Broadcom BCM2035 */
> { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
> { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
> @@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
> return 0;
> }
>
> +static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
> + const bdaddr_t *bdaddr)
> +{
> + struct sk_buff *skb;
> + u8 buf[6];
> + long ret;
> +
> + memcpy(buf, bdaddr, sizeof(bdaddr_t));
> +
> + skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf, HCI_INIT_TIMEOUT);
> + if (IS_ERR(skb)) {
> + ret = PTR_ERR(skb);
> + bt_dev_err(hdev, "Change address command failed (%ld)", ret);
> + return ret;
> + }
> + kfree_skb(skb);
> +
> + return 0;
> +}

What is wrong with using qca_set_bdaddr() function.

> +
> #define QCA_DFU_PACKET_LEN 4096
>
> #define QCA_GET_TARGET_VERSION 0x09
> @@ -3428,6 +3453,8 @@ static const struct qca_device_info qca_devices_table[] = {
> { 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
> { 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
> { 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
> + { 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */
> + { 0x00130200, 40, 4, 18 } /* WCN6855 2.0 */
> };
>
> static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
> @@ -3530,7 +3557,7 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
> struct qca_rampatch_version *rver;
> const struct firmware *fw;
> u32 ver_rom, ver_patch;
> - u16 rver_rom, rver_patch;
> + u32 rver_rom, rver_patch;
> char fwname[64];
> int err;
>
> @@ -3552,6 +3579,9 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
> rver_rom = le16_to_cpu(rver->rom_version);
> rver_patch = le16_to_cpu(rver->patch_version);
>
> + if (ver_rom & ~0xffffU)
> + rver_rom = *(u16 *)(fw->data + 16) << 16 | rver_rom;
> +

You will require proper unaligned access unless you can guarantee things are aligned properly. And since I assume the firmware data is in a specific endian format, you need to convert it correctly.

In addition, you change the variables to u32, but still use le16_to_cpu function above. Something is not adding up. Have you actually run a sparse check?

> bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
> "firmware rome 0x%x build 0x%x",
> rver_rom, rver_patch, ver_rom, ver_patch);
> @@ -3625,9 +3655,6 @@ static int btusb_setup_qca(struct hci_dev *hdev)
> return err;
>
> ver_rom = le32_to_cpu(ver.rom_version);
> - /* Don't care about high ROM versions */
> - if (ver_rom & ~0xffffU)
> - return 0;
>
> for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
> if (ver_rom == qca_devices_table[i].rom_version)
> @@ -4063,6 +4090,13 @@ static int btusb_probe(struct usb_interface *intf,
> btusb_check_needs_reset_resume(intf);
> }
>
> + if (id->driver_info & BTUSB_QCA_WCN6855) {
> + data->setup_on_usb = btusb_setup_qca;
> + hdev->set_bdaddr = btusb_set_bdaddr_wcn6855;
> + hdev->cmd_timeout = btusb_qca_cmd_timeout;
> + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
> + }
> +

Regards

Marcel

2020-09-14 09:28:39

by Rocky Liao

[permalink] [raw]
Subject: [PATCH v2] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

This patch add support for WCN6855 i.e. patch and nvm download
support.

Signed-off-by: Rocky Liao <[email protected]>
---
drivers/bluetooth/btusb.c | 50 ++++++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index fe80588c7bd3..789e8d5e829e 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_MEDIATEK 0x200000
#define BTUSB_WIDEBAND_SPEECH 0x400000
#define BTUSB_VALID_LE_STATES 0x800000
+#define BTUSB_QCA_WCN6855 0x1000000

static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@@ -273,6 +274,10 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },

+ /* QCA WCN6855 chipset */
+ { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
+ BTUSB_WIDEBAND_SPEECH },
+
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
return 0;
}

+static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
+ const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ u8 buf[6];
+ long ret;
+
+ memcpy(buf, bdaddr, sizeof(bdaddr_t));
+
+ skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ ret = PTR_ERR(skb);
+ bt_dev_err(hdev, "Change address command failed (%ld)", ret);
+ return ret;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+
#define QCA_DFU_PACKET_LEN 4096

#define QCA_GET_TARGET_VERSION 0x09
@@ -3428,6 +3453,8 @@ static const struct qca_device_info qca_devices_table[] = {
{ 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
{ 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
+ { 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */
+ { 0x00130200, 40, 4, 18 } /* WCN6855 2.0 */
};

static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
@@ -3529,8 +3556,8 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
{
struct qca_rampatch_version *rver;
const struct firmware *fw;
- u32 ver_rom, ver_patch;
- u16 rver_rom, rver_patch;
+ u32 ver_rom, ver_patch, rver_rom;
+ u16 rver_rom_low, rver_rom_high, rver_patch;
char fwname[64];
int err;

@@ -3549,9 +3576,16 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
bt_dev_info(hdev, "using rampatch file: %s", fwname);

rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
- rver_rom = le16_to_cpu(rver->rom_version);
+ rver_rom_low = le16_to_cpu(rver->rom_version);
rver_patch = le16_to_cpu(rver->patch_version);

+ if (ver_rom & ~0xffffU) {
+ rver_rom_high = le16_to_cpu(*(__le16 *)(fw->data + 16));
+ rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);
+ } else {
+ rver_rom = (__force u32)rver_rom_low;
+ }
+
bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
"firmware rome 0x%x build 0x%x",
rver_rom, rver_patch, ver_rom, ver_patch);
@@ -3625,9 +3659,6 @@ static int btusb_setup_qca(struct hci_dev *hdev)
return err;

ver_rom = le32_to_cpu(ver.rom_version);
- /* Don't care about high ROM versions */
- if (ver_rom & ~0xffffU)
- return 0;

for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
if (ver_rom == qca_devices_table[i].rom_version)
@@ -4063,6 +4094,13 @@ static int btusb_probe(struct usb_interface *intf,
btusb_check_needs_reset_resume(intf);
}

+ if (id->driver_info & BTUSB_QCA_WCN6855) {
+ data->setup_on_usb = btusb_setup_qca;
+ hdev->set_bdaddr = btusb_set_bdaddr_wcn6855;
+ hdev->cmd_timeout = btusb_qca_cmd_timeout;
+ set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
+ }
+
if (id->driver_info & BTUSB_AMP) {
/* AMP controllers do not support SCO packets */
data->isoc = NULL;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project

2020-09-14 13:35:30

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v2] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

Hi Rocky,

> This patch add support for WCN6855 i.e. patch and nvm download
> support.
>
> Signed-off-by: Rocky Liao <[email protected]>
> ---
> drivers/bluetooth/btusb.c | 50 ++++++++++++++++++++++++++++++++++-----
> 1 file changed, 44 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index fe80588c7bd3..789e8d5e829e 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
> #define BTUSB_MEDIATEK 0x200000
> #define BTUSB_WIDEBAND_SPEECH 0x400000
> #define BTUSB_VALID_LE_STATES 0x800000
> +#define BTUSB_QCA_WCN6855 0x1000000
>
> static const struct usb_device_id btusb_table[] = {
> /* Generic Bluetooth USB device */
> @@ -273,6 +274,10 @@ static const struct usb_device_id blacklist_table[] = {
> { USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
> { USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
>
> + /* QCA WCN6855 chipset */
> + { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
> + BTUSB_WIDEBAND_SPEECH },
> +
> /* Broadcom BCM2035 */
> { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
> { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
> @@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
> return 0;
> }
>
> +static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
> + const bdaddr_t *bdaddr)
> +{
> + struct sk_buff *skb;
> + u8 buf[6];
> + long ret;
> +
> + memcpy(buf, bdaddr, sizeof(bdaddr_t));
> +
> + skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf, HCI_INIT_TIMEOUT);
> + if (IS_ERR(skb)) {
> + ret = PTR_ERR(skb);
> + bt_dev_err(hdev, "Change address command failed (%ld)", ret);
> + return ret;
> + }
> + kfree_skb(skb);
> +
> + return 0;
> +}
> +
> #define QCA_DFU_PACKET_LEN 4096
>
> #define QCA_GET_TARGET_VERSION 0x09
> @@ -3428,6 +3453,8 @@ static const struct qca_device_info qca_devices_table[] = {
> { 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
> { 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
> { 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
> + { 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */
> + { 0x00130200, 40, 4, 18 } /* WCN6855 2.0 */
> };
>
> static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
> @@ -3529,8 +3556,8 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
> {
> struct qca_rampatch_version *rver;
> const struct firmware *fw;
> - u32 ver_rom, ver_patch;
> - u16 rver_rom, rver_patch;
> + u32 ver_rom, ver_patch, rver_rom;
> + u16 rver_rom_low, rver_rom_high, rver_patch;
> char fwname[64];
> int err;
>
> @@ -3549,9 +3576,16 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
> bt_dev_info(hdev, "using rampatch file: %s", fwname);
>
> rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
> - rver_rom = le16_to_cpu(rver->rom_version);
> + rver_rom_low = le16_to_cpu(rver->rom_version);
> rver_patch = le16_to_cpu(rver->patch_version);
>
> + if (ver_rom & ~0xffffU) {
> + rver_rom_high = le16_to_cpu(*(__le16 *)(fw->data + 16));
> + rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);
> + } else {
> + rver_rom = (__force u32)rver_rom_low;
> + }
> +

I don’t get this. Is anything wrong with get_unaligned_le32 etc.?

My brain just hurts with your casting and pointer magic. Maybe the whole rver logic needs a clean up first.

Regards

Marcel

2020-09-14 14:18:07

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH v1] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

Hi Rocky,

>>> This patch add support for WCN6855 i.e. patch and nvm download
>>> support.
>>> Signed-off-by: Rocky Liao <[email protected]>
>>> ---
>>> drivers/bluetooth/btusb.c | 42 +++++++++++++++++++++++++++++++++++----
>>> 1 file changed, 38 insertions(+), 4 deletions(-)
>>> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
>>> index fe80588c7bd3..e51e754ca9b8 100644
>>> --- a/drivers/bluetooth/btusb.c
>>> +++ b/drivers/bluetooth/btusb.c
>>> @@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
>>> #define BTUSB_MEDIATEK 0x200000
>>> #define BTUSB_WIDEBAND_SPEECH 0x400000
>>> #define BTUSB_VALID_LE_STATES 0x800000
>>> +#define BTUSB_QCA_WCN6855 0x1000000
>>> static const struct usb_device_id btusb_table[] = {
>>> /* Generic Bluetooth USB device */
>>> @@ -273,6 +274,10 @@ static const struct usb_device_id blacklist_table[] = {
>>> { USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
>>> { USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
>>> + /* QCA WCN6855 chipset */
>>> + { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
>>> + BTUSB_WIDEBAND_SPEECH },
>>> +
>>> /* Broadcom BCM2035 */
>>> { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
>>> { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
>>> @@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
>>> return 0;
>>> }
>>> +static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
>>> + const bdaddr_t *bdaddr)
>>> +{
>>> + struct sk_buff *skb;
>>> + u8 buf[6];
>>> + long ret;
>>> +
>>> + memcpy(buf, bdaddr, sizeof(bdaddr_t));
>>> +
>>> + skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf, HCI_INIT_TIMEOUT);
>>> + if (IS_ERR(skb)) {
>>> + ret = PTR_ERR(skb);
>>> + bt_dev_err(hdev, "Change address command failed (%ld)", ret);
>>> + return ret;
>>> + }
>>> + kfree_skb(skb);
>>> +
>>> + return 0;
>>> +}
>> What is wrong with using qca_set_bdaddr() function.
> WCN6855 is using different VSC to set the bt addr

int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
struct sk_buff *skb;
int err;

skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6, bdaddr,
HCI_EV_VENDOR, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(hdev, "QCA Change address cmd failed (%d)", err);
return err;
}

kfree_skb(skb);

return 0;
}
EXPORT_SYMBOL_GPL(qca_set_bdaddr);

I see that the other command is using HCI_EV_VENDOR, but is that on purpose or an accident? Might want to confirm with the btmon trace.

Regards

Marcel

2020-09-15 09:30:39

by Rocky Liao

[permalink] [raw]
Subject: Re: [PATCH v2] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

Hi Marcel,

在 2020-09-14 21:28,Marcel Holtmann 写道:
> Hi Rocky,
>
>> This patch add support for WCN6855 i.e. patch and nvm download
>> support.
>>
>> Signed-off-by: Rocky Liao <[email protected]>
>> ---
>> drivers/bluetooth/btusb.c | 50 ++++++++++++++++++++++++++++++++++-----
>> 1 file changed, 44 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
>> index fe80588c7bd3..789e8d5e829e 100644
>> --- a/drivers/bluetooth/btusb.c
>> +++ b/drivers/bluetooth/btusb.c
>> @@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
>> #define BTUSB_MEDIATEK 0x200000
>> #define BTUSB_WIDEBAND_SPEECH 0x400000
>> #define BTUSB_VALID_LE_STATES 0x800000
>> +#define BTUSB_QCA_WCN6855 0x1000000
>>
>> static const struct usb_device_id btusb_table[] = {
>> /* Generic Bluetooth USB device */
>> @@ -273,6 +274,10 @@ static const struct usb_device_id
>> blacklist_table[] = {
>> { USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
>> { USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
>>
>> + /* QCA WCN6855 chipset */
>> + { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
>> + BTUSB_WIDEBAND_SPEECH },
>> +
>> /* Broadcom BCM2035 */
>> { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
>> { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
>> @@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct
>> hci_dev *hdev,
>> return 0;
>> }
>>
>> +static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
>> + const bdaddr_t *bdaddr)
>> +{
>> + struct sk_buff *skb;
>> + u8 buf[6];
>> + long ret;
>> +
>> + memcpy(buf, bdaddr, sizeof(bdaddr_t));
>> +
>> + skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf,
>> HCI_INIT_TIMEOUT);
>> + if (IS_ERR(skb)) {
>> + ret = PTR_ERR(skb);
>> + bt_dev_err(hdev, "Change address command failed (%ld)", ret);
>> + return ret;
>> + }
>> + kfree_skb(skb);
>> +
>> + return 0;
>> +}
>> +
>> #define QCA_DFU_PACKET_LEN 4096
>>
>> #define QCA_GET_TARGET_VERSION 0x09
>> @@ -3428,6 +3453,8 @@ static const struct qca_device_info
>> qca_devices_table[] = {
>> { 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
>> { 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
>> { 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
>> + { 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */
>> + { 0x00130200, 40, 4, 18 } /* WCN6855 2.0 */
>> };
>>
>> static int btusb_qca_send_vendor_req(struct usb_device *udev, u8
>> request,
>> @@ -3529,8 +3556,8 @@ static int btusb_setup_qca_load_rampatch(struct
>> hci_dev *hdev,
>> {
>> struct qca_rampatch_version *rver;
>> const struct firmware *fw;
>> - u32 ver_rom, ver_patch;
>> - u16 rver_rom, rver_patch;
>> + u32 ver_rom, ver_patch, rver_rom;
>> + u16 rver_rom_low, rver_rom_high, rver_patch;
>> char fwname[64];
>> int err;
>>
>> @@ -3549,9 +3576,16 @@ static int btusb_setup_qca_load_rampatch(struct
>> hci_dev *hdev,
>> bt_dev_info(hdev, "using rampatch file: %s", fwname);
>>
>> rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
>> - rver_rom = le16_to_cpu(rver->rom_version);
>> + rver_rom_low = le16_to_cpu(rver->rom_version);
>> rver_patch = le16_to_cpu(rver->patch_version);
>>
>> + if (ver_rom & ~0xffffU) {
>> + rver_rom_high = le16_to_cpu(*(__le16 *)(fw->data + 16));
>> + rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);
>> + } else {
>> + rver_rom = (__force u32)rver_rom_low;
>> + }
>> +
>
> I don’t get this. Is anything wrong with get_unaligned_le32 etc.?
>
> My brain just hurts with your casting and pointer magic. Maybe the
> whole rver logic needs a clean up first.
>
It's not a 4 bytes le data, for example the version stream is 0x13,
0x00, 0x00, 0x01 and we need to convert it to 0x00130100. So we have to
convert it to 2 u16 value then combine them to a u32.

> Regards
>
> Marcel

2020-09-16 02:03:35

by Rocky Liao

[permalink] [raw]
Subject: Re: [PATCH v2] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

Hi Marcel,

在 2020-09-15 21:57,Marcel Holtmann 写道:
> Hi Rocky,
>
>>>> This patch add support for WCN6855 i.e. patch and nvm download
>>>> support.
>>>> Signed-off-by: Rocky Liao <[email protected]>
>>>> ---
>>>> drivers/bluetooth/btusb.c | 50
>>>> ++++++++++++++++++++++++++++++++++-----
>>>> 1 file changed, 44 insertions(+), 6 deletions(-)
>>>> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
>>>> index fe80588c7bd3..789e8d5e829e 100644
>>>> --- a/drivers/bluetooth/btusb.c
>>>> +++ b/drivers/bluetooth/btusb.c
>>>> @@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
>>>> #define BTUSB_MEDIATEK 0x200000
>>>> #define BTUSB_WIDEBAND_SPEECH 0x400000
>>>> #define BTUSB_VALID_LE_STATES 0x800000
>>>> +#define BTUSB_QCA_WCN6855 0x1000000
>>>> static const struct usb_device_id btusb_table[] = {
>>>> /* Generic Bluetooth USB device */
>>>> @@ -273,6 +274,10 @@ static const struct usb_device_id
>>>> blacklist_table[] = {
>>>> { USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
>>>> { USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
>>>> + /* QCA WCN6855 chipset */
>>>> + { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
>>>> + BTUSB_WIDEBAND_SPEECH },
>>>> +
>>>> /* Broadcom BCM2035 */
>>>> { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
>>>> { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
>>>> @@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct
>>>> hci_dev *hdev,
>>>> return 0;
>>>> }
>>>> +static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
>>>> + const bdaddr_t *bdaddr)
>>>> +{
>>>> + struct sk_buff *skb;
>>>> + u8 buf[6];
>>>> + long ret;
>>>> +
>>>> + memcpy(buf, bdaddr, sizeof(bdaddr_t));
>>>> +
>>>> + skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf,
>>>> HCI_INIT_TIMEOUT);
>>>> + if (IS_ERR(skb)) {
>>>> + ret = PTR_ERR(skb);
>>>> + bt_dev_err(hdev, "Change address command failed (%ld)", ret);
>>>> + return ret;
>>>> + }
>>>> + kfree_skb(skb);
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> #define QCA_DFU_PACKET_LEN 4096
>>>> #define QCA_GET_TARGET_VERSION 0x09
>>>> @@ -3428,6 +3453,8 @@ static const struct qca_device_info
>>>> qca_devices_table[] = {
>>>> { 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
>>>> { 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
>>>> { 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
>>>> + { 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */
>>>> + { 0x00130200, 40, 4, 18 } /* WCN6855 2.0 */
>>>> };
>>>> static int btusb_qca_send_vendor_req(struct usb_device *udev, u8
>>>> request,
>>>> @@ -3529,8 +3556,8 @@ static int
>>>> btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
>>>> {
>>>> struct qca_rampatch_version *rver;
>>>> const struct firmware *fw;
>>>> - u32 ver_rom, ver_patch;
>>>> - u16 rver_rom, rver_patch;
>>>> + u32 ver_rom, ver_patch, rver_rom;
>>>> + u16 rver_rom_low, rver_rom_high, rver_patch;
>>>> char fwname[64];
>>>> int err;
>>>> @@ -3549,9 +3576,16 @@ static int
>>>> btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
>>>> bt_dev_info(hdev, "using rampatch file: %s", fwname);
>>>> rver = (struct qca_rampatch_version *)(fw->data +
>>>> info->ver_offset);
>>>> - rver_rom = le16_to_cpu(rver->rom_version);
>>>> + rver_rom_low = le16_to_cpu(rver->rom_version);
>>>> rver_patch = le16_to_cpu(rver->patch_version);
>>>> + if (ver_rom & ~0xffffU) {
>>>> + rver_rom_high = le16_to_cpu(*(__le16 *)(fw->data + 16));
>>>> + rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);
>>>> + } else {
>>>> + rver_rom = (__force u32)rver_rom_low;
>>>> + }
>>>> +
>>> I don’t get this. Is anything wrong with get_unaligned_le32 etc.?
>>> My brain just hurts with your casting and pointer magic. Maybe the
>>> whole rver logic needs a clean up first.
>> It's not a 4 bytes le data, for example the version stream is 0x13,
>> 0x00, 0x00, 0x01 and we need to convert it to 0x00130100. So we have
>> to convert it to 2 u16 value then combine them to a u32.
>
> what is it then? Is it big endian formatted. If it is not a 32-bit
> value, then don’t store it as one.
>
OK, let me refine the patch to a more readable format.

> Regards
>
> Marcel

2020-09-25 09:03:18

by Rocky Liao

[permalink] [raw]
Subject: Re: [PATCH v1] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

Hi Marcel,

在 2020-09-14 21:25,Marcel Holtmann 写道:
> Hi Rocky,
>
>>>> This patch add support for WCN6855 i.e. patch and nvm download
>>>> support.
>>>> Signed-off-by: Rocky Liao <[email protected]>
>>>> ---
>>>> drivers/bluetooth/btusb.c | 42
>>>> +++++++++++++++++++++++++++++++++++----
>>>> 1 file changed, 38 insertions(+), 4 deletions(-)
>>>> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
>>>> index fe80588c7bd3..e51e754ca9b8 100644
>>>> --- a/drivers/bluetooth/btusb.c
>>>> +++ b/drivers/bluetooth/btusb.c
>>>> @@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;
>>>> #define BTUSB_MEDIATEK 0x200000
>>>> #define BTUSB_WIDEBAND_SPEECH 0x400000
>>>> #define BTUSB_VALID_LE_STATES 0x800000
>>>> +#define BTUSB_QCA_WCN6855 0x1000000
>>>> static const struct usb_device_id btusb_table[] = {
>>>> /* Generic Bluetooth USB device */
>>>> @@ -273,6 +274,10 @@ static const struct usb_device_id
>>>> blacklist_table[] = {
>>>> { USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
>>>> { USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
>>>> + /* QCA WCN6855 chipset */
>>>> + { USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
>>>> + BTUSB_WIDEBAND_SPEECH },
>>>> +
>>>> /* Broadcom BCM2035 */
>>>> { USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
>>>> { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
>>>> @@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct
>>>> hci_dev *hdev,
>>>> return 0;
>>>> }
>>>> +static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
>>>> + const bdaddr_t *bdaddr)
>>>> +{
>>>> + struct sk_buff *skb;
>>>> + u8 buf[6];
>>>> + long ret;
>>>> +
>>>> + memcpy(buf, bdaddr, sizeof(bdaddr_t));
>>>> +
>>>> + skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf,
>>>> HCI_INIT_TIMEOUT);
>>>> + if (IS_ERR(skb)) {
>>>> + ret = PTR_ERR(skb);
>>>> + bt_dev_err(hdev, "Change address command failed (%ld)", ret);
>>>> + return ret;
>>>> + }
>>>> + kfree_skb(skb);
>>>> +
>>>> + return 0;
>>>> +}
>>> What is wrong with using qca_set_bdaddr() function.
>> WCN6855 is using different VSC to set the bt addr
>
> int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
>
> {
>
> struct sk_buff *skb;
>
> int err;
>
>
>
> skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6,
> bdaddr,
> HCI_EV_VENDOR, HCI_INIT_TIMEOUT);
>
> if (IS_ERR(skb)) {
>
> err = PTR_ERR(skb);
>
> bt_dev_err(hdev, "QCA Change address cmd failed (%d)",
> err);
> return err;
>
> }
>
>
>
> kfree_skb(skb);
>
>
>
> return 0;
>
> }
>
> EXPORT_SYMBOL_GPL(qca_set_bdaddr);
>
> I see that the other command is using HCI_EV_VENDOR, but is that on
> purpose or an accident? Might want to confirm with the btmon trace.
>

You are right this is an accident, this command for WCN6855 have command
complete event return. I will modify this in next patch update. Below is
the btmon log:

Bluetooth monitor ver 5.48
= Note: Linux version 5.8.0-rc6-hsp-upstream+ (x86_64)
0.729933
= Note: Bluetooth subsystem version 2.22
0.729934
= New Index: 00:00:00:00:5A:AD (Primary,USB,hci1) [hci1]
0.729935
= Open Index: 00:00:00:00:5A:AD [hci1]
0.729935
= Index Info: 00:00:00:00:5A:AD (Qualcomm) [hci1]
0.729935
= New Index: 00:00:00:00:00:00 (Primary,UART,hci0) [hci0]
0.729936
@ MGMT Open: bluetoothd (privileged) version 1.18 {0x0002}
0.729936
@ MGMT Open: bluetoothd (privileged) version 1.18 {0x0001}
0.729936
@ MGMT Open: btmon (privileged) version 1.18 {0x0003}
0.729945
@ RAW Open: hcitool (privileged) version 2.22 {0x0004}
122.556176
@ RAW Close: hcitool {0x0004}
122.556200
@ RAW Open: hcitool (privileged) version 2.22 {0x0004}
122.556219
@ RAW Close: hcitool {0x0004}
122.556223
@ RAW Open: hcitool (privileged) version 2.22 {0x0004} [hci1]
122.556242
< HCI Command: Vendor (0x3f|0x0014) plen 6 #1 [hci1]
122.556643
01 02 03 04 05 06 ......
> HCI Event: Command Complete (0x0e) plen 4 #2 [hci1]
> 122.675312
Vendor (0x3f|0x0014) ncmd 1
Status: Success (0x00)
@ RAW Close: hcitool {0x0004} [hci1]
122.675545
@ RAW Open: hcitool (privileged) version 2.22 {0x0004}
124.528658
@ RAW Close: hcitool {0x0004}
124.528683
@ RAW Open: hcitool (privileged) version 2.22 {0x0004}
124.528703
@ RAW Close: hcitool {0x0004}
124.528708
@ RAW Open: hcitool (privileged) version 2.22 {0x0004} [hci1]
124.528760
< HCI Command: Read BD ADDR (0x04|0x0009) plen 0 #3 [hci1]
124.529024
> HCI Event: Command Complete (0x0e) plen 10 #4 [hci1]
> 124.530311
Read BD ADDR (0x04|0x0009) ncmd 1
Status: Success (0x00)
Address: 01:02:03:04:05:06 (OUI 01-02-03)
@ RAW Close: hcitool {0x0004} [hci1]
124.530509



> Regards
>
> Marcel