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@xxxxxxxxxx> Signed-off-by: Johan Korsnes <johan.korsnes@xxxxxxxxxxxxx> Signed-off-by: Kristian Husevåg Krohn <kristian.krohn@xxxxxxxxxxxxx> Tested-by: Neeraj Sanjay Kale <neeraj.sanjaykale@xxxxxxx> Signed-off-by: Neeraj Sanjay Kale <neeraj.sanjaykale@xxxxxxx> --- drivers/bluetooth/btnxpuart.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c index 1230045d78a5..deb546a4e664 100644 --- a/drivers/bluetooth/btnxpuart.c +++ b/drivers/bluetooth/btnxpuart.c @@ -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) { @@ -1547,8 +1575,12 @@ 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); + 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; -- 2.25.1