diff mbox series

[v5,2/2] Bluetooth: btnxpuart: Add support for set BD address

Message ID 20250220114157.232997-2-neeraj.sanjaykale@nxp.com (mailing list archive)
State New
Headers show
Series [v5,1/2] dt-bindings: net: bluetooth: nxp: Add support to set BD address | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
tedd_an/SubjectPrefix success Gitlint PASS

Commit Message

Neeraj Sanjay Kale Feb. 20, 2025, 11:41 a.m. UTC
This adds support for setting BD address during hci registration. NXP
FW does not allow vendor commands unless it receives a reset command
after FW download and initialization done.
As a workaround, the .set_bdaddr callback function will first send the
HCI reset command, followed by the actual vendor command to set BD
address.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Signed-off-by: Johan Korsnes <johan.korsnes@remarkable.no>
Signed-off-by: Kristian Husevåg Krohn <kristian.krohn@remarkable.no>
Tested-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
---
v4: hci0 interface shows RAW mode if 'local-bd-address' not defined and
    HCI_QUIRK_USE_BDADDR_PROPERTY is set. Add Quirk only if device tree
    property 'local-bd-address' found. (Neeraj)
v5: Initialize local variable ba, update Copywrite year. (Kristian)
---
 drivers/bluetooth/btnxpuart.c | 39 ++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

Comments

Paul Menzel Feb. 20, 2025, 12:04 p.m. UTC | #1
Dear Neeraj,


Thank you for your patch. In the summary/title you could use *to set* or 
*for setting*.

Am 20.02.25 um 12:41 schrieb Neeraj Sanjay Kale:
> This adds support for setting BD address during hci registration. NXP
> FW does not allow vendor commands unless it receives a reset command
> after FW download and initialization done.

I’d add a blank line between paragraphs.

> As a workaround, the .set_bdaddr callback function will first send the
> HCI reset command, followed by the actual vendor command to set BD
> address.

Where is the command 0xfc22 documented?

How did you verify this? Maybe document the commands how to set the BD 
address, and how to verify it.

Does Linux log new messages with your patch?

> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> Signed-off-by: Johan Korsnes <johan.korsnes@remarkable.no>
> Signed-off-by: Kristian Husevåg Krohn <kristian.krohn@remarkable.no>

The last name has some wrong character.

> Tested-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
> Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
> ---
> v4: hci0 interface shows RAW mode if 'local-bd-address' not defined and
>      HCI_QUIRK_USE_BDADDR_PROPERTY is set. Add Quirk only if device tree
>      property 'local-bd-address' found. (Neeraj)
> v5: Initialize local variable ba, update Copywrite year. (Kristian)
> ---
>   drivers/bluetooth/btnxpuart.c | 39 ++++++++++++++++++++++++++++++++++-
>   1 file changed, 38 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
> index 1230045d78a5..dd9161bfd52c 100644
> --- a/drivers/bluetooth/btnxpuart.c
> +++ b/drivers/bluetooth/btnxpuart.c
> @@ -1,7 +1,7 @@
>   // SPDX-License-Identifier: GPL-2.0-or-later
>   /*
>    *  NXP Bluetooth driver
> - *  Copyright 2023 NXP
> + *  Copyright 2023-2025 NXP
>    */
>   
>   #include <linux/module.h>
> @@ -1197,6 +1197,34 @@ static int nxp_set_ind_reset(struct hci_dev *hdev, void *data)
>   	return hci_recv_frame(hdev, skb);
>   }
>   
> +static int nxp_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
> +{
> +	u8 data[8] = { 0xfe, 0x06, 0, 0, 0, 0, 0, 0 };
> +	struct sk_buff *skb;
> +	int err;
> +
> +	memcpy(data + 2, bdaddr, 6);
> +

Add a comment about the firmware limitation/requirement?

> +	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
> +	if (IS_ERR(skb)) {
> +		err = PTR_ERR(skb);
> +		bt_dev_err(hdev, "Reset before setting local-bd-addr failed (%ld)",
> +			   PTR_ERR(skb));
> +		return err;
> +	}
> +	kfree_skb(skb);
> +
> +	skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(data), data, HCI_CMD_TIMEOUT);
> +	if (IS_ERR(skb)) {
> +		err = PTR_ERR(skb);
> +		bt_dev_err(hdev, "Changing device address failed (%d)", err);
> +		return err;
> +	}
> +	kfree_skb(skb);
> +
> +	return 0;
> +}
> +
>   /* NXP protocol */
>   static int nxp_setup(struct hci_dev *hdev)
>   {
> @@ -1500,6 +1528,7 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
>   {
>   	struct hci_dev *hdev;
>   	struct btnxpuart_dev *nxpdev;
> +	bdaddr_t ba = {0};
>   
>   	nxpdev = devm_kzalloc(&serdev->dev, sizeof(*nxpdev), GFP_KERNEL);
>   	if (!nxpdev)
> @@ -1547,8 +1576,16 @@ static int nxp_serdev_probe(struct serdev_device *serdev)
>   	hdev->send  = nxp_enqueue;
>   	hdev->hw_error = nxp_hw_err;
>   	hdev->shutdown = nxp_shutdown;
> +	hdev->set_bdaddr = nxp_set_bdaddr;
> +
>   	SET_HCIDEV_DEV(hdev, &serdev->dev);
>   
> +	device_property_read_u8_array(&nxpdev->serdev->dev,
> +				      "local-bd-address",
> +				      (u8 *)&ba, sizeof(ba));
> +	if (bacmp(&ba, BDADDR_ANY))
> +		set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);

Please elaborate in the commit message, why the quirk is needed.

> +
>   	if (hci_register_dev(hdev) < 0) {
>   		dev_err(&serdev->dev, "Can't register HCI device\n");
>   		goto probe_fail;


Kind regards,

Paul
diff mbox series

Patch

diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 1230045d78a5..dd9161bfd52c 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -1,7 +1,7 @@ 
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  *  NXP Bluetooth driver
- *  Copyright 2023 NXP
+ *  Copyright 2023-2025 NXP
  */
 
 #include <linux/module.h>
@@ -1197,6 +1197,34 @@  static int nxp_set_ind_reset(struct hci_dev *hdev, void *data)
 	return hci_recv_frame(hdev, skb);
 }
 
+static int nxp_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+	u8 data[8] = { 0xfe, 0x06, 0, 0, 0, 0, 0, 0 };
+	struct sk_buff *skb;
+	int err;
+
+	memcpy(data + 2, bdaddr, 6);
+
+	skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		err = PTR_ERR(skb);
+		bt_dev_err(hdev, "Reset before setting local-bd-addr failed (%ld)",
+			   PTR_ERR(skb));
+		return err;
+	}
+	kfree_skb(skb);
+
+	skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(data), data, HCI_CMD_TIMEOUT);
+	if (IS_ERR(skb)) {
+		err = PTR_ERR(skb);
+		bt_dev_err(hdev, "Changing device address failed (%d)", err);
+		return err;
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
 /* NXP protocol */
 static int nxp_setup(struct hci_dev *hdev)
 {
@@ -1500,6 +1528,7 @@  static int nxp_serdev_probe(struct serdev_device *serdev)
 {
 	struct hci_dev *hdev;
 	struct btnxpuart_dev *nxpdev;
+	bdaddr_t ba = {0};
 
 	nxpdev = devm_kzalloc(&serdev->dev, sizeof(*nxpdev), GFP_KERNEL);
 	if (!nxpdev)
@@ -1547,8 +1576,16 @@  static int nxp_serdev_probe(struct serdev_device *serdev)
 	hdev->send  = nxp_enqueue;
 	hdev->hw_error = nxp_hw_err;
 	hdev->shutdown = nxp_shutdown;
+	hdev->set_bdaddr = nxp_set_bdaddr;
+
 	SET_HCIDEV_DEV(hdev, &serdev->dev);
 
+	device_property_read_u8_array(&nxpdev->serdev->dev,
+				      "local-bd-address",
+				      (u8 *)&ba, sizeof(ba));
+	if (bacmp(&ba, BDADDR_ANY))
+		set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
+
 	if (hci_register_dev(hdev) < 0) {
 		dev_err(&serdev->dev, "Can't register HCI device\n");
 		goto probe_fail;