nRF54L15 DK + NCS v3.3.1: Channel Sounding Procedure Enable fails with 0x1E on Galaxy S26+ / Android 17

## Environment

- Reflector: nRF54L15 DK
- Firmware: pristine NCS v3.3.1 `ras_reflector` sample
- Board target: `nrf54l15dk/nrf54l15/cpuapp`
- Extra configuration: `android_ranging.conf`
- Initiator: Samsung Galaxy S26+ (`SM-S947U`, device `m2q`)
- Android: 17 / API 37
- nRF Toolbox: 4.4.0 (`versionCode=26080501`)
- The phone was kept at least 0.5 m away when pairing and starting ranging.

## Pristine build command

```text
west build -p always \
-b nrf54l15dk/nrf54l15/cpuapp \
-d C:\ncs\v3.3.1\build_ras_reflector_android_nrf54l15dk_official \
C:\ncs\v3.3.1\nrf\samples\bluetooth\channel_sounding\ras_reflector \
-- -DEXTRA_CONF_FILE=android_ranging.conf
```

Relevant values verified in the final `zephyr/.config`:

```text
CONFIG_BT_BONDABLE=y
CONFIG_BT_SETTINGS=y
CONFIG_SETTINGS=y
CONFIG_NVS=y
CONFIG_BT_RAS_MAX_ANTENNA_PATHS=2
CONFIG_BT_CTLR_SDC_CS_MAX_ANTENNA_PATHS=2
CONFIG_BT_CTLR_SDC_CS_NUM_ANTENNAS=1
CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT=7500
CONFIG_BT_CTLR_SDC_CS_EVENT_LEN_DEFAULT=5000
```

Controller information printed by the DK:

```text
SoftDevice Controller build revision:
fc 51 7a e9 58 2c 6f fb
6d 35 9f 17 3e 08 c8 c1
7b e9 5b 95

Firmware: Standard Bluetooth controller Version 252.31313 Build 1865177321
HCI: version 6.3 (0x11) revision 0x301f, manufacturer 0x0059
LMP: version 6.3 (0x11) subver 0x301f
```

## Reproduction

1. Flash the pristine v3.3.1 build above.
2. Clear the bond on both the phone and DK, then pair again using nRF Toolbox.
3. Select Channel Sounding and start ranging with Frequency set to Infrequent.
4. Keep the phone more than 0.5 m from the DK.

## Result

The ACL connection, RAS discovery, CS capability exchange, CS config creation, and CS security all succeed. `LE CS Set Procedure Parameters` also succeeds. The following `LE CS Procedure Enable` fails with `INVALID_LMP_OR_LL_PARAMETERS (0x1E)`.


Android reports the expected remote capability values:

```text
remote_num_antennas_supported: 1
max_antenna_paths_supported: 2
```

The effective procedure parameters are:

```text
connection interval: 24 units (30 ms)
tone_antenna_config_selection: 1
preferred_peer_antenna: 1
PHY: LE 1M
max_procedure_duration: 1600
min_procedure_interval: 1000
max_procedure_interval: 5000
max_procedure_count: 0
min_sub_event_len: 1250
max_sub_event_len: 2000000
```

Config creation completes with:

```text
mode: 2 (PBR)
mode_0_steps: 2
channel selection: Algorithm #3b
ch3c_jump: 2
T_IP1: 145 us
T_IP2: 145 us
T_FCS: 150 us
T_PM: 10 us
channel map: 0x1FFFFFFFFFFFFC7FFFFC
```

The failure event contains no selected schedule:

```text
LeCsProcedureEnableComplete {
status = INVALID_LMP_OR_LL_PARAMETERS(0x1e),
state = DISABLED,
tone_antenna_config_selection = 0,
selected_tx_power = 0,
subevent_len = 0,
subevents_per_event = 0,
subevent_interval = 0,
event_interval = 0,
procedure_interval = 0,
procedure_count = 0,
max_procedure_len = 0
}
```

The DK UART log stops after `CS security enabled`; no ranging result is generated.

## Additional isolation tests

The following changes were tested one at a time and produced the same `0x1E` result:

- `max_procedure_count`: `0` -> `1`
- Frequency: Infrequent and Normal
- `CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT`: `7500 us` -> `5000 us`
- Procedure ranges `1000-5000 ms` and `500-1000 ms`

The same phone running nRF Toolbox can discover and connect to another Galaxy S26+ advertising through our internal Android test app, complete Channel Sounding, and produce distance results. Separately, both nRF Toolbox and our internal Android initiator app fail against the nRF54L15 DK at the same HCI stage.

We also tested an NCS v3.4.0 SDC build (HCI revision `0x3039`, SDC build revision `c8da3098...`) and observed the same `0x1E` result.

## Questions

1. Is there a known Channel Sounding interoperability issue between the Samsung Android 17 Bluetooth controller and the nRF54L15 SoftDevice Controller at `LE CS Procedure Enable`?
2. Does the all-zero `LE CS Procedure Enable Complete` payload indicate that the local Samsung controller rejected the procedure before schedule negotiation, or can this status/payload also represent rejection by the remote SDC?
3. Is there any SDC trace or vendor-specific diagnostic command that can identify which LL parameter caused `0x1E`?
4. Are `1 antenna / 2 antenna paths` and effective `tone_antenna_config_selection=1` the expected combination for the nRF54L15 DK in this Android use case?
5. Is there a newer SDC library or pending fix that should be tested for this Samsung interoperability case?

## Related DevZone discussions

-  Channel sounding android nRFtools, only works when frequency set to infrequent.
- devzone.nordicsemi.com/.../cs-procedures-never-start-after-cs-security-enable-channel_sounding_ras_reflector-stuck-on-nrf54l15dk-with-android-17-pixel-10-nrf-toolbox-v4-3-2
- Channel Sounding Not Working with nRF Toolbox App and nRF54L15-DK

Due to our corporate security policy, I cannot upload attachment files to this public ticket. I have included the relevant configuration and sanitized log excerpts directly in the description. I can provide additional specific values or excerpts upon request.

  • Hi, 

    I am working on your case and will update you once I gather enough information. 

    Regards,
    Amanda H.

  • Hi Amanda,

    Thanks. While you look into it, I isolated the failure and found a working configuration — sharing in case it's useful.

    The 0x1E turned out to be two separate gates, both surfacing as INVALID_LMP_OR_LL_PARAMETERS:

    Gate A — LL negotiation rejection (phone reports 0x1E, reflector stays silent).
    The phone's Min_Subevent_Len (the device's default of 1250 µs, which is the CS spec minimum for Subevent_Len) is too low and the reflector rejects the resulting LL_CS_REQ. Raising min_sub_event_len via the phone's cs_configuration clears it.

    Gate B — reflector local scheduling rejection (phone reports SUCCESS, board logs Procedure Enable failed with status 0x1E).
    The S26+ negotiates the maximum interlude timings — T_IP1=145, T_IP2=145, T_FCS=150 µs — giving a subevent length of 23,750 µs with event_interval=2. With the default CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT=7500, 23,750 µs + the ACL reservation does not fit inside the Android-fixed 30 ms connection interval, so the reflector rejects it.

    Working configuration (both required):

    • Board: CONFIG_BT_CTLR_SDC_MAX_CONN_EVENT_LEN_DEFAULT=1250
    • Phone: min_sub_event_len ≥ ~2250 (I use 12000)

    With both, the S26+ ranges reliably (hundreds of results, no 0x1E). Cross-check:

    • board 1250 + phone default 1250 → fails (Gate A)
    • board 7500 + phone 12000 → fails (Gate B)
    • board 1250 + phone 12000 → works

    Questions:

    1. Is lowering MAX_CONN_EVENT_LEN_DEFAULT the intended way to accommodate an initiator requesting a ~23.75 ms subevent, and should android_ranging.conf carry a lower value by default? What is the recommended/safe value (1250 works; the sample default 7500 fails)?
    2. For Gate A — is there a spec-mandated minimum Min_Subevent_Len (tied to Mode_0_Steps / Min_Main_Mode_Steps) that the reflector enforces? We can't see the rejected LL_CS_REQ contents, so any insight into why a low min is rejected would help.
  • Hi, 

    It's hard to reproduce on our side. Could you provide sniffer traces to help with the investigation? 

Related