Commit fixes configuration of the sequence store rate.
KConfig picks up the first met default option.
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
An LE credit-based connection request or response may carry 0 initial
credits. l2cap_chan_tx_give_credits() still set BT_L2CAP_STATUS_OUT for
such a grant, reporting the channel as sendable. An SDU queued before the
peer granted credits then never went out: l2cap_data_pull() dropped the
channel from the ready list for lack of credits, and the first real grant
found the bit already set and did not add the channel back.
Ignore grants of 0 credits, so that the first real grant sets the bit and
resumes TX.
Fixes#121544
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_disable() completes the commands that are still queued when it
closes the HCI transport, but not the one that has been handed to the
driver. A command that another thread sends while bt_disable() waits
for the controller to be reset is transmitted once the controller has
responded to the reset. The transport is then closed before the
response to the command arrives, and its sender waits for the command
timeout, which ends in an assertion.
Complete the command in flight with an error once the transport has
been closed, since nothing can respond to it any more.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
When send_buf() fails, typically because the HCI driver failed to send
the packet, the TX processor gives the connection up and disconnects
it. bt_conn_disconnect() waits for its HCI command, and the TX
processor is what transmits commands: with
CONFIG_BT_TX_PROCESSOR_THREAD, the default, it waits for a command
that it cannot send, holding the host lock, until the command times
out and the Host asserts.
Leave the disconnecting to the Bluetooth workqueue, which can wait for
the command. The connection is flagged for it, and the TX processor
passes a flagged connection over for as long as it is connected, so
that nothing more is sent on it while it is being disconnected. A
connection that is still connected after that, because the command
failed, loses the flag and goes on sending. A disconnected one loses
it too, as a central CIS keeps its object for its next connection.
A BIS is left alone: it cannot be disconnected on its own, and
terminating its BIG would take the other BISes down too. What failed
to go out on it is lost, and sending goes on.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_disable() clears BT_DEV_READY and then waits for the controller to
be reset, with the connections still in place since
commit 78ea662dfe ("Bluetooth: Host: Reset controller before conn
teardown in bt_disable()"). Data sent meanwhile is dropped by
send_buf(), the Host being no longer ready, which the TX processor
takes for a fatal error and answers by disconnecting the connection.
That is a synchronous HCI command issued from the thread that
transmits commands, so it waits for a command that it cannot send, and
does so holding the host lock. With CONFIG_BT_SMP bt_disable() takes
that lock once the controller has been reset and never gets to purge
the command queue, which would have ended the wait: both threads stay
blocked until the command times out and the Host asserts.
Seen with auto-pts, which powers the tester off while a broadcast
source is streaming.
Have the TX processor pass over the connections while the Host is not
ready, before it takes anything from them. What is queued stays where
it is until bt_disable() tears the connections down, as for any
connection that goes away with data queued, or until the Host is ready
again after a failed reset, which now restarts the TX processor.
That replaces the check in send_buf(), which came too late: the upper
layer had by then accounted for the data as handed over, and the
failure was reported to a callback running in the TX processor.
bt_disable() now clears BT_DEV_READY under the host lock, which the TX
processor holds for a whole pass, so that the flag does not change
under a pass that another thread is in the middle of.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_smp_encrypt_change() clears BT_SMP_DIST_LINK_KEY inside its Secure
Connections branch, and the comment there already says these bits double
as the pairing-finished indicator. On the legacy path the bit is never
cleared, so with CONFIG_BT_CLASSIC=y and CONFIG_BT_SMP_SC_PAIR_ONLY=n,
against a peer that sets LinkKey while Secure Connections is not
selected, local_dist keeps BT_SMP_DIST_LINK_KEY after key distribution
has finished. The `if (!smp->local_dist && !smp->remote_dist)` checks
never become true, smp_pairing_complete() is never called, and the SMP
timeout eventually reports the pairing as failed even though the link is
encrypted and the keys were exchanged.
Move the clearing out of the Secure Connections branch, leaving only
SMP_FLAG_DERIVE_LK inside it. A link key can only be derived from a
Secure Connections LTK, so the bit has nothing to signal on the legacy
path. Nothing on air changes.
Signed-off-by: Zhijie Zhong <zhongzhijie1@xiaomi.com>
Assisted-by: Kiro:claude-opus-5
bt_l2cap_br_connless_send() adds the PSM to the buffer before sending,
and returned the buffer to the caller with the PSM still added when
sending failed, although the caller keeps the buffer on error.
Remove the PSM again when sending fails, and document that the caller
gets the buffer back unchanged.
Tested with tests/bluetooth/host_l2cap_br_send on native_sim.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
In basic mode, bt_l2cap_br_send_cb() added the L2CAP header before
checking that the buffer's user data has room for the send callback.
When that check failed, the caller, who keeps the buffer on error, got
it back with the header added, for example from bt_l2cap_chan_send().
Check the user data before adding the header.
Tested with tests/bluetooth/host_l2cap_br_send on native_sim.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Solve two issues:
* Other storage modes than CONFIG_BT_MESH_RPL_STORAGE_MODE_SETTINGS
could not reuse the pending store scheduler used by the settings
backend.
* The store timing of SRPL, which is always stored through the
Settings subsystem, would use CONFIG_BT_MESH_RPL_STORE_TIMEOUT if
RPL was also stored in settings via
CONFIG_BT_MESH_RPL_STORAGE_MODE_SETTINGS, but not if another storage
mode was used for RPL.
Decouple the store scheduler from the Settings subsystem and the
chosen RPL storage mode, so the scheduler code and the separate
CONFIG_BT_MESH_RPL_STORE_TIMEOUT option are
a) Available regardless of storage mode, and always used for SRPL when
set and
b) Available without CONFIG_BT_SETTINGS, in case an RPL storage mode
does not need Settings but would like the scheduling.
Also change the BT_MESH_SETTINGS_RPL_RESET_PENDING to always store
immediately. This was in practice already the case whenever settings was
used, since this was only ever scheduled right before a second NO_WAIT
configuration was scheduled (like net key, IV, etc.). Now this behavior
is consistent both with and without BT_SETTINGS enabled.
Assisted-by: Copilot:claude-sonnet-5.5
Signed-off-by: Ludvig Jordet <ludvig.jordet@nordicsemi.no>
When the Controller is missing, unpowered or does not run HCI, the first
command that bt_enable() sends times out, and the Host asserts:
ASSERTION FAIL [err == 0] @ .../bluetooth/host/hci_core.c:572
Controller unresponsive, command opcode 0x0c03 timeout with err -11
An application cannot handle this, so Bluetooth cannot be optional at run
time, for example on a board with the Controller on a plug-in module.
The Host now records whether the Controller has sent a packet while
bt_enable() runs. When bt_hci_cmd_send_sync() times out waiting for a
response during bt_enable(), and the Controller has not sent anything,
the Host closes the transport, as bt_disable() does, and bt_enable() fails
with -ETIMEDOUT. The close stops a late response from completing a
command whose sender has returned. Because the transport is closed,
bt_enable() can be called again. This also applies to a command that the
TX processor thread never sends, such as HCI Reset with CONFIG_BT_WAIT_NOP
when no NOP arrives: the close completes it.
The Host still asserts when a command times out after the Controller has
responded. Such a Controller is present but faulty, and once packets have
come in, a clean failure needs the RX teardown that bt_disable() does. The
record is kept across HCI Reset, so a Controller that answers HCI Reset
and then stops also causes the assert. The Host also asserts when the
driver cannot close the transport, and, without
CONFIG_BT_TX_PROCESSOR_THREAD, when a command sent from the system work
queue cannot be sent.
The transport must not be closed while the driver is in send(), and a
send() can outlast the command timeout. The TX processor holds the host
lock during send(), so the Host takes the lock without waiting before it
closes the transport. When the lock is not free, the Host asserts.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Vandra-Meyer Akos <akos@lvgl.io>
Several LOG_ and __ASSERT format strings use %u or %d for arguments
that are size_t or ssize_t, which produces -Wformat= warnings on
LP64 targets (e.g. AArch64). Switch to %zu / %zd.
* subsys/bluetooth/host/classic/sdp.c: three format strings that
compare against sizeof() or use ssize_t counters.
* drivers/bluetooth/hci/hci_nxp_setup.c: matching V1 and V3
"Out of sending buffer range" messages (both LOG_ERR and the
neighbouring __ASSERT that uses the same string).
No functional change; eliminates 5 build warnings on
nitrogen93_smarc/mimx9352/a55/nx611.
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Ryan Erickson <ryan.erickson@ezurio.com>
The explicit-erase path in wr_chunk() programs a shared write block
twice when a chunk boundary is not write-block aligned, which corrupts
the ECC syndrome on flash that allows only one program per erase (e.g.
some NXP MCXW SoCs) and faults on the next read. Commit a9ad258c84
fixed only the non-erase path.
Add opt-in CONFIG_BT_MESH_BLOB_IO_FLASH_BLOCK_CACHE (default n) that
buffers a block in RAM and, on the chunk that completes the block,
programs it write-block-aligned once, so no write block is programmed
twice. The flush runs in wr() rather than block_end so a failed
flash_area_write is returned to the server (the chunk stays missing and
the client retries) and a sticky error prevents any later re-program;
an unaligned init offset is rejected up front. Default builds are
unchanged.
Signed-off-by: Axel Le Bourhis <axel.lebourhis@nxp.com>
With privacy enabled random address is set via
bt_id_set_adv_private_addr() which has a shortcut for NRPA
when BT_LE_ADV_OPT_USE_NRPA flag is set. Previously advertising
instance options were set at the very beginning of configuration
and this was working correctly. But now new options are set only
after configuration was successful and this resulted in RPA being
set by bt_id_set_adv_private_addr() since options were not yet
updated.
Pass new options to bt_id_set_adv_private_addr() directly allowing
it to take proper actions. This is also consistent with current design
of bt_id_set_adv_own_addr().
This is a regression after
commit 2548b7b100 ("Bluetooth: Host: Set adv->options only on success")
This is affecting GAP/BROB/BCST/BV-04-C qualification test case.
Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
Break radio_switch_complete_and_tx lines that exceed the 100-column
checkpatch limit after expanding tabs.
Signed-off-by: Hugo Zamith <hhzamith@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace remaining magic 0/0U phy and flag arguments in Nordic and
OpenISA LLL radio setup/timing helpers with PHY_LEGACY and
PHY_FLAGS_UNUSED.
Coded PHY S2/S8 call sites already use PHY_FLAGS_S2/S8; this finishes
the cleanup for legacy paths so radio_phy_set,
radio_switch_complete_and_tx, and delay helpers consistently use the
named macros from pdu.h.
Fixes#37458
Signed-off-by: Hugo Zamith <hhzamith@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Utilize a code spell-checking tool to scan for and correct spelling errors
in all files within:
- `subsys/bluetooth/audio`
Assisted-by: Claude:claude-sonnet-5-5 codespell
Signed-off-by: Pisit Sawangvonganan <pisit@ndrsolution.com>
When the resolving list cannot be changed, bt_id_del() defers the
removal by flagging the keys, but bt_keys_clear() wipes the keys
right after, so the removal is lost. The stale entry keeps
counting in rl_entries and can force the switch to host-side
resolution, after which no bonded peer using an RPA passes the
filter accept list. The removal has been lost this way since
commit e25d925242 ("Bluetooth: Defer RL update if there's an
ongoing connection").
Queue the peer identity address instead, so the removal survives
the keys being cleared or reused. bt_id_add() carries out the
queued removals before adding, so a peer added again after the
deferring condition ended is not removed afterwards, and
rebuilding the list after host-side resolution drops the queued
removals it no longer holds. The limited scan flag is dropped as
the removal is carried out right away in that case.
Assisted-by: Claude:opus-5
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
The help text calls the option the stack size of the receiving thread
and says that all callbacks to the application come from that thread.
Neither holds. Since commit 9ef7acd7d7 ("Bluetooth: Host: Add a
general purpose Bluetooth workqueue") the stack is that of the Bluetooth
workqueue, which also runs the deferred work of the Host, and the
documented callback contract promises no thread: some callbacks run in
the thread that calls the API which triggers them.
Say what the option sizes.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Clamp the entry count in handle_receivers_get() so a First Index past
the end of the receivers list yields a Receivers List with the list
field omitted, instead of a count computed from a negative difference,
as required by the Mesh DFU Model specification, section 6.2.3.5.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
keys_commit() marks every bond with an IRK BT_KEYS_ID_PENDING_ADD on
each settings_load(), including one whose IRK is already in the
resolving list. The next advertising or scan start then calls
bt_id_add() for it again.
A Controller that rejects duplicates fails LE Add Device To Resolving
List with 0x12. With host address resolution, rl_entries counts the bond
twice.
Skip bonds that already have BT_KEYS_ID_ADDED set.
Fixes#120829
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Arkadiusz Grzelka <devitwise@gmail.com>
With BT_ISO_SYNC_RECEIVER enabled but no unicast role, the shell
failed to build: the big-sync command took its RX QoS from the
unicast iso_rx_qos, and connection_info compared against the
unicast iso_chan. Give the sync receiver its own RX QoS, since
the host only requires it to be non-NULL, compare against
iso_chan only when unicast is enabled, and declare iso_chan
under the same guard as its definition.
Assisted-by: Claude:opus-5
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
Use the public bt_att_get_max_ntf_size function to get the
current notification size, rather than using the
LE Audio specific one.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Applications that send notifications larger than the ATT_MTU have to
truncate them to ATT_MTU - 3, but the 3-octet ATT_HANDLE_VALUE_NTF
header size was only available in the internal ATT header, so every
user had to define it again.
Add bt_att_get_max_notify_size() and bt_att_get_max_indicate_size()
to the public ATT API.
Assisted-by: Copilot:claude-sonnet-4.5
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
CONFIG_BT_MESH_RPL_STORE_TIMEOUT was only honored while no other
storage flag was pending. As soon as a generic flag such as model
data, keys or config was scheduled alongside a replay protection
list flag, the shared work item was rescheduled to the shorter
CONFIG_BT_MESH_STORE_TIMEOUT deadline, and the replay lists got
stored on that shorter deadline too, causing extra flash wear.
Give the replay protection list and solicitation replay list
their own work item so they are always stored on
CONFIG_BT_MESH_RPL_STORE_TIMEOUT regardless of what else is
pending. The replay list invalidated by an IV Index update or
cleared keeps using CONFIG_BT_MESH_STORE_TIMEOUT, as intended.
bt_mesh_rpl_reset() also no longer schedules that store when an
IV Index update leaves the replay list empty.
Assisted-by: Copilot:claude-opus-5
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
bt_avdtp_parse_capability_codec() left an unrecognised category's LOSC and
content in the buffer, so the next iteration misparsed those bytes and
bailed with -EINVAL, stopping the discover walk.
Skip unknown category content instead, as AVDTP requires receivers to
ignore capabilities they do not recognise.
Found during PTS AVDTP/SRC/INT/SIG/SMG/BI-30-C and BI-36-C (ignore
reserved capabilities) qualification runs.
Assisted-by: DeepSeek:deepseek-flash
Signed-off-by: Yuheng Li <liyuheng@xiaomi.com>
Replace scripts/kconfig/hardened.csv with a distributed YAML database.
The CSV format could not carry any explanation for its recommendations,
had no validation (a malformed line was silently dropped), no notion of
profiles, no ownership story, and no way to extend it out of tree.
The database now lives where the code lives: the central
scripts/kconfig/hardening.yaml defines the hardening profiles (plus
rules for top-level Kconfig symbols), and per-subsystem hardening.yaml
fragments next to the relevant Kconfig files carry the rules, so each
rule is reviewed by the maintainers of the code it hardens. Every rule
has a required rationale and optional references, supports exact-value
and integer min/max recommendations (STACK_POINTER_RANDOM is now
'>=100' instead of '==100'), and belongs to a profile: 'base' (memory
protection and inherently insecure features) or 'strict' (extends base
with debug/observability feature removal). The default profile is
'strict', matching the rule set the CSV checked.
hardenconfig is restructured around a serializable HardeningReport
model so results can be consumed programmatically, and gains:
- a Rationale column in the report
- profile selection:
west build -t hardenconfig -- -DHARDENCONFIG_PROFILE=base
- HARDENCONFIG_SHOW_ALL to also list PASS/NA results
- HARDENCONFIG_STRICT to exit non-zero on failures, for CI use
- HARDENCONFIG_JSON to write machine-readable results, including which
database file each rule came from
- HARDENCONFIG_EXTRA_SOURCES to layer out-of-tree database files that
may add profiles/rules and override in-tree ones
The EXPERIMENTAL/DEPRECATED/NOT_SECURE marker symbol detection is
preserved unchanged.
Three CSV entries are intentionally not carried over because they were
redundant: BT_CONN_DISABLE_SECURITY and BT_OOB_DATA_FIXED can only be
enabled together with BT_TESTING, and TIMER_RANDOM_GENERATOR together
with TEST_RANDOM_GENERATOR, all of which the database already
recommends disabling for the same profiles.
Behavioral fix: the CSV's DEBUG_COREDUMP line used '=' instead of ','
and was silently ignored, so CONFIG_DEBUG_COREDUMP was never actually
checked; it now is.
Also add tabulate to requirements-base.txt: hardenconfig has always
imported it, but it was only pulled in via other requirements files.
Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
The value passed to a CCC's cfg_changed callback is the highest value
any connected peer wrote, Reserved bits included. A peer that sets one
next to the notify bit (0x0005) is then reported as not subscribed by
every callback that compares the value with BT_GATT_CCC_NOTIFY, such as
the Current Time Service's, although a receiver shall ignore Reserved
bits (Core 6.3, Vol 1, Part E, Section 2.4.1). Mask them before taking
the highest value, which leaves the value unchanged for peers that set
none.
The Reserved bit scenario added to the GATT notify bsim test in the
next commit fails without this change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The Service Changed CCC keeps the per-peer entry that records database
changes made while a bonded peer is disconnected only when the peer
wrote exactly 0x0002. A peer that also sets a Reserved bit, which a
receiver shall ignore (Core 6.3, Vol 1, Part E, Section 2.4.1), gets no
entry, so a change made while it is disconnected is never indicated
when it reconnects. Test the indicate bit instead.
The Reserved bit scenario added to the sc_indicate bsim test in the
next commit fails without this change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
A notification or indication sent to all peers skips every peer whose
stored CCC value is not exactly that procedure's bit. The value is a bit
field: a client may enable both procedures (Core 6.3, Vol 3, Part G,
Section 3.3.3.3), and a Reserved bit that a client sets anyway is to be
ignored (Vol 1, Part E, Section 2.4.1). Such a peer gets no broadcast at
all, while a notification addressed to its connection reaches it, as the
subscription check on that path, bt_gatt_is_subscribed(), tests the bit.
Test the bit here too.
The broadcast scenario added to the GATT notify bsim test in the next
commit fails without this change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bond_delete callback should only be called if actual bond was present
and deleted. Currently it is being called unconditionally when
bt_unpair is called. Bond present is check by validating if any
key was present, this matches bt_foreach_bond() and also handles
paired, but not bonded connected peers.
Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
Introduce ZASSERT, a self-contained assertion facility configured per
source file through a named module rather than the single global
CONFIG_ASSERT switch.
A file selects its module with ZASSERT_MODULE(); the level is resolved
from CONFIG_ASSERT_MODULE_<MODULE>_LEVEL and may be overridden per file.
Modules are defined with the Kconfig.template.assert template, which takes
module/module-str inputs following the logging template convention.
The four levels are:
- Off (compiled out)
- Terse (check only)
- On (check + location only)
- Verbose (Check, location, condition and message)
Since the level is known at compile time, disabled assertions are folded
away by the compiler, and below Verbose the optional message and its
arguments are as well.
zassert provides a set of __weak overridable hooks:
- zassert_fail() - called when an assertion fails
- zassert_vprint() - called to print the assertion failure message
- zassert_post_action() - the terminal action after an assertion failure
CONFIG_ASSERT remains the master switch. The assert Kconfig moves from
subsys/debug to lib/os/zassert, the legacy CONFIG_ASSERT_* symbols are kept
but deprecated (mapped onto the DEFAULT module), and lib/os/assert.c is
removed. The __ASSERT() family is preserved as a thin compatibility shim
over the DEFAULT module, so existing call sites keep working unchanged.
Signed-off-by: Måns Ansgariusson <mansgariusson@gmail.com>
Reject identity handles that are outside the current identity set or refer
to an empty deleted slot before producing local LE OOB data.
Add native_sim coverage for the first unused handle and a deleted non-tail
identity.
Assisted-by: ChatGPT:gpt-5.6-sol
Signed-off-by: Taha Zarif <tahazarif380@gmail.com>
The monitor log backend registered monitor_ts_get() as the logging
core's timestamp source from its init callback and then passed message
timestamps on to encode_hdr() unconverted, assuming they were already
in the monitor's 1/10th millisecond unit. Backends are however only
initialized once the logging subsystem starts up, which with the
default CONFIG_LOG_PROCESS_THREAD means when the logging thread first
gets to run. Everything logged before that point is stamped by the
logging core's default clock, i.e. the raw cycle counter (or uptime in
milliseconds for cycle counters above 1 MHz), and ends up in btmon in
the wrong unit.
With samples/bluetooth/observer on nrf52dk/nrf52832, where the cycle
counter runs at 32768 Hz, the logging thread does not run before main()
has returned, so the boot banner and all of the Bluetooth
initialization messages are affected and show up 3.2768 times too late:
the banner, logged at 0.3233 s right before bt_enable() sent the New
Index record, carried the timestamp 10595 (its cycle count) and was
displayed at 1.0595 s, 0.74 s after the HCI initialization that
followed it.
Fix this by leaving the logging core's clock alone and converting the
message timestamp through log_output_timestamp_to_us(), which knows
the rate of whatever clock the logging core is using, in
monitor_log_process(). HCI packets keep being stamped by
monitor_ts_get(), which by default derives from the same system timer
as the logging core's clock, so log messages and packets stay on a
common time base. With the fix the banner is displayed at 0.3046 s
against the New Index record at 0.3047 s, and the HW Platform message
falls between the Zephyr Read Version Info command complete event that
produces it and the next command. Also verified on xg24_rb4186c (32768 Hz
cycle counter as well) and on siwx917_rb4338a, whose 180 MHz SysTick makes
the logging core default to uptime in milliseconds: on all three boards
each "Device found" message is stamped within a millisecond of the
advertising report it is logged for. A side effect is that enabling the
monitor no longer changes the timestamp rate seen by all other log
backends, nor overrides a timestamp source registered by the
application.
For the packet timestamps to stay comparable with the converted message
timestamps in every configuration, monitor_ts_get() now follows the
logging core's choice of clock: the real-time clock with
CONFIG_LOG_TIMESTAMP_USE_REALTIME, and the (64-bit) tick counter where a
32-bit cycle counter runs above 1 MHz, since such a counter wraps within
minutes while the messages, stamped with uptime by the logging core, do
not. Verified on siwx917_rb4338a with its 64-bit cycle counter disabled
(CONFIG_CORTEX_M_SYSTICK_64BIT_CYCLE_COUNTER=n, the 180 MHz counter then
wraps every 24 s): a 60 s capture stays monotonic and the messages stay
within a millisecond of their advertising reports throughout. Also
verified with CONFIG_LOG_TIMESTAMP_USE_REALTIME on nrf52dk.
monitor_ts_get() is no longer a log_timestamp_get_t, so it and
encode_hdr() now use a plain uint64_t; the truncation to the 32-bit
wire format stays in encode_hdr().
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_disable() resets the advertiser pool, stops RX processing, resets
the controller, tears down all connections and purges the command
queue before it asks the HCI driver to close its transport. When that
fails it set BT_DEV_READY again, "to avoid inconsistent stack state",
which is exactly what it produced: a Host that says it is ready on top
of a controller that has just been reset, whose event masks are back at
their defaults, and with its connection bookkeeping gone.
Six in-tree HCI drivers have no close() op at all (h5, psoc6_bless,
sf32lb, siwx91x, stm32wb0 and the generic SPI one), so for them every
bt_disable() took that path and returned -ENOSYS having done all of the
above.
Ask bt_hci_can_close() before anything is torn down, and return
-ENOSYS with Bluetooth left exactly as it was. When a driver that has
the op fails to close, leave the stack not ready: the transport is
still open, so BT_DEV_OPEN is kept, and the only thing left to do is to
call bt_disable() again, which the documentation now says.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The retry state in struct bt_att_req and the retry path in
bt_att_encrypt_change() are built whenever CONFIG_BT_SMP is enabled,
although only CONFIG_BT_ATT_RETRY_ON_SEC_ERR ever sets req->retrying.
commit c3c7b54ccf ("Bluetooth: Host: Option for disabling of ATT
auto retry") narrowed the security elevation and that assignment to
the new option but left the fields and the retry code behind the
CONFIG_BT_SMP guard, so a CONFIG_BT_SMP=y
CONFIG_BT_ATT_RETRY_ON_SEC_ERR=n build carries a retry path that can
never run: a flag that is always false and three request fields
nothing ever reads.
Guard them with CONFIG_BT_ATT_RETRY_ON_SEC_ERR, and make retrying a
bool since the bit-field shared its storage unit with nothing.
No functional change: bt_att_req_alloc() zeroes the request, so
retrying was already always false with the option disabled. On
samples/bluetooth/central_hr for nrf52840dk/nrf52840 the disabled
build loses 176 bytes of flash and 36 bytes of RAM, the enabled build
16 bytes of flash.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
With CONFIG_BT_ATT_RETRY_ON_SEC_ERR a request rejected for insufficient
security stays on its bearer, marked retrying, while the host elevates
security: att_error_rsp() has consumed the error response and stopped
the ATT timeout, and bt_att_encrypt_change() resends or fails the
request once the security procedure completes.
Cancelling such a request left it in that state. bt_att_chan_req_cancel()
parked the cancel placeholder on the bearer, and the encryption change
handler only acts on a retrying request, so neither a response nor a
timeout was left to clear the placeholder. The bearer stayed busy until
disconnect and every request queued for it was never sent, for example
the CCC disable write of a bt_gatt_unsubscribe() that had cancelled its
pending enable write.
Release the bearer immediately when the cancelled request is waiting for
a retry and send the next queued request, as att_handle_rsp() does when
a response arrives.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The CCC write handler accepted any value without consulting the
properties of the characteristic the descriptor belongs to, so a client
could enable notifications on an indicate-only characteristic, or
indications on a notify-only one. The subscription was then recorded and
reported by bt_gatt_is_subscribed(), but nothing could ever be sent for
it.
Look up the properties of the nearest preceding characteristic
declaration and reject a configuration the characteristic does not
support with the error the spec reserves for this, Client Characteristic
Configuration Descriptor Improperly Configured. Writes that clear the
configuration are unaffected, since they request nothing.
If the declaration cannot be located or read, a warning is logged and
the write is let through unchanged, so a database that is not built from
the BT_GATT_CHARACTERISTIC macros keeps working as before.
Note that this rejects configurations previously accepted. A server whose
characteristic properties do not match what its clients subscribe to will
now see those subscriptions fail, which is the intended outcome: it makes
a mis-declared database visible instead of silently producing a
subscription that never delivers.
Fixes: #81005
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Assisted-by: Claude:claude-opus-5
Assisted-by: Claude:claude-fable-5
l2cap_br_conf_opt_qos() rejects the whole Configuration Request unless
the QoS bit is set both in the peer's extended feature mask and in
L2CAP_EXTENDED_FEAT_MASK, but the local mask never carried that bit, so
a peer including a QoS option could never complete channel
configuration. The handler was also not spec compliant in two ways: a
Guaranteed request was answered with Unacceptable Parameters while the
service type was echoed back unchanged, leaving the peer without a
usable counter-proposal, and an accepted QoS option was not returned in
the positive Configuration Response.
Add CONFIG_BT_L2CAP_QOS to advertise the QoS bit in the local extended
feature mask, and guard the QoS default values with it since only that
path uses them. Only the Best Effort service type has to be supported
(Core 5.4, Vol 3, Part A, 5.3), so counter-propose Best Effort when the
peer asks for the optional Guaranteed type, and add the agreed option
to the Configuration Response when the option is accepted.
Signed-off-by: Make Shi <make.shi@nxp.com>
Currently, synchronous controller functions in media_proxy.c blindly
dereference local player callbacks. This triggers a hard fault if a
local player has not been registered or if it does not implement all
optional callbacks (leaving some function pointers as NULL).
This commit adds validation guards to verify that mprx.local_player.calls
and the individual callback function pointers are not NULL across all
synchronous media control getters and setters. If a callback is
unimplemented, a safe fallback value (e.g., "" for strings, 0U for
integers) is returned instead.
Additionally, it relaxes the check in media_proxy_pl_register to allow
partial implementation of callbacks during player registration, as
allowed by the public contract in media_proxy.h, while still preventing
a completely NULL callback table from being registered.
Signed-off-by: harshit kudhial <harshitkudhial@gmail.com>
Improve error handling consistency across OBEX client operations by
ensuring proper state recovery on all error paths.
Add `obex_client_restore_active_state()` helper function to restore
client state (`opcode` and `active_client`) on error paths.
Convert early returns to goto failed pattern to ensure cleanup happens
consistently. It is used to ensure internally allocated net buffer is
properly freed on all error paths. And also ensure the changed states
and flags are recovered on all error paths.
The changes ensure that client state is properly restored when
operations fail, preventing state corruption and resource leaks.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
update_recv_state_encryption() copied sizeof(recv_state->num_subgroups)
bytes of the subgroups, which is a single byte, instead of the whole
array. The receive state written back when the BIG encryption changed
therefore lost the metadata of every subgroup and kept only one byte of
the BIS sync value of the first subgroup.
Copy the whole array, and check in the BAP broadcast assistant BSIM test
that the metadata is still set when the broadcast code is requested.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Arkadiusz Grzelka <devitwise@gmail.com>
Store the public identity address that the Host hands to the driver's
setup() op also in the common HCI driver data, through the new
bt_hci_set_public_addr() API, before the HCI transport is opened. The
driver reads it with bt_hci_get_public_addr() and can apply it during
open(), i.e. from vendor-specific initialization that does not depend
on the Host's command APIs being available.
bt_hci_get_public_addr() returns BT_ADDR_ANY while no public address
has been set, which is what setup() receives in that case, so a driver
moving from one to the other keeps the check it has, and driver data
that has never been written needs no flag to say so. BT_ADDR_NONE is
the name that suggests itself for this, so the choice is spelled out
where a driver author looks: on both functions, with the check a driver
is expected to make, on the field, on the setup() parameter, which did
not document its value until now, and in the Kconfig help. The test
pins the value.
The channel is set on every bt_enable() and cleared when there is no
public identity, so that an address an earlier enable left behind is
not applied to the controller by a later one.
The setup() path keeps receiving the address as before; both channels
coexist until the drivers implementing setup() have migrated. So that
enabling the new channel no longer pulls in the mechanism it replaces,
BT_HCI_SET_PUBLIC_ADDR stops selecting BT_HCI_SETUP; the drivers that
apply the address in setup() (BlueNRG ACI, STM32WBA, CYW208XX) now
select BT_HCI_SETUP themselves, matching the conditions their setup()
implementations are compiled under.
Both functions are declared unconditionally, as coding guideline rule
A.1 requires of a header, so that their callers can select on the
option with IS_ENABLED() rather than the preprocessor, and defined in
a source file that is compiled only when the option is enabled, so
that a call that is not guarded fails to link rather than quietly
doing nothing. Only the field they work on is conditional, so a driver
that does not announce the capability pays nothing for it.
The driver API group version goes to 0.3.0 for the two functions added
to it.
The host identity test gains a scenario that creates a public identity
before bt_enable() and checks what the driver is handed while the
transport is opened, including that an enable without a public identity
hands it nothing rather than what the previous one left. The scenario
enables the capability through a prompt the test adds to it, since the
option is otherwise selected by drivers only. Its fake driver gains a
close() op, which the test needs in order to cycle the transport.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The helper documented that initializing it again restores the initial
command allowance, for a controller that has been reset by other means
than an HCI command. That is not safe: bt_hci_lockstep_init() calls
k_sem_init(), which with CONFIG_OBJ_CORE_SEM links the semaphore's
object core, so initializing the same helper twice links the same
object twice and corrupts the tracking list. No in-tree driver does it
today, the one user initializing the helper from its device
initialization function, so this is a contract that invites the defect
rather than an active one.
Add bt_hci_lockstep_reset(), which restores the allowance and forgets
the outstanding command without re-initializing the semaphore, and
document initialization as the once-only call it has to be. The
transport send function and the caller's timeout survive the reset, so
a driver that resets its controller while opening it does not have to
repeat what it set up at device initialization.
The reset may be called from any context and takes the helper's lock,
so it may run while packets are being fed, and a driver that is fed
from a callback it cannot stop can use it too. It signals the change of
state by giving the helper's semaphore, as feeding does, so a sender
that waits for the controller to allow its command goes ahead.
A driver is expected not to reset its controller while a command is
outstanding, since it cannot be known which side of the reset the
command ended up on. If it does, the command is abandoned: its response
is no longer consumed and its sender fails at its deadline, not
earlier, so that a response which still arrives cannot be taken for
that of a later command with the same opcode. What the reset cannot do
either is tell packets the controller sent before it from the responses
to what follows, so those are not to be fed afterwards, which the
documentation now says.
The helper keeps its view of the command allowance from one opening of
the transport to the next, so the group documentation now says when a
driver has to call the reset.
Five cases are added to the unit test: the allowance is restored after
a command that went unanswered, a repeated reset, which is what a
driver resetting its controller on every open performs, a reset that
releases a sender waiting for the allowance, the same from an ISR, and
a reset with a command outstanding, whose sender must not return before
its deadline.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Previously audio.conf was a standalone configuration file, but
has now been changed to work as an extra_conf_file instead.
The purpose of this is to avoid having too many duplicate
configs in the shell application.
Additionally the LE audio tests in tests.yaml has been changed
to use YAML anchors to reduce the amount of duplicated
configurations in that file too, keep each test case simpler.
Some of these changes exposed some existing surpressed warnings
that were similarly fixed.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Nothing stops smp_send_security_req() from running again while a
Security Request is still unanswered. SMP_FLAG_PAIRING is only set once
the peer replies, and the required_sec_level check in
bt_conn_set_security() only filters a repeat at the same level, so an
escalation or BT_SECURITY_FORCE_PAIR gets through. A second request puts
another PDU on air and re-runs smp_init(), which discards the nonce
generated for the request already in flight.
Claim SMP_FLAG_SEC_REQ with atomic_test_and_set_bit() and return
-EALREADY if it was already set, so two threads calling
bt_conn_set_security() cannot both start the procedure. smp_init()
clears smp->flags, so it now keeps that bit while clearing the rest. A
save and restore would not do: the bit would still read as clear for
the duration of the memset, which is enough for a concurrent caller to
pass the test.
bt_conn_set_security() overwrites required_sec_level and FORCE_PAIR
before calling in, so a rejected second call would lower the level the
in-flight request is held to. Restore both on -EALREADY and document it
in conn.h. Documenting the new return value is a backwards compatible
API change, so the bt_conn group patch version moves to 1.0.1.
Signed-off-by: Zhijie Zhong <zhongzhijie1@xiaomi.com>
Assisted-by: Kiro:claude-opus-5
smp_send_security_req() sets SMP_FLAG_SEC_REQ and allows
BT_SMP_CMD_PAIRING_REQ only after bt_l2cap_send_pdu() returns.
bt_l2cap_send_pdu() only queues the PDU, and the Pairing Request that
answers it is handled by bt_smp_recv() on the Bluetooth RX thread, not on
the thread that called bt_conn_set_security(). The answer can therefore be
processed before the two atomic_set_bit() calls have run, in which case the
allowed_cmds check in bt_smp_recv() drops it without even sending a Pairing
Failed and the peer waits for a response that never comes.
Publish the state before handing the PDU to L2CAP, and roll it back if the
send fails.
Signed-off-by: Zhijie Zhong <zhongzhijie1@xiaomi.com>
Assisted-by: Kiro:claude-opus-5
When the Controller resolves a Resolvable Private Address to an identity
address, it signals this by setting bit 1 of the Address_Type field in
the relevant HCI LE event (e.g. LE Enhanced Connection Complete, LE
Advertising Report, LE Scan Request Received). Previously the default
case of the address-type switch in bt_addr_le_to_str() printed the raw
type byte, so the resolved bit was preserved (as 0x02 or 0x03) in log
output.
With the move to the prefix-based string format bt_addr_le_to_str()
formats such values by their base type, so this information would be
silently dropped from logs. Print a " (resolved)" suffix at the
affected log sites so the indication remains visible in the log message
without leaking the HCI-specific extended type into the public API.
Use the existing bt_addr_le_is_resolved() helper from addr_internal.h
rather than introducing a new helper.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>