Refactor the Retransmission Disable (R) bit handling in L2CAP BR/EDR
to reuse the existing L2CAP_FLAG_REMOTE_BUSY flag instead of
maintaining separate R-bit tracking flags.
The previous implementation used dedicated flags (
`L2CAP_FLAG_RECV_FRAME_R` and `L2CAP_FLAG_RECV_FRAME_R_CHANGED`) to
track the R-bit state, which duplicated the functionality of
L2CAP_FLAG_REMOTE_BUSY and added unnecessary complexity.
Key changes:
- Remove `L2CAP_FLAG_RECV_FRAME_R` and
`L2CAP_FLAG_RECV_FRAME_R_CHANGED` flags
- Update `bt_l2cap_br_update_r()` to directly use
`L2CAP_FLAG_REMOTE_BUSY` for tracking remote busy state
- Trigger I-frame retransmission when R-bit transitions from 1 to 0
- Update I-frame and S-frame header packing to set R-bit based on
local busy state in retransmission mode
- Simplify I-frame sending logic by consolidating remote busy checks
- Remove redundant R-bit checks in data pull path
- Add RET mode specific handling in S-frame reception for RR and REJ
frames
- Enhance `bt_l2cap_br_chan_recv_complete()` to support both RET and
ERET modes with proper local busy state management
- Set S-frame type to REJ when local busy and in RET mode
These changes eliminate code duplication and make the remote busy
state management more consistent across the L2CAP implementation.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Fix the retransmit timer start logic to account for remote busy state
in L2CAP BR/EDR flow control.
The previous implementation would start the retransmit timer when there
are outstanding unacknowledged I-frames, but it didn't check if the
remote side is in a busy state (RNR received). Starting the timer while
the remote is busy is incorrect since the remote cannot process I-frames
until it sends an RR to clear the busy condition.
Add a check for L2CAP_FLAG_REMOTE_BUSY before starting the retransmit
timer to ensure the timer is only started when the remote side is ready
to receive I-frames.
This prevents unnecessary timer expirations and retransmissions when the
remote peer has signaled it cannot accept additional I-frames.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Refactor the I-frame retransmission mechanism to improve clarity and
correctness in L2CAP BR/EDR flow control.
The previous implementation used multiple flags (L2CAP_FLAG_PDU_RETRANS
and L2CAP_FLAG_REQ_SEQ_UPDATED) to track retransmission state, which
made the logic complex and error-prone. This change introduces a
per-window retransmit flag and dedicated helper functions to manage
retransmission of all unacknowledged I-frames.
Key changes:
- Replace L2CAP_FLAG_PDU_RETRANS with L2CAP_FLAG_RET_I_FRAME for
timeout-triggered retransmission of the first unacked I-frame
- Replace L2CAP_FLAG_REQ_SEQ_UPDATED with L2CAP_FLAG_RET_I_FRAMES for
retransmission of all unacked I-frames
- Add `retransmit` flag to `bt_l2cap_br_window` structure to track
which I-frames need retransmission
- Add `l2cap_br_retransmit_i_frames()` to mark all outstanding I-frames
for retransmission
- Add `l2cap_br_stop_retransmit_i_frames()` to clear retransmission
state
- Add `l2cap_br_get_ret_win()` to retrieve the next I-frame marked
for retransmission
- Update `l2cap_br_ret_fc_data_pull()` to handle both single I-frame
timeout retransmission and bulk retransmission separately
- Fix window memory management to only free newly allocated windows on
error, not retransmitted ones
- Update S-frame handlers (RR, REJ, RNR) to use new retransmission
helpers instead of setting flags directly
- Update comment for L2CAP_FLAG_RET_I_FRAME to clarify it handles
timeout retransmission
These changes make the retransmission logic more explicit and easier
to maintain while ensuring proper flow control behavior.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
There is a corner case that the S-frame (RR) needs to be sent. And
there is an I-frame (and only one I-frame) is in pending. But the
I-frame is pending for waiting for ack instead of sending. In this
case, the S-frame (RR) will not be preformed.
The previous implementation incorrectly checked for pending data
before sending S-frames, which could prevent timely acknowledgments.
Fix the S-frame sending logic to ensure proper flow control in L2CAP
BR/EDR channels.
Simplify the S-frame sending mechanism by removing the dedicated
S-frame buffer allocation and transmission path. Instead, rely on
the existing data ready mechanism to trigger S-frame transmission
when needed.
Key changes:
- Remove S-frame specific macros and flags for identifying S-frames
- Change `l2cap_br_send_s_frame()` to only set the pending flag
instead of allocating and sending buffers directly
- Remove error handling paths that would disconnect on S-frame send
failures since S-frames are now queued through the normal path
- Simplify `l2cap_br_get_next_sdu()` and `l2cap_br_ret_fc_data_pull()`
by removing S-frame specific handling
- Update `bt_l2cap_br_chan_recv_complete()` to always return 0
These changes ensure S-frames are sent promptly for flow control
regardless of pending I-frames in the transmission queue.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Fix buffer pool allocation size for BR/EDR L2CAP non-basic modes by
using the appropriate macro that accounts for SDU segmentation
overhead.
The previous implementation used BT_L2CAP_BUF_SIZE() which is designed
for basic mode and does not account for the additional overhead
required when segmenting SDUs in retransmission or flow control modes
(I-frame control field, FCS, and SDU length field).
- Replace BT_L2CAP_BUF_SIZE() with BT_L2CAP_RT_FC_MAX_SDU_BUF_SIZE()
- Ensures sufficient buffer space for segmented I-frames
- Aligns buffer allocation with recent MPS and MTU calculation fixes
This prevents potential buffer overruns when transmitting segmented
SDUs in non-basic modes.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Simplify the PDU length calculation in get_pdu_len() by using the
configured MPS value directly without manual adjustments for overhead.
The previous implementation attempted to manually calculate available
payload space by subtracting header/tail sizes and then adding back
the SDU length field size, which was unnecessarily complex and
error-prone.
- Remove manual calculation of actual_mps with header/tail overhead
- Use br_chan->tx.mps directly as the MPS limit
- Remove special handling for start segments (SDU length field
adjustment)
- Simplify logic: return pdu_len if within MPS, otherwise return MPS
The MPS value already represents the maximum PDU size that can be
transmitted, so no additional adjustments are needed. This aligns with
the recent fixes to MPS validation and MTU calculation.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Fix incorrect MPS validation for segmented I-frames by extracting the
SDU length field before checking payload size against MPS.
When an I-frame has SAR (Segmentation and Reassembly) set to START,
it contains a 2-byte SDU length field that precedes the actual payload.
The previous implementation validated buf->len against MPS before
removing this header, causing false positives when the SDU length field
pushed the total size over MPS.
- Extract SAR field from control header for all L2CAP modes
- Initialize SAR to UNSEG by default
- Pull SDU length (2 bytes) when SAR indicates START segment
- Perform MPS validation after SDU length extraction
- Move net_buf_simple_save/restore to encompass SDU length handling
This ensures MPS validation checks only the actual payload size,
preventing spurious disconnections for legitimate segmented transfers.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Fix incorrect RX MTU calculation when retransmission/flow control modes
are enabled. The previous implementation did not account for I-frame
overhead (control field and FCS), which could cause MTU to exceed the
maximum I-frame payload.
- Add l2cap_br_get_rx_mtu() helper to calculate proper RX MTU
- Discount extended control field size (4 bytes) when enhanced
retransmission or streaming mode is enabled
- Discount standard control field size (2 bytes) for basic mode
- Always discount FCS size (2 bytes) as it may be required by peer
- Add assertion to validate MTU meets minimum requirements
- Update l2cap_br_check_chan_config() to use new MTU calculation
This ensures the negotiated MTU fits within the I-frame payload limits
and prevents buffer overruns in non-basic L2CAP modes.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Currently, the CID for dynamic channels are not cleared on reuse.
l2cap_chan_alloc_cid() sees the non-zero CID and skips allocation.
If another dynamic channel (e.g. EATT) has claimed that CID in the
meantime, the reused CID collides and the remote rejects with
BT_L2CAP_LE_ERR_SCID_IN_USE.
This commit adds clearing of bt_l2cap_le_chan.rx.cid to
`l2cap_chan_rx_init()`, to match the pattern for how state is cleared
for bt_l2cap_le_chan.tx in `l2cap_chan_tx_init()`. As a consequence of
this, the function calling the CID-allocating function on the server
side (`l2cap_chan_add()`) is moved after the init functions.
Signed-off-by: Håvard Reierstad <haavard.reierstad@nordicsemi.no>
Replace the manual linked list (using _next pointer) for RFCOMM
servers with sys_slist_t. This enables use of slist utility functions
like sys_slist_find_and_remove(), which is needed to support server
unregistration in a subsequent commit.
Signed-off-by: Kai Cheng <chengkai@xiaomi.com>
Move the avdtp_tx_raise() call from avdtp_tx_processor() into
avdtp_tx_frags() to ensure the tx is not raised if there is no idle
net_buf.
The issue is: the `avdtp_tx_raise` is called always to trigger the
worker to run again, it will keeps occupying the cpu if there is pending
tx, but there is no idle net_buf. After moving the calling to
`avdtp_tx_frags`, it is only called when there is still idle net_buf.
After the previous avdtp sending net_buf is released, the `avdtp_tx_cb`
is called, and the `avdtp_tx_raise` will be triggered again.
Signed-off-by: Mark Wang <yichang.wang@nxp.com>
Move AVRCP SDP record registration and AVCTP server register from
bt_avrcp_init() to callback registration functions to align with
other Bluetooth Classic profiles.
Signed-off-by: Make Shi <make.shi@nxp.com>
Commit adds checking that the PB-ADV bearer has been
closed before opening the PB-Remote link for NPPI
interface. NPPI interface callbacks are NULL if
PB-ADV server bearer is still open.
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
Resume from cli->block.number instead of block 0,
so BLOCK_START matches the server's current block.
Blob client does not drop server due to this anymore.
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
Accept WAITING_FOR_CHUNK phase on resume
when server responds SUCCESS
(server's XFER_START idempotency path).
Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
Add function to get an instance pointer by index.
This works the same as bt_tbs_client_get_by_ccid except that
it uses the index instead of the CCID.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
When calling bt_avrcp_ct_register_notification,
it sets ct->ct_notify[event_id].cb = cb.
In process_register_notification_rsp, it clears the callback
by setting ct->ct_notify[event_id].cb = NULL. However, when
the connection is disconnected, the callback
ct->ct_notify[event_id].cb is not set to NULL , causing
subsequent notification registrations to fail immediately with
an error because the callback pointer is still active.
Similarly, this issue also exists in the AVRCP TG.
Signed-off-by: Lu Jia <jialu@xiaomi.com>
Refactored the Stream End Point (SEP) callback mechanism to use a
unified bt_avdtp_sep_ops structure instead of individual function
pointers. This change consolidates the connected, disconnected, and
media_data_cb callbacks into a single operations structure. The stream
established callback should be called when the stream l2cap is
connected not the open cmd is finished.
Signed-off-by: Mark Wang <yichang.wang@nxp.com>
bt_mesh_suspend/resume now only re-enable provisioning bearers that
were previously active.
Adds internal bt_mesh_provisionee_suspend/resume APIs.
bt_mesh_suspend() now return -EBUSY if provisioning is active before any
suspend actions are performed.
Signed-off-by: Stine Åkredalen <stine.akredalen@nordicsemi.no>
When proc_param->is_unicast_to_broadcast == false we should clear
the broadcast_to_unicast.broadcast_source instead of the
unicast_to_broadcast.broadcast_source.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Remove the required_sec_level for struct bt_iso_chan and
all related automatic security machinery built around it
(iso_chan_connect_security, bt_iso_security_changed,
BT_ISO_STATE_ENCRYPT_PENDING and the CONFIG_BT_SMP checks
in iso.c)
Applications can just call bt_conn_set_security() on the
ACL connection before bt_iso_chan_connect() instead.
Fixes#104751
Signed-off-by: Vedant Malkar <vedantitsme@gmail.com>
Modify bt_ccp_call_control_server_get_bearer_provider_name to
store the bearer provider name in an output buffer, instead of just
providing the pointer.
The reason for this is to make the result thread safe, and
avoid the user/application having a direct pointer to
internal storage.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Currently the other of the ACL and CIS disconnect callbacks
depend on the order of the HCI events received. Since this
order is not specified by the core spec, it means that any
users/applications of ISO will need to wait for all CIS
disconnects callbacks and the ACL disconnect callback before
attempting to reuse any of them.
From an API perspective this is not ideal, and the API will
be much simpler if the order of ACL and ISO disconnect
callbacks were deterministic, regardless of the controller.
This change postpones the finalization of the ACL disconnect
until all the CIS associated with it has been disconnected.
This will also make the API more similar to e.g. the L2CAP
disconnect order.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Add a new callback for when the broadcast source has been
created. This callback is useful for the application to
configure the periodic advertising with the BASE of the
broadcast source. Configuring and starting the
periodic advertising with the BASE at that point in time
may optimize how quickly the procedure can be completed.
A callback was chosen, rather than having the stack set
up the data itself, because that the application may
want to add additional data in the periodic advertising,
and thus the owner of the data should be the application,
and not the stack.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Fix OBEX abort response handling when no active client exists by
tracking the last executing client and its previous opcode.
- Add _last_client pointer to track the most recent executing client
- Add _pre_opcode to store the opcode before clearing _opcode
- Save client state before clearing opcode in all operation handlers
- Implement obex_get_last_client() to recover client context for abort
- Handle abort responses even when _active_client is already cleared
- Clear last client tracking on transport connect/disconnect
This ensures abort responses are properly delivered to the correct
client callback even if the operation has already completed.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Add validation to detect and handle zero-length data elements during
SDP attribute parsing. When the parsed data element length is zero,
log a debug message and return early to avoid unnecessary processing.
This check is placed after parsing the data element length but before
the nesting level validation, ensuring that:
- Empty data elements are gracefully handled without errors
- The parser doesn't attempt to process or skip zero bytes of data
- Subsequent attribute parsing continues normally
This prevents potential issues when SDP records contain empty data
elements and improves parser robustness when handling malformed or
edge-case SDP attribute structures.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Move the nesting level check to occur after parsing the data element
length instead of before. This ensures that when the maximum nesting
level is exceeded, the parser can properly skip the nested data by
pulling the correct length from the buffer.
Previously, checking the nesting level before parsing the length meant
the parser would return early without consuming the nested data,
potentially causing parsing errors for subsequent attributes.
The updated logic:
- Parses the data element type and length first
- Checks if maximum nesting level is exceeded
- If exceeded, logs a warning and skips the data element entirely
- Otherwise, proceeds with recursive parsing as normal
This prevents buffer misalignment when deeply nested sequences are
encountered in SDP attribute records.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Fix SDP attribute parsing to properly handle nested sequences within
attribute values. Previously, when an attribute value itself contained
a sequence, the parser would not recursively parse the nested sequence,
potentially missing nested attribute data.
Add recursive parsing logic that:
- Detects if the current value buffer contains a sequence type
- Recursively calls sdp_attr_parse() with incremented nest level
- Properly handles nested sequence structures in SDP records
This ensures complete parsing of complex SDP attribute structures that
contain sequences within sequences, such as protocol descriptor lists
or service class ID lists with nested elements.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Extract common GOEP RFCOMM initialization logic into a separate function
to eliminate code duplication between accept and connect paths.
- Add new goep_rfcomm_init() function containing shared initialization:
* MTU calculation and validation
* Transport operations registration
* RFCOMM DLC configuration
* GOEP state setup
- Update goep_rfcomm_accept() to use the new init function
- Update bt_goep_transport_rfcomm_connect() to use the new init function
This refactoring reduces code duplication and ensures consistent
initialization behavior for both server (accept) and client (connect)
code paths.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
Extract common GOEP L2CAP initialization logic into a separate function
to eliminate code duplication between accept and connect paths.
- Add new goep_l2cap_init() function containing shared initialization:
* MTU calculation and validation
* Transport operations registration
* L2CAP channel configuration
* GOEP state setup
- Update goep_l2cap_accept() to use the new init function
- Update bt_goep_transport_l2cap_connect() to use the new init function
This refactoring reduces code duplication and ensures consistent
initialization behavior for both server (accept) and client (connect)
code paths.
Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
This change ensure that TBS bearers promote dialing -> alerting
independently of GTBS. GTBS no longer blocks the state transitions,
promotion only waits for the bearer's own pending notifications to
clear, preserving notification ordering. GTBS continues to aggregate
the updated state correctly
Signed-off-by: Alex Ciascai <alexandru.ciascai@nordicsemi.no>
If we receive a control point notification with an ASE ID that
does not match any existing streams, i.e. audio_stream_by_ep_id
returns NULL, we should not continue by calling the subsequent
functions like unicast_client_notify_ep_config with a NULL stream.
A single notification may contain multiple ASE IDs; if any of them
are unknown, we can either reject the entire notification, or
we can ignore the specific ASE ID. For now, ignore the
specific ASE ID to do a best effort to continue with
any other changes.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Remove calls to atomic_clear_bit on reads. Even if a characterstic
is read while there is a pending notification, we shall
(as per the MCS spec) still send the notification.
There are 3 special cases for long (string) values, where we
need to know the difference between a changed value (pending
for notification), and a value that has changed since last
read. To support this, these 3 cases now have _DIRTY flags
to indicate that the values are dirty and must be read from
the beginning again.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Fix nRF54Lx DTM implementation when using GRTC. The Radio
start needs to be offset by a maximum ISR latency value that
is less than inter-frame switching, plus minimum counter
compare offset that can be set, plus minimum CPU latency to
set the counter compare register.
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
Use clock startup time from devicetree.
Relates to commit 72dac165d8 ("Bluetooth: Controller: Use
OVERHEAD_XTAL_US from devicetree").
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This file fails to compile since commit ef7b132bfd ("Bluetooth:
Classic: Fix initialization to support re-initialization"), which added
a LOG_ERR() invocation but didn't setup logging for the file.
Fixes#101810
Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
Use the ZTESTABLE_STATIC macro to define symbols which need to be
accessible from ztests, instead of redefining STATIC which causes
trouble with some hals.
Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
Add support for CS IPT (Channel Sounding Inline PCT Transfer)
in the Bluetooth host stack.
Changes include:
* definition of new CS IPT HCI opcodes;
* handling of CS IPT control procedures;
* integration with existing CS infrastructure;
* necessary updates to public headers.
Signed-off-by: Aleksandr Mirlenko <aleksandr.mirlenko@nordicsemi.no>
Before this we have a memory leak in the prep_pool when reassembly fails
in :c:func:`att_exec_write_rsp`. Now on error the buffer is dequeued and
freed, as are remaining queued prepare buffers.
Signed-off-by: Kyra Lengfeld <kyra.lengfeld@nordicsemi.no>
Rename it to USB buffers so we can use it in host support without
confusion. Keep the UDC_* macros for now, we can deprecate and remove
them later.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
The implementation only used the receive state's PA sync state
to determine whether to call the PA sync req or PA sync term req,
but that state does not include the syncing state.
Rather than using the receive state's PA sync state, we add a local
boolean to keep track of whether the PA sync was requested, so if
we receive a mod_src with PA sync == BT_BAP_BASS_PA_REQ_NO_SYNC then
we request a termination, even if the PA sync was not established yet.
Some cleanup in the mutex handling was also done as part of this.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
Make sure choice option name is not same as actual config option
that is enabling it. Use _SECURITY suffix for clarity of what
choice is actually about.
Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
CTS is missing the Local Time Information characteristic and this
commit adds the UUID and the full characteristic to its service.
The peripheral example has been updated as well to use this and
implement it on the example so it is easy to test it out.
Signed-off-by: Martin Moya <moyamartin1@gmail.com>
- Add kconfig for HCI event synchronous buf pool to allow vendors
to configure buffer count based on the application/host platform
requirements
Signed-off-by: Vinit Mehta <vinit.mehta@nxp.com>
Added support for elapsed time service (ETS). The service
is introduced currently with the experimental tag.
Signed-off-by: Dipak Shetty <shetty.dipak@gmx.com>
The TBS spec only specificially disallows join for calls in
the incoming state. The Alerting and Dialing state in Zephyr
were disallowed, but that fails some TBS join tests.
Removed the (implicit) checks for alerting and dialing and
updated the state changer code to be more explicitly so that
all call states, except for incoming, is explicitly handled.
Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>