1 /* cs.c - Bluetooth Channel Sounding handling */
2
3 /*
4 * Copyright (c) 2024 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <string.h>
13
14 #include <zephyr/autoconf.h>
15 #include <zephyr/bluetooth/conn.h>
16 #include <zephyr/bluetooth/cs.h>
17 #include <zephyr/bluetooth/hci.h>
18 #include <zephyr/bluetooth/hci_types.h>
19 #include <zephyr/kernel.h>
20 #include <zephyr/logging/log.h>
21 #include <zephyr/net_buf.h>
22 #include <zephyr/sys/byteorder.h>
23 #include <zephyr/sys/slist.h>
24 #include <zephyr/sys/util.h>
25 #include <zephyr/sys/util_macro.h>
26
27 #include "conn_internal.h"
28
29 #define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL
30 LOG_MODULE_REGISTER(bt_cs);
31
32 #if defined(CONFIG_BT_CHANNEL_SOUNDING_TEST)
33 static struct bt_le_cs_test_cb cs_test_callbacks;
34 #endif
35
36 #define A1 (0)
37 #define A2 (1)
38 #define A3 (2)
39 #define A4 (3)
40
41 struct reassembly_buf_meta_data {
42 uint16_t conn_handle;
43 };
44
45 static void clear_on_disconnect(struct bt_conn *conn, uint8_t reason);
46
47 NET_BUF_POOL_FIXED_DEFINE(reassembly_buf_pool, CONFIG_BT_CHANNEL_SOUNDING_REASSEMBLY_BUFFER_CNT,
48 CONFIG_BT_CHANNEL_SOUNDING_REASSEMBLY_BUFFER_SIZE,
49 sizeof(struct reassembly_buf_meta_data), NULL);
50
51 static sys_slist_t reassembly_bufs = SYS_SLIST_STATIC_INIT(&reassembly_bufs);
52
53 struct bt_conn_le_cs_subevent_result reassembled_result;
54
55 BT_CONN_CB_DEFINE(cs_conn_callbacks) = {
56 .disconnected = clear_on_disconnect,
57 };
58
59 /** @brief Allocates new reassembly buffer identified by the connection handle
60 *
61 * @param conn_handle Connection handle
62 * @return struct net_buf* Reassembly buffer, NULL if allocation fails
63 */
alloc_reassembly_buf(uint16_t conn_handle)64 static struct net_buf *alloc_reassembly_buf(uint16_t conn_handle)
65 {
66 struct net_buf *buf = net_buf_alloc(&reassembly_buf_pool, K_NO_WAIT);
67
68 if (!buf) {
69 LOG_ERR("Failed to allocate new reassembly buffer");
70 return NULL;
71 }
72
73 struct reassembly_buf_meta_data *buf_meta_data =
74 (struct reassembly_buf_meta_data *)buf->user_data;
75
76 buf_meta_data->conn_handle = conn_handle;
77 net_buf_slist_put(&reassembly_bufs, buf);
78
79 LOG_DBG("Allocated new reassembly buffer for conn handle %d", conn_handle);
80 return buf;
81 }
82
83 /** @brief Frees a reassembly buffer
84 *
85 * @note Takes the ownership of the pointer and sets it to NULL
86 *
87 * @param buf Double pointer to reassembly buffer
88 */
free_reassembly_buf(struct net_buf ** buf)89 static void free_reassembly_buf(struct net_buf **buf)
90 {
91 if (!buf) {
92 LOG_ERR("NULL double pointer was passed when attempting to free reassembly buffer");
93 return;
94 }
95
96 if (!(*buf)) {
97 LOG_WRN("Attempted double free on reassembly buffer");
98 return;
99 }
100
101 struct reassembly_buf_meta_data *buf_meta_data =
102 (struct reassembly_buf_meta_data *)((*buf)->user_data);
103
104 LOG_DBG("De-allocating reassembly buffer for conn handle %d", buf_meta_data->conn_handle);
105 if (!sys_slist_find_and_remove(&reassembly_bufs, &(*buf)->node)) {
106 LOG_WRN("The buffer was not in the list");
107 }
108
109 net_buf_unref(*buf);
110 *buf = NULL;
111 }
112
113 /** @brief Gets the reassembly buffer identified by the connection handle
114 *
115 * @param conn_handle Connection handle
116 * @param allocate Allocates a new reassembly buffer if it's not allocated already
117 * @return struct net_buf* Reassembly buffer, NULL if it doesn't exist or failed when allocating new
118 */
get_reassembly_buf(uint16_t conn_handle,bool allocate)119 static struct net_buf *get_reassembly_buf(uint16_t conn_handle, bool allocate)
120 {
121 sys_snode_t *node;
122
123 SYS_SLIST_FOR_EACH_NODE(&reassembly_bufs, node) {
124 struct net_buf *buf = CONTAINER_OF(node, struct net_buf, node);
125 struct reassembly_buf_meta_data *buf_meta_data =
126 (struct reassembly_buf_meta_data *)(buf->user_data);
127
128 if (buf_meta_data->conn_handle == conn_handle) {
129 return buf;
130 }
131 }
132
133 return allocate ? alloc_reassembly_buf(conn_handle) : NULL;
134 }
135
136 /** @brief Adds step data to a reassembly buffer
137 *
138 * @param reassembly_buf Reassembly buffer
139 * @param data Step data
140 * @param data_len Step data length
141 * @return true if successful, false if there is insufficient space
142 */
add_reassembly_data(struct net_buf * reassembly_buf,const uint8_t * data,uint16_t data_len)143 static bool add_reassembly_data(struct net_buf *reassembly_buf, const uint8_t *data,
144 uint16_t data_len)
145 {
146 if (data_len > net_buf_tailroom(reassembly_buf)) {
147 LOG_ERR("Not enough reassembly buffer space for subevent result");
148 return false;
149 }
150
151 net_buf_add_mem(reassembly_buf, data, data_len);
152 return true;
153 }
154
155 /** @brief Initializes a reassembly buffer from partial step data
156 *
157 * @note Upon first call, this function also registers the disconnection callback
158 * to ensure any dangling reassembly buffer is freed
159 *
160 * @param conn_handle Connection handle
161 * @param steps Step data
162 * @param step_data_len Step data length
163 * @return struct net_buf* Pointer to reassembly buffer, NULL if fails to allocate or insert data
164 */
start_reassembly(uint16_t conn_handle,const uint8_t * steps,uint16_t step_data_len)165 static struct net_buf *start_reassembly(uint16_t conn_handle, const uint8_t *steps,
166 uint16_t step_data_len)
167 {
168 struct net_buf *reassembly_buf = get_reassembly_buf(conn_handle, true);
169
170 if (!reassembly_buf) {
171 LOG_ERR("No buffer allocated for the result reassembly");
172 return NULL;
173 }
174
175 if (reassembly_buf->len) {
176 LOG_WRN("Over-written incomplete CS subevent results");
177 }
178
179 net_buf_reset(reassembly_buf);
180
181 bool success = add_reassembly_data(reassembly_buf, steps, step_data_len);
182
183 return success ? reassembly_buf : NULL;
184 }
185
186 /** @brief Adds more step data to reassembly buffer identified by the connection handle
187 *
188 * @param conn_handle Connection handle
189 * @param steps Step data
190 * @param step_data_len Step data length
191 * @return struct net_buf* Pointer to reassembly buffer, NULL if fails to insert data
192 */
continue_reassembly(uint16_t conn_handle,const uint8_t * steps,uint16_t step_data_len)193 static struct net_buf *continue_reassembly(uint16_t conn_handle, const uint8_t *steps,
194 uint16_t step_data_len)
195 {
196 struct net_buf *reassembly_buf = get_reassembly_buf(conn_handle, false);
197
198 if (!reassembly_buf) {
199 LOG_ERR("No reassembly buffer was allocated for this CS procedure, possibly due to "
200 "an out-of-order subevent result continue event");
201 return NULL;
202 }
203
204 if (!reassembly_buf->len) {
205 LOG_WRN("Discarded out-of-order partial CS subevent results");
206 return NULL;
207 }
208
209 if (!step_data_len) {
210 return reassembly_buf;
211 }
212
213 bool success = add_reassembly_data(reassembly_buf, steps, step_data_len);
214
215 return success ? reassembly_buf : NULL;
216 }
217
218 /**
219 * @brief Disconnect callback to clear any dangling reassembly buffer
220 *
221 * @param conn Connection
222 * @param reason Reason
223 */
clear_on_disconnect(struct bt_conn * conn,uint8_t reason)224 static void clear_on_disconnect(struct bt_conn *conn, uint8_t reason)
225 {
226 struct net_buf *buf = get_reassembly_buf(conn->handle, false);
227
228 if (buf) {
229 free_reassembly_buf(&buf);
230 }
231 }
232
233 /** @brief Invokes user callback for new subevent results
234 *
235 * @param conn Connection context, NULL for CS Test subevent results
236 * @param p_result Pointer to subevent results
237 */
invoke_subevent_result_callback(struct bt_conn * conn,struct bt_conn_le_cs_subevent_result * p_result)238 static void invoke_subevent_result_callback(struct bt_conn *conn,
239 struct bt_conn_le_cs_subevent_result *p_result)
240 {
241 #if defined(CONFIG_BT_CHANNEL_SOUNDING_TEST)
242 if (!conn) {
243 cs_test_callbacks.le_cs_test_subevent_data_available(p_result);
244 } else
245 #endif /* CONFIG_BT_CHANNEL_SOUNDING_TEST */
246 {
247 bt_conn_notify_cs_subevent_result(conn, p_result);
248 }
249 }
250
251 /** @brief Resets reassembly results
252 *
253 */
reset_reassembly_results(void)254 static void reset_reassembly_results(void)
255 {
256 memset(&reassembled_result, 0, sizeof(struct bt_conn_le_cs_subevent_result));
257 }
258
259 /** @brief Converts PCT to a pair of int16_t
260 *
261 */
bt_le_cs_parse_pct(const uint8_t pct[3])262 struct bt_le_cs_iq_sample bt_le_cs_parse_pct(const uint8_t pct[3])
263 {
264 uint32_t pct_u32 = sys_get_le24(pct);
265
266 /* Extract I and Q. */
267 uint16_t i_u16 = pct_u32 & BT_HCI_LE_CS_PCT_I_MASK;
268 uint16_t q_u16 = (pct_u32 & BT_HCI_LE_CS_PCT_Q_MASK) >> 12;
269
270 /* Convert from 12-bit 2's complement to int16_t */
271 int16_t i = (i_u16 ^ BIT(11)) - BIT(11);
272 int16_t q = (q_u16 ^ BIT(11)) - BIT(11);
273
274 return (struct bt_le_cs_iq_sample){.i = i, .q = q};
275 }
276
bt_le_cs_set_valid_chmap_bits(uint8_t channel_map[10])277 void bt_le_cs_set_valid_chmap_bits(uint8_t channel_map[10])
278 {
279 memset(channel_map, 0xFF, 10);
280
281 /** Channels n = 0, 1, 23, 24, 25, 77, and 78 are not allowed and shall be set to zero.
282 * Channel 79 is reserved for future use and shall be set to zero.
283 */
284 BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 0, 0);
285 BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 1, 0);
286 BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 23, 0);
287 BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 24, 0);
288 BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 25, 0);
289 BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 77, 0);
290 BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 78, 0);
291 BT_LE_CS_CHANNEL_BIT_SET_VAL(channel_map, 79, 0);
292 }
293
bt_le_cs_read_remote_supported_capabilities(struct bt_conn * conn)294 int bt_le_cs_read_remote_supported_capabilities(struct bt_conn *conn)
295 {
296 struct bt_hci_cp_le_read_remote_supported_capabilities *cp;
297 struct net_buf *buf;
298
299 buf = bt_hci_cmd_alloc(K_FOREVER);
300 if (!buf) {
301 return -ENOBUFS;
302 }
303
304 cp = net_buf_add(buf, sizeof(*cp));
305 cp->handle = sys_cpu_to_le16(conn->handle);
306
307 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES, buf, NULL);
308 }
309
bt_hci_le_cs_read_remote_supported_capabilities_complete(struct net_buf * buf)310 void bt_hci_le_cs_read_remote_supported_capabilities_complete(struct net_buf *buf)
311 {
312 struct bt_conn *conn;
313 struct bt_conn_le_cs_capabilities remote_cs_capabilities;
314 struct bt_hci_evt_le_cs_read_remote_supported_capabilities_complete *evt;
315
316 if (buf->len < sizeof(*evt)) {
317 LOG_ERR("Unexpected end of buffer");
318 return;
319 }
320
321 evt = net_buf_pull_mem(buf, sizeof(*evt));
322 if (evt->status) {
323 LOG_WRN("Read Remote Supported Capabilities failed (status 0x%02X)", evt->status);
324 }
325
326 conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle), BT_CONN_TYPE_LE);
327 if (!conn) {
328 LOG_ERR("Could not lookup connection handle when reading remote CS capabilities");
329 return;
330 }
331
332 if (evt->status == BT_HCI_ERR_SUCCESS) {
333 remote_cs_capabilities.num_config_supported = evt->num_config_supported;
334 remote_cs_capabilities.max_consecutive_procedures_supported =
335 sys_le16_to_cpu(evt->max_consecutive_procedures_supported);
336 remote_cs_capabilities.num_antennas_supported = evt->num_antennas_supported;
337 remote_cs_capabilities.max_antenna_paths_supported =
338 evt->max_antenna_paths_supported;
339
340 remote_cs_capabilities.initiator_supported =
341 evt->roles_supported & BT_HCI_LE_CS_INITIATOR_ROLE_MASK;
342 remote_cs_capabilities.reflector_supported =
343 evt->roles_supported & BT_HCI_LE_CS_REFLECTOR_ROLE_MASK;
344 remote_cs_capabilities.mode_3_supported =
345 evt->modes_supported & BT_HCI_LE_CS_MODES_SUPPORTED_MODE_3_MASK;
346
347 remote_cs_capabilities.rtt_aa_only_n = evt->rtt_aa_only_n;
348 remote_cs_capabilities.rtt_sounding_n = evt->rtt_sounding_n;
349 remote_cs_capabilities.rtt_random_payload_n = evt->rtt_random_payload_n;
350
351 if (evt->rtt_aa_only_n) {
352 if (evt->rtt_capability & BT_HCI_LE_CS_RTT_AA_ONLY_N_10NS_MASK) {
353 remote_cs_capabilities.rtt_aa_only_precision =
354 BT_CONN_LE_CS_RTT_AA_ONLY_10NS;
355 } else {
356 remote_cs_capabilities.rtt_aa_only_precision =
357 BT_CONN_LE_CS_RTT_AA_ONLY_150NS;
358 }
359 } else {
360 remote_cs_capabilities.rtt_aa_only_precision =
361 BT_CONN_LE_CS_RTT_AA_ONLY_NOT_SUPP;
362 }
363
364 if (evt->rtt_sounding_n) {
365 if (evt->rtt_capability & BT_HCI_LE_CS_RTT_SOUNDING_N_10NS_MASK) {
366 remote_cs_capabilities.rtt_sounding_precision =
367 BT_CONN_LE_CS_RTT_SOUNDING_10NS;
368 } else {
369 remote_cs_capabilities.rtt_sounding_precision =
370 BT_CONN_LE_CS_RTT_SOUNDING_150NS;
371 }
372 } else {
373 remote_cs_capabilities.rtt_sounding_precision =
374 BT_CONN_LE_CS_RTT_SOUNDING_NOT_SUPP;
375 }
376
377 if (evt->rtt_random_payload_n) {
378 if (evt->rtt_capability & BT_HCI_LE_CS_RTT_RANDOM_PAYLOAD_N_10NS_MASK) {
379 remote_cs_capabilities.rtt_random_payload_precision =
380 BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_10NS;
381 } else {
382 remote_cs_capabilities.rtt_random_payload_precision =
383 BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_150NS;
384 }
385 } else {
386 remote_cs_capabilities.rtt_random_payload_precision =
387 BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_NOT_SUPP;
388 }
389
390 remote_cs_capabilities.phase_based_nadm_sounding_supported =
391 sys_le16_to_cpu(evt->nadm_sounding_capability) &
392 BT_HCI_LE_CS_NADM_SOUNDING_CAPABILITY_PHASE_BASED_MASK;
393
394 remote_cs_capabilities.phase_based_nadm_random_supported =
395 sys_le16_to_cpu(evt->nadm_random_capability) &
396 BT_HCI_LE_CS_NADM_RANDOM_CAPABILITY_PHASE_BASED_MASK;
397
398 remote_cs_capabilities.cs_sync_2m_phy_supported =
399 evt->cs_sync_phys_supported & BT_HCI_LE_CS_SYNC_PHYS_2M_MASK;
400
401 remote_cs_capabilities.cs_sync_2m_2bt_phy_supported =
402 evt->cs_sync_phys_supported & BT_HCI_LE_CS_SYNC_PHYS_2M_2BT_MASK;
403
404 remote_cs_capabilities.cs_without_fae_supported =
405 sys_le16_to_cpu(evt->subfeatures_supported) &
406 BT_HCI_LE_CS_SUBFEATURE_NO_TX_FAE_MASK;
407
408 remote_cs_capabilities.chsel_alg_3c_supported =
409 sys_le16_to_cpu(evt->subfeatures_supported) &
410 BT_HCI_LE_CS_SUBFEATURE_CHSEL_ALG_3C_MASK;
411
412 remote_cs_capabilities.pbr_from_rtt_sounding_seq_supported =
413 sys_le16_to_cpu(evt->subfeatures_supported) &
414 BT_HCI_LE_CS_SUBFEATURE_PBR_FROM_RTT_SOUNDING_SEQ_MASK;
415
416 remote_cs_capabilities.t_ip1_times_supported =
417 sys_le16_to_cpu(evt->t_ip1_times_supported);
418 remote_cs_capabilities.t_ip2_times_supported =
419 sys_le16_to_cpu(evt->t_ip2_times_supported);
420 remote_cs_capabilities.t_fcs_times_supported =
421 sys_le16_to_cpu(evt->t_fcs_times_supported);
422 remote_cs_capabilities.t_pm_times_supported =
423 sys_le16_to_cpu(evt->t_pm_times_supported);
424
425 remote_cs_capabilities.t_sw_time = evt->t_sw_time_supported;
426 remote_cs_capabilities.tx_snr_capability = evt->tx_snr_capability;
427
428 bt_conn_notify_remote_cs_capabilities(conn, BT_HCI_ERR_SUCCESS,
429 &remote_cs_capabilities);
430 } else {
431 bt_conn_notify_remote_cs_capabilities(conn, evt->status, NULL);
432 }
433
434 bt_conn_unref(conn);
435 }
436
bt_le_cs_set_default_settings(struct bt_conn * conn,const struct bt_le_cs_set_default_settings_param * params)437 int bt_le_cs_set_default_settings(struct bt_conn *conn,
438 const struct bt_le_cs_set_default_settings_param *params)
439 {
440 struct bt_hci_cp_le_cs_set_default_settings *cp;
441 struct net_buf *buf;
442
443 buf = bt_hci_cmd_alloc(K_FOREVER);
444 if (!buf) {
445 return -ENOBUFS;
446 }
447
448 cp = net_buf_add(buf, sizeof(*cp));
449 cp->handle = sys_cpu_to_le16(conn->handle);
450 cp->max_tx_power = params->max_tx_power;
451 cp->cs_sync_antenna_selection = params->cs_sync_antenna_selection;
452 cp->role_enable = 0;
453
454 if (params->enable_initiator_role) {
455 cp->role_enable |= BT_HCI_OP_LE_CS_INITIATOR_ROLE_MASK;
456 }
457
458 if (params->enable_reflector_role) {
459 cp->role_enable |= BT_HCI_OP_LE_CS_REFLECTOR_ROLE_MASK;
460 }
461
462 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_SET_DEFAULT_SETTINGS, buf, NULL);
463 }
464
bt_le_cs_read_remote_fae_table(struct bt_conn * conn)465 int bt_le_cs_read_remote_fae_table(struct bt_conn *conn)
466 {
467 struct bt_hci_cp_le_read_remote_fae_table *cp;
468 struct net_buf *buf;
469
470 buf = bt_hci_cmd_alloc(K_FOREVER);
471 if (!buf) {
472 return -ENOBUFS;
473 }
474
475 cp = net_buf_add(buf, sizeof(*cp));
476 cp->handle = sys_cpu_to_le16(conn->handle);
477
478 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_READ_REMOTE_FAE_TABLE, buf, NULL);
479 }
480
bt_hci_le_cs_read_remote_fae_table_complete(struct net_buf * buf)481 void bt_hci_le_cs_read_remote_fae_table_complete(struct net_buf *buf)
482 {
483 struct bt_conn *conn;
484 struct bt_conn_le_cs_fae_table fae_table;
485 struct bt_hci_evt_le_cs_read_remote_fae_table_complete *evt;
486
487 if (buf->len < sizeof(*evt)) {
488 LOG_ERR("Unexpected end of buffer");
489 return;
490 }
491
492 evt = net_buf_pull_mem(buf, sizeof(*evt));
493 if (evt->status) {
494 LOG_WRN("Read Remote FAE Table failed with status 0x%02X", evt->status);
495 }
496
497 conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->conn_handle), BT_CONN_TYPE_LE);
498 if (!conn) {
499 LOG_ERR("Could not lookup connection handle when reading remote FAE Table");
500 return;
501 }
502
503 if (evt->status == BT_HCI_ERR_SUCCESS) {
504 fae_table.remote_fae_table = evt->remote_fae_table;
505
506 bt_conn_notify_remote_cs_fae_table(conn, BT_HCI_ERR_SUCCESS, &fae_table);
507 } else {
508 bt_conn_notify_remote_cs_fae_table(conn, evt->status, NULL);
509 }
510
511 bt_conn_unref(conn);
512 }
513
514 #if defined(CONFIG_BT_CHANNEL_SOUNDING_TEST)
bt_le_cs_test_cb_register(struct bt_le_cs_test_cb cb)515 int bt_le_cs_test_cb_register(struct bt_le_cs_test_cb cb)
516 {
517 cs_test_callbacks = cb;
518 return 0;
519 }
520
bt_le_cs_start_test(const struct bt_le_cs_test_param * params)521 int bt_le_cs_start_test(const struct bt_le_cs_test_param *params)
522 {
523 struct bt_hci_op_le_cs_test *cp;
524 struct net_buf *buf;
525
526 buf = bt_hci_cmd_alloc(K_FOREVER);
527 if (!buf) {
528 return -ENOBUFS;
529 }
530
531 cp = net_buf_add(buf, sizeof(*cp));
532
533 cp->main_mode_type = BT_CONN_LE_CS_MODE_MAIN_MODE_PART(params->mode);
534
535 uint8_t sub_mode_type = BT_CONN_LE_CS_MODE_SUB_MODE_PART(params->mode);
536
537 if (sub_mode_type) {
538 cp->sub_mode_type = sub_mode_type;
539 } else {
540 cp->sub_mode_type = BT_HCI_OP_LE_CS_SUB_MODE_UNUSED;
541 }
542
543 cp->main_mode_repetition = params->main_mode_repetition;
544 cp->mode_0_steps = params->mode_0_steps;
545 cp->role = params->role;
546 cp->rtt_type = params->rtt_type;
547 cp->cs_sync_phy = params->cs_sync_phy;
548 cp->cs_sync_antenna_selection = params->cs_sync_antenna_selection;
549 sys_put_le24(params->subevent_len, cp->subevent_len);
550 cp->subevent_interval = sys_cpu_to_le16(params->subevent_interval);
551 cp->max_num_subevents = params->max_num_subevents;
552 cp->transmit_power_level = params->transmit_power_level;
553 cp->t_ip1_time = params->t_ip1_time;
554 cp->t_ip2_time = params->t_ip2_time;
555 cp->t_fcs_time = params->t_fcs_time;
556 cp->t_pm_time = params->t_pm_time;
557 cp->t_sw_time = params->t_sw_time;
558 cp->tone_antenna_config_selection = params->tone_antenna_config_selection;
559
560 cp->reserved = 0;
561
562 cp->snr_control_initiator = params->initiator_snr_control;
563 cp->snr_control_reflector = params->reflector_snr_control;
564 cp->drbg_nonce = sys_cpu_to_le16(params->drbg_nonce);
565 cp->channel_map_repetition = params->override_config_0.channel_map_repetition;
566 cp->override_config = sys_cpu_to_le16(params->override_config);
567
568 uint8_t override_parameters_length = 0;
569
570 if (params->override_config & BT_HCI_OP_LE_CS_TEST_OVERRIDE_CONFIG_0_MASK) {
571 const uint8_t num_channels = params->override_config_0.set.num_channels;
572
573 net_buf_add_u8(buf, num_channels);
574 override_parameters_length++;
575 net_buf_add_mem(buf, params->override_config_0.set.channels, num_channels);
576 override_parameters_length += num_channels;
577 } else {
578 net_buf_add_mem(buf, params->override_config_0.not_set.channel_map,
579 sizeof(params->override_config_0.not_set.channel_map));
580 net_buf_add_u8(buf, params->override_config_0.not_set.channel_selection_type);
581 net_buf_add_u8(buf, params->override_config_0.not_set.ch3c_shape);
582 net_buf_add_u8(buf, params->override_config_0.not_set.ch3c_jump);
583
584 override_parameters_length +=
585 (sizeof(params->override_config_0.not_set.channel_map) +
586 sizeof(params->override_config_0.not_set.channel_selection_type) +
587 sizeof(params->override_config_0.not_set.ch3c_shape) +
588 sizeof(params->override_config_0.not_set.ch3c_jump));
589 }
590
591 if (params->override_config & BT_HCI_OP_LE_CS_TEST_OVERRIDE_CONFIG_2_MASK) {
592 net_buf_add_mem(buf, ¶ms->override_config_2, sizeof(params->override_config_2));
593 override_parameters_length += sizeof(params->override_config_2);
594 }
595
596 if (params->override_config & BT_HCI_OP_LE_CS_TEST_OVERRIDE_CONFIG_3_MASK) {
597 net_buf_add_mem(buf, ¶ms->override_config_3, sizeof(params->override_config_3));
598 override_parameters_length += sizeof(params->override_config_3);
599 }
600
601 if (params->override_config & BT_HCI_OP_LE_CS_TEST_OVERRIDE_CONFIG_4_MASK) {
602 net_buf_add_mem(buf, ¶ms->override_config_4, sizeof(params->override_config_4));
603 override_parameters_length += sizeof(params->override_config_4);
604 }
605
606 if (params->override_config & BT_HCI_OP_LE_CS_TEST_OVERRIDE_CONFIG_5_MASK) {
607 net_buf_add_le32(buf, params->override_config_5.cs_sync_aa_initiator);
608 net_buf_add_le32(buf, params->override_config_5.cs_sync_aa_reflector);
609 override_parameters_length += sizeof(params->override_config_5);
610 }
611
612 if (params->override_config & BT_HCI_OP_LE_CS_TEST_OVERRIDE_CONFIG_6_MASK) {
613 net_buf_add_mem(buf, ¶ms->override_config_6, sizeof(params->override_config_6));
614 override_parameters_length += sizeof(params->override_config_6);
615 }
616
617 if (params->override_config & BT_HCI_OP_LE_CS_TEST_OVERRIDE_CONFIG_7_MASK) {
618 net_buf_add_mem(buf, ¶ms->override_config_7, sizeof(params->override_config_7));
619 override_parameters_length += sizeof(params->override_config_7);
620 }
621
622 if (params->override_config & BT_HCI_OP_LE_CS_TEST_OVERRIDE_CONFIG_8_MASK) {
623 net_buf_add_mem(buf, ¶ms->override_config_8, sizeof(params->override_config_8));
624 override_parameters_length += sizeof(params->override_config_8);
625 }
626
627 cp->override_parameters_length = override_parameters_length;
628
629 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_TEST, buf, NULL);
630 }
631 #endif /* CONFIG_BT_CHANNEL_SOUNDING_TEST */
632
bt_hci_le_cs_subevent_result(struct net_buf * buf)633 void bt_hci_le_cs_subevent_result(struct net_buf *buf)
634 {
635 struct bt_conn *conn = NULL;
636 struct bt_hci_evt_le_cs_subevent_result *evt;
637 struct bt_conn_le_cs_subevent_result result;
638 struct bt_conn_le_cs_subevent_result *p_result = &result;
639 struct net_buf_simple step_data_buf;
640 struct net_buf *reassembly_buf = NULL;
641
642 if (buf->len < sizeof(*evt)) {
643 LOG_ERR("Unexpected end of buffer");
644 return;
645 }
646
647 evt = net_buf_pull_mem(buf, sizeof(*evt));
648 uint16_t conn_handle = sys_le16_to_cpu(evt->conn_handle);
649
650 #if defined(CONFIG_BT_CHANNEL_SOUNDING_TEST)
651 if (conn_handle == BT_HCI_LE_CS_TEST_CONN_HANDLE) {
652 if (!cs_test_callbacks.le_cs_test_subevent_data_available) {
653 LOG_WRN("No callback registered. Discarded subevent results from CS Test.");
654 return;
655 }
656 } else
657 #endif /* CONFIG_BT_CHANNEL_SOUNDING_TEST */
658 {
659 conn = bt_conn_lookup_handle(conn_handle, BT_CONN_TYPE_LE);
660 if (!conn) {
661 LOG_ERR("Unknown connection handle when processing subevent results");
662 return;
663 }
664 }
665
666 if (evt->subevent_done_status != BT_HCI_LE_CS_SUBEVENT_DONE_STATUS_PARTIAL) {
667 p_result->step_data_buf = NULL;
668 if (evt->num_steps_reported) {
669 net_buf_simple_init_with_data(&step_data_buf, evt->steps, buf->len);
670 p_result->step_data_buf = &step_data_buf;
671 }
672 } else {
673 if (evt->procedure_done_status != BT_HCI_LE_CS_PROCEDURE_DONE_STATUS_PARTIAL) {
674 LOG_WRN("Procedure status is inconsistent with subevent status. Discarding "
675 "subevent results");
676 goto abort;
677 }
678
679 if (!evt->num_steps_reported) {
680 LOG_WRN("Discarding partial results without step data");
681 goto abort;
682 }
683
684 reassembly_buf = start_reassembly(conn_handle, evt->steps, buf->len);
685 if (!reassembly_buf) {
686 goto abort;
687 }
688
689 p_result = &reassembled_result;
690 p_result->step_data_buf = (struct net_buf_simple *)&reassembly_buf->data;
691 }
692
693 p_result->header.procedure_counter = sys_le16_to_cpu(evt->procedure_counter);
694 p_result->header.frequency_compensation = sys_le16_to_cpu(evt->frequency_compensation);
695 p_result->header.procedure_done_status = evt->procedure_done_status;
696 p_result->header.subevent_done_status = evt->subevent_done_status;
697 p_result->header.procedure_abort_reason = evt->procedure_abort_reason;
698 p_result->header.subevent_abort_reason = evt->subevent_abort_reason;
699 p_result->header.reference_power_level = evt->reference_power_level;
700 p_result->header.num_antenna_paths = evt->num_antenna_paths;
701 p_result->header.num_steps_reported = evt->num_steps_reported;
702 p_result->header.abort_step =
703 evt->subevent_done_status == BT_HCI_LE_CS_SUBEVENT_DONE_STATUS_ABORTED ? 0 : 255;
704
705 p_result->header.config_id = 0;
706 p_result->header.start_acl_conn_event = 0;
707 if (conn) {
708 p_result->header.config_id = evt->config_id;
709 p_result->header.start_acl_conn_event =
710 sys_le16_to_cpu(evt->start_acl_conn_event_counter);
711 }
712
713 if (evt->subevent_done_status != BT_HCI_LE_CS_SUBEVENT_DONE_STATUS_PARTIAL) {
714 invoke_subevent_result_callback(conn, p_result);
715 }
716
717 if (evt->procedure_done_status != BT_CONN_LE_CS_PROCEDURE_INCOMPLETE) {
718 /* We can now clear the any reassembly buffer allocated for this procedure,
719 * to avoid code duplication, we're using the abort label to do so
720 */
721 goto abort;
722 }
723
724 if (conn) {
725 bt_conn_unref(conn);
726 conn = NULL;
727 }
728
729 return;
730
731 abort:
732 if (conn) {
733 bt_conn_unref(conn);
734 conn = NULL;
735 }
736
737 reassembly_buf = get_reassembly_buf(conn_handle, false);
738 if (reassembly_buf) {
739 free_reassembly_buf(&reassembly_buf);
740 }
741 }
742
bt_hci_le_cs_subevent_result_continue(struct net_buf * buf)743 void bt_hci_le_cs_subevent_result_continue(struct net_buf *buf)
744 {
745 struct bt_conn *conn = NULL;
746 struct bt_hci_evt_le_cs_subevent_result_continue *evt;
747 struct net_buf *reassembly_buf = NULL;
748 uint16_t conn_handle;
749
750 if (buf->len < sizeof(*evt)) {
751 LOG_ERR("Unexpected end of buffer");
752 return;
753 }
754
755 evt = net_buf_pull_mem(buf, sizeof(*evt));
756 conn_handle = sys_le16_to_cpu(evt->conn_handle);
757
758 #if defined(CONFIG_BT_CHANNEL_SOUNDING_TEST)
759 if (conn_handle == BT_HCI_LE_CS_TEST_CONN_HANDLE) {
760 if (!cs_test_callbacks.le_cs_test_subevent_data_available) {
761 LOG_WRN("No callback registered. Discarded subevent results from CS Test.");
762 return;
763 }
764 } else
765 #endif /* CONFIG_BT_CHANNEL_SOUNDING_TEST */
766 {
767 conn = bt_conn_lookup_handle(conn_handle, BT_CONN_TYPE_LE);
768 if (!conn) {
769 LOG_ERR("Unknown connection handle when processing subevent results");
770 return;
771 }
772 }
773
774 uint16_t step_data_len = evt->num_steps_reported ? buf->len : 0;
775
776 reassembly_buf = continue_reassembly(conn_handle, evt->steps, step_data_len);
777 if (!reassembly_buf) {
778 goto abort;
779 }
780
781 reassembled_result.header.procedure_done_status = evt->procedure_done_status;
782 reassembled_result.header.subevent_done_status = evt->subevent_done_status;
783 reassembled_result.header.procedure_abort_reason = evt->procedure_abort_reason;
784 reassembled_result.header.subevent_abort_reason = evt->subevent_abort_reason;
785
786 if (evt->num_antenna_paths != reassembled_result.header.num_antenna_paths) {
787 LOG_WRN("Received inconsistent number of antenna paths from the controller: %d, "
788 "previous number was: %d",
789 evt->num_antenna_paths, reassembled_result.header.num_antenna_paths);
790 }
791
792 if (evt->subevent_done_status == BT_HCI_LE_CS_SUBEVENT_DONE_STATUS_ABORTED &&
793 reassembled_result.header.num_steps_reported < reassembled_result.header.abort_step) {
794 reassembled_result.header.abort_step = reassembled_result.header.num_steps_reported;
795 }
796
797 reassembled_result.header.num_steps_reported += evt->num_steps_reported;
798
799 if (evt->subevent_done_status != BT_HCI_LE_CS_SUBEVENT_DONE_STATUS_PARTIAL) {
800 invoke_subevent_result_callback(conn, &reassembled_result);
801 net_buf_reset(reassembly_buf);
802 reset_reassembly_results();
803 }
804
805 if (evt->procedure_done_status != BT_HCI_LE_CS_PROCEDURE_DONE_STATUS_PARTIAL) {
806 if (evt->subevent_done_status == BT_HCI_LE_CS_SUBEVENT_DONE_STATUS_PARTIAL) {
807 LOG_WRN("Procedure status is inconsistent with subevent status. Discarding "
808 "subevent results");
809 goto abort;
810 }
811
812 free_reassembly_buf(&reassembly_buf);
813 }
814
815 if (conn) {
816 bt_conn_unref(conn);
817 conn = NULL;
818 }
819
820 return;
821
822 abort:
823 if (conn) {
824 bt_conn_unref(conn);
825 conn = NULL;
826 }
827
828 if (reassembly_buf) {
829 free_reassembly_buf(&reassembly_buf);
830 }
831 }
832
bt_hci_le_cs_config_complete_event(struct net_buf * buf)833 void bt_hci_le_cs_config_complete_event(struct net_buf *buf)
834 {
835 struct bt_hci_evt_le_cs_config_complete *evt;
836 struct bt_conn_le_cs_config config;
837 struct bt_conn *conn;
838
839 if (buf->len < sizeof(*evt)) {
840 LOG_ERR("Unexpected end of buffer");
841 return;
842 }
843
844 evt = net_buf_pull_mem(buf, sizeof(*evt));
845 if (evt->status) {
846 LOG_WRN("CS Config failed (status 0x%02X)", evt->status);
847 }
848
849 conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->handle), BT_CONN_TYPE_LE);
850 if (!conn) {
851 LOG_ERR("Could not lookup connection handle when reading CS configuration");
852 return;
853 }
854
855 if (evt->status == BT_HCI_ERR_SUCCESS) {
856 if (evt->action == BT_HCI_LE_CS_CONFIG_ACTION_REMOVED) {
857 bt_conn_notify_cs_config_removed(conn, evt->config_id);
858 bt_conn_unref(conn);
859 return;
860 }
861
862 if (evt->sub_mode_type == BT_HCI_OP_LE_CS_SUB_MODE_UNUSED) {
863 config.mode = evt->main_mode_type;
864 } else {
865 config.mode = evt->main_mode_type | (evt->sub_mode_type << 4);
866 }
867
868 config.id = evt->config_id;
869 config.min_main_mode_steps = evt->min_main_mode_steps;
870 config.max_main_mode_steps = evt->max_main_mode_steps;
871 config.main_mode_repetition = evt->main_mode_repetition;
872 config.mode_0_steps = evt->mode_0_steps;
873 config.role = evt->role;
874 config.rtt_type = evt->rtt_type;
875 config.cs_sync_phy = evt->cs_sync_phy;
876 config.channel_map_repetition = evt->channel_map_repetition;
877 config.channel_selection_type = evt->channel_selection_type;
878 config.ch3c_shape = evt->ch3c_shape;
879 config.ch3c_jump = evt->ch3c_jump;
880 config.t_ip1_time_us = evt->t_ip1_time;
881 config.t_ip2_time_us = evt->t_ip2_time;
882 config.t_fcs_time_us = evt->t_fcs_time;
883 config.t_pm_time_us = evt->t_pm_time;
884 memcpy(config.channel_map, evt->channel_map, ARRAY_SIZE(config.channel_map));
885
886 bt_conn_notify_cs_config_created(conn, BT_HCI_ERR_SUCCESS, &config);
887 } else {
888 bt_conn_notify_cs_config_created(conn, evt->status, NULL);
889 }
890
891 bt_conn_unref(conn);
892 }
893
bt_le_cs_create_config(struct bt_conn * conn,struct bt_le_cs_create_config_params * params,enum bt_le_cs_create_config_context context)894 int bt_le_cs_create_config(struct bt_conn *conn, struct bt_le_cs_create_config_params *params,
895 enum bt_le_cs_create_config_context context)
896 {
897 struct bt_hci_cp_le_cs_create_config *cp;
898 struct net_buf *buf;
899
900 buf = bt_hci_cmd_alloc(K_FOREVER);
901 if (!buf) {
902 return -ENOBUFS;
903 }
904
905 cp = net_buf_add(buf, sizeof(*cp));
906 cp->handle = sys_cpu_to_le16(conn->handle);
907 cp->config_id = params->id;
908 cp->create_context = context;
909 cp->main_mode_type = BT_CONN_LE_CS_MODE_MAIN_MODE_PART(params->mode);
910
911 uint8_t sub_mode_type = BT_CONN_LE_CS_MODE_SUB_MODE_PART(params->mode);
912
913 if (sub_mode_type) {
914 cp->sub_mode_type = sub_mode_type;
915 } else {
916 cp->sub_mode_type = BT_HCI_OP_LE_CS_SUB_MODE_UNUSED;
917 }
918
919 cp->min_main_mode_steps = params->min_main_mode_steps;
920 cp->max_main_mode_steps = params->max_main_mode_steps;
921 cp->main_mode_repetition = params->main_mode_repetition;
922 cp->mode_0_steps = params->mode_0_steps;
923 cp->role = params->role;
924 cp->rtt_type = params->rtt_type;
925 cp->cs_sync_phy = params->cs_sync_phy;
926 cp->channel_map_repetition = params->channel_map_repetition;
927 cp->channel_selection_type = params->channel_selection_type;
928 cp->ch3c_shape = params->ch3c_shape;
929 cp->ch3c_jump = params->ch3c_jump;
930 cp->reserved = 0;
931 memcpy(cp->channel_map, params->channel_map, ARRAY_SIZE(cp->channel_map));
932
933 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_CREATE_CONFIG, buf, NULL);
934 }
935
bt_le_cs_remove_config(struct bt_conn * conn,uint8_t config_id)936 int bt_le_cs_remove_config(struct bt_conn *conn, uint8_t config_id)
937 {
938 struct bt_hci_cp_le_cs_remove_config *cp;
939 struct net_buf *buf;
940
941 buf = bt_hci_cmd_alloc(K_FOREVER);
942 if (!buf) {
943 return -ENOBUFS;
944 }
945
946 cp = net_buf_add(buf, sizeof(*cp));
947 cp->handle = sys_cpu_to_le16(conn->handle);
948 cp->config_id = config_id;
949
950 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_REMOVE_CONFIG, buf, NULL);
951 }
952
bt_le_cs_security_enable(struct bt_conn * conn)953 int bt_le_cs_security_enable(struct bt_conn *conn)
954 {
955 struct bt_hci_cp_le_security_enable *cp;
956 struct net_buf *buf;
957
958 buf = bt_hci_cmd_alloc(K_FOREVER);
959 if (!buf) {
960 return -ENOBUFS;
961 }
962
963 cp = net_buf_add(buf, sizeof(*cp));
964 cp->handle = sys_cpu_to_le16(conn->handle);
965
966 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_SECURITY_ENABLE, buf, NULL);
967 }
968
bt_le_cs_procedure_enable(struct bt_conn * conn,const struct bt_le_cs_procedure_enable_param * params)969 int bt_le_cs_procedure_enable(struct bt_conn *conn,
970 const struct bt_le_cs_procedure_enable_param *params)
971 {
972 struct bt_hci_cp_le_procedure_enable *cp;
973 struct net_buf *buf;
974
975 buf = bt_hci_cmd_alloc(K_FOREVER);
976 if (!buf) {
977 return -ENOBUFS;
978 }
979
980 cp = net_buf_add(buf, sizeof(*cp));
981 cp->handle = sys_cpu_to_le16(conn->handle);
982 cp->config_id = params->config_id;
983 cp->enable = params->enable;
984
985 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_PROCEDURE_ENABLE, buf, NULL);
986 }
987
bt_le_cs_set_procedure_parameters(struct bt_conn * conn,const struct bt_le_cs_set_procedure_parameters_param * params)988 int bt_le_cs_set_procedure_parameters(struct bt_conn *conn,
989 const struct bt_le_cs_set_procedure_parameters_param *params)
990 {
991 struct bt_hci_cp_le_set_procedure_parameters *cp;
992 struct net_buf *buf;
993
994 buf = bt_hci_cmd_alloc(K_FOREVER);
995 if (!buf) {
996 return -ENOBUFS;
997 }
998
999 cp = net_buf_add(buf, sizeof(*cp));
1000 cp->handle = sys_cpu_to_le16(conn->handle);
1001 cp->config_id = params->config_id;
1002 cp->max_procedure_len = sys_cpu_to_le16(params->max_procedure_len);
1003 cp->min_procedure_interval = sys_cpu_to_le16(params->min_procedure_interval);
1004 cp->max_procedure_interval = sys_cpu_to_le16(params->max_procedure_interval);
1005 cp->max_procedure_count = sys_cpu_to_le16(params->max_procedure_count);
1006 sys_put_le24(params->min_subevent_len, cp->min_subevent_len);
1007 sys_put_le24(params->max_subevent_len, cp->max_subevent_len);
1008 cp->tone_antenna_config_selection = params->tone_antenna_config_selection;
1009 cp->phy = params->phy;
1010 cp->tx_power_delta = params->tx_power_delta;
1011 cp->preferred_peer_antenna = params->preferred_peer_antenna;
1012 cp->snr_control_initiator = params->snr_control_initiator;
1013 cp->snr_control_reflector = params->snr_control_reflector;
1014
1015 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_SET_PROCEDURE_PARAMETERS, buf, NULL);
1016 }
1017
bt_le_cs_set_channel_classification(uint8_t channel_classification[10])1018 int bt_le_cs_set_channel_classification(uint8_t channel_classification[10])
1019 {
1020 uint8_t *cp;
1021 struct net_buf *buf;
1022
1023 buf = bt_hci_cmd_alloc(K_FOREVER);
1024 if (!buf) {
1025 return -ENOBUFS;
1026 }
1027
1028 cp = net_buf_add(buf, 10);
1029 memcpy(cp, channel_classification, 10);
1030
1031 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_SET_CHANNEL_CLASSIFICATION, buf, NULL);
1032 }
1033
bt_le_cs_read_local_supported_capabilities(struct bt_conn_le_cs_capabilities * ret)1034 int bt_le_cs_read_local_supported_capabilities(struct bt_conn_le_cs_capabilities *ret)
1035 {
1036 struct bt_hci_rp_le_read_local_supported_capabilities *rp;
1037 struct net_buf *rsp;
1038
1039 int err =
1040 bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_READ_LOCAL_SUPPORTED_CAPABILITIES, NULL, &rsp);
1041
1042 if (err) {
1043 return err;
1044 }
1045
1046 rp = (void *)rsp->data;
1047
1048 uint8_t status = rp->status;
1049
1050 ret->num_config_supported = rp->num_config_supported;
1051 ret->max_consecutive_procedures_supported =
1052 sys_le16_to_cpu(rp->max_consecutive_procedures_supported);
1053 ret->num_antennas_supported = rp->num_antennas_supported;
1054 ret->max_antenna_paths_supported = rp->max_antenna_paths_supported;
1055
1056 ret->initiator_supported = rp->roles_supported & BT_HCI_LE_CS_INITIATOR_ROLE_MASK;
1057 ret->reflector_supported = rp->roles_supported & BT_HCI_LE_CS_REFLECTOR_ROLE_MASK;
1058 ret->mode_3_supported = rp->modes_supported & BT_HCI_LE_CS_MODES_SUPPORTED_MODE_3_MASK;
1059
1060 ret->rtt_aa_only_n = rp->rtt_aa_only_n;
1061 ret->rtt_sounding_n = rp->rtt_sounding_n;
1062 ret->rtt_random_payload_n = rp->rtt_random_payload_n;
1063
1064 if (rp->rtt_aa_only_n) {
1065 if (rp->rtt_capability & BT_HCI_LE_CS_RTT_AA_ONLY_N_10NS_MASK) {
1066 ret->rtt_aa_only_precision = BT_CONN_LE_CS_RTT_AA_ONLY_10NS;
1067 } else {
1068 ret->rtt_aa_only_precision = BT_CONN_LE_CS_RTT_AA_ONLY_150NS;
1069 }
1070 } else {
1071 ret->rtt_aa_only_precision = BT_CONN_LE_CS_RTT_AA_ONLY_NOT_SUPP;
1072 }
1073
1074 if (rp->rtt_sounding_n) {
1075 if (rp->rtt_capability & BT_HCI_LE_CS_RTT_SOUNDING_N_10NS_MASK) {
1076 ret->rtt_sounding_precision = BT_CONN_LE_CS_RTT_SOUNDING_10NS;
1077 } else {
1078 ret->rtt_sounding_precision = BT_CONN_LE_CS_RTT_SOUNDING_150NS;
1079 }
1080 } else {
1081 ret->rtt_sounding_precision = BT_CONN_LE_CS_RTT_SOUNDING_NOT_SUPP;
1082 }
1083
1084 if (rp->rtt_random_payload_n) {
1085 if (rp->rtt_capability & BT_HCI_LE_CS_RTT_RANDOM_PAYLOAD_N_10NS_MASK) {
1086 ret->rtt_random_payload_precision = BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_10NS;
1087 } else {
1088 ret->rtt_random_payload_precision = BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_150NS;
1089 }
1090 } else {
1091 ret->rtt_random_payload_precision = BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_NOT_SUPP;
1092 }
1093
1094 ret->phase_based_nadm_sounding_supported =
1095 sys_le16_to_cpu(rp->nadm_sounding_capability) &
1096 BT_HCI_LE_CS_NADM_SOUNDING_CAPABILITY_PHASE_BASED_MASK;
1097
1098 ret->phase_based_nadm_random_supported =
1099 sys_le16_to_cpu(rp->nadm_random_capability) &
1100 BT_HCI_LE_CS_NADM_RANDOM_CAPABILITY_PHASE_BASED_MASK;
1101
1102 ret->cs_sync_2m_phy_supported = rp->cs_sync_phys_supported & BT_HCI_LE_CS_SYNC_PHYS_2M_MASK;
1103
1104 ret->cs_sync_2m_2bt_phy_supported =
1105 rp->cs_sync_phys_supported & BT_HCI_LE_CS_SYNC_PHYS_2M_2BT_MASK;
1106
1107 ret->cs_without_fae_supported =
1108 sys_le16_to_cpu(rp->subfeatures_supported) & BT_HCI_LE_CS_SUBFEATURE_NO_TX_FAE_MASK;
1109
1110 ret->chsel_alg_3c_supported = sys_le16_to_cpu(rp->subfeatures_supported) &
1111 BT_HCI_LE_CS_SUBFEATURE_CHSEL_ALG_3C_MASK;
1112
1113 ret->pbr_from_rtt_sounding_seq_supported =
1114 sys_le16_to_cpu(rp->subfeatures_supported) &
1115 BT_HCI_LE_CS_SUBFEATURE_PBR_FROM_RTT_SOUNDING_SEQ_MASK;
1116
1117 ret->t_ip1_times_supported = sys_le16_to_cpu(rp->t_ip1_times_supported);
1118 ret->t_ip2_times_supported = sys_le16_to_cpu(rp->t_ip2_times_supported);
1119 ret->t_fcs_times_supported = sys_le16_to_cpu(rp->t_fcs_times_supported);
1120 ret->t_pm_times_supported = sys_le16_to_cpu(rp->t_pm_times_supported);
1121
1122 ret->t_sw_time = rp->t_sw_time_supported;
1123 ret->tx_snr_capability = rp->tx_snr_capability;
1124
1125 net_buf_unref(rsp);
1126 return status;
1127 }
1128
bt_le_cs_write_cached_remote_supported_capabilities(struct bt_conn * conn,const struct bt_conn_le_cs_capabilities * params)1129 int bt_le_cs_write_cached_remote_supported_capabilities(
1130 struct bt_conn *conn, const struct bt_conn_le_cs_capabilities *params)
1131 {
1132 struct bt_hci_cp_le_write_cached_remote_supported_capabilities *cp;
1133 struct net_buf *buf;
1134
1135 buf = bt_hci_cmd_alloc(K_FOREVER);
1136 if (!buf) {
1137 return -ENOBUFS;
1138 }
1139
1140 cp = net_buf_add(buf, sizeof(*cp));
1141
1142 cp->handle = sys_cpu_to_le16(conn->handle);
1143
1144 cp->num_config_supported = params->num_config_supported;
1145
1146 cp->max_consecutive_procedures_supported =
1147 sys_cpu_to_le16(params->max_consecutive_procedures_supported);
1148
1149 cp->num_antennas_supported = params->num_antennas_supported;
1150 cp->max_antenna_paths_supported = params->max_antenna_paths_supported;
1151
1152 cp->roles_supported = 0;
1153 if (params->initiator_supported) {
1154 cp->roles_supported |= BT_HCI_LE_CS_INITIATOR_ROLE_MASK;
1155 }
1156 if (params->reflector_supported) {
1157 cp->roles_supported |= BT_HCI_LE_CS_REFLECTOR_ROLE_MASK;
1158 }
1159
1160 cp->modes_supported = 0;
1161 if (params->mode_3_supported) {
1162 cp->modes_supported |= BT_HCI_LE_CS_MODES_SUPPORTED_MODE_3_MASK;
1163 }
1164
1165 cp->rtt_aa_only_n = params->rtt_aa_only_n;
1166 cp->rtt_sounding_n = params->rtt_sounding_n;
1167 cp->rtt_random_payload_n = params->rtt_random_payload_n;
1168
1169 cp->rtt_capability = 0;
1170 if (params->rtt_aa_only_precision == BT_CONN_LE_CS_RTT_AA_ONLY_10NS) {
1171 cp->rtt_capability |= BT_HCI_LE_CS_RTT_AA_ONLY_N_10NS_MASK;
1172 }
1173
1174 if (params->rtt_sounding_precision == BT_CONN_LE_CS_RTT_SOUNDING_10NS) {
1175 cp->rtt_capability |= BT_HCI_LE_CS_RTT_SOUNDING_N_10NS_MASK;
1176 }
1177
1178 if (params->rtt_random_payload_precision == BT_CONN_LE_CS_RTT_RANDOM_PAYLOAD_10NS) {
1179 cp->rtt_capability |= BT_HCI_LE_CS_RTT_RANDOM_PAYLOAD_N_10NS_MASK;
1180 }
1181
1182 cp->nadm_sounding_capability = 0;
1183 if (params->phase_based_nadm_sounding_supported) {
1184 cp->nadm_sounding_capability |=
1185 sys_cpu_to_le16(BT_HCI_LE_CS_NADM_SOUNDING_CAPABILITY_PHASE_BASED_MASK);
1186 }
1187
1188 cp->nadm_random_capability = 0;
1189 if (params->phase_based_nadm_random_supported) {
1190 cp->nadm_random_capability |=
1191 sys_cpu_to_le16(BT_HCI_LE_CS_NADM_RANDOM_CAPABILITY_PHASE_BASED_MASK);
1192 }
1193
1194 cp->cs_sync_phys_supported = 0;
1195 if (params->cs_sync_2m_phy_supported) {
1196 cp->cs_sync_phys_supported |= BT_HCI_LE_CS_SYNC_PHYS_2M_MASK;
1197 }
1198 if (params->cs_sync_2m_2bt_phy_supported) {
1199 cp->cs_sync_phys_supported |= BT_HCI_LE_CS_SYNC_PHYS_2M_2BT_MASK;
1200 }
1201
1202 cp->subfeatures_supported = 0;
1203 if (params->cs_without_fae_supported) {
1204 cp->subfeatures_supported |=
1205 sys_cpu_to_le16(BT_HCI_LE_CS_SUBFEATURE_NO_TX_FAE_MASK);
1206 }
1207 if (params->chsel_alg_3c_supported) {
1208 cp->subfeatures_supported |=
1209 sys_cpu_to_le16(BT_HCI_LE_CS_SUBFEATURE_CHSEL_ALG_3C_MASK);
1210 }
1211 if (params->pbr_from_rtt_sounding_seq_supported) {
1212 cp->subfeatures_supported |=
1213 sys_cpu_to_le16(BT_HCI_LE_CS_SUBFEATURE_PBR_FROM_RTT_SOUNDING_SEQ_MASK);
1214 }
1215
1216 cp->t_ip1_times_supported = sys_cpu_to_le16(params->t_ip1_times_supported);
1217 cp->t_ip2_times_supported = sys_cpu_to_le16(params->t_ip2_times_supported);
1218 cp->t_fcs_times_supported = sys_cpu_to_le16(params->t_fcs_times_supported);
1219 cp->t_pm_times_supported = sys_cpu_to_le16(params->t_pm_times_supported);
1220 cp->t_sw_time_supported = params->t_sw_time;
1221 cp->tx_snr_capability = params->tx_snr_capability;
1222
1223 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES, buf,
1224 NULL);
1225 }
1226
bt_le_cs_write_cached_remote_fae_table(struct bt_conn * conn,int8_t remote_fae_table[72])1227 int bt_le_cs_write_cached_remote_fae_table(struct bt_conn *conn, int8_t remote_fae_table[72])
1228 {
1229 struct bt_hci_cp_le_write_cached_remote_fae_table *cp;
1230 struct net_buf *buf;
1231
1232 buf = bt_hci_cmd_alloc(K_FOREVER);
1233 if (!buf) {
1234 return -ENOBUFS;
1235 }
1236
1237 cp = net_buf_add(buf, sizeof(*cp));
1238
1239 cp->handle = sys_cpu_to_le16(conn->handle);
1240 memcpy(cp->remote_fae_table, remote_fae_table, sizeof(cp->remote_fae_table));
1241
1242 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE, buf, NULL);
1243 }
1244
bt_hci_le_cs_security_enable_complete(struct net_buf * buf)1245 void bt_hci_le_cs_security_enable_complete(struct net_buf *buf)
1246 {
1247 struct bt_conn *conn;
1248
1249 struct bt_hci_evt_le_cs_security_enable_complete *evt;
1250
1251 if (buf->len < sizeof(*evt)) {
1252 LOG_ERR("Unexpected end of buffer");
1253 return;
1254 }
1255
1256 evt = net_buf_pull_mem(buf, sizeof(*evt));
1257 if (evt->status) {
1258 LOG_WRN("Security Enable failed with status 0x%02X", evt->status);
1259 }
1260
1261 conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->handle), BT_CONN_TYPE_LE);
1262 if (!conn) {
1263 LOG_ERR("Can't lookup conn handle when reading Security Enable Complete event");
1264 return;
1265 }
1266
1267 bt_conn_notify_cs_security_enable_available(conn, evt->status);
1268
1269 bt_conn_unref(conn);
1270 }
1271
bt_hci_le_cs_procedure_enable_complete(struct net_buf * buf)1272 void bt_hci_le_cs_procedure_enable_complete(struct net_buf *buf)
1273 {
1274 struct bt_conn *conn;
1275
1276 struct bt_hci_evt_le_cs_procedure_enable_complete *evt;
1277 struct bt_conn_le_cs_procedure_enable_complete params;
1278
1279 if (buf->len < sizeof(*evt)) {
1280 LOG_ERR("Unexpected end of buffer");
1281 return;
1282 }
1283
1284 evt = net_buf_pull_mem(buf, sizeof(*evt));
1285 if (evt->status) {
1286 LOG_WRN("Procedure Enable failed with status 0x%02X", evt->status);
1287 }
1288
1289 conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->handle), BT_CONN_TYPE_LE);
1290 if (!conn) {
1291 LOG_ERR("Can't lookup conn handle when reading Procedure Enable Complete event");
1292 return;
1293 }
1294
1295 if (evt->state == BT_HCI_OP_LE_CS_PROCEDURES_DISABLED) {
1296 struct net_buf *reassembly_buf = get_reassembly_buf(conn->handle, false);
1297
1298 if (reassembly_buf) {
1299 LOG_WRN("De-allocating a dangling reassembly buffer");
1300 free_reassembly_buf(&reassembly_buf);
1301 }
1302 }
1303
1304 if (evt->status == BT_HCI_ERR_SUCCESS) {
1305 params.config_id = evt->config_id;
1306 params.state = evt->state;
1307 params.tone_antenna_config_selection = evt->tone_antenna_config_selection;
1308 params.selected_tx_power = evt->selected_tx_power;
1309 params.subevent_len = sys_get_le24(evt->subevent_len);
1310 params.subevents_per_event = evt->subevents_per_event;
1311 params.subevent_interval = sys_le16_to_cpu(evt->subevent_interval);
1312 params.event_interval = sys_le16_to_cpu(evt->event_interval);
1313 params.procedure_interval = sys_le16_to_cpu(evt->procedure_interval);
1314 params.procedure_count = sys_le16_to_cpu(evt->procedure_count);
1315 params.max_procedure_len = sys_le16_to_cpu(evt->max_procedure_len);
1316
1317 bt_conn_notify_cs_procedure_enable_available(conn, BT_HCI_ERR_SUCCESS, ¶ms);
1318 } else {
1319 bt_conn_notify_cs_procedure_enable_available(conn, evt->status, NULL);
1320 }
1321
1322 bt_conn_unref(conn);
1323 }
1324
1325 #if defined(CONFIG_BT_CHANNEL_SOUNDING_TEST)
bt_le_cs_stop_test(void)1326 int bt_le_cs_stop_test(void)
1327 {
1328 struct net_buf *buf;
1329
1330 buf = bt_hci_cmd_alloc(K_FOREVER);
1331 if (!buf) {
1332 return -ENOBUFS;
1333 }
1334
1335 return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_TEST_END, buf, NULL);
1336 }
1337
bt_hci_le_cs_test_end_complete(struct net_buf * buf)1338 void bt_hci_le_cs_test_end_complete(struct net_buf *buf)
1339 {
1340 struct bt_hci_evt_le_cs_test_end_complete *evt;
1341
1342 if (buf->len < sizeof(*evt)) {
1343 LOG_ERR("Unexpected end of buffer");
1344 return;
1345 }
1346
1347 evt = net_buf_pull_mem(buf, sizeof(*evt));
1348 if (evt->status) {
1349 LOG_WRN("CS Test End failed with status 0x%02X", evt->status);
1350 return;
1351 }
1352
1353 struct net_buf *reassembly_buf = get_reassembly_buf(BT_HCI_LE_CS_TEST_CONN_HANDLE, false);
1354
1355 if (reassembly_buf) {
1356 LOG_WRN("De-allocating a dangling reassembly buffer");
1357 free_reassembly_buf(&reassembly_buf);
1358 }
1359
1360 if (cs_test_callbacks.le_cs_test_end_complete) {
1361 cs_test_callbacks.le_cs_test_end_complete();
1362 }
1363 }
1364 #endif /* CONFIG_BT_CHANNEL_SOUNDING_TEST */
1365
bt_le_cs_step_data_parse(struct net_buf_simple * step_data_buf,bool (* func)(struct bt_le_cs_subevent_step * step,void * user_data),void * user_data)1366 void bt_le_cs_step_data_parse(struct net_buf_simple *step_data_buf,
1367 bool (*func)(struct bt_le_cs_subevent_step *step, void *user_data),
1368 void *user_data)
1369 {
1370 if (!step_data_buf) {
1371 LOG_INF("Tried to parse empty step data.");
1372 return;
1373 }
1374
1375 while (step_data_buf->len > 1) {
1376 struct bt_le_cs_subevent_step step;
1377
1378 step.mode = net_buf_simple_pull_u8(step_data_buf);
1379 step.channel = net_buf_simple_pull_u8(step_data_buf);
1380 step.data_len = net_buf_simple_pull_u8(step_data_buf);
1381
1382 if (step.data_len == 0) {
1383 LOG_WRN("Encountered zero-length step data.");
1384 return;
1385 }
1386
1387 step.data = step_data_buf->data;
1388
1389 if (step.data_len > step_data_buf->len) {
1390 LOG_WRN("Step data appears malformed.");
1391 return;
1392 }
1393
1394 if (!func(&step, user_data)) {
1395 return;
1396 }
1397
1398 net_buf_simple_pull(step_data_buf, step.data_len);
1399 }
1400 }
1401
1402 /* Bluetooth Core Specification 6.0, Table 4.13, Antenna Path Permutation for N_AP=2.
1403 * The last element corresponds to extension slot
1404 */
1405 static const uint8_t antenna_path_lut_n_ap_2[2][3] = {
1406 {A1, A2, A2},
1407 {A2, A1, A1},
1408 };
1409
1410 /* Bluetooth Core Specification 6.0, Table 4.14, Antenna Path Permutation for N_AP=3.
1411 * The last element corresponds to extension slot
1412 */
1413 static const uint8_t antenna_path_lut_n_ap_3[6][4] = {
1414 {A1, A2, A3, A3},
1415 {A2, A1, A3, A3},
1416 {A1, A3, A2, A2},
1417 {A3, A1, A2, A2},
1418 {A3, A2, A1, A1},
1419 {A2, A3, A1, A1},
1420 };
1421
1422 /* Bluetooth Core Specification 6.0, Table 4.15, Antenna Path Permutation for N_AP=4.
1423 * The last element corresponds to extension slot
1424 */
1425 static const uint8_t antenna_path_lut_n_ap_4[24][5] = {
1426 {A1, A2, A3, A4, A4},
1427 {A2, A1, A3, A4, A4},
1428 {A1, A3, A2, A4, A4},
1429 {A3, A1, A2, A4, A4},
1430 {A3, A2, A1, A4, A4},
1431 {A2, A3, A1, A4, A4},
1432 {A1, A2, A4, A3, A3},
1433 {A2, A1, A4, A3, A3},
1434 {A1, A4, A2, A3, A3},
1435 {A4, A1, A2, A3, A3},
1436 {A4, A2, A1, A3, A3},
1437 {A2, A4, A1, A3, A3},
1438 {A1, A4, A3, A2, A2},
1439 {A4, A1, A3, A2, A2},
1440 {A1, A3, A4, A2, A2},
1441 {A3, A1, A4, A2, A2},
1442 {A3, A4, A1, A2, A2},
1443 {A4, A3, A1, A2, A2},
1444 {A4, A2, A3, A1, A1},
1445 {A2, A4, A3, A1, A1},
1446 {A4, A3, A2, A1, A1},
1447 {A3, A4, A2, A1, A1},
1448 {A3, A2, A4, A1, A1},
1449 {A2, A3, A4, A1, A1},
1450 };
1451
bt_le_cs_get_antenna_path(uint8_t n_ap,uint8_t antenna_path_permutation_index,uint8_t tone_index)1452 int bt_le_cs_get_antenna_path(uint8_t n_ap,
1453 uint8_t antenna_path_permutation_index,
1454 uint8_t tone_index)
1455 {
1456 switch (n_ap) {
1457 case 1:
1458 {
1459 uint8_t antenna_path_permutations = 1;
1460 uint8_t num_tones = n_ap + 1; /* one additional tone extension slot */
1461
1462 if (antenna_path_permutation_index >= antenna_path_permutations ||
1463 tone_index >= num_tones) {
1464 return -EINVAL;
1465 }
1466 return A1;
1467 }
1468 case 2:
1469 {
1470 if (antenna_path_permutation_index >= ARRAY_SIZE(antenna_path_lut_n_ap_2) ||
1471 tone_index >= ARRAY_SIZE(antenna_path_lut_n_ap_2[0])) {
1472 return -EINVAL;
1473 }
1474 return antenna_path_lut_n_ap_2[antenna_path_permutation_index][tone_index];
1475 }
1476 case 3:
1477 {
1478 if (antenna_path_permutation_index >= ARRAY_SIZE(antenna_path_lut_n_ap_3) ||
1479 tone_index >= ARRAY_SIZE(antenna_path_lut_n_ap_3[0])) {
1480 return -EINVAL;
1481 }
1482 return antenna_path_lut_n_ap_3[antenna_path_permutation_index][tone_index];
1483 }
1484 case 4:
1485 {
1486 if (antenna_path_permutation_index >= ARRAY_SIZE(antenna_path_lut_n_ap_4) ||
1487 tone_index >= ARRAY_SIZE(antenna_path_lut_n_ap_4[0])) {
1488 return -EINVAL;
1489 }
1490 return antenna_path_lut_n_ap_4[antenna_path_permutation_index][tone_index];
1491 }
1492 default:
1493 return -EINVAL;
1494 }
1495 }
1496