a2dp_get_connection() wipes the whole bt_a2dp object, including the
embedded AVDTP session, with memset() when the object is not currently
associated with a connection. The session's _release_work, submitted
from bt_avdtp_l2cap_disconnected(), may still be queued at that point,
and wiping a queued work item corrupts the work queue's pending list.
Skip the reuse and return NULL while the release work is still
pending, mirroring the check on the AVDTP side in the preceding
commit. Both callers already handle a NULL return by rejecting the
connection attempt, which can be retried once the release work has
completed.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_avdtp_l2cap_disconnected() submits session->_release_work to defer
the release of the session's endpoints. Both bt_avdtp_connect() and
bt_avdtp_l2cap_accept() unconditionally k_work_init() the same work
item when the session object is reused for a new connection.
Re-initializing a work item that is still queued corrupts the work
queue's pending list.
The work item cannot simply be canceled on reuse, since the deferred
endpoint release must always run. Instead, reject the session reuse
with an error while the release work is still pending; the connection
can be retried once the work has completed. The check is done under
avdtp_sem_lock, and since the session has no L2CAP connection at that
point, no new submission of the work can race with it.
A similar lifecycle issue with session->timeout_work being
re-initialized while potentially still scheduled is being addressed
separately.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
If the connection drops in the middle of reassembling a fragmented
vendor dependent response, ct->reassembly_buf is left referenced. The
buffer is only reclaimed if the same connection index later starts a
new reassembly, so in the meantime such disconnections can exhaust the
RX pool, which is only CONFIG_BT_MAX_CONN deep.
Drop the reassembly buffer on disconnection. This is the same class of
issue as the TG vendor response TX state fixed in the preceding
commit.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
avrcp_disconnected() neither cancels tg->vd_rsp_tx_work nor releases
the buffers queued in tg->vd_rsp_tx_pending. If the connection drops
in the middle of a fragmented vendor dependent response, the pending
buffer, from a pool that is only CONFIG_BT_MAX_CONN deep, is leaked
with its TX_ONGOING flag still set in the buffer user data. Since the
TG object is selected by connection index, a new connection on the
same index finds the stale buffer at the head of the pending list, and
the TX state machine remains permanently stalled with any new
responses queued behind the stale head and never sent.
Cancel the TX work and release all queued TX buffers on disconnection.
The per-buffer TX context, including the TX_ONGOING flag, lives in the
buffer user data, so releasing the buffers also resets the TX state.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Since this a "get" function that does not, and never should,
modify the provided advertising set pointer, modify it to be
const.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Use S8 flags when setting up Coded PHY reception.
This keeps receive timing consistent with other coded RX setup paths.
Pass selected advertising PHY flags to coded TX delay calculations.
This avoids treating S2/S8 selection as unused during delay setup.
Use unsigned zero literals for the zero-valued PHY macros.
Document the RX/TX coding flag choice in advertising paths.
Signed-off-by: Daniel Polimac <danielpolimac@gmail.com>
Replace literal Coded-PHY flags with the named S2 and S8 constants
throughout the Nordic and OpenISA controller paths.
Part of #37458
Signed-off-by: Daniel Polimac <danielpolimac@gmail.com>
Move channel state transition to config rsp sent callback to ensure
the response is actually transmitted before marking the channel as
connected. Previously, the state was updated with connected state and
the channel `connected` will also be involved immediately after queuing
the response. In the callback `connected`, the packets will be sent by
the upper layer profiles to the sending queue immediately. Because the
config RSP and the upper-layer profile send data through different
channels, the host cannot guarantee that these packets are sent in the
order of the sending function calls. Therefore, it is possible that
profile packets may precede config RSP packets on the HCI bus.
This change introduces `l2cap_br_config_rsp_sent_cb()` to handle the
`L2CAP_FLAG_CONN_RCONF_DONE` flag and state transition only after the
config response is successfully sent. Error responses continue to use
the non-callback send path as they don't affect channel state.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Replace programming error checking with runtime assertions in
`mce_mns_accept()` and `mse_mas_accept()` functions. The instance
and callback validation checks are converted to `__ASSERT()` calls
since these conditions indicate programming errors rather than
runtime failures.
Initialize mce_mns and mse_mas to NULL to ensure the assertions can
properly detect uninitialized instances passed from the accept
callbacks.
The change aligns with the error handling approach used in the GOEP
layers' accept callbacks, treating invalid instance parameters and
initialization failures as programming errors that should be caught
during development.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Replace programming error checking with runtime assertions in
`bip_rfcomm_accept()` and `bip_l2cap_accept()` functions. The bip
instance validation is converted to `__ASSERT()` calls since a NULL
instance indicates a programming error in the upper layer's accept
callback implementation rather than a runtime failure.
Initialize bip to NULL to ensure the assertion can properly detect
uninitialized instances passed from the accept callbacks.
The change aligns with the error handling approach used in the GOEP
layers' accept callbacks, treating invalid instance parameters as
programming errors that should be caught during development.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Replace programming errors with runtime assertions in
`pbap_pse_rfcomm_accept()` and `pbap_pse_l2cap_accept()` functions.
The pbap_pse instance validation is converted to `__ASSERT()` calls
since a NULL instance indicates a programming error in the upper
layer's accept callback implementation.
Initialize pbap_pse to NULL to ensure the assertion can properly
detect uninitialized instances passed from the accept callbacks.
The change aligns with the error handling approach used in the GOEP
layer's accept callbacks, treating invalid instance parameters as
programming errors that should be caught during development.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
In original implementation, there is a corner case that the instance
has been allocated by upper layer and passed it through `accept()`
callbacks. And normally the allocated instance will be destroyed after
the connection broken. While in the post-accept, due to some errors,
it is possible that the connection may not be accepted by
`goep_rfcomm_accept()` or `goep_l2cap_accept()` functions. And all of
these errors are programming errors.
Replace programming error checking with runtime assertions in
`goep_rfcomm_accept()` and `goep_l2cap_accept()` functions. The
parameter validation and initialization error checks are converted to
`__ASSERT()` calls since these conditions indicate programming errors
rather than runtime failures.
The change is used to treat invalid instance parameters as programming
errors that should be caught during development.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
The `goep_rfcomm_init()` and `goep_l2cap_init()` functions are used
internally during transport setup, and their error conditions
represent programming errors.
Convert both initialization functions from returning error codes to
using runtime assertions.
The change treats transport initialization failures as programming
errors that should be caught during development.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
The function `bt_obex_reg_transport()` is used internally by the
Bluetooth Classic Host, and its parameter should not be NULL unless
there is a programming error.
Convert `bt_obex_reg_transport()` from returning error codes to using
runtime assertions. Replace if-condition NULL pointer checks with
`__ASSERT()` to catch invalid parameters during development.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
For the BIS specific data configuration, we should check
stream_param->data for NULL before supplying that to memcpy,
even if stream_param->data_len == 0, as memcpy does not
support NULL pointers.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
The check was comparing `rank` to `rank`, rather than
the minimum and maxmimum values of rank.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
BT_MESH_IVU_HOURS is BT_MESH_IVU_MIN_HOURS divided by
CONFIG_BT_MESH_IVU_DIVIDER with integer truncation, so the step by
which bt_mesh.ivu_duration grows need not divide 96. For dividers 5,
7, 9, 10, 13, 17, 18 and 19 the step is 19, 13, 10, 9, 7, 5, 5 and
5, and the duration steps over the 96 hour boundary without landing
on it. The old exact-multiple test then never flushed the beacon
cache, so a beacon refused because of the limit stayed cached, every
identical retransmission was dropped as a duplicate, and the node
never ran IV Update or IV Index Recovery once the limit expired.
Assisted-by: GitHub Copilot:claude-opus-5
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
bt_mesh_iv_update_test() lifts the 96-hour dwell time of the IV Update
procedure, but left the Secure Network beacon cache untouched. A
beacon that arrives while the limit is in force is cached by
net_beacon_resolve() and only then refused, so every identical
retransmission is filtered as a duplicate and the IV Update never
happens.
ivu_refresh() already clears the cache when the limit expires in
normal operation. Test mode lifts it without the timer running, so
apply the same invalidation there. Caching stays independent of test
mode, as required by MshPRT v1.1.1, section 3.11.5.1.
Assisted-by: GitHub Copilot:claude-opus-5
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
hfp_hf_disconnected() cancels hf->work and hf->deferred_work, but not
hf->slc_work, which is submitted to the system work queue both from
hfp_hf_connected() and from the SDP discovery callback. Once the
object has been marked as free (hf->acl == NULL), hfp_hf_create()
wipes the whole object with memset() when the slot is reused. Wiping a
work item that is still queued corrupts the work queue's pending list.
Additionally, an ongoing SDP discovery cannot be canceled
(bt_sdp_discover_cancel() is declared but has no implementation), so
the discovery callback may fire after the RFCOMM DLC has been
disconnected and re-submit slc_work for an already released object.
Fix this by canceling slc_work in hfp_hf_disconnected(), and by making
the discovery callback check that the object has not been released by
hfp_hf_disconnected() while the discovery was still ongoing. To make
that check reliable also on the connecting path, assign hf->acl before
starting the discovery in hfp_hf_create(), since the callback may
otherwise run before the assignment and treat the object as released.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The Passkey Entry protocol carries the 6-digit passkey one bit per
confirm/random round, over exactly 20 rounds. The peripheral however
re-armed BT_SMP_CMD_PAIRING_CONFIRM in smp_pairing_random() before
checking whether the last round had been reached, so a peer was able to
keep sending confirm/random pairs indefinitely once the real passkey bits
were exhausted.
Those extra rounds also passed validation: smp->passkey is a 20-bit value
held in a uint32_t, so rounds 20 through 31 simply compared the zero bits
above the passkey. Beyond round 31 the shift in smp_send_pairing_confirm()
and sc_smp_check_confirm() exceeds the width of the promoted operand and
is undefined behaviour.
Only arm BT_SMP_CMD_PAIRING_CONFIRM when a round actually remains, so that
a 21st Pairing Confirm is rejected as an unexpected command and pairing
fails. Additionally reject a round past the last one wherever the round
counter is incremented, so it can never exceed SMP_PASSKEY_ROUNDS and the
terminating comparisons stay exact. Replace the open-coded round count
with SMP_PASSKEY_ROUNDS.
Fixes#114792
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The PAwR advertiser previously discarded fragmented Periodic Advertising
Response Reports, so applications never received responses that spanned
multiple HCI reports.
Add optional reassembly, guarded by the new
CONFIG_BT_PER_ADV_RSP_REASSEMBLY (disabled by default). Fragments are
buffered per advertising set and delivered to the pawr_response callback
once the COMPLETE report arrives. Buffer overflow, a fragment for a
different chain, or an RX_FAILED report resets the reassembly state.
Signed-off-by: Alex Zhou <alex.zhou@nxp.com>
The extended advertising reassembly timeout handler mutates the
reassembling_advertiser state, which is also read and written by the
extended advertising report processing without any locking. The report
processing runs on the Bluetooth workqueue, while the timeout handler
was scheduled with k_work_reschedule() and so ran on the system
workqueue.
This is serialized only implicitly, by cooperative scheduling: it
holds because both workqueues run at cooperative priority (the
Bluetooth subsystem clamps SYSTEM_WORKQUEUE_PRIORITY to the
cooperative range for this reason) and as long as they share a CPU.
The latter is not structural: on SMP builds cooperative threads on
different CPUs run concurrently, in which case a timeout firing
concurrently with report processing can flip the state mid-sequence,
e.g. letting a chain that should have been discarded be delivered.
Schedule the timeout on the Bluetooth workqueue instead, making the
serialization structural instead of relying on scheduler
characteristics. This also makes the non-blocking
k_work_cancel_delayable() performed by the report processing reliably
effective, as canceller and handler now share a workqueue. The
remaining reset callers (HCI reset complete, bt_finalize_init() and
scan teardown) run while no advertising reports are being processed.
This is host-internal work with no application callback, so there are
no application-visible context changes.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_hfp_ag_connect() wipes the whole AG object with memset() when
bt_rfcomm_dlc_connect() fails. At that point the SDP discovery started
by hfp_ag_create() is still ongoing, and the embedded
ag->sdp_param._node is linked in the SDP client's request list, so the
memset() corrupts that list in place. It can also wipe a queued
ag->slc_work item, corrupting the work queue's pending list.
This is the same issue as the HF side one fixed in the preceding
commit; fix it in the same way by deferring the release of the object
to the SDP discovery callback, since an ongoing SDP discovery cannot
be canceled (bt_sdp_discover_cancel() is declared in the public header
but has no implementation).
Additionally, make the discovery callback check that the AG object has
not been released by hfp_ag_disconnected() while the discovery was
still ongoing. Since the discovery cannot be canceled, the callback
would otherwise set the DISCOVER_DONE flag and re-submit slc_work for
an already released object. To make that check reliable also on the
connecting path, assign ag->acl_conn before starting the discovery in
hfp_ag_create(), since the callback may otherwise run before the
assignment and treat the object as released.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_hfp_hf_connect() wipes the whole HF object with memset() when
bt_rfcomm_dlc_connect() fails. At that point the SDP discovery started
by hfp_hf_create() is still ongoing, and the embedded
hf->sdp_param._node is linked in the SDP client's request list, so the
memset() corrupts that list in place. It can also wipe a queued
hf->slc_work item, corrupting the work queue's pending list.
An ongoing SDP discovery cannot be canceled (bt_sdp_discover_cancel()
is declared in the public header but has no implementation), so the
object cannot be safely torn down synchronously. Instead, keep the
object allocated and mark it with the new RELEASING flag, making the
SDP discovery callback release it once the discovery has completed,
rather than proceeding with SLC establishment. In the unlikely case
that the discovery has already completed when the RFCOMM connection
creation fails, release the object immediately.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
sc_save() only calls sc_store() when a bond already exists for the peer,
so a client that subscribes to Service Changed before it bonds gets an
sc_cfg entry in RAM that is never written to settings. iOS does exactly
this: it subscribes right after connecting and only pairs later, once the
user accepts the dialog.
bt_gatt_identity_resolved() does not cover it either, since its sc_store()
call is likewise conditional on the bond already existing, and identity
resolution happens during key distribution rather than after the bond has
been committed.
The result is that the subscription survives in RAM for the current
connection but is lost across a reboot, so a characteristic change made
while disconnected is never indicated and the client keeps a stale cache.
Reconnecting papers over it, because the client subscribes again and by
then the bond exists.
Store the Service Changed configuration from bt_gatt_pairing_complete(),
where the ccc and cf data is already persisted for the same reason.
Fixes: #111078
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Assisted-by: Claude:claude-opus-5
MISRA C:2012 Rule 8.2 requires every parameter in a function type to be
named, including the parameters of function pointer parameters.
The LLCP remote request helper, the LLL test and scan helpers and the
PSoC 6 BLESS receive thread left parameters unnamed. The BLESS thread
gets ARG_UNUSED() for the arguments it deliberately ignores.
Name them after the arguments the documentation or the
definitions already use. No functional change.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Report the error code when bt_disable() fails, including the new
-EAGAIN case where initialization has not yet completed.
Signed-off-by: Guotao Zhang <guotao.zhang@nxp.com>
When bt_enable() is called with a ready callback, bt_init() runs
asynchronously on the system workqueue. If bt_disable() is invoked
before that work item completes, it races with bt_init() over
bt_dev.sent_cmd, which can be freed twice and trigger a buf.c:472
assert.
Fix this by checking k_work_busy_get(&bt_dev.init) at the top of
bt_disable(). If init is still queued or running, return -EAGAIN so
the caller can retry once the ready callback fires.
Note: the same race can occur with a synchronous bt_enable(NULL)
called concurrently from another thread; that case will be covered
by BT_DEV_ENABLING/BT_DEV_DISABLING transition flags introduced in
a follow-up change.
Document the new -EAGAIN return code in bt_disable()'s Doxygen.
Signed-off-by: Guotao Zhang <guotao.zhang@nxp.com>
The BAP stream callbacks does not mirror the ASCS states 1:1
so there are a few cases where the callbacks are called without
matching the ASCS state.
BAP stream ops are intended to be the same for sink and source
ASEs, even though they have different state machine,
but sink streams did
stopped()
disabled()
qos_configured()
when exiting the streaming state (without a release), and source
streams did
disabled()
stopped()
qos_configured()
Refactor unicast_client_ep_notify_app a bit to have the same
callbacks in the same order for sinks and sources:
disabled()
stopped()
qos_configured()
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
bt_le_ext_adv_get_info() handed out a pointer to the advertising set's
random_addr, which is only written when a per-set random address is
programmed. When the set advertises with a public identity address the
reported address was never populated, and with a controller without the
extended advertising feature it was never written at all.
Instead of adding a second address field alongside random_addr, widen
the meaning of the existing one: rename it to adv_addr, the address the
set advertises with regardless of type. The per-set random address
cases keep being updated in bt_id_set_adv_random_addr(), so the
reported address stays correct across RPA and NRPA rotation, and
le_update_private_addr() refreshes the legacy advertiser, which
advertises with the device-wide random address.
The cases that do not program a per-set address - a public identity
address, and the device-wide random address on controllers without the
extended advertising feature, e.g. an RPA set through
bt_id_set_private_addr() when privacy is enabled - are saved by a new
bt_id_save_adv_addr(), which the advertising parameter setting calls
once the controller has accepted the parameters. Saving only at that
point ensures a failed parameter update does not overwrite the reported
address with one the controller never took into use.
Widening the field is safe for the existing readers: the connection
responder address and OOB paths that read it only execute in
configurations where the set advertises with a random address, in which
case the value is unchanged, and a pending random address is programmed
from the field before bt_id_save_adv_addr() runs.
For the BT_HCI_OWN_ADDR_RPA_OR_* types the controller substitutes a
locally generated RPA whenever the peer is in the resolving list, which
the host cannot observe; the configured fallback address is reported in
that case, as documented on the info struct.
Fixes: #112667
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Move the responder role check outside the is_bip_primary_connect()
conditional so it applies to all connection types. Remove the
initiator role check from the secondary path since a responder role
is valid for secondary connections initiated by the remote device.
This ensures that a BIP instance configured as responder cannot
initiate any client connections, regardless of connection type.
Signed-off-by: Cheng Chang <cheng.chang@nxp.com>
bt_bap_unicast_group_reconfig did not properly set the fields
related to CONFIG_BT_ISO_TEST_PARAMS nor packing.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Add the CIG parameters of the unicast group (SDU intervals, transport
latencies, framing, packing and, when CONFIG_BT_ISO_TEST_PARAMS is
enabled, the flush timeouts and the ISO interval) as well as the
has_been_connected state to struct bt_bap_unicast_group_info, so that
applications can retrieve all relevant information about a group.
The framing is stored internally using the ISO values, and is converted
back to the BAP QoS configuration values when reported.
The existing bsim tests for bt_bap_unicast_group_get_info have been
expanded to verify the new values, including for a group with
asymmetric parameters and for a reconfigured group.
Assisted-by: Copilot coding agent
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
The ep->unicast_group was never assigned and thus
has_been_connected was never set for the BAP unicast groups.
Change to use the stream->group instead.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
CONFIG_BT_FIXED_PASSKEY, bt_passkey_set() and BT_PASSKEY_INVALID were
deprecated in commit 82cfb5a056 ("Bluetooth: Host: Deprecate
BT_FIXED_PASSKEY"), released in Zephyr 4.3, in favour of the app_passkey
callback gated on CONFIG_BT_APP_PASSKEY. Two releases have passed, so
remove them.
The replacement covers what the option did: an application that returns a
constant from bt_conn_auth_cb.app_passkey gets a fixed passkey, and one
that returns BT_PASSKEY_RAND gets a Host generated one, which is what
BT_PASSKEY_INVALID was used to fall back to.
DISPLAY_FIXED() could only ever be true with a fixed passkey configured,
so the four conditions using it reduce to the JUST_WORKS test they were
already OR'd with. Likewise the two branches in get_io_capa() that
upgraded the reported capability when a fixed passkey was set collapse to
the values they already returned otherwise; the CONFIG_BT_APP_PASSKEY
block above them covers that case for the replacement API. Behaviour is
therefore unchanged for anyone not enabling the removed option.
Drop the accompanying build warning and the hardened.csv entry, both of
which existed only to steer users away from the option.
Fixes: #36005
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Assisted-by: Claude:claude-opus-5
The playback_speed_param value was not used to correct
adjust the position while in the playing or state.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
The UART monitor backend sends every byte with uart_poll_out(). At
common UART rates this blocks the Bluetooth host while HCI traffic
and logs are serialized.
Add an opt-in interrupt-driven mode that buffers complete monitor
records and drains them from the UART interrupt handler. Record
fragments are copied in with ring_buf_put_ptr() and published with a
single ring_buf_commit(), so a record is either fully present in the
buffer or absent. This matters on panic: the panic handler flushes
only complete records before switching to polling, keeping the
stream parseable. Only the header-inline zero-copy ring buffer API
is used, so the option does not need to select RING_BUFFER.
A record that does not fit is dropped whole and reported through the
existing drop counters. Counts already consumed into a dropped
record's header are restored, keeping the accounting exact across
consecutive drops, and counts exceeding the 8-bit header field carry
over to the next record. Both kinds of loss previously also affected
the RTT backend, which shares this code.
Polling output remains the default and the panic-mode fallback,
since interrupts may no longer run during panic handling. It is also
the runtime fallback when the monitor UART driver lacks interrupt
support, since SERIAL_SUPPORT_INTERRUPT only guarantees that some
driver has it. The option depends on !LOG_MODE_MINIMAL because
minimal logging has no panic hook to flush buffered output.
Measured on nrf52dk/nrf52832 and xg24_rb4186c with a peripheral
flooding GATT notifications and the monitor sharing the 115200 baud
console UART: polling caps throughput at 5.9-6.6 KB/s, slows a paced
25 notifications/s workload to 15/s and blocks the producing context
~6 ms per large record (10-line printk burst: 58-65 ms). The
interrupt-driven mode restores radio-limited throughput (41 KB/s)
and the nominal paced rate, with the same burst at 0.8-1.3 ms. The
trade-off is load shedding: under sustained overload ~87% of
full-size ACL records are dropped (and accounted), while small
records such as Number of Completed Packets events keep flowing.
Unit tests cover contiguous and wrapped records, failed
reservations, zero-length fragments and exact-fit records; an
integration test runs the real producer/ISR path against the
emulated serial-test UART, covering drain, buffer-full drops with
accounting, and wrap-around consistency. The Bluetooth init test
builds the interrupt-driven path with the deferred log backend,
since tests default to minimal logging. Builds also pass with
polling UART and RTT.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The L2CAP server is now registered when the upper layer registers AVDTP
callback, which is a more appropriate time since AVDTP cannot function
when the upper layer doesn't register callback to enable the AVDTP
function.
Signed-off-by: Mark Wang <yichang.wang@nxp.com>
The AVDTP event handlers are now registered when the application
registers its A2DP callback, which is a more appropriate time since
A2DP cannot function when the application doesn't register a callback
to enable the A2DP functionality.
Signed-off-by: Mark Wang <yichang.wang@nxp.com>
Remove CONFIG_BT_MESH_BLOB_IO_FLASH_WITH_ERASE and
CONFIG_BT_MESH_BLOB_IO_FLASH_WITHOUT_ERASE. There is no replacement: the
BLOB IO Flash module stopped reading them in Zephyr 4.3 and instead
queries the erase capability at runtime through
flash_params_get_erase_cap(), so both options have been no-ops since
then. The enclosing "if BT_MESH_BLOB_IO_FLASH" block is kept for
BT_MESH_BLOB_IO_FLASH_WRITE_BLOCK_SIZE_MAX.
Deprecated in Zephyr 4.3.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
Remove the CONFIG_BT_CTRL_ADV_ADI_IN_SCAN_RSP compatibility symbol,
which only selected the renamed CONFIG_BT_CTLR_ADV_ADI_IN_SCAN_RSP. The
CTLR-spelled option and its users in ull_adv_aux.c are untouched.
Deprecated in Zephyr 4.3.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
Remove the CONFIG_BT_CONN_TX_MAX Kconfig option and its only in-tree
user, the SiWx91x SoC configdefault. No C code has read the symbol since
it was deprecated, so it had no effect on any build; the number of
pending TX buffers with a callback follows CONFIG_BT_BUF_ACL_TX_COUNT,
which was already both the default and the range floor of the removed
option. The SiWx91x default of 15 matched that SoC's
BT_BUF_ACL_TX_COUNT default, so behaviour is unchanged there too.
Deprecated in Zephyr 4.2.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
Remove the CONFIG_BT_DIS_MANUF and CONFIG_BT_DIS_MODEL string options,
together with the BT_DIS_MANUF_DEPRECATED_USED and
BT_DIS_MODEL_DEPRECATED_USED helper symbols whose only purpose was to
detect their use. Use CONFIG_BT_DIS_MANUF_NAME /
CONFIG_BT_DIS_MANUF_NAME_STR and CONFIG_BT_DIS_MODEL_NUMBER /
CONFIG_BT_DIS_MODEL_NUMBER_STR instead.
With the helper symbols gone, the two characteristic bools no longer
need their "depends on !*_DEPRECATED_USED" guards and are
unconditionally default y again, and the #if/#elif ladders in dis.c
collapse to the non-deprecated branch.
Deprecated in Zephyr 4.1.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
This fixes a leak for the following scenario:
A bonded peer connects via undirected adv set while directed connectable
extended advertisement runs on the same identity.
The enhanced connection complete is cached, not yet processed and the
undirected set is terminated, which clears the `BT_ADV_ENABLED` flag.
During processing of the cached enhanced connection complete event, the
`find_pending_connect()` function then finds the directed set instead of
the undirected set (as until now there was no distinction of the
advertising set type in the lookup function). This leads to a
reservation leak, as the directed set is not terminated (but the
`BT_ADV_ENABLED` flag is cleared).
This commits adds the advertising set context to the
`bt_hci_le_enh_conn_complete()` and `find_pending_connect()` functions,
so that the correct advertising set is used for the lookup.
Note: This change has been locally tested with a test case created by AI
that reproduces the above scenario.
Signed-off-by: Kyra Lengfeld <kyra.lengfeld@nordicsemi.no>
oacp_command_decode() accepted the op code unconditionally while
oacp_proc_validate() handles it under a Kconfig guard. Both answer Op
Code Not Supported, so guard the decode arm to match, the way Create,
Delete and Write already are.
Signed-off-by: Flavio Ceolin <flavio@hubble.com>
oacp_ind_send() appended the Checksum Value based on the requested op
code alone, but validation only fills the response buffer on success.
Every error path therefore pulled four bytes from an empty buffer,
panicking with assertions enabled and reading stale stack without them.
Signed-off-by: Flavio Ceolin <flavio@hubble.com>
CONFIG_BT_AUTO_PHY_UPDATE was deprecated in Zephyr 4.3 in favour of the
role-specific BT_AUTO_PHY_CENTRAL and BT_AUTO_PHY_PERIPHERAL Kconfig
choices, which also allow picking which PHY is preferred. Remove it as
part of the 4.5 deprecation removal cycle.
All C code and all in-tree samples and tests were already migrated to
the role-specific options when the deprecation was introduced, so only
the remaining Kconfig references need dropping. Since the deprecated
symbol lost its "default y if !BT_USER_PHY_UPDATE" in 4.3, it has been
unset in every in-tree configuration ever since, which makes each of
these references dead code today:
- The BT_AUTO_PHY_PERIPHERAL choice loses its "default
BT_AUTO_PHY_PERIPHERAL_2M if BT_AUTO_PHY_UPDATE" entry and keeps
falling through to _NONE, as it already did.
- BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM loses the always-false
"BT_AUTO_PHY_UPDATE=y" disjunct of its "default 6" condition, which
now reads exactly as it already evaluated: BT_AUTO_DATA_LEN_UPDATE=y
&& BT_CTLR_LLCP_CONN < 4.
- The STM32WB0 SoC defconfig set BT_AUTO_PHY_UPDATE=n, which had no
effect on either role, and is simply dropped.
This keeps the change behaviour-neutral. Two pre-existing quirks are
deliberately left alone rather than fixed here, since they are policy
changes for their respective maintainers and not part of removing a
deprecated symbol: the local procedure context count no longer reaches
6 via automatic PHY update, and the STM32WB0 series follows the
BT_AUTO_PHY_CENTRAL default of _2M for central-role connections.
The BT_BUF_CMD_TX_COUNT help text is updated to name the replacement
choices.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
Instead of assigning the individual callbacks at read time,
they are now all assigned at once. The main reason for this
is to be able to handle notifications that come, that use the
same callbacks, before any reads have been done. Notifications
would otherwise have been missed, if the application did not
perform a read first.
The CONN_CB functions were just moved to avoid needing function
prototypes.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>