Commit graph zephyr/subsys/bluetooth
Author SHA1 Message Date
Emil Gydesen
21e609b847 Bluetooth: CCP: Client: Add support for get bearer tech
Add support for getting the remote bearer tech.

Also slightly modified the test of the CCP samples
to properly catch issues (e.g. we disconnect on error,
and now we check for disconnect as the samples may reconnect
and thus have false positives).

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-25 08:58:52 +02:00
Johan Hedberg
ecaaec9786 Bluetooth: AVDTP: Initialize the session lock before publishing the session
bt_avdtp_connect() and bt_avdtp_l2cap_accept() store the connection
pointer in the session, and only then initialize session->sem_lock.
The connection pointer is what makes the session visible to other
contexts, and the upper layer clears the whole session structure when
it is reused, so between the two the session can be reached with a
zero-initialized semaphore.

Initialize the semaphore before the session is published, while the
global lock is still held.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-24 18:42:55 +02:00
Johan Hedberg
660bcc45a2 Bluetooth: AVDTP: Fix lock order inversion in bt_avdtp_register_sep()
bt_avdtp_register_sep() calls bt_avdtp_set_state_lock() while holding
the global avdtp_sem_lock, i.e. it takes avdtp_sem_lock and then
sep->sem_lock. The command handlers use the opposite order: they run
with sep->sem_lock held and take avdtp_sem_lock when queuing the
response for transmission (avdtp_send_rsp() -> avdtp_send_common()).
Registering an endpoint while signalling is in progress can therefore
deadlock.

The endpoint has not been added to the `seps` list at that point, so no
other context can reach it. Set the state without taking sep->sem_lock.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-24 18:42:55 +02:00
Johan Hedberg
5e48f97cfd Bluetooth: Classic: AVRCP: Fix dangling conn in cover art disconnect
The BIP transport disconnected callbacks for the Cover Art Target and
Controller unreference tg->conn and ct->conn without clearing the
pointers. The API functions in this file rely on a conn == NULL check
to detect that the Cover Art channel is not connected, so after a
transport disconnect these checks pass with a dangling pointer. Since
connection objects are recycled, the stale pointer may also end up
aliasing an unrelated live connection.

Use bt_conn_drop(), which unreferences the connection and clears the
pointer, keeping the not-connected checks in the API functions sound.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-24 18:42:35 +02:00
Can Wang
3d7b14a21b bluetooth: classic: shell: map: use ARRAY_FOR_EACH for array iterations
Replace manual for loops iterating over fixed-size arrays with the
ARRAY_FOR_EACH macro for consistency with the rest of the codebase.

The following loops are converted:
- mce_mas_select(): iterate mce_mas_instances[index]
- mse_mas_select(): iterate mse_mas_instances[index]
- mse_mns_find(): iterate mse_mns_instances

Signed-off-by: Can Wang <can.wang@nxp.com>
2026-08-24 10:28:20 +01:00
Can Wang
218d1be5c3 bluetooth: classic: map: add required app parameters for GetMessage
The GetMessage operation was missing required application parameters
in its validation macro. According to the MAP specification, the
Attachment and Charset parameters are mandatory for GetMessage
requests.

Add BT_MAP_APPL_PARAM_TAG_ID_ATTACHMENT and
BT_MAP_APPL_PARAM_TAG_ID_CHARSET to GET_MSG_REQUIRED_AP to ensure
these parameters are validated by has_required_app_params().

Signed-off-by: Can Wang <can.wang@nxp.com>
2026-08-24 10:28:20 +01:00
Can Wang
b7f3437188 bluetooth: classic: shell: map: prevent duplicate MAS connections
The MCE MAS connect commands could allow multiple connections to the
same MAS instance ID to be established, leading to resource conflicts.

Fix this by checking if a connection to the requested instance ID
already exists before allocating a new MCE MAS instance in both
bt_map_mce_mas_rfcomm_connect() and bt_map_mce_mas_l2cap_connect()
shell commands.

The MSE MAS accept callbacks could allow multiple connections of the
same transport type (RFCOMM or L2CAP) to be established for a single
MAS instance.

Fix this by validating both the PSM and RFCOMM channel in the accept
callbacks and rejecting duplicate connection attempts.

Signed-off-by: Can Wang <can.wang@nxp.com>
2026-08-24 10:28:20 +01:00
Can Wang
7998157f68 bluetooth: classic: map: align callback registration with PBAP/BIP
For client roles (MCE MAS and MSE MNS), remove the dedicated
*_cb_register() functions and pass the callback pointer directly
to rfcomm_connect() / l2cap_connect() calls, matching the pattern
used by the PBAP and BIP client APIs.

For server roles (MCE MNS and MSE MAS), rename *_cb_register() to
*_register(). The new function both stores the callback table and
registers the instance with the underlying OBEX server. The
accept() callbacks no longer register callbacks per-connection;
callers must invoke *_register() once before registering the
transport server.

Add shell commands `map mce mns register` and `map mse mas
register`, and update the shell documentation accordingly.

Signed-off-by: Can Wang <can.wang@nxp.com>
2026-08-24 10:28:20 +01:00
Emil Gydesen
8f0f2db779 Bluetooth: BAP: Use bt_ascs_op_str to print string rep of ase_op
Print the string alongside the numeric value to easier to
debug for humans.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-24 10:26:11 +01:00
Lyle Zhu
1eeec680f1 bluetooth: classic: Add BT_DEV_READY checks to BR/EDR APIs
Add checks for `BT_DEV_READY` flag in Bluetooth Classic (BR/EDR) API
functions to prevent operations before the Bluetooth stack is fully
initialized.

The following functions now return `-EAGAIN` if called before the stack
is ready, including functions `bt_br_discovery_start()`,
`bt_br_set_connectable()`, `bt_br_set_discoverable()`, and
`bt_br_write_eir()`.

For the function `bt_conn_create_br()`, it returns `NULL` if the stack
is not ready.

The changes prevent potential issues from attempting BR/EDR operations
before the controller and host are properly initialized.

Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
2026-08-24 10:25:56 +01:00
Aleksandr Khromykh
7f4b68ae81 bluetooth: mesh: complete distribution on asynchronous self-apply
When the Distributor updates itself, the Firmware Update Server defers
its apply callback until the distribution reaches the Confirm step. The
callback may reboot the device, or call bt_mesh_dfu_srv_applied() and
return. An application that installs the image asynchronously and calls
bt_mesh_dfu_srv_applied() later left the distribution stuck: by then
dfu_confirmed() had returned with the Distribution Phase at Applying
Update, and nothing re-entered it.

Notify a co-located Firmware Distribution Server from
bt_mesh_dfu_srv_applied() so a deferred apply can complete the
distribution without a reboot. dfu_confirmed() skips its own transition
when the notification already completed the distribution, so an apply
that finishes inside the callback still reports Completed once.

Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-21 13:40:14 -07:00
Aleksandr Khromykh
65018d0f1e bluetooth: mesh: resume self-update confirm step after reboot
Add a .start model callback to the DFD Server that resumes the
self-update confirm step after reboot. When the DFD Server wakes
up in APPLYING_UPDATE phase (restored from settings), the start
callback:

1. Finds the co-located DFU Server; if it is still in APPLYING
   phase, calls bt_mesh_dfu_srv_applied() to transition it to
   IDLE so it responds to Firmware Update Information Get with
   the new FWID.
2. Calls bt_mesh_dfu_cli_confirm() to resume polling targets
   for their updated firmware image.

Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-21 13:40:14 -07:00
Aleksandr Khromykh
5bdbd50157 bluetooth: mesh: defer self-target apply until distribution completes
When the Distributor is also a DFU target of its own distribution
(self-update), applying the firmware immediately upon receiving the
Update Apply message would reboot the device before it can complete
the confirm step for other targets.

Defer the apply callback on the DFU Server when the Update Start
originated from a local address (self-update detected via
bt_mesh_has_addr). The DFD Server triggers the deferred apply after
the distribution reaches a terminal state (completed or failed).

In the DFU Client confirmed() callback, treat the self-target as
successful even though it hasn't ACKed the Firmware Update Check
message yet — it can't respond because apply was deferred.

Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-21 13:40:14 -07:00
Aleksandr Khromykh
3792c349f0 bluetooth: mesh: fix dfu srv state persistence on failure paths
The persistence refactoring introduced store_state() calls for the
APPLYING phase, but the error paths in apply_rsp_sent() incorrectly
store state instead of erasing it when transitioning to IDLE:

- When apply prerequisites are missing (no callback or invalid idx),
  the phase resets to IDLE but store_state() persists an IDLE phase
  that will be rejected on restore. Use erase_state() instead.

- When the application apply callback fails, same issue.

- When handle_cancel() resets the phase to IDLE, the previously
  persisted APPLYING state is not erased, causing stale state to
  survive across reboots.

Replace store_state() with erase_state() on all paths that transition
to IDLE, and add erase_state() in handle_cancel().

Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-21 13:40:14 -07:00
Aleksandr Khromykh
66f253efee bluetooth: mesh: decouple dfu srv persisted state from runtime struct
Introduce a __packed struct dfu_srv_persistent_state for storing
the DFU Server update state to flash, instead of persisting the
runtime srv->update substruct directly. The store and restore
functions now explicitly marshal/unmarshal each field.

This decouples the on-flash binary layout from the runtime struct,
making it safe to extend or reorder the runtime struct in the future
without breaking previously stored data. The approach matches the
pattern already used by the DFD Server persistence.

The new packed struct is binary-compatible with the existing runtime
layout, so no settings migration is needed.

Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-21 13:40:14 -07:00
Aleksandr Khromykh
3fb6e7d21e bluetooth: mesh: restore dfu client state for self-update resume
Add bt_mesh_dfu_cli_restore() to put the DFU client into the applied
state with a valid inputs pointer after reboot. Called from
dfd_srv_settings_set() when recovering the Applying Update phase.

This allows bt_mesh_dfu_cli_confirm() to succeed post-reboot, which
is required for the confirm step to poll targets and complete the
distribution.

Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-21 13:40:14 -07:00
Aleksandr Khromykh
7cfbd1f449 bluetooth: mesh: persist dfd srv state for self-update resume
Persist distribution parameters and target list in the DFD Server
when entering the Applying Update phase. Erase persisted state at
terminal phases (Idle, Completed, Failed) to prevent re-triggering
after subsequent reboots. This is the only phase that needs recovery
after reboot for self-update resume.

The slot pointer is resolved in dfd_srv_start() because the slot
settings subtree may load after model settings during initialization.

Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-21 13:40:14 -07:00
Aleksandr Khromykh
1de08e0b6e bluetooth: mesh: dfu_cli, dfu_srv: accept SUCCESS + APPLYING as terminal
MshDFUv1.0 Section 6.1.3.6 requires the Firmware Update Server to
respond to a Firmware Update Apply message with status Success and
phase Applying Update when its Update Phase state is Verification
Succeeded or Applying Update (idempotency). The response phase is
always Applying Update in the SUCCESS case.

Section 7.1.2.6 defines the removal rules for the Apply Firmware On
Target Nodes procedure: a Target whose Firmware Update Additional
Information state is not 0x03 (i.e. stays provisioned) that responds
with the Update Phase field set to Applying Update is kept in the
Active Update Receivers state, meaning the Apply step completed
successfully for that Target. The subsequent Refresh Target Nodes
Status procedure (Section 7.1.2.8) is responsible for verifying that
the Target eventually reaches phase Idle.

On the client side, ack any target that answers SUCCESS + APPLYING
during STATE_APPLY, not only the self-target. Previously the response
was dropped without acking the broadcast, so the broadcast retried
Update Apply until timeout and then failed the target with
BT_MESH_DFU_ERR_INTERNAL, wasting ~10 s before the Confirm step could
start. Retrying is also pointless because the Update Apply message is
idempotent (Section 6.1.3.6): further retries cannot change the SUCCESS
+ APPLYING response.

On the server side, split the Firmware Update Status send callback
handling by error type. A start-of-send error (buffer alloc, cancel,
...) means no segments were transmitted; revert the phase to
Verification Succeeded so a client retry is accepted as a fresh apply
per Section 6.1.3.6 "Apply firmware". An end-of-send -ETIMEDOUT means
segments were transmitted but no segment ack was received; a
spec-compliant client that received any complete copy of the SUCCESS
+ APPLYING response has treated it as terminal for the Apply step and
will not retry Update Apply, so proceed with the apply so our state
matches what the client believes. Any other end-of-send error still
reverts the phase. If the client did miss the response and does retry,
the retry hits handle_apply's idempotent APPLYING-phase branch.

Update test_cli_stop's APPLYING case to match: it now expects
BT_MESH_DFU_SUCCESS + PHASE_APPLYING instead of the obsolete
INTERNAL failure outcome.

Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-21 13:40:14 -07:00
Johan Hedberg
abdc9ec155 Bluetooth: Host: Lock the TX complete list when appending to it
hci_num_completed_packets() appends the TX contexts to conn->tx_complete
without any locking, while tx_notify_process() pops them with interrupts
locked. The list is therefore only safe as long as the producer cannot
be preempted by the consumer, which is not something the list itself
guarantees.

Append with the same lock the consumer uses.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-21 16:19:41 +02:00
Johan Hedberg
a39ff7fc96 Bluetooth: HCI: Identify the controller in the startup banner
The startup banner made it hard to tell which controller an image is
running against. The line was labelled "Firmware", the fw_variant 0x00
string was the generic "Standard Bluetooth controller", and the only
manufacturer shown was the one on the "HCI: version" line, which is the
Bluetooth company identifier of whoever wrote the controller and reads as
if it identified the stack.

Label the line "Controller" and include the manufacturer on it. Print
"Zephyr Bluetooth Controller" when the controller reports the standard
variant together with The Linux Foundation company identifier, which is
what the Zephyr controller responds with. The meaning of the fw_variant
values is unchanged, since 0x00 is also reported by other conforming
controllers, both in-tree (ESP32) and out of tree. Rename the fw_variant
0x01 string to "Vendor specific Bluetooth Controller" and update the
sample output in the shell documentation to match.

Fixes: #80679

Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Assisted-by: Claude:claude-opus-5
Assisted-by: Claude:claude-fable-5
2026-08-21 16:18:56 +02:00
Johan Hedberg
7fe0fd9b78 Bluetooth: Classic: SDP: Do not block the workqueue on buffer allocation
The SDP client allocates the receive buffer from the application
provided pool with K_FOREVER, in sdp_client_discover() while holding
the session lock, and in the L2CAP alloc_buf callback which
sdp_client_connected() also calls with the lock held.

Both run in the Bluetooth workqueue, which is the same context that
releases these buffers once a discovery completes, so waiting for a
buffer there cannot make progress. It also blocks any other user of the
session for as long as the pool stays empty.

Allocate without waiting. Both call sites already handle the allocation
failure by disconnecting the SDP channel, and the L2CAP layer handles
alloc_buf() returning NULL, so the assert on the returned buffer is
dropped.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-20 08:16:23 -07:00
Johan Hedberg
6834471202 Bluetooth: Host: Remove unused num_phys from bt_le_create_conn_ext()
num_phys was used to size the command buffer, and became dead when
commit 2ea9605380 ("Bluetooth: Host: core: Use bt_hci_cmd_alloc()")
made the buffer be allocated without a length.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-20 08:14:36 -07:00
Johan Hedberg
f9f9dd8796 Bluetooth: Host: Mark assert-only variables as __maybe_unused
Same as the previous commit, for the remaining variables in conn.c and
l2cap.c that are only ever read by an __ASSERT().

Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-20 08:14:36 -07:00
Johan Hedberg
eb712322e8 Bluetooth: SMP: Mark assert-only variables as __maybe_unused
These variables exist only to be checked by __ASSERT_NO_MSG(), which
compiles out when CONFIG_ASSERT is disabled, leaving them set but never
read. GCC builds do not show this since Zephyr passes
-Wno-unused-but-set-variable, but clang and arcmwdt enable the warning
at warning level 1.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-20 08:14:36 -07:00
Johan Hedberg
de7466e9c4 Bluetooth: SMP: Unlock mutex on public key generation timeout
bt_smp_le_oob_generate_sc_data() returns directly when k_condvar_wait()
times out, without unlocking pub_key_gen.lock. k_condvar_wait()
re-acquires the mutex before returning, on timeout as well as on
signal, so the mutex is left locked forever.

Any subsequent public key generation callback then blocks whichever
context runs it indefinitely, since pub_key_ready_notify() takes the
same mutex with K_FOREVER.

Unlock the mutex before returning on the timeout path.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-20 08:10:37 -07:00
Emil Gydesen
86121554c4 Bluetooth: BAP: SD: Notify only bonded devices on reconnect
When a bonded device reconnects and the receive state has changed
while the bonded device was offline, then per the BASS specification
the Scan Delegator shall send a notification with the receive state.

Previous implementation did this too by simply sending the notification
for all receive states regardless of whether the reconnected device
was bonded or not.

Some minor changes to prevent race conditions were also done.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-20 08:53:30 +02:00
Emil Gydesen
ce301f954e Revert "Bluetooth: CAP: add subprocedure callbacks for unicast start and stop"
This reverts commit 54737c9fb0b7294d2cc7c396ba04782dd9b72f9b.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-19 18:43:29 -04:00
Emil Gydesen
e5741df27c Bluetooth: CAP: Fix bug in cap_to_bap_unicast_params.stream_params
BAP_UNICAST_CLIENT_ASE counts are per connection, and not reflect
the actual number of streams that may exist in a group. Changed to
use CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT * @ which does
reflect that exactly. The reason why it needs to be multiplied by 2,
is that CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT refers to the
number of CIS, and we may have twice as many BAP streams (as they
unidirection, and CIS may be bidirectional).

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-19 18:42:38 -04:00
Szymon Janc
6b2c9d26b3 Bluetooth: ATT: Fix not ignoring write cmd from change unware client
ATT Write commands from change unware client shall be ignored.
Previously ATT request opcode was used for request but 0 for command
when passed to att_write_rsp() which was not updated when refactored
to perform_write() which expects ATT opcode for all operations.

Also rename req to op in struct write_data to better describe what
is being keep there now.

This was affecting GATT/SR/GAS/BV-05-C qualification test case.

Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
2026-08-19 17:16:34 +01:00
Emil Gydesen
7ccf8a1dc0 Bluetooth: CAP: add subprocedure callbacks for unicast start and stop
The CAP unicast audio start and stop procedures consist of several
subprocedures, and applications may need to know when each of these have
completed, e.g. to reconfigure the unicast group after the streams have
been codec configured but before they are QoS configured.

Add new callbacks to bt_cap_initiator_cb for each subprocedure of the
unicast audio start and unicast audio stop procedures. The callbacks are
only called if at least one request was sent to a CAP acceptor as part of
the subprocedure, so that subprocedures that are skipped because all
streams are already in the requested state do not trigger a callback. To
support this a new subproc_initiated field has been added to the common
procedure struct, which is reset whenever a new subprocedure is set.

The unit tests have been extended to verify both that the callbacks are
called when the subprocedures are performed, and that they are not called
when the subprocedures are skipped, and the BSIM CAP initiator unicast
test now waits for the new callbacks as part of the start and stop
procedures.

Assisted-by: Copilot:claude-opus-4.5

Co-authored-by: Thalley <2520413+Thalley@users.noreply.github.com>
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-19 17:12:05 +01:00
Emil Gydesen
acd3b540fa Bluetooth: CAP: fix start from QoS
Starting from QoS was not properly tested in the unit tests, and
thus did not catch a bug in the actual procedure.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-19 17:12:05 +01:00
Lyle Zhu
b6633c0343 bluetooth: classic: shell: add RLS command to SPP shell
Add a new shell command `spp rls` to allow testing of the RFCOMM Remote
Line Status (RLS) functionality through the SPP shell interface.

The command accepts optional error type parameters (overrun, parity, or
framing) to simulate serial port errors. When no parameter is provided,
it sends a no-error status.

The implementation uses the newly added `bt_rfcomm_send_rls_cmd()` API
to send RLS commands on the active SPP connection.

Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
2026-08-19 17:10:44 +01:00
Lyle Zhu
2964ab78f0 bluetooth: classic: rfcomm: add API to send Remote Line Status command
Add public API `bt_rfcomm_send_rls_cmd()` to allow applications to send
Remote Line Status (RLS) commands to RFCOMM DLC connections.

The new API validates the DLC connection state and sends RLS commands
with application-specified line status values to report serial port
errors such as overrun, parity, and framing errors.

Add helper macros `BT_RFCOMM_RLS_NO_ERR`, `BT_RFCOMM_RLS_ERR()`,
`BT_RFCOMM_RLS_ERR_OVERRUN_ERROR`, `BT_RFCOMM_RLS_ERR_PARITY_ERROR`,
and `BT_RFCOMM_RLS_ERR_FRAMING_ERROR` to simplify construction of line
status values.

Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
2026-08-19 17:10:44 +01:00
Vinayak Kariappa Chettimada
7a0096b5c9 Bluetooth: Controller: Use IS_ENABLED for sw switch timer guards
Replace the preprocessor "#if !defined(CONFIG_BT_CTLR_SW_SWITCH_
SINGLE_TIMER)" guards with runtime "if
(!IS_ENABLED(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER))" checks in
the DPPI and PPI radio HAL helpers. SW_SWITCH_TIMER and the
timer task enums are always defined, so the guarded code compiles
in both configurations and the compiler discards the disabled
branch, preserving behaviour while improving readability.

Assisted-by: CoPilot:Claude Opus 4.8
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2026-08-19 17:10:05 +01:00
Vinayak Kariappa Chettimada
d2c1019790 Bluetooth: Controller: Fix race in software radio switch timer
Fix race in software switch timer by starting and stopping
the switch on Radio End and Radio Enable, respectively.

The Radio PHYEND event and the software-switch timer compare
event occurred at the same timer value. This allowed the
next RADIO TXEN/RXEN operation to start while PHYEND was
resetting the timer for the next software-TIFS interval,
leaving the controller in an invalid state.

Relates to commit 5fe53aaa84 ("Bluetooth: Controller: Use
PPI/DPPI to start s/w switch timer").

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2026-08-19 17:10:05 +01:00
Vinayak Kariappa Chettimada
8b8178b7e5 Revert "Bluetooth: Controller: Fix timer start without LLL prepare at margin"
This reverts commit 1b93c8b973.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
2026-08-19 17:10:05 +01:00
Johan Hedberg
ee78599867 Bluetooth: Classic: L2CAP: Handle channel add failure in connection req
l2cap_br_conn_req() ignores the return value of l2cap_br_chan_add(),
unlike both of its other callers. When the dynamic CID allocation
fails, the code continues as if the channel was fully set up: it sends
a connection response whose DCID is the CID that was never allocated
(0), and the channel object that the server just accepted is never
attached to the connection. Since the channel is not on the
connection's channel list, no disconnected or released callback will
ever be called for it, so the server considers the object in use
forever and one of its channels is permanently leaked.

Check the return value, give the channel back to the server through
the normal bt_l2cap_br_chan_del() lifecycle, and reply to the remote
with "no resources available".

Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-19 11:27:21 +02:00
Lyle Zhu
31ab67be91 bluetooth: classic: rfcomm: refactor RPN handler
There is an issue that the receive buffer was modified while
processing the command to set the RPN.

Remove `default_rpn` to `rsp`. Simplify `rfcomm_handle_rpn()` by
consolidating response handling into a single `rsp` variable.

In the command handler path, copy the received `rpn` structure to
`rsp`, modify the param_mask, and send the response. This replaces the
previous approach of modifying the input received buffer structure
directly.

Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
2026-08-19 11:25:31 +02:00
Lyle Zhu
0040ef781e bluetooth: classic: rfcomm: improve error handling and buffer check
Add comprehensive error handling and buffer validation to RFCOMM
message handlers to prevent potential buffer underflow and invalid
data processing.

Remove FCS byte from buffer using `net_buf_remove_mem()` in
`rfcomm_recv()` instead of relying on length checks in data handler.

Simplify `rfcomm_handle_data()` by removing redundant FCS length check
since FCS is now removed earlier in the processing chain.

Refactor MCC message handler to properly validate buffer length and
use `net_buf_pull_mem()`/`net_buf_pull_u8()` for safe buffer access.

Add length check in TEST command handler to prevent overflow when
casting to `uint8_t`.

The change addresses a potential out-of-bounds buffer access issue,
preventing potential security issues in RFCOMM operations.

Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
2026-08-19 11:25:31 +02:00
Make Shi
b0c22ba6fe Bluetooth: Classic: HID: fix buffer tailroom in HID device
The second argument of bt_l2cap_create_pdu() is the reserve
(headroom), not the payload size. The code passed
sizeof(struct bt_hid_hdr), which consumed the whole buffer as
headroom and left tailroom = 0. The following net_buf_add() then
hits the __ASSERT() and hangs on debug builds, or writes out of
bounds on release builds.

Signed-off-by: Make Shi <make.shi@nxp.com>
2026-08-19 11:19:24 +02:00
Johan Hedberg
59c947c71f Bluetooth: Classic: HFP: Fix HF teardown and object reuse on disconnect
hfp_hf_disconnected() leaves the HF object in a state where reusing it
is unsafe:

- The work items are canceled, but cancellation does not affect a
  handler that is already running, and the handlers can block for a
  long time in hfp_hf_send_cmd(), which allocates from hf_pool with
  K_FOREVER. hfp_hf_create() only checks hf->acl before wiping the
  object with memset(), so a new connection on the same index can wipe
  the work items, the TX FIFO and the AT client state under a
  still-running handler.

- Buffers still queued on tx_pending are never freed. Nothing sends
  them once the DLC is gone, and the memset() on reuse then loses them
  from hf_pool permanently. A fully parked pool also means a handler
  blocked in the hfp_hf_send_cmd() allocation never wakes up.

- The CONNECTED flag is never cleared (only the memset() on reuse
  does), so command senders keep queueing buffers for the dead DLC
  between disconnection and reuse instead of failing with -ENOTCONN.

Clear the CONNECTED flag and drain tx_pending in
hfp_hf_disconnected(), and make hfp_hf_create() refuse to reuse the
object while any of the work items is still pending or running. The
refusal is a transient condition: once the handlers have finished, the
next connection attempt succeeds.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
2026-08-19 11:17:42 +02:00
Anas Nashif
d9dd702b2f Bluetooth: CAP: fix function names in disconnect handling
Commit 6c461f291f ("Bluetooth: CAP: Handle disconnects during
procedures") added calls to active_proc_is_initiator() and
active_proc_is_commander() in bt_cap_common_disconnected(), but no
such functions exist; the actual helpers are prefixed with
bt_cap_common_. This fails the build with an implicit function
declaration error (-Werror) whenever CONFIG_BT_CAP_INITIATOR_UNICAST
or CONFIG_BT_CAP_COMMANDER is enabled, breaking the bsim audio tests
in push CI on main.

Use the correctly prefixed function names.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-08-18 20:21:01 -04:00
Emil Gydesen
61f8752bd0 Bluetooth: BAP: Shell: Change to use CONFIG_BT_ISO_MAX_CHAN for cnt
Instead of support a `shell_stream` for each supported ASE,
we now just support CONFIG_BT_ISO_MAX_CHAN. Since
CONFIG_BT_ISO_MAX_CHAN is the limiting factor in actually setting
up a stream, this is a significantly better way to control the
number of streams. We could optimize further as
CONFIG_BT_ISO_MAX_CHAN contains both unicast and broadcast
streams, so we may only support fewer unicast streams
than CONFIG_BT_ISO_MAX_CHAN at some points in time.

With the default audio.conf this results in a massive RAM
savings:

Before:
Memory region         Used Size  Region Size  %age Used
           FLASH:      890368 B         1 MB     84.91%
             RAM:      405410 B       448 KB     88.37%
        IDT_LIST:           0 B        32 KB      0.00%

After:
Memory region         Used Size  Region Size  %age Used
           FLASH:      890480 B         1 MB     84.92%
             RAM:      330674 B       448 KB     72.08%
        IDT_LIST:           0 B        32 KB      0.00%

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-18 17:19:48 -04:00
Emil Gydesen
bd669af116 Bluetooth: CAP: Add bt_cap_handover_cancel
Add a new function to specifically cancel handover
procedures, similar to the command and initiator functions.
Additionally adds checks for the procedure type to ensure
that the right cancel function is used, to avoid any
unexpected behavior from CAP.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-18 17:19:38 -04:00
Aleksandr Khromykh
33ead0df85 Bluetooth: Mesh: Make the LPN Friend Offer wait time configurable
Add BT_MESH_LPN_OFFER_WAIT_TIMEOUT to configure how long the Low
Power node listens for Friend Offer messages after sending a Friend
Request. The Mesh Protocol specification section 3.6.6.4.1
recommends up to 1 second, but the optimal value depends on the
deployment, so keep 1000 ms as the default and allow tuning it.

Also introduce a separate FRIEND_CLEAR_TIMEOUT for the Friend Clear
Confirm wait. The specification defines no timeout for it, so it
must not change when the Friend Offer window is tuned.

Assisted-by: GitHub Copilot:claude-opus-5
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
2026-08-18 19:18:18 +01:00
Emil Gydesen
0afc892200 Bluetooth: CAP: Handover: Shell: Workaround for case for bsrc started
If the broadcast source was created and started but the handover
still failed, then we should stop and delete the broadcast source.

However bt_cap_initiator_broadcast_audio_stop is not a synchronous
function, and we cannot just stop it directly in the callback.
Instead of offloading that to another thread, we simply instruct
the shell user to manually stop and delete the source (if they
want to).

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-18 19:15:16 +01:00
Emil Gydesen
6c2817ec2c Bluetooth: CAP: Ini: Fix bad assign to group on fail
If int bt_cap_unicast_group_create failed then the out
group should not be assigned, but it was.
This commit ensures that on failure, the out group will
point to NULL.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-18 19:14:39 +01:00
Emil Gydesen
328fe1d22f Bluetooth: AICS: Add bt_aics_mode_to_str
Add function to return a human-readable version of the AICS
gain mode.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-18 19:14:26 +01:00
Emil Gydesen
40c3d9d89c Bluetooth: BAP: Shell: Add additional pretty printing for values
Modify a few places to print the string and numeric values,
instead of just the numeric value.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-18 19:14:08 +01:00
Emil Gydesen
6e1ed38e4f Bluetooth: Audio: Shell: Pretty print location
Pretty print the locations of the remote server during discovery.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
2026-08-18 19:14:08 +01:00