Skip to content

Add Bluetooth 6.3 CS Enhancements (Inline PCT) support#953

Open
JoeBakalor wants to merge 2 commits into
google:mainfrom
JoeBakalor:bt63-cs-inline-pct
Open

Add Bluetooth 6.3 CS Enhancements (Inline PCT) support#953
JoeBakalor wants to merge 2 commits into
google:mainfrom
JoeBakalor:bt63-cs-inline-pct

Conversation

@JoeBakalor

Copy link
Copy Markdown

Summary

Adds Bluetooth 6.3 Channel Sounding Enhancements support to Bumble — specifically the Inline Phase Correction Term transfer (IPT) feature. Two commits:

  1. hci: — pure additive HCI plumbing (opcodes, event codes, dataclasses, IntFlag enums, supports-commands mask, host dispatch handler). One breaking rename inside HCI_LE_CS_Create_Config_Command: the trailing reserved byte becomes cs_enhancements_1 (see notes).
  2. device: — wires the plumbing into Device.power_on() (prefer V2 caps read, fall back to 6.0) and create_cs_config() (new cs_enhancements_1 kwarg, default 0).

Net change: +185 / -7 across three files (hci.py, device.py, host.py).

What's implemented

Symbol Value / meaning
HCI_LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES_V2_COMMAND 0x20A5 — new opcode; return-params append t_ip2_ipt_times_supported (2 B) + t_sw_ipt_time_supported (1 B).
HCI_LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES_V2_COMMAND 0x20A6 — opcode constant only (no in-tree caller yet).
HCI_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE_V2_EVENT Subevent 0x38 — 6.3 variant of 0x2C with the same V2 tail.
HCI_LE_CS_Read_Local_Supported_Capabilities_V2_Command / _V2_ReturnParameters New dataclasses.
HCI_LE_CS_Read_Remote_Supported_Capabilities_Complete_V2_Event New event class.
CsSubfeature.CS_IPT_REFLECTOR 1 << 4 — bit in subfeatures_supported that advertises IPT reflector capability.
CsEnhancements1.INLINE_PCT 0x01 — bit 0 of the last byte of HCI_LE_CS_Create_Config that enables IPT on this configuration.
HCI_LE_CS_Create_Config_Command.reservedcs_enhancements_1 Rename of the trailing byte (see below).
Device.create_cs_config(..., cs_enhancements_1=0) New kwarg; default preserves 6.0 behavior.
Device.power_on() CS bring-up Tries V2 caps read first; falls back to 6.0 on UNKNOWN_HCI_COMMAND.
ChannelSoundingCapabilities Gains t_ip2_ipt_times_supported, t_sw_ipt_time_supported, cs_ipt_reflector_supported.

The reservedcs_enhancements_1 rename

The trailing byte of HCI_LE_CS_Create_Config was reserved in 6.0. Bluetooth 6.3 §7.8.137 assigns bit 0 as CS Enhancements 1 — Inline PCT enable; this is the field Nordic exposes as cs_enhancements_1 in zephyr/include/zephyr/bluetooth/hci_types.h:2986 and bt_conn_le_cs_config::cs_enhancements_1 in conn.h:851-855.

Impact on downstream callers: the field is now named cs_enhancements_1 rather than reserved. Callers that were passing reserved=0x00 explicitly must update to cs_enhancements_1=0x00 (or drop the kwarg entirely — default is 0). No known in-tree caller does this — Device.create_cs_config is patched in the second commit.

Design notes

  • try/except V2 fallback instead of supports_command gate: some vendor hci_uart firmwares implement the V2 command without setting the corresponding bit in the LE Supported Commands reply (octet 49 bit 2). A blind V2 call with fallback on UNKNOWN_HCI_COMMAND handles both correctly-advertising and misadvertising controllers without vendor-specific probing.
  • V2 event dispatch is separate from V1: the two events have different payload shapes, so host.py emits a distinct cs_remote_supported_capabilities_v2 event and device.py routes both through a single _on_cs_remote_supported_capabilities_impl builder. Existing listeners on cs_remote_supported_capabilities continue to fire for 6.0 events unchanged.
  • ChannelSoundingCapabilities default values: the three new fields all default to 0 / False, keeping any existing positional constructor call working.

Testing

Verified end-to-end against Nordic hardware:

  • Initiator: nRF54L15 running hci_uart from nRF Connect SDK v3.4.0 (with CONFIG_BT_CTLR_EXTENDED_FEAT_SET=y), attached as Bumble's HCI transport over USB serial.
  • Reflector: nRF54L15 running Nordic's channel_sounding/ipt_reflector sample from nRF Connect SDK v3.4.0.

Observed:

  • V2 caps read returned t_ip2_ipt_times_supported = 0x7E (bits 1–6 set → 10/20/30/40/50/60 μs), t_sw_ipt_time_supported = 0x0A (10 μs), subfeatures_supported = 0x12 (bit 4 → CS_IPT_REFLECTOR set).
  • HCI_LE_CS_Create_Config with cs_enhancements_1 = 0x01 completed with status: SUCCESS.
  • HCI_LE_CS_Config_Complete_Event echoed cs_enhancements_1: 1 back.
  • HCI_LE_CS_Procedure_Enable_Complete_Event returned state: ENABLED.
  • Multiple HCI_LE_CS_Subevent_Result_Events streamed with procedure_counter incrementing normally.

On a purely 6.0 controller (verified by simulating the UNKNOWN_HCI_COMMAND reply against V2_Command), everything falls back to the pre-existing 6.0 path and cs_ipt_reflector_supported stays False.

Spec references

  • Bluetooth Core Spec 6.3, Vol 4 Part E §7.8.137 — LE CS Create Config: cs_enhancements_1 bit 0 = Inline PCT enable.
  • §7.8.130 (V2) — LE CS Read Local Supported Capabilities: V2 opcode and return-parameter format including the IPT timing fields.
  • §7.7.65 (V2 event) — LE CS Read Remote Supported Capabilities Complete: V2 subevent code.

Follow-ups (not in this PR)

  • Adding a corresponding HCI_LE_CS_Write_Cached_Remote_Supported_Capabilities_V2_Command dataclass (opcode constant is defined; body not wired). Uncommon path in practice.
  • Any further CS Enhancements defined past Inline PCT (bits 1..7 of cs_enhancements_1 remain reserved).

Adds the HCI-layer definitions for the Bluetooth 6.3 Channel Sounding
Enhancements feature (Inline Phase Correction Term transfer, "IPT"),
none of which are wired to any existing behavior — this commit is
purely additive so it can land independently of any policy change.

New in bumble/hci.py:
- HCI_LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES_V2_COMMAND (opcode 0x20A5)
  with matching HCI_LE_CS_Read_Local_Supported_Capabilities_V2_Command
  class + _V2_ReturnParameters that append `t_ip2_ipt_times_supported`
  (uint16) and `t_sw_ipt_time_supported` (uint8) after the 6.0 field
  list.
- HCI_LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES_V2_COMMAND
  opcode constant (0x20A6) for symmetry (no class yet — no in-tree
  caller).
- HCI_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES_COMPLETE_V2_EVENT
  subevent code (0x38) + matching event class carrying the same
  V2 tail. Emitted (instead of the 6.0 event 0x2C) when the LE
  Extended Feature Set has been negotiated on the link.
- CsSubfeature IntFlag with the `CS_IPT_REFLECTOR = 1 << 4` bit —
  the subfeatures_supported flag advertised by a controller that
  can act as an IPT reflector.
- CsEnhancements1 IntFlag with `INLINE_PCT = 0x01` — the value used
  in the last byte of HCI_LE_CS_Create_Config to enable IPT per-
  configuration.
- Rename the trailing `reserved` byte of HCI_LE_CS_Create_Config_Command
  to `cs_enhancements_1` and drop it from the "pre-6.3 rsvd" comment.
  This is the field name Nordic uses in
  zephyr/bluetooth/hci_types.h:2986 and mirrors the semantics of
  `bt_conn_le_cs_config::cs_enhancements_1` in conn.h:851.
- Add the V2 read command to HCI_SUPPORTED_COMMANDS_MASKS at octet 49
  bit 2 per the spec. Callers can now feature-detect V2 via
  Host.supports_command().

bumble/host.py:
- Add on_hci_le_cs_read_remote_supported_capabilities_complete_v2_event
  handler that emits `cs_remote_supported_capabilities_v2` so device.py
  can pick the right payload shape (see the follow-up commit).

Verified end-to-end against a Nordic nRF54L15 (nRF Connect SDK v3.4.0)
running as an IPT initiator against Nordic's channel_sounding/ipt_reflector
sample: V2 caps read returned `t_ip2_ipt_times_supported = 0x7e`,
`t_sw_ipt_time_supported = 0x0a`, `subfeatures_supported = 0x12`
(CS_IPT_REFLECTOR bit set). Create_Config with
`cs_enhancements_1 = 0x01` completed with status SUCCESS and CS
procedures streamed subevent results.
Wires the HCI additions from the previous commit into Device:

- ChannelSoundingCapabilities gains three trailing fields:
  `t_ip2_ipt_times_supported`, `t_sw_ipt_time_supported`, and the
  derived boolean `cs_ipt_reflector_supported` (from bit 4 of
  `subfeatures_supported`, per CsSubfeature.CS_IPT_REFLECTOR).
  Defaults keep the constructor backwards-compatible with any call
  site that still passes only the 6.0 field set positionally.

- Device.power_on()'s CS bring-up now issues the V2 caps read
  (opcode 0x20A5) preferentially, falling back to the 6.0 read on
  UNKNOWN_HCI_COMMAND. Using try/except rather than
  supports_command() is deliberate: some hci_uart controllers
  implement the V2 command without setting octet 49 bit 2 in
  their LE Supported Commands reply, and this flow handles both
  cases without needing a per-vendor probe. The V2 dataclass
  renamed rtt_random_sequence_n → rtt_random_payload_n (same
  semantic) so the constructor unpacks either.

- `on_cs_remote_supported_capabilities` is split into an outer
  V1/V2 dispatch pair and an inner _impl builder so both event
  shapes feed the same ChannelSoundingCapabilities instantiation.
  Same rtt_random field renaming applies. The new
  `cs_ipt_reflector_supported` bit propagates onto every emitted
  capability record regardless of which event fired.

- create_cs_config() gains a `cs_enhancements_1: int = 0` keyword
  parameter (default 0 preserves the 6.0 behavior) and passes it
  through to HCI_LE_CS_Create_Config_Command. The old
  `reserved=0x00` call-site keyword was replaced by the rename
  in the previous commit; existing callers that did not set the
  reserved field remain unaffected.

Verified against the same nRF54L15 rig described in the previous
commit: caps report `cs_ipt_reflector_supported=True`, and a
`create_cs_config(..., cs_enhancements_1=CsEnhancements1.INLINE_PCT)`
call runs a full CS procedure with IPT enabled end-to-end.
@google-cla

google-cla Bot commented Jul 9, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@JoeBakalor JoeBakalor closed this Jul 9, 2026
@JoeBakalor JoeBakalor reopened this Jul 9, 2026
@JoeBakalor JoeBakalor changed the title Add Bluetooth 6.3 CS Enhancements (Inline PCT) support [WIP] Add Bluetooth 6.3 CS Enhancements (Inline PCT) support Jul 9, 2026
@JoeBakalor JoeBakalor marked this pull request as draft July 9, 2026 22:42
@JoeBakalor JoeBakalor marked this pull request as ready for review July 9, 2026 23:08
@JoeBakalor JoeBakalor changed the title [WIP] Add Bluetooth 6.3 CS Enhancements (Inline PCT) support Add Bluetooth 6.3 CS Enhancements (Inline PCT) support Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant