Skip to content

Commit 27bf358

Browse files
alexstanoev-nordicrlubos
authored andcommitted
bluetooth: services: ras: Implement Ranging Responder role of RAS
Implement the ranging responder (RRSP) server role of the Ranging Service draft specification. This allows a ranging requestor (RREQ) to retrieve channel sounding ranging data from the local device. This implementation contains support for all mandatory features, as well as using notifications for data transfer. Signed-off-by: Aleksandar Stanoev <[email protected]>
1 parent e4172b8 commit 27bf358

File tree

8 files changed

+1249
-16
lines changed

8 files changed

+1249
-16
lines changed

include/bluetooth/services/ras.h

Lines changed: 183 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <zephyr/kernel.h>
1212
#include <zephyr/bluetooth/conn.h>
1313
#include <zephyr/bluetooth/uuid.h>
14+
#include <zephyr/bluetooth/hci_types.h>
1415

1516
/** @file
1617
* @defgroup bt_ras Ranging Service API
@@ -54,7 +55,38 @@ extern "C" {
5455
#define BT_RAS_RANGING_HEADER_LEN 4
5556
#define BT_RAS_SUBEVENT_HEADER_LEN 8
5657
#define BT_RAS_STEP_MODE_LEN 1
57-
#define BT_RAS_MAX_STEP_DATA_LEN 35
58+
59+
#define BT_RAS_MAX_SUBEVENTS_PER_PROCEDURE 32
60+
#define BT_RAS_MAX_STEPS_PER_PROCEDURE 256
61+
62+
#define BT_RAS_STEP_MODE_2_3_ANT_DEPENDENT_LEN(antenna_paths) \
63+
((antenna_paths + 1) * sizeof(struct bt_hci_le_cs_step_data_tone_info))
64+
65+
#define BT_RAS_STEP_MODE_0_MAX_LEN \
66+
MAX(sizeof(struct bt_hci_le_cs_step_data_mode_0_initiator), \
67+
sizeof(struct bt_hci_le_cs_step_data_mode_0_reflector))
68+
#define BT_RAS_STEP_MODE_1_MAX_LEN (sizeof(struct bt_hci_le_cs_step_data_mode_1))
69+
#define BT_RAS_STEP_MODE_2_MAX_LEN \
70+
(sizeof(struct bt_hci_le_cs_step_data_mode_2) + \
71+
BT_RAS_STEP_MODE_2_3_ANT_DEPENDENT_LEN(CONFIG_BT_RAS_MAX_ANTENNA_PATHS))
72+
#define BT_RAS_STEP_MODE_3_MAX_LEN \
73+
(sizeof(struct bt_hci_le_cs_step_data_mode_3) + \
74+
BT_RAS_STEP_MODE_2_3_ANT_DEPENDENT_LEN(CONFIG_BT_RAS_MAX_ANTENNA_PATHS))
75+
76+
#define BT_RAS_STEP_MODE_0_1_MAX_LEN MAX(BT_RAS_STEP_MODE_0_MAX_LEN, BT_RAS_STEP_MODE_1_MAX_LEN)
77+
#define BT_RAS_STEP_MODE_0_1_2_MAX_LEN MAX(BT_RAS_STEP_MODE_0_1_MAX_LEN, BT_RAS_STEP_MODE_2_MAX_LEN)
78+
79+
#if defined(CONFIG_BT_RAS_MODE_3_SUPPORTED)
80+
#define BT_RAS_MAX_STEP_DATA_LEN MAX(BT_RAS_STEP_MODE_0_1_2_MAX_LEN, BT_RAS_STEP_MODE_3_MAX_LEN)
81+
#else
82+
#define BT_RAS_MAX_STEP_DATA_LEN BT_RAS_STEP_MODE_0_1_2_MAX_LEN
83+
#endif
84+
85+
#define BT_RAS_PROCEDURE_MEM \
86+
(BT_RAS_RANGING_HEADER_LEN + \
87+
(BT_RAS_MAX_SUBEVENTS_PER_PROCEDURE * BT_RAS_SUBEVENT_HEADER_LEN) + \
88+
(BT_RAS_MAX_STEPS_PER_PROCEDURE * BT_RAS_STEP_MODE_LEN) + \
89+
(BT_RAS_MAX_STEPS_PER_PROCEDURE * BT_RAS_MAX_STEP_DATA_LEN))
5890

5991
/** @brief Ranging Header structure as defined in RAS Specification, Table 3.7. */
6092
struct ras_ranging_header {
@@ -130,6 +162,156 @@ struct ras_subevent_header {
130162
} __packed;
131163
BUILD_ASSERT(sizeof(struct ras_subevent_header) == BT_RAS_SUBEVENT_HEADER_LEN);
132164

165+
/** @brief RAS Ranging Data Buffer callback structure. */
166+
struct bt_ras_rd_buffer_cb {
167+
/** @brief New ranging data has been received from the local controller.
168+
*
169+
* This callback notifies the application that the ranging data buffer
170+
* has reassembled a complete ranging procedure from the local controller.
171+
*
172+
* @param conn Connection object.
173+
* @param ranging_counter Ranging counter of the stored procedure.
174+
*/
175+
void (*new_ranging_data_received)(struct bt_conn *conn, uint16_t ranging_counter);
176+
177+
/** @brief Ranging data has been overwritten.
178+
*
179+
* This callback notifies the application that the ranging data buffer
180+
* has overwritten a stored procedure due to running out of buffers
181+
* to store a newer procedure from the local controller.
182+
*
183+
* @param conn Connection object.
184+
* @param ranging_counter Ranging counter of the overwritten procedure.
185+
*/
186+
void (*ranging_data_overwritten)(struct bt_conn *conn, uint16_t ranging_counter);
187+
188+
sys_snode_t node;
189+
};
190+
191+
/** @brief RAS Ranging Data buffer structure.
192+
*
193+
* Provides storage and metadata to store a complete Ranging Data body
194+
* as defined in RAS Specification, Section 3.2.1.2.
195+
* Buffers can be accessed by the application and RRSP concurrently, and will not
196+
* be overwritten while any references are held via @ref bt_ras_rd_buffer_claim.
197+
*
198+
* @note The following CS subevent fields are not included by specification:
199+
* subevent count, step channel, step length.
200+
*/
201+
struct ras_rd_buffer {
202+
/** Connection with an RRSP instance owning this buffer. */
203+
struct bt_conn *conn;
204+
/** CS Procedure Ranging Counter stored in this buffer. */
205+
uint16_t ranging_counter;
206+
/** Write cursor into the procedure subevent buffer. */
207+
uint16_t subevent_cursor;
208+
/** Reference counter for buffer.
209+
* The buffer will not be overwritten with active references.
210+
*/
211+
atomic_t refcount;
212+
/** All ranging data has been written, buffer is ready to send. */
213+
bool ready;
214+
/** Ranging data is being written to this buffer. */
215+
bool busy;
216+
/** The peer has ACKed this buffer, the overwritten callback will not be called. */
217+
bool acked;
218+
/** Complete ranging data procedure buffer. */
219+
union {
220+
uint8_t buf[BT_RAS_PROCEDURE_MEM];
221+
struct {
222+
struct ras_ranging_header ranging_header;
223+
uint8_t subevents[];
224+
} __packed;
225+
} procedure;
226+
};
227+
228+
/** @brief Allocate Ranging Responder instance for connection.
229+
*
230+
* This will allocate an instance of the Ranging Responder service for the given connection.
231+
*
232+
* @note This method must not be called if CONFIG_BT_RAS_RRSP_AUTO_ALLOC_INSTANCE is enabled.
233+
* @note The number of supported instances can be set using CONFIG_BT_RAS_RRSP_MAX_ACTIVE_CONN.
234+
*
235+
* @param conn Connection instance.
236+
*
237+
* @return Zero in case of success and error code in case of error.
238+
*/
239+
int bt_ras_rrsp_alloc(struct bt_conn *conn);
240+
241+
/** @brief Free Ranging Responder instance for connection.
242+
*
243+
* This will free an allocated instance of the Ranging Responder service for
244+
* the given connection, if one has been allocated.
245+
* If the connection has no instance allocated, this method has no effect.
246+
*
247+
* @note This method must not be called if CONFIG_BT_RAS_RRSP_AUTO_ALLOC_INSTANCE is enabled.
248+
*
249+
* @param conn Connection instance.
250+
*/
251+
void bt_ras_rrsp_free(struct bt_conn *conn);
252+
253+
/** @brief Register ranging data buffer callbacks.
254+
*
255+
* Register callbacks to monitor ranging data buffer state.
256+
*
257+
* @param cb Callback struct. Must point to memory that remains valid.
258+
*/
259+
void bt_ras_rd_buffer_cb_register(struct bt_ras_rd_buffer_cb *cb);
260+
261+
/** @brief Check if a given ranging counter is available.
262+
*
263+
* Checks if the given ranging counter is stored in the buffer and
264+
* has a valid complete ranging data body stored.
265+
*
266+
* @param conn Connection instance.
267+
* @param ranging_counter CS procedure ranging counter.
268+
*
269+
* @retval true A buffer storing this ranging counter exists and can be claimed.
270+
* @retval false A buffer storing this ranging counter does not exist.
271+
*/
272+
bool bt_ras_rd_buffer_ready_check(struct bt_conn *conn, uint16_t ranging_counter);
273+
274+
/** @brief Claim a buffer with a given ranging counter.
275+
*
276+
* Returns a pointer to a buffer storing a valid complete ranging data body with
277+
* the requested procedure counter, and increments its reference counter.
278+
*
279+
* @param conn Connection instance.
280+
* @param ranging_counter CS procedure ranging counter.
281+
*
282+
* @return Pointer to ranging data buffer structure or NULL if no such buffer exists.
283+
*/
284+
struct ras_rd_buffer *bt_ras_rd_buffer_claim(struct bt_conn *conn, uint16_t ranging_counter);
285+
286+
/** @brief Release a claimed ranging data buffer.
287+
*
288+
* Returns a buffer and decrements its reference counter.
289+
* The buffer will stay available until overwritten by newer ranging data, if
290+
* it has no remaining references.
291+
*
292+
* @param buf Pointer to claimed ranging data buffer.
293+
*
294+
* @retval 0 Success.
295+
* @retval -EINVAL Invalid buffer provided.
296+
*/
297+
int bt_ras_rd_buffer_release(struct ras_rd_buffer *buf);
298+
299+
/** @brief Pull bytes from a ranging data buffer.
300+
*
301+
* Utility method to consume up to max_data_len bytes from a buffer.
302+
* The provided read_cursor will be used as the initial offset and updated.
303+
*
304+
* @param buf Pointer to claimed ranging data buffer.
305+
* @param out_buf Destination to copy up to max_data_len bytes to.
306+
* @param max_data_len Maximum amount of bytes to copy from the buffer.
307+
* @param read_cursor Current offset into procedure subevent buffer, will be read and written to.
308+
* @param empty Set to true if all data has been read from the ranging data buffer.
309+
*
310+
* @return Number of bytes written into out_buf.
311+
*/
312+
int bt_ras_rd_buffer_bytes_pull(struct ras_rd_buffer *buf, uint8_t *out_buf, uint16_t max_data_len,
313+
uint16_t *read_cursor, bool *empty);
314+
133315
#ifdef __cplusplus
134316
}
135317
#endif

subsys/bluetooth/services/ras/Kconfig.ras

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,34 @@
44
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
55
#
66

7-
config BT_RAS
8-
bool
7+
menuconfig BT_RAS
8+
bool "Ranging Service [EXPERIMENTAL]"
9+
depends on BT_CHANNEL_SOUNDING
10+
select BT_NRF_SERVICES
11+
select EXPERIMENTAL
912
help
10-
Common Bluetooth GATT Ranging Service modules.
13+
Bluetooth GATT Ranging Service modules - RREQ and RRSP.
14+
15+
if BT_RAS
1116

1217
rsource "rreq/Kconfig.ras_rreq"
1318
rsource "rrsp/Kconfig.ras_rrsp"
19+
20+
config BT_RAS_MAX_ANTENNA_PATHS
21+
int "Maximum number of antenna paths supported"
22+
default 4
23+
range 1 4
24+
help
25+
The number of antenna paths per step that can be stored inside RAS.
26+
Must match the supported CS capabilities of the local device.
27+
This affects the per-instance memory usage of RAS.
28+
29+
config BT_RAS_MODE_3_SUPPORTED
30+
bool "Support storing Mode 3 CS steps"
31+
default y
32+
help
33+
If enabled, RAS will allocate memory for storing Mode 3 CS steps.
34+
Must match the supported CS capabilities of the local device.
35+
This affects the per-instance memory usage of RAS.
36+
37+
endif # BT_RAS

subsys/bluetooth/services/ras/ras_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ extern "C" {
2222
#define RASCP_CMD_PARAMS_OFFSET RASCP_CMD_OPCODE_LEN
2323
#define RASCP_CMD_PARAMS_MAX_LEN 4
2424
#define RASCP_WRITE_MAX_LEN (RASCP_CMD_OPCODE_LEN + RASCP_CMD_PARAMS_MAX_LEN)
25+
#define RASCP_ACK_DATA_TIMEOUT K_SECONDS(5)
2526

2627
/** @brief RAS Control Point opcodes as defined in RAS Specification, Table 3.10. */
2728
enum rascp_opcode {

subsys/bluetooth/services/ras/rreq/Kconfig.ras_rreq

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@
55
#
66

77
menuconfig BT_RAS_RREQ
8-
bool "Enable GATT Ranging Requester Client [EXPERIMENTAL]"
9-
depends on BT_CHANNEL_SOUNDING
8+
bool "GATT Ranging Requester Client [EXPERIMENTAL]"
109
select EXPERIMENTAL
11-
select BT_NRF_SERVICES
12-
select BT_RAS
1310

1411
if BT_RAS_RREQ
1512

subsys/bluetooth/services/ras/rrsp/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66

77
zephyr_library_sources_ifdef(
88
CONFIG_BT_RAS_RRSP
9-
ras_rrsp.c)
9+
ras_rrsp.c
10+
ras_rd_buffer.c)

subsys/bluetooth/services/ras/rrsp/Kconfig.ras_rrsp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,29 @@
55
#
66

77
menuconfig BT_RAS_RRSP
8-
bool "Enable GATT Ranging Responder Server [EXPERIMENTAL]"
9-
depends on BT_CHANNEL_SOUNDING
8+
bool "GATT Ranging Responder Server [EXPERIMENTAL]"
109
select EXPERIMENTAL
11-
select BT_NRF_SERVICES
12-
select BT_RAS
1310

1411
if BT_RAS_RRSP
1512

13+
config BT_RAS_RRSP_AUTO_ALLOC_INSTANCE
14+
bool "Automatically allocate RRSP instances to new connections"
15+
default y
16+
17+
config BT_RAS_RRSP_MAX_ACTIVE_CONN
18+
int "Number of simultaneously supported RRSP instances"
19+
default BT_MAX_CONN
20+
range 1 BT_MAX_CONN
21+
help
22+
The number of simultaneous connections with an instance of RAS RRSP
23+
24+
config BT_RAS_RRSP_RD_BUFFERS_PER_CONN
25+
int "Number of ranging data buffers per connection"
26+
default 1
27+
range 1 10
28+
help
29+
The number of ranging procedures that can be stored inside RRSP.
30+
1631
module = BT_RAS_RRSP
1732
module-str = RAS_RRSP
1833
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"

0 commit comments

Comments
 (0)