1 /*
2  * Copyright (c) 2020-2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stdint.h>
7 #include <assert.h>
8 #include <sys/check.h>
9 #include <sys/byteorder.h>
10 
11 #include <bluetooth/bluetooth.h>
12 #include <bluetooth/conn.h>
13 #include <bluetooth/l2cap.h>
14 #include <bluetooth/hci.h>
15 #include <bluetooth/direction.h>
16 
17 #include "hci_core.h"
18 #include "scan.h"
19 #include "conn_internal.h"
20 #include "direction_internal.h"
21 
22 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_DF)
23 #define LOG_MODULE_NAME bt_df
24 #include "common/log.h"
25 
26 /* @brief Antenna information for LE Direction Finding */
27 struct bt_le_df_ant_info {
28 	/* Bitfield holding optional switching and sampling rates */
29 	uint8_t switch_sample_rates;
30 	/* Available antennae number */
31 	uint8_t num_ant;
32 	/* Maximum supported antennae switching pattern length */
33 	uint8_t max_switch_pattern_len;
34 	/* Maximum length of CTE in 8[us] units */
35 	uint8_t max_cte_len;
36 };
37 
38 static struct bt_le_df_ant_info df_ant_info;
39 #if defined(CONFIG_BT_DF_CONNECTIONLESS_CTE_RX)
40 const static uint8_t df_dummy_switch_pattern[BT_HCI_LE_SWITCH_PATTERN_LEN_MIN] = { 0, 0 };
41 #endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */
42 
43 #define DF_AOD_TX_1US_SUPPORT(supp)             (supp & BT_HCI_LE_1US_AOD_TX)
44 #define DF_AOD_RX_1US_SUPPORT(supp)             (supp & BT_HCI_LE_1US_AOD_RX)
45 #define DF_AOA_RX_1US_SUPPORT(supp)             (supp & BT_HCI_LE_1US_AOA_RX)
46 
47 #define DF_SAMPLING_ANTENNA_NUMBER_MIN 0x2
48 
49 #if defined(CONFIG_BT_DF_CONNECTIONLESS_CTE_RX)
50 static int validate_cte_rx_params(const struct bt_df_per_adv_sync_cte_rx_param *params);
51 static void prepare_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_le_per_adv_sync *sync,
52 					     const struct bt_df_per_adv_sync_cte_rx_param *params,
53 					     bool enable);
54 static int hci_df_set_cl_cte_rx_enable(struct bt_le_per_adv_sync *sync, bool enable,
55 				       const struct bt_df_per_adv_sync_cte_rx_param *params);
56 #endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */
57 
hci_df_set_cl_cte_tx_params(const struct bt_le_ext_adv * adv,const struct bt_df_adv_cte_tx_param * params)58 static int hci_df_set_cl_cte_tx_params(const struct bt_le_ext_adv *adv,
59 				    const struct bt_df_adv_cte_tx_param *params)
60 {
61 	struct bt_hci_cp_le_set_cl_cte_tx_params *cp;
62 	struct net_buf *buf;
63 
64 	/* If AoD is not enabled, ant_ids are ignored by controller:
65 	 * BT Core spec 5.2 Vol 4, Part E sec. 7.8.80.
66 	 */
67 	if (params->cte_type == BT_HCI_LE_AOD_CTE_1US ||
68 	    params->cte_type == BT_HCI_LE_AOD_CTE_2US) {
69 
70 		if (!BT_FEAT_LE_ANT_SWITCH_TX_AOD(bt_dev.le.features)) {
71 			return -EINVAL;
72 		}
73 
74 		if (params->cte_type == BT_HCI_LE_AOD_CTE_1US &&
75 		    !DF_AOD_TX_1US_SUPPORT(df_ant_info.switch_sample_rates)) {
76 			return -EINVAL;
77 		}
78 
79 		if (params->num_ant_ids < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN ||
80 		    params->num_ant_ids > BT_HCI_LE_SWITCH_PATTERN_LEN_MAX ||
81 		    !params->ant_ids) {
82 			return -EINVAL;
83 		}
84 	} else if (params->cte_type != BT_HCI_LE_AOA_CTE) {
85 		return -EINVAL;
86 	}
87 
88 	if (params->cte_len < BT_HCI_LE_CTE_LEN_MIN ||
89 	    params->cte_len > BT_HCI_LE_CTE_LEN_MAX) {
90 		return -EINVAL;
91 	}
92 
93 	if (params->cte_count < BT_HCI_LE_CTE_COUNT_MIN ||
94 	    params->cte_count > BT_HCI_LE_CTE_COUNT_MAX) {
95 		return -EINVAL;
96 	}
97 
98 	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_TX_PARAMS,
99 				sizeof(*cp) + params->num_ant_ids);
100 	if (!buf) {
101 		return -ENOBUFS;
102 	}
103 
104 	cp = net_buf_add(buf, sizeof(*cp));
105 	cp->handle = adv->handle;
106 	cp->cte_len = params->cte_len;
107 	cp->cte_type = params->cte_type;
108 	cp->cte_count = params->cte_count;
109 
110 	if (params->num_ant_ids) {
111 		uint8_t *dest_ant_ids = net_buf_add(buf, params->num_ant_ids);
112 
113 		memcpy(dest_ant_ids, params->ant_ids, params->num_ant_ids);
114 		cp->switch_pattern_len = params->num_ant_ids;
115 	} else {
116 		cp->switch_pattern_len = 0;
117 	}
118 
119 	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CL_CTE_TX_PARAMS,
120 				    buf, NULL);
121 }
122 
123 /* @brief Function provides information about DF antennae numer and
124  *	  controller capabilities related with Constant Tone Extension.
125  *
126  * @param[out] switch_sample_rates      Optional switching and sampling rates.
127  * @param[out] num_ant                  Antennae number.
128  * @param[out] max_switch_pattern_len   Maximum supported antennae switching
129  *                                      paterns length.
130  * @param[out] max_cte_len              Maximum length of CTE in 8[us] units.
131  *
132  * @return Zero in case of success, other value in case of failure.
133  */
hci_df_read_ant_info(uint8_t * switch_sample_rates,uint8_t * num_ant,uint8_t * max_switch_pattern_len,uint8_t * max_cte_len)134 static int hci_df_read_ant_info(uint8_t *switch_sample_rates,
135 				uint8_t *num_ant,
136 				uint8_t *max_switch_pattern_len,
137 				uint8_t *max_cte_len)
138 {
139 	__ASSERT_NO_MSG(switch_sample_rates);
140 	__ASSERT_NO_MSG(num_ant);
141 	__ASSERT_NO_MSG(max_switch_pattern_len);
142 	__ASSERT_NO_MSG(max_cte_len);
143 
144 	struct bt_hci_rp_le_read_ant_info *rp;
145 	struct net_buf *rsp;
146 	int err;
147 
148 	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_ANT_INFO, NULL, &rsp);
149 	if (err) {
150 		BT_ERR("Failed to read antenna information");
151 		return err;
152 	}
153 
154 	rp = (void *)rsp->data;
155 
156 	BT_DBG("DF: sw. sampl rates: %x ant num: %u , max sw. pattern len: %u,"
157 	       "max CTE len %d", rp->switch_sample_rates, rp->num_ant,
158 	       rp->max_switch_pattern_len, rp->max_cte_len);
159 
160 	*switch_sample_rates = rp->switch_sample_rates;
161 	*num_ant = rp->num_ant;
162 	*max_switch_pattern_len = rp->max_switch_pattern_len;
163 	*max_cte_len = rp->max_cte_len;
164 
165 	net_buf_unref(rsp);
166 
167 	return 0;
168 }
169 
170 /* @brief Function handles send of HCI commnad to enable or disables CTE
171  *        transmission for given advertising set.
172  *
173  * @param[in] adv               Pointer to advertising set
174  * @param[in] enable            Enable or disable CTE TX
175  *
176  * @return Zero in case of success, other value in case of failure.
177  */
hci_df_set_adv_cte_tx_enable(struct bt_le_ext_adv * adv,bool enable)178 static int hci_df_set_adv_cte_tx_enable(struct bt_le_ext_adv *adv,
179 					bool enable)
180 {
181 	struct bt_hci_cp_le_set_cl_cte_tx_enable *cp;
182 	struct bt_hci_cmd_state_set state;
183 	struct net_buf *buf;
184 
185 	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_TX_ENABLE, sizeof(*cp));
186 	if (!buf) {
187 		return -ENOBUFS;
188 	}
189 
190 	cp = net_buf_add(buf, sizeof(*cp));
191 	(void)memset(cp, 0, sizeof(*cp));
192 
193 	cp->handle = adv->handle;
194 	cp->cte_enable = enable ? 1 : 0;
195 
196 	bt_hci_cmd_state_set_init(buf, &state, adv->flags, BT_PER_ADV_CTE_ENABLED,
197 				  enable);
198 
199 	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CL_CTE_TX_ENABLE,
200 				   buf, NULL);
201 }
202 
203 #if defined(CONFIG_BT_DF_CONNECTIONLESS_CTE_RX)
validate_cte_rx_params(const struct bt_df_per_adv_sync_cte_rx_param * params)204 static int validate_cte_rx_params(const struct bt_df_per_adv_sync_cte_rx_param *params)
205 {
206 	if (!(params->cte_type &
207 	      (BT_DF_CTE_TYPE_AOA | BT_DF_CTE_TYPE_AOD_1US | BT_DF_CTE_TYPE_AOD_2US))) {
208 		return -EINVAL;
209 	}
210 
211 	if (params->cte_type & BT_DF_CTE_TYPE_AOA) {
212 		if (df_ant_info.num_ant < DF_SAMPLING_ANTENNA_NUMBER_MIN ||
213 		    !BT_FEAT_LE_ANT_SWITCH_RX_AOA(bt_dev.le.features)) {
214 			return -EINVAL;
215 		}
216 
217 		if (!(params->slot_durations == BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US ||
218 		      (params->slot_durations == BT_HCI_LE_ANTENNA_SWITCHING_SLOT_1US &&
219 		       DF_AOA_RX_1US_SUPPORT(df_ant_info.switch_sample_rates)))) {
220 			return -EINVAL;
221 		}
222 
223 		if (params->num_ant_ids < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN ||
224 		    params->num_ant_ids > df_ant_info.max_switch_pattern_len || !params->ant_ids) {
225 			return -EINVAL;
226 		}
227 	}
228 
229 	return 0;
230 }
231 
prepare_cte_rx_enable_cmd_params(struct net_buf * buf,struct bt_le_per_adv_sync * sync,const struct bt_df_per_adv_sync_cte_rx_param * params,bool enable)232 static void prepare_cte_rx_enable_cmd_params(struct net_buf *buf, struct bt_le_per_adv_sync *sync,
233 					     const struct bt_df_per_adv_sync_cte_rx_param *params,
234 					     bool enable)
235 {
236 	struct bt_hci_cp_le_set_cl_cte_sampling_enable *cp;
237 	const uint8_t *ant_ids;
238 
239 	cp = net_buf_add(buf, sizeof(*cp));
240 	(void)memset(cp, 0, sizeof(*cp));
241 
242 	cp->sync_handle = sys_cpu_to_le16(sync->handle);
243 	cp->sampling_enable = enable ? 1 : 0;
244 
245 	if (enable) {
246 		uint8_t *dest_ant_ids;
247 
248 		cp->max_sampled_cte = params->max_cte_count;
249 
250 		if (params->cte_type & BT_DF_CTE_TYPE_AOA) {
251 			cp->slot_durations = params->slot_durations;
252 			cp->switch_pattern_len = params->num_ant_ids;
253 			ant_ids = params->ant_ids;
254 		} else {
255 			/* Those values are put here due to constraints from HCI command
256 			 * specification: Bluetooth Core Spec. Vol 4,Part E, sec 7.8.82.
257 			 * There is no right way to successfully send the command to enable CTE
258 			 * receive for AoD mode (e.g. device equipped with single antenna).
259 			 */
260 			cp->slot_durations = BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US;
261 			cp->switch_pattern_len = ARRAY_SIZE(df_dummy_switch_pattern);
262 			ant_ids = &df_dummy_switch_pattern[0];
263 		}
264 
265 		dest_ant_ids =	net_buf_add(buf, params->num_ant_ids);
266 		memcpy(dest_ant_ids, params->ant_ids, params->num_ant_ids);
267 	}
268 }
269 
hci_df_set_cl_cte_rx_enable(struct bt_le_per_adv_sync * sync,bool enable,const struct bt_df_per_adv_sync_cte_rx_param * params)270 static int hci_df_set_cl_cte_rx_enable(struct bt_le_per_adv_sync *sync, bool enable,
271 				       const struct bt_df_per_adv_sync_cte_rx_param *params)
272 {
273 	struct bt_hci_rp_le_set_cl_cte_sampling_enable *rp;
274 	struct bt_hci_cmd_state_set state;
275 	struct net_buf *buf, *rsp;
276 	int err;
277 
278 	if (enable) {
279 		err = validate_cte_rx_params(params);
280 		if (err != 0) {
281 			return err;
282 		}
283 	}
284 
285 	/* If CTE Rx is enabled, command parameters total length must include
286 	 * antenna ids, so command size if extended by num_and_ids.
287 	 */
288 	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE,
289 				(sizeof(struct bt_hci_cp_le_set_cl_cte_sampling_enable) +
290 				 (enable ? params->num_ant_ids : 0)));
291 	if (!buf) {
292 		return -ENOBUFS;
293 	}
294 
295 	prepare_cte_rx_enable_cmd_params(buf, sync, params, enable);
296 
297 	bt_hci_cmd_state_set_init(buf, &state, sync->flags, BT_PER_ADV_SYNC_CTE_ENABLED, enable);
298 
299 	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE, buf, &rsp);
300 	if (err) {
301 		return err;
302 	}
303 
304 	rp = (void *)rsp->data;
305 	if (sync->handle != sys_le16_to_cpu(rp->sync_handle)) {
306 		err = -EIO;
307 	} else {
308 		sync->cte_type = (enable ? params->cte_type : 0);
309 	}
310 
311 	net_buf_unref(rsp);
312 
313 	return err;
314 }
315 
hci_df_prepare_connectionless_iq_report(struct net_buf * buf,struct bt_df_per_adv_sync_iq_samples_report * report,struct bt_le_per_adv_sync ** per_adv_sync_to_report)316 void hci_df_prepare_connectionless_iq_report(struct net_buf *buf,
317 					     struct bt_df_per_adv_sync_iq_samples_report *report,
318 					     struct bt_le_per_adv_sync **per_adv_sync_to_report)
319 {
320 	struct bt_hci_evt_le_connectionless_iq_report *evt;
321 	struct bt_le_per_adv_sync *per_adv_sync;
322 
323 	if (buf->len < sizeof(*evt)) {
324 		BT_ERR("Unexpected end of buffer");
325 		return;
326 	}
327 
328 	evt = net_buf_pull_mem(buf, sizeof(*evt));
329 
330 	per_adv_sync = bt_hci_get_per_adv_sync(sys_le16_to_cpu(evt->sync_handle));
331 
332 	if (!per_adv_sync) {
333 		BT_ERR("Unknown handle 0x%04X for iq samples report",
334 		       sys_le16_to_cpu(evt->sync_handle));
335 		return;
336 	}
337 
338 	if (!atomic_test_bit(per_adv_sync->flags, BT_PER_ADV_SYNC_CTE_ENABLED)) {
339 		BT_ERR("Received PA CTE report when CTE receive disabled");
340 		return;
341 	}
342 
343 	if (!(per_adv_sync->cte_type & BIT(evt->cte_type))) {
344 		BT_DBG("CTE filtered out by cte_type: %u", evt->cte_type);
345 		return;
346 	}
347 
348 	report->chan_idx = evt->chan_idx;
349 	report->rssi = evt->rssi;
350 	report->rssi_ant_id = evt->rssi_ant_id;
351 	report->cte_type = BIT(evt->cte_type);
352 	report->packet_status = evt->packet_status;
353 	report->slot_durations = evt->slot_durations;
354 	report->sample_count = evt->sample_count;
355 	report->sample = &evt->sample[0];
356 
357 	*per_adv_sync_to_report = per_adv_sync;
358 }
359 #endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */
360 
361 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
362 /* @brief Function sets CTE parameters for connection object
363  *
364  * @param[in] cte_types         Allowed response CTE types
365  * @param[in] num_ant_id        Number of available antenna identification
366  *                              patterns in @p ant_id array.
367  * @param[in] ant_id            Array with antenna identification patterns.
368  *
369  * @return Zero in case of success, other value in case of failure.
370  */
hci_df_set_conn_cte_tx_param(struct bt_conn * conn,uint8_t cte_types,uint8_t num_ant_id,uint8_t * ant_id)371 static int hci_df_set_conn_cte_tx_param(struct bt_conn *conn, uint8_t cte_types,
372 					uint8_t num_ant_id, uint8_t *ant_id)
373 {
374 	__ASSERT_NO_MSG(conn);
375 	__ASSERT_NO_MSG(cte_types != 0);
376 
377 	struct bt_hci_cp_le_set_conn_cte_tx_params *cp;
378 	struct bt_hci_rp_le_set_conn_cte_tx_params *rp;
379 	struct net_buf *buf, *rsp;
380 	int err;
381 
382 	/* If AoD is not enabled, ant_ids are ignored by controller:
383 	 * BT Core spec 5.2 Vol 4, Part E sec. 7.8.84.
384 	 */
385 	if (cte_types & BT_HCI_LE_AOD_CTE_RSP_1US ||
386 	    cte_types & BT_HCI_LE_AOD_CTE_RSP_2US) {
387 
388 		if (num_ant_id < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN ||
389 		    num_ant_id > BT_HCI_LE_SWITCH_PATTERN_LEN_MAX ||
390 		    !ant_id) {
391 			return -EINVAL;
392 		}
393 		__ASSERT_NO_MSG((sizeof(*cp) + num_ant_id) <  UINT8_MAX);
394 	}
395 
396 	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS,
397 				sizeof(*cp) + num_ant_id);
398 	if (!buf) {
399 		return -ENOBUFS;
400 	}
401 
402 	cp = net_buf_add(buf, sizeof(*cp));
403 	cp->handle = sys_cpu_to_le16(conn->handle);
404 	cp->cte_types = cte_types;
405 
406 	if (num_ant_id) {
407 		uint8_t *dest_ant_id = net_buf_add(buf, num_ant_id);
408 
409 		memcpy(dest_ant_id, ant_id, num_ant_id);
410 		cp->switch_pattern_len = num_ant_id;
411 	} else {
412 		cp->switch_pattern_len = 0;
413 	}
414 
415 	err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS,
416 				   buf, &rsp);
417 	if (err) {
418 		return err;
419 	}
420 
421 	rp = (void *)rsp->data;
422 	if (conn->handle != sys_le16_to_cpu(rp->handle)) {
423 		err = -EIO;
424 	}
425 
426 	net_buf_unref(rsp);
427 
428 	return err;
429 }
430 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RSP */
431 
432 /* @brief Function initializes Direction Finding in Host
433  *
434  * @return Zero in case of success, other value in case of failure.
435  */
le_df_init(void)436 int le_df_init(void)
437 {
438 	uint8_t max_switch_pattern_len;
439 	uint8_t switch_sample_rates;
440 	uint8_t max_cte_len;
441 	uint8_t num_ant;
442 	int err;
443 
444 	err = hci_df_read_ant_info(&switch_sample_rates, &num_ant,
445 			     &max_switch_pattern_len, &max_cte_len);
446 	if (err) {
447 		return err;
448 	}
449 
450 	df_ant_info.max_switch_pattern_len = max_switch_pattern_len;
451 	df_ant_info.switch_sample_rates = switch_sample_rates;
452 	df_ant_info.max_cte_len = max_cte_len;
453 	df_ant_info.num_ant = num_ant;
454 
455 	BT_DBG("DF initialized.");
456 	return 0;
457 }
458 
bt_df_set_adv_cte_tx_param(struct bt_le_ext_adv * adv,const struct bt_df_adv_cte_tx_param * params)459 int bt_df_set_adv_cte_tx_param(struct bt_le_ext_adv *adv,
460 				const struct bt_df_adv_cte_tx_param *params)
461 {
462 	__ASSERT_NO_MSG(adv);
463 	__ASSERT_NO_MSG(params);
464 
465 	int err;
466 
467 	if (!BT_FEAT_LE_CONNECTIONLESS_CTE_TX(bt_dev.le.features)) {
468 		return -ENOTSUP;
469 	}
470 
471 	/* Check if BT_ADV_PARAMS_SET is set, because it implies the set
472 	 * has already been created.
473 	 */
474 	if (!atomic_test_bit(adv->flags, BT_ADV_PARAMS_SET)) {
475 		return -EINVAL;
476 	}
477 
478 	if (atomic_test_bit(adv->flags, BT_PER_ADV_CTE_ENABLED)) {
479 		return -EINVAL;
480 	}
481 
482 	err = hci_df_set_cl_cte_tx_params(adv, params);
483 	if (err) {
484 		return err;
485 	}
486 
487 	atomic_set_bit(adv->flags, BT_PER_ADV_CTE_PARAMS_SET);
488 
489 	return 0;
490 }
491 
bt_df_set_adv_cte_tx_enabled(struct bt_le_ext_adv * adv,bool enable)492 static int bt_df_set_adv_cte_tx_enabled(struct bt_le_ext_adv *adv, bool enable)
493 {
494 	if (!atomic_test_bit(adv->flags, BT_PER_ADV_PARAMS_SET)) {
495 		return -EINVAL;
496 	}
497 
498 	if (!atomic_test_bit(adv->flags, BT_PER_ADV_CTE_PARAMS_SET)) {
499 		return -EINVAL;
500 	}
501 
502 	if (enable == atomic_test_bit(adv->flags, BT_PER_ADV_CTE_ENABLED)) {
503 		return -EALREADY;
504 	}
505 
506 	return hci_df_set_adv_cte_tx_enable(adv, enable);
507 }
508 
bt_df_adv_cte_tx_enable(struct bt_le_ext_adv * adv)509 int bt_df_adv_cte_tx_enable(struct bt_le_ext_adv *adv)
510 {
511 	__ASSERT_NO_MSG(adv);
512 	return bt_df_set_adv_cte_tx_enabled(adv, true);
513 }
514 
bt_df_adv_cte_tx_disable(struct bt_le_ext_adv * adv)515 int bt_df_adv_cte_tx_disable(struct bt_le_ext_adv *adv)
516 {
517 	__ASSERT_NO_MSG(adv);
518 	return bt_df_set_adv_cte_tx_enabled(adv, false);
519 }
520 
521 #if defined(CONFIG_BT_DF_CONNECTIONLESS_CTE_RX)
522 static int
bt_df_set_per_adv_sync_cte_rx_enable(struct bt_le_per_adv_sync * sync,bool enable,const struct bt_df_per_adv_sync_cte_rx_param * params)523 bt_df_set_per_adv_sync_cte_rx_enable(struct bt_le_per_adv_sync *sync, bool enable,
524 				     const struct bt_df_per_adv_sync_cte_rx_param *params)
525 {
526 	if (!BT_FEAT_LE_CONNECTIONLESS_CTE_RX(bt_dev.le.features)) {
527 		return -ENOTSUP;
528 	}
529 
530 	if (!atomic_test_bit(sync->flags, BT_PER_ADV_SYNC_SYNCED)) {
531 		return -EINVAL;
532 	}
533 
534 	if (!enable &&
535 	    !atomic_test_bit(sync->flags, BT_PER_ADV_SYNC_CTE_ENABLED)) {
536 		return -EALREADY;
537 	}
538 
539 	return hci_df_set_cl_cte_rx_enable(sync, enable, params);
540 }
541 
bt_df_per_adv_sync_cte_rx_enable(struct bt_le_per_adv_sync * sync,const struct bt_df_per_adv_sync_cte_rx_param * params)542 int bt_df_per_adv_sync_cte_rx_enable(struct bt_le_per_adv_sync *sync,
543 				     const struct bt_df_per_adv_sync_cte_rx_param *params)
544 {
545 	CHECKIF(!sync) {
546 		return -EINVAL;
547 	}
548 	CHECKIF(!params) {
549 		return -EINVAL;
550 	}
551 
552 	return bt_df_set_per_adv_sync_cte_rx_enable(sync, true, params);
553 }
554 
bt_df_per_adv_sync_cte_rx_disable(struct bt_le_per_adv_sync * sync)555 int bt_df_per_adv_sync_cte_rx_disable(struct bt_le_per_adv_sync *sync)
556 {
557 	CHECKIF(!sync) {
558 		return -EINVAL;
559 	}
560 
561 	return bt_df_set_per_adv_sync_cte_rx_enable(sync, false, NULL);
562 }
563 #endif /* CONFIG_BT_DF_CONNECTIONLESS_CTE_RX */
564