Bluetooth: hci_sync: Disable legacy instance's ext adv before setup snapshot

hci_setup_ext_adv_instance_sync(...) only disabled
HCI_OP_LE_SET_EXT_ADV_ENABLE before setup snapshot in case of non-legacy
instances (instance > 0) and never disabled the same for legacy instance
(instance == 0). This would lead to failure in setting ext adv params
with HCI_ERROR_COMMAND_DISALLOWED (0x0c) error like below, when toggling
the discoverable/connectable property of a controller with advertising
enabled.
```
$ btmgmt advertising off
hci0 Set Advertising complete, settings: powered ssp br/edr le
  secure-conn wide-band-speech cis-central cis-peripheral
$ btmgmt connectable on
hci0 Set Connectable complete, settings: powered connectable ssp br/edr
  le secure-conn wide-band-speech cis-central cis-peripheral
$ btmgmt connectable off
hci0 Set Connectable complete, settings: powered ssp br/edr le
  secure-conn wide-band-speech cis-central cis-peripheral

$ btmgmt advertising on
hci0 Set Advertising complete, settings: powered connectable ssp br/edr
  le advertising secure-conn wide-band-speech cis-central cis-peripheral
$ btmgmt connectable on
Set Connectable for hci0 failed with status 0x0a (Busy)
$ btmgmt connectable off
Set Connectable for hci0 failed with status 0x0a (Busy)

$ dmesg
...
[   21.970527] hci0: Opcode 0x2036
[   21.970529] hci0: opcode 0x2036 plen 25
[   21.970537] hci0: skb len 28
[   21.970539] hci0: length 1
[   21.976099] hci0: result 0x0c
[   21.976105] hci0: end: err -16
[   21.976114] Bluetooth: hci0: Opcode 0x2036 failed: -16
```

Signed-off-by: Muhammad Saheed <muhammad.saheed.iam@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Muhammad Saheed
2026-08-05 01:40:51 +05:30
committed by Luiz Augusto von Dentz
parent e3643fbddb
commit 75722cde87

View File

@@ -1150,6 +1150,32 @@ int hci_update_random_address_sync(struct hci_dev *hdev, bool require_privacy,
return 0;
}
static int hci_disable_ext_adv_legacy_instance_sync(struct hci_dev *hdev)
{
struct hci_cp_le_set_ext_adv_enable *cp;
struct hci_cp_ext_adv_set *set;
u8 data[sizeof(*cp) + sizeof(*set) * 1];
u8 size;
if (!hci_dev_test_flag(hdev, HCI_LE_ADV_0))
return 0;
memset(data, 0, sizeof(data));
cp = (void *)data;
set = (void *)cp->data;
cp->num_of_sets = 0x01;
cp->enable = 0x00;
set->handle = 0x00;
size = sizeof(*cp) + sizeof(*set) * cp->num_of_sets;
return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE,
size, data, HCI_CMD_TIMEOUT);
}
static int hci_disable_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)
{
struct hci_cp_le_set_ext_adv_enable *cp;
@@ -1375,6 +1401,10 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)
return -EINVAL;
}
} else {
err = hci_disable_ext_adv_legacy_instance_sync(hdev);
if (err)
return err;
adv = NULL;
}