BLUETOOTHCTL-CS(1)

πŸ“¦
version 5.87+2.git8750129efca8 Β· 4 versions
, in centos-stream 9

πŸŽ€ NAME

bluetoothctl-cs β€” Channel Sounding Submenu. Manual page name: bluetoothctl-cs(1). Yep, this is the Linux System Administration page for the CS submenu, and we're gonna make it make sense πŸ’–


✨ SYNOPSIS

bluetoothctl [--options] [cs.commands]

Okay so this submenu controls Bluetooth Channel Sounding (CS) distance measurement using the org.bluez.ChannelSounding1(5) D-Bus interface. It lets you start and stop measurements and inspect the current parameter state and active session identifier πŸ‘‘

Each CS parameter has its own cs.<param> set command (see the CS Parameter Commands section below). Overrides are applied to the local parameter state immediately, so show reflects them right away; start always uses whatever values are currently set. No cap.


πŸ’– CHANNEL SOUNDING COMMANDS πŸ’–

πŸš€ start

Starts a distance measurement on the connected device using the currently set CS parameters (see the cs.<param> commands below). All configuration is sent to the daemon in a single StartMeasurement call. On success the device path is printed to the console. Multiple simultaneous sessions across different devices are supported; each is tracked independently 🫢

Tiny but important: calling start on a device that already has an active measurement returns an error without starting a second session on the same device.

For Initiator role (or Both), the mandatory parameters are the positional dev_addr and duration_secs; every cs.<param> command below is optional configuration with a usable default.

If role is set to Reflector (0x02, via cs.role), start does not begin measuring distance: a Reflector never initiates a CS procedure. It only pushes the current parameters to the daemon and arms the device to respond once the remote Initiator starts one; the call still succeeds. When the remote side starts or stops a procedure, the console prints Measurement started/Measurement stopped for that device β€” use show or watch the Active property to see the same transition. In this role the only parameters that are required or have any effect are role, sync_ant_sel and max_tx_power; every other cs.<param> command below is accepted but unused.

Positional arguments are optional:

  • dev_addr β€” Bluetooth address of the target device; uses the only available CS-capable device when omitted.
  • duration_secs β€” auto-stop timeout in seconds; 0 (default) means no timeout.

Usage

> start [dev_addr] [duration_secs]

Uses org.bluez.ChannelSounding1(5) method StartMeasurement

  • [dev_addr] β€” Bluetooth address of the target device (optional; uses the only available CS-capable device when omitted)
  • [duration_secs] β€” Seconds before auto-stop (optional, default 0 = no timeout)

Example β€” Start with all defaults, no timeout

> start

Example β€” Start on a specific device

> start AA:BB:CC:DD:EE:FF

Example β€” Start on a specific device with 10-second auto-stop

> start AA:BB:CC:DD:EE:FF 10

Example β€” Start with 10-second auto-stop (single device, address omitted)

> start 0 10

Example β€” Start with 5-minute auto-stop

> start AA:BB:CC:DD:EE:FF 300

πŸ›‘ stop

Stops an active CS distance measurement. When only one measurement is running the device address may be omitted. When multiple measurements are active the address is required to identify which one to stop 🎯

Usage

> stop [dev_addr]

Uses org.bluez.ChannelSounding1(5) method StopMeasurement

  • [dev_addr] β€” Bluetooth address of the device to stop (optional when only one session is active; required otherwise)

Example β€” Stop the only active measurement

> stop

Example β€” Stop a specific device when multiple are active

> stop AA:BB:CC:DD:EE:FF

Example β€” Stop a second device

> stop 11:22:33:44:55:66

πŸ‘€ show

Displays all active measurements (device path for each) and the full set of CS parameter values that will be used on the next start call. When no measurements are active, none is shown.

The parameter output is divided into three sections:

  • Default Settings β€” role, CS sync antenna selection, max TX power.
  • CS Config Params β€” per-procedure configuration fields including mode type, step counts, PHY, and channel map.
  • CS Frequency Params β€” procedure scheduling fields including duration, period, subevent lengths, and SNR control.

Usage

> show

Example β€” Show active session and all CS parameters

> show

πŸ“‘ register_provider

Reference implementation only β€” not a real ranging algorithm. Registers bluetoothctl itself as a Channel Sounding ranging provider via RegisterRangingProvider(), then listens for ProcedureData signals on org.bluez.ChannelSounding1(5) and turns each one into a bounded, illustrative distance estimate (not an accurate measurement) exposed via org.bluez.RangingProvider1(5) β€” visible on the device's org.bluez.Ranging1(5) Distance property once bluetoothd reflects it 🧚

The provider path defaults to /, the only path bluetoothctl exposes an ObjectManager at; a different path will register but bluetoothd will not discover any objects under it. The exported RangingProvider1 objects themselves are nested under /org/example/ranging rather than directly under /. See test/example-ranging-provider for a minimal standalone provider skeleton, which reports a fixed placeholder distance and does not parse ProcedureData at all.

Only one ranging provider may be registered per adapter at a time. If a real ranging daemon is already registered, this command fails with AlreadyExists; conversely, a real daemon cannot register while bluetoothctl's reference provider is active. Run unregister_provider (or stop the other provider) first πŸ’€

Usage

> register_provider [path]

Uses org.bluez.RangingProviderManager1(5) method RegisterRangingProvider

  • [path] β€” Provider root object path (optional; default /)

Example β€” Register with the default path

> register_provider

🧹 unregister_provider

Unregisters the ranging provider previously registered with register_provider, removing its exposed RangingProvider objects ✨

Usage

> unregister_provider

Uses org.bluez.RangingProviderManager1(5) method UnregisterRangingProvider

Example β€” Unregister the provider

> unregister_provider

🌈 CS PARAMETER COMMANDS 🌈

Each CS parameter is set with its own command, of the form cs.<param> <value>. Entering a param command with no value shows its current setting. Overrides apply to the local parameter state immediately, so show reflects them right away; start always uses whatever values are currently set. Array-valued parameters (channel_map, min_sub_event_len, max_sub_event_len) take colon-separated hex bytes with no 0x prefix. Slay.

Usage

> <param> [value]

🎭 role

Get/set the CS role.

Usage

> role [0x01|0x02|0x03]
  • [0x01|0x02|0x03] β€” 0x01 Initiator, 0x02 Reflector, 0x03 Both (optional, shows current if omitted; default 0x03)

Example β€” Show current role

> role

Example β€” Set role to Initiator only

> role 0x01

Example β€” Set role to Reflector only (does not measure)

> role 0x02

Example β€” Set role to both Initiator and Reflector

> role 0x03

πŸ“Ά sync_ant_sel

Get/set the CS sync antenna selection.

Usage

> sync_ant_sel [value]
  • [value] β€” CS sync antenna selection; 0xFE/0xFF reserved (optional, shows current if omitted; default 0xFF)

Example β€” Show current antenna selection

> sync_ant_sel

Example β€” Select antenna 1

> sync_ant_sel 0x01

πŸ”‹ max_tx_power

Get/set the maximum TX power.

Usage

> max_tx_power [dBm]
  • [dBm] β€” Max TX power in dBm, signed (optional, shows current if omitted; range βˆ’127 to +20; default 20)

Example β€” Show current max TX power

> max_tx_power

Example β€” Reduce max TX power to 10 dBm

> max_tx_power 10

🏷️ config_id

Get/set the CS configuration identifier.

Usage

> config_id [value]
  • [value] β€” CS configuration identifier (optional, shows current if omitted; default 0)

Example β€” Show current config id

> config_id

Example β€” Set config id to 1

> config_id 1

πŸ“ create_context

Get/set where the CS configuration is written when cs.start sends it to the Controller.

Usage

> create_context [0|1]
  • [0|1] β€” 0x00 write the configuration to the local Controller only; 0x01 also write it to the remote Controller using the CS Configuration procedure (optional, shows current if omitted; default 1)

Example β€” Show current value

> create_context

Example β€” Write the configuration to the local Controller only

> create_context 0

Example β€” Write the configuration to both local and remote Controllers

> create_context 1

πŸŽ›οΈ main_mode_type

Get/set the CS main mode type.

Usage

> main_mode_type [1|2|3]
  • [1|2|3] β€” 1 Mode 1 (RTT), 2 Mode 2 (PBR), 3 Both (optional, shows current if omitted; default 1)

Example β€” Show current main mode type

> main_mode_type

Example β€” Set main mode to Mode 2 (PBR)

> main_mode_type 2

Example β€” Set main mode to both RTT and PBR

> main_mode_type 3

🧬 sub_mode_type

Get/set the CS sub-mode type within the main mode.

Usage

> sub_mode_type [value]
  • [value] β€” Sub-mode within main mode; 0xFF = unused (optional, shows current if omitted; default 0xFF)

Example β€” Show current sub-mode type

> sub_mode_type

Example β€” Set sub-mode type to 0x01

> sub_mode_type 0x01

πŸͺœ main_mode_min_steps

Get/set the minimum CS main mode steps per subevent.

Usage

> main_mode_min_steps [value]
  • [value] β€” Min CS main mode steps per subevent (optional, shows current if omitted; default 2)

Example β€” Show current value

> main_mode_min_steps

Example β€” Set minimum steps to 4

> main_mode_min_steps 4

πŸͺœ main_mode_max_steps

Get/set the maximum CS main mode steps per subevent.

Usage

> main_mode_max_steps [value]
  • [value] β€” Max CS main mode steps per subevent (optional, shows current if omitted; default 3)

Example β€” Show current value

> main_mode_max_steps

Example β€” Set maximum steps to 8

> main_mode_max_steps 8

πŸ” main_mode_repetition

Get/set how many times main mode steps are repeated in a subevent.

Usage

> main_mode_repetition [value]
  • [value] β€” Repetition count (optional, shows current if omitted; default 1)

Example β€” Show current value

> main_mode_repetition

Example β€” Repeat main mode steps twice

> main_mode_repetition 2

0️⃣ mode0_steps

Get/set the number of CS Mode 0 steps at the beginning of each subevent.

Usage

> mode0_steps [value]
  • [value] β€” CS Mode 0 step count (optional, shows current if omitted; default 2)

...and the examples for the last param, bestie β€” showing the current value and then setting it, because that's the whole pattern here:

> mode0_steps

and if you wanna switch it up:

> mode0_steps 3

rtt_types

Get/set the RTT measurement types bitmask β€” it's giving "which round-trip flavour are we doing" energy.

Usage: > rtt_types [value]

  • [value] β€” the RTT measurement types bitmask. It's optional; if you leave it out it just shows you the current one. Default is 0. πŸ’…

Peep the current value:

> rtt_types

Now set the bitmask, bestie:

> rtt_types 0x01

sync_phy

Get/set the PHY used for CS sync. lowkey important.

Usage: > sync_phy [0x01|0x02]

  • [0x01|0x02] β€” 0x01 is LE 1M, 0x02 is LE 2M. Optional, shows current if you omit it. Default 0x01. ✨

Show current sync PHY:

> sync_phy

Set CS sync PHY to LE 2M (iconic choice tbh):

> sync_phy 0x02

channel_map

Get/set the 10-byte CS channel map bitmap. yeah, ten whole bytes. slay.

Usage: > channel_map [b0:b1:...:b9]

  • [b0:b1:...:b9] β€” 10 colon-separated hex bytes. Optional, shows current if omitted. Default is FC:FF:7F:FC:FF:FF:FF:FF:FF:1F 🫢

Show current channel map:

> channel_map

Set a custom channel map with literally everything enabled:

> channel_map FF:FF:FF:FF:FF:FF:FF:FF:FF:FF

channel_map_repetition

Get/set how many times in a row the channel map repeats. yes, consecutive repetition is a thing.

Usage: > channel_map_repetition [value]

  • [value] β€” the repetition count. Optional, shows current if omitted. Default 1. 🌸

Show current value:

> channel_map_repetition

Repeat the channel map 3 times like you mean it:

> channel_map_repetition 3

channel_selection_type

Get/set the CS channel selection algorithm. pick your fighter. πŸ‘‘

Usage: > channel_selection_type [value]

  • [value] β€” the channel selection algorithm. Optional, shows current if omitted. Default 0. ⭐

Show current value:

> channel_selection_type

Select algorithm 1:

> channel_selection_type 1

channel_shape

Get/set the shape used in the channel selection algorithm. it's giving geometry class but make it bluetooth.

Usage: > channel_shape [value]

  • [value] β€” the channel shape. Optional, shows current if omitted. Default 0. πŸ¦‹

Show current value:

> channel_shape

Set channel shape to 1:

> channel_shape 1

channel_jump

Get/set the channel jump size. hopping, but make it mathematical ✨

Usage: > channel_jump [value]

  • [value] β€” the channel jump size. Optional, shows current if omitted. Default 2. πŸ”₯

Show current value:

> channel_jump

Set channel jump to 4:

> channel_jump 4

companion_signal_enable

Get/set whether the companion signal actually gets transmitted. yes or no, no in-between.

Usage: > companion_signal_enable [0|1]

  • [0|1] β€” 1 transmits the companion signal, 0 disables it. Optional, shows current if omitted. Default 0. πŸ™ˆ

Show current value:

> companion_signal_enable

Enable the companion signal:

> companion_signal_enable 1

max_procedure_duration

Get/set the maximum duration of one CS measurement procedure. one (1) procedure, and no more than this long, bestie.

Usage: > max_procedure_duration [value]

  • [value] β€” the max procedure duration. Optional, shows current if omitted. Default 1600. πŸ’œ

Show current value:

> max_procedure_duration

Set max procedure duration to 800:

> max_procedure_duration 800

min_period_between_procedures

Get/set the minimum time between consecutive procedures. the gossip needs at least this much gap. πŸ’€

Usage: > min_period_between_procedures [value]

  • [value] β€” the minimum period. Optional, shows current if omitted. Default 30. πŸŽ€

Show current value:

> min_period_between_procedures

Set minimum period to 50:

> min_period_between_procedures 50

max_period_between_procedures

Get/set the maximum time between consecutive procedures. the outer limit on the gap. 🌈

Usage: > max_period_between_procedures [value]

  • [value] β€” the maximum period. Optional, shows current if omitted. Default 150. ⭐

Show current value:

> max_period_between_procedures

Set maximum period to 200:

> max_period_between_procedures 200

max_procedure_count

Get/set the maximum number of procedures. and yes, there's a cheat code for unlimited.

Usage: > max_procedure_count [value]

  • [value] β€” max procedure count, where 0 = no limit at all, go off. Optional, shows current if omitted. Default 0. πŸ”₯

Show current value:

> max_procedure_count

Limit the procedure count to 100:

> max_procedure_count 100

min_sub_event_len

Get/set the minimum CS subevent length. three bytes, little-endian, colon-separated, no I will not be simplifying that. πŸ’…

Usage: > min_sub_event_len [b0:b1:b2]

  • [b0:b1:b2] β€” a 3-byte LE value, colon-separated hex. Optional, shows current if omitted. Default 00:20:00. 🫢

Show current value:

> min_sub_event_len

Set the minimum subevent length:

> min_sub_event_len 00:10:00

max_sub_event_len

Get/set the maximum CS subevent length. the ceiling version of the last one.

Usage: > max_sub_event_len [b0:b1:b2]

  • [b0:b1:b2] β€” a 3-byte LE value, colon-separated hex. Optional, shows current if omitted. Default 03:20:00. 🌸

Show current value:

> max_sub_event_len

Set the maximum subevent length:

> max_sub_event_len 04:20:00

tone_antenna_config_selection

Get/set the antenna configuration for CS tone exchanges. antenna choreography, honestly.

Usage: > tone_antenna_config_selection [value]

  • [value] β€” the antenna config selection. Optional, shows current if omitted. Default 0x07. πŸ‘‘

Show current value:

> tone_antenna_config_selection

Set antenna config to 0x01:

> tone_antenna_config_selection 0x01

phy

Get/set the PHY used for CS procedures β€” not to be confused with sync_phy up there, this one's for the procedures themselves. iykyk.

Usage: > phy [0x01|0x02]

  • [0x01|0x02] β€” 0x01 is LE 1M, 0x02 is LE 2M. Optional, shows current if omitted. Default 0x01. ✨

Show current procedure PHY:

> phy

Set CS procedure PHY to LE 2M:

> phy 0x02

tx_power_delta

Get/set the remote versus local TX power delta. the math between the two of you.

Usage: > tx_power_delta [value]

  • [value] β€” the TX power delta, where 0x80 means "not applicable". Optional, shows current if omitted. Default 0x80. 😭

Show current value:

> tx_power_delta

Set TX power delta to 0x05:

> tx_power_delta 0x05

preferred_peer_antenna

Get/set the preferred antenna for the peer device. manifesting antenna energy for your bestie 🫢

Usage: > preferred_peer_antenna [value]

  • [value] β€” the preferred peer antenna. Optional, shows current if omitted. Default 0x03. πŸ¦‹

Show current value:

> preferred_peer_antenna

Prefer antenna 1 on the peer:

> preferred_peer_antenna 0x01

snr_control_initiator

Get/set the SNR control for the initiator. who's starting things? that one.

Usage: > snr_control_initiator [value]

  • [value] β€” the SNR control, where 0xFF means no preference. Optional, shows current if omitted. Default 0xFF. πŸ’œ

Show current value:

> snr_control_initiator

Prefer high SNR on the initiator:

> snr_control_initiator 0x01

snr_control_reflector

Get/set the SNR control for the reflector. the other half of the duo.

Usage: > snr_control_reflector [value]

  • [value] β€” the SNR control, where 0xFF means no preference. Optional, shows current if omitted. Default 0xFF. 🌈

Show current value:

> snr_control_reflector

Prefer high SNR on the reflector:

> snr_control_reflector 0x01

And if you want high SNR on both roles β€” main character energy for the whole pair, periodt:

> snr_control_initiator 0x01
> snr_control_reflector 0x01

🌐 RESOURCES 🌐

The whole vibe lives at http://www.bluez.org β€” go lurk, it's iconic. πŸ’–


πŸ› REPORTING BUGS πŸ›

Found something cursed? Tell the grown-ups at linux-bluetooth@vger.kernel.org. no cap, they actually want to know. πŸ’€


Free use of this software is granted under the terms of the GNU Lesser General Public Licenses (LGPL). slay, legally speaking. πŸ‘‘


okay that's the whole page bestie, you ate that πŸ’…βœ¨ This whole thing ships with BlueZ, dated June 2026, and it's the BLUETOOTHCTL-CS(1) man page β€” go forth and sound some channels, you absolute icon. πŸŽ€πŸ¦‹πŸŒΈ

πŸ“¦ where this page comes from