* [PATCH] mesh: Fix Command Disallowed on random address change in generic IO
@ 2026-09-14 9:15 Aurélien Rivet
2026-09-14 14:35 ` bluez.test.bot
2026-09-29 18:55 ` bluez.test.bot
0 siblings, 2 replies; 4+ messages in thread
From: Aurélien Rivet @ 2026-09-14 9:15 UTC (permalink / raw)
To: linux-bluetooth
send_cancel_done() issues LE Set Random Address at the end of every
burst of ADVs. The controller rejects that command with Command
Disallowed (0x0c) while scanning is enabled, per Core Spec, Vol 4,
Part E, Section 7.8.4, so the address never rotates as long as any
scan is registered, such as a provisioner discovering unprovisioned
devices.
Pause scanning around the address change and resume it afterwards,
mirroring the disable/re-enable sequence restart_scan() already uses.
When no scan is registered there is nothing to pause, so the address
change is issued directly.
Confirmed with btmon on a Raspberry Pi built-in controller: over a
60 s capture, 12 rotations about 5 s apart, each one LE Set Scan
Enable(disable) -> LE Set Random Address -> LE Set Scan
Enable(enable), every command completing with Success and every
rotation programming a distinct address. No Command Disallowed
anywhere in the capture, where the address change previously failed
on every attempt. Scanning is suspended for 1.2 ms to 2.6 ms per
rotation, which mesh retransmissions absorb.
Assisted-by: Claude:claude-sonnet-5
Assisted-by: Claude:claude-opus-5
---
mesh/mesh-io-generic.c | 68 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 62 insertions(+), 6 deletions(-)
diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
index df1450ebe..7f65ec4f2 100644
--- a/mesh/mesh-io-generic.c
+++ b/mesh/mesh-io-generic.c
@@ -39,6 +39,7 @@ struct mesh_io_private {
struct tx_pkt *tx;
uint16_t interval;
bool sending;
+ bool scan_paused;
bool active;
};
@@ -454,22 +455,77 @@ static bool dev_caps(struct mesh_io *io, struct mesh_io_caps *caps)
return true;
}
-static void send_cancel_done(const void *buf, uint8_t size,
+static void set_random_address_rsp(const void *buf, uint8_t size,
void *user_data)
{
struct mesh_io_private *pvt = user_data;
- struct bt_hci_cmd_le_set_random_address cmd;
+ uint8_t status = *((uint8_t *) buf);
- if (!pvt)
+ if (status)
+ l_error("LE Set Random Address failed (0x%02x)", status);
+
+ if (!pvt->scan_paused)
return;
- pvt->sending = false;
+ pvt->scan_paused = false;
+
+ /* Only resume if a scan is still wanted: recv_deregister() may have
+ * stopped it while the address change was in flight.
+ */
+ if (!l_queue_isempty(pvt->io->rx_regs))
+ set_recv_scan_enable(NULL, 0, pvt);
+}
+
+static void send_set_random_address(struct mesh_io_private *pvt)
+{
+ struct bt_hci_cmd_le_set_random_address cmd;
- /* At end of any burst of ADVs, change random address */
l_getrandom(cmd.addr, 6);
cmd.addr[5] |= 0xc0;
bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_RANDOM_ADDRESS,
- &cmd, sizeof(cmd), NULL, NULL, NULL);
+ &cmd, sizeof(cmd), set_random_address_rsp,
+ pvt, NULL);
+}
+
+static void scan_disable_for_addr_change_rsp(const void *buf, uint8_t size,
+ void *user_data)
+{
+ struct mesh_io_private *pvt = user_data;
+ uint8_t status = *((uint8_t *) buf);
+
+ if (status)
+ l_error("LE Scan disable failed (0x%02x)", status);
+
+ send_set_random_address(pvt);
+}
+
+static void send_cancel_done(const void *buf, uint8_t size,
+ void *user_data)
+{
+ struct mesh_io_private *pvt = user_data;
+ struct bt_hci_cmd_le_set_scan_enable cmd;
+
+ if (!pvt)
+ return;
+
+ pvt->sending = false;
+
+ /* At end of any burst of ADVs, change random address. The controller
+ * rejects LE Set Random Address with Command Disallowed while
+ * scanning is enabled (Core Spec, Vol 4, Part E, Section 7.8.4).
+ */
+ pvt->scan_paused = !l_queue_isempty(pvt->io->rx_regs);
+
+ if (!pvt->scan_paused) {
+ send_set_random_address(pvt);
+ return;
+ }
+
+ cmd.enable = 0x00; /* Disable scanning */
+ cmd.filter_dup = 0x00; /* Report duplicates */
+ bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+ &cmd, sizeof(cmd),
+ scan_disable_for_addr_change_rsp, pvt, NULL);
}
static void send_cancel(struct mesh_io_private *pvt)
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* RE: mesh: Fix Command Disallowed on random address change in generic IO
2026-09-14 9:15 [PATCH] mesh: Fix Command Disallowed on random address change in generic IO Aurélien Rivet
@ 2026-09-14 14:35 ` bluez.test.bot
2026-09-29 18:55 ` bluez.test.bot
1 sibling, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-09-14 14:35 UTC (permalink / raw)
To: linux-bluetooth, aurelienrivet
[-- Attachment #1: Type: text/plain, Size: 964 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1164346/
---Test result---
Test Summary:
CheckPatch PASS 0.46 seconds
GitLint PASS 0.30 seconds
BuildEll PASS 18.17 seconds
BluezMake PASS 311.80 seconds
MakeCheck PASS 0.88 seconds
MakeDistcheck PASS 134.21 seconds
CheckValgrind PASS 137.30 seconds
CheckSmatch PASS 233.12 seconds
bluezmakeextell PASS 88.27 seconds
IncrementalBuild PASS 312.79 seconds
ScanBuild PASS 927.70 seconds
https://github.com/bluez/bluez/pull/2527
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: mesh: Fix Command Disallowed on random address change in generic IO
2026-09-14 9:15 [PATCH] mesh: Fix Command Disallowed on random address change in generic IO Aurélien Rivet
2026-09-14 14:35 ` bluez.test.bot
@ 2026-09-29 18:55 ` bluez.test.bot
1 sibling, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-09-29 18:55 UTC (permalink / raw)
To: linux-bluetooth, aurelienrivet
[-- Attachment #1: Type: text/plain, Size: 707 bytes --]
This is an automated email and please do not reply to this email.
Dear Submitter,
This series was picked up by the CI more than 2 weeks ago and the pull
request created for it is still open, which means the series was never
applied to the tree.
Series: mesh: Fix Command Disallowed on random address change in generic IO
Pull Request: https://github.com/bluez/bluez/pull/2527
Created: 2026-09-14 13:56:59+00:00
The pull request has been closed and no further action is taken on this
series.
If the change should still be considered, it must be resent to the Linux
Bluetooth mailing list (linux-bluetooth@vger.kernel.org) so that it is
picked up again.
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] mesh: Fix Command Disallowed on random address change in generic IO
@ 2026-09-30 14:21 Aurélien Rivet
2026-09-30 20:20 ` bluez.test.bot
0 siblings, 1 reply; 4+ messages in thread
From: Aurélien Rivet @ 2026-09-30 14:21 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Aurélien Rivet
send_cancel_done() issues LE Set Random Address at the end of every
burst of ADVs. The controller rejects that command with Command
Disallowed (0x0c) while scanning is enabled, per Core Spec, Vol 4,
Part E, Section 7.8.4, so the address never rotates as long as any
scan is registered, such as a provisioner discovering unprovisioned
devices.
Pause scanning around the address change and resume it afterwards,
mirroring the disable/re-enable sequence restart_scan() already uses.
When no scan is registered there is nothing to pause, so the address
change is issued directly.
Confirmed with btmon on a Raspberry Pi built-in controller: over a
60 s capture, 12 rotations about 5 s apart, each one LE Set Scan
Enable(disable) -> LE Set Random Address -> LE Set Scan
Enable(enable), every command completing with Success and every
rotation programming a distinct address. No Command Disallowed
anywhere in the capture, where the address change previously failed
on every attempt. Scanning is suspended for 1.2 ms to 2.6 ms per
rotation, which mesh retransmissions absorb.
Assisted-by: Claude:claude-sonnet-5
Assisted-by: Claude:claude-opus-5
---
Resend: the original submission was archived by the CI bot after two
weeks without review, per the automated notice on the thread. The
patch is unchanged, rebased onto current master.
Original thread:
https://lore.kernel.org/linux-bluetooth/PAXP250MB0544B307EB9802855B711F71CBBB2@PAXP250MB0544.EURP250.PROD.OUTLOOK.COM/
mesh/mesh-io-generic.c | 68 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 62 insertions(+), 6 deletions(-)
diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
index df1450ebe..7f65ec4f2 100644
--- a/mesh/mesh-io-generic.c
+++ b/mesh/mesh-io-generic.c
@@ -39,6 +39,7 @@ struct mesh_io_private {
struct tx_pkt *tx;
uint16_t interval;
bool sending;
+ bool scan_paused;
bool active;
};
@@ -454,22 +455,77 @@ static bool dev_caps(struct mesh_io *io, struct mesh_io_caps *caps)
return true;
}
-static void send_cancel_done(const void *buf, uint8_t size,
+static void set_random_address_rsp(const void *buf, uint8_t size,
void *user_data)
{
struct mesh_io_private *pvt = user_data;
- struct bt_hci_cmd_le_set_random_address cmd;
+ uint8_t status = *((uint8_t *) buf);
- if (!pvt)
+ if (status)
+ l_error("LE Set Random Address failed (0x%02x)", status);
+
+ if (!pvt->scan_paused)
return;
- pvt->sending = false;
+ pvt->scan_paused = false;
+
+ /* Only resume if a scan is still wanted: recv_deregister() may have
+ * stopped it while the address change was in flight.
+ */
+ if (!l_queue_isempty(pvt->io->rx_regs))
+ set_recv_scan_enable(NULL, 0, pvt);
+}
+
+static void send_set_random_address(struct mesh_io_private *pvt)
+{
+ struct bt_hci_cmd_le_set_random_address cmd;
- /* At end of any burst of ADVs, change random address */
l_getrandom(cmd.addr, 6);
cmd.addr[5] |= 0xc0;
bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_RANDOM_ADDRESS,
- &cmd, sizeof(cmd), NULL, NULL, NULL);
+ &cmd, sizeof(cmd), set_random_address_rsp,
+ pvt, NULL);
+}
+
+static void scan_disable_for_addr_change_rsp(const void *buf, uint8_t size,
+ void *user_data)
+{
+ struct mesh_io_private *pvt = user_data;
+ uint8_t status = *((uint8_t *) buf);
+
+ if (status)
+ l_error("LE Scan disable failed (0x%02x)", status);
+
+ send_set_random_address(pvt);
+}
+
+static void send_cancel_done(const void *buf, uint8_t size,
+ void *user_data)
+{
+ struct mesh_io_private *pvt = user_data;
+ struct bt_hci_cmd_le_set_scan_enable cmd;
+
+ if (!pvt)
+ return;
+
+ pvt->sending = false;
+
+ /* At end of any burst of ADVs, change random address. The controller
+ * rejects LE Set Random Address with Command Disallowed while
+ * scanning is enabled (Core Spec, Vol 4, Part E, Section 7.8.4).
+ */
+ pvt->scan_paused = !l_queue_isempty(pvt->io->rx_regs);
+
+ if (!pvt->scan_paused) {
+ send_set_random_address(pvt);
+ return;
+ }
+
+ cmd.enable = 0x00; /* Disable scanning */
+ cmd.filter_dup = 0x00; /* Report duplicates */
+ bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+ &cmd, sizeof(cmd),
+ scan_disable_for_addr_change_rsp, pvt, NULL);
}
static void send_cancel(struct mesh_io_private *pvt)
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-30 20:20 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-14 9:15 [PATCH] mesh: Fix Command Disallowed on random address change in generic IO Aurélien Rivet
2026-09-14 14:35 ` bluez.test.bot
2026-09-29 18:55 ` bluez.test.bot
-- strict thread matches above, loose matches on Subject: below --
2026-09-30 14:21 [PATCH] " Aurélien Rivet
2026-09-30 20:20 ` bluez.test.bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox