Skip to content

Commit

Permalink
bluetooth: services: ras: Implement Ranging Responder role of RAS
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
alexstanoev-nordic committed Nov 8, 2024
1 parent 1ecafe0 commit cf80a30
Show file tree
Hide file tree
Showing 6 changed files with 1,223 additions and 5 deletions.
186 changes: 185 additions & 1 deletion include/bluetooth/services/ras.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,41 @@ extern "C" {
#define BT_RAS_RANGING_HEADER_LEN 4
#define BT_RAS_SUBEVENT_HEADER_LEN 8
#define BT_RAS_STEP_MODE_LEN 1
#define BT_RAS_MAX_STEP_DATA_LEN 35

#define BT_RAS_MAX_SUBEVENTS_PER_PROCEDURE 32
#define BT_RAS_MAX_STEPS_PER_PROCEDURE 256

#define BT_RAS_STEP_MODE_2_3_ANT_DEPENDENT_LEN(antenna_paths) \
((antenna_paths + 1) * sizeof(struct bt_hci_le_cs_step_data_tone_info))

#define BT_RAS_STEP_MODE_0_MAX_LEN \
MAX(sizeof(struct bt_hci_le_cs_step_data_mode_0_initiator), \
sizeof(struct bt_hci_le_cs_step_data_mode_0_reflector))
#define BT_RAS_STEP_MODE_1_MAX_LEN \
MAX(sizeof(struct bt_hci_le_cs_step_data_mode_1), \
sizeof(struct bt_hci_le_cs_step_data_mode_1_ss_rtt))
#define BT_RAS_STEP_MODE_2_MAX_LEN \
(sizeof(struct bt_hci_le_cs_step_data_mode_2) + \
BT_RAS_STEP_MODE_2_3_ANT_DEPENDENT_LEN(CONFIG_BT_RAS_RRSP_MAX_ANTENNA_PATHS))
#define BT_RAS_STEP_MODE_3_MAX_LEN \
(MAX(sizeof(struct bt_hci_le_cs_step_data_mode_3), \
sizeof(struct bt_hci_le_cs_step_data_mode_3_ss_rtt)) + \
BT_RAS_STEP_MODE_2_3_ANT_DEPENDENT_LEN(CONFIG_BT_RAS_RRSP_MAX_ANTENNA_PATHS))

#define BT_RAS_STEP_MODE_0_1_MAX_LEN MAX(BT_RAS_STEP_MODE_0_MAX_LEN, BT_RAS_STEP_MODE_1_MAX_LEN)
#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)

#if defined(CONFIG_BT_RAS_RRSP_MODE_3_SUPPORTED)
#define BT_RAS_MAX_STEP_DATA_LEN MAX(BT_RAS_STEP_MODE_0_1_2_MAX_LEN, BT_RAS_STEP_MODE_3_MAX_LEN)
#else
#define BT_RAS_MAX_STEP_DATA_LEN BT_RAS_STEP_MODE_0_1_2_MAX_LEN
#endif

#define BT_RAS_PROCEDURE_MEM \
(BT_RAS_RANGING_HEADER_LEN + \
(BT_RAS_MAX_SUBEVENTS_PER_PROCEDURE * BT_RAS_SUBEVENT_HEADER_LEN) + \
(BT_RAS_MAX_STEPS_PER_PROCEDURE * BT_RAS_STEP_MODE_LEN) + \
(BT_RAS_MAX_STEPS_PER_PROCEDURE * BT_RAS_MAX_STEP_DATA_LEN))

/** @brief Ranging Header structure as defined in RAS Specification, Table 3.7. */
struct ras_ranging_header {
Expand Down Expand Up @@ -130,6 +164,156 @@ struct ras_subevent_header {
} __packed;
BUILD_ASSERT(sizeof(struct ras_subevent_header) == BT_RAS_SUBEVENT_HEADER_LEN);

/** @brief RAS Ranging Data Buffer callback structure. */
struct bt_ras_rd_buffer_cb {
/** @brief New ranging data has been received from the local controller.
*
* This callback notifies the application that the ranging data buffer
* has reassembled a complete ranging procedure from the local controller.
*
* @param conn Connection object.
* @param ranging_counter Ranging counter of the stored procedure.
*/
void (*new_ranging_data_received)(struct bt_conn *conn, uint16_t ranging_counter);

/** @brief Ranging data has been overwritten.
*
* This callback notifies the application that the ranging data buffer
* has overwritten a stored procedure due to running out of buffers
* to store a newer procedure from the local controller.
*
* @param conn Connection object.
* @param ranging_counter Ranging counter of the overwritten procedure.
*/
void (*ranging_data_overwritten)(struct bt_conn *conn, uint16_t ranging_counter);

sys_snode_t node;
};

/** @brief RAS Ranging Data buffer structure.
*
* Provides storage and metadata to store a complete Ranging Data body
* as defined in RAS Specification, Section 3.2.1.2.
* Buffers can be accessed by the application and RRSP concurrently, and will not
* be overwritten while any references are held via @ref bt_ras_rd_buffer_claim.
*
* @note The following CS subevent fields are not included by specification:
* subevent count, step channel, step length.
*/
struct ras_rd_buffer {
/** Connection with an RRSP instance owning this buffer. */
struct bt_conn *conn;
/** CS Procedure Ranging Counter stored in this buffer. */
uint16_t ranging_counter;
/** Write cursor into the procedure subevent buffer. */
uint16_t subevent_cursor;
/** Reference counter for buffer.
* The buffer will not be overwritten with active references.
*/
atomic_t refcount;
/** All ranging data has been written, buffer is ready to send. */
bool ready;
/** Ranging data is being written to this buffer. */
bool busy;
/** The peer has ACKed this buffer, the overwritten callback will not be called. */
bool acked;
/** Complete ranging data procedure buffer. */
union {
uint8_t buf[BT_RAS_PROCEDURE_MEM];
struct {
struct ras_ranging_header ranging_header;
uint8_t subevents[];
} __packed;
} procedure;
};

/** @brief Allocate Ranging Responder instance for connection.
*
* This will allocate an instance of the Ranging Responder service for the given connection.
*
* @note This method must not be called if CONFIG_BT_RAS_RRSP_AUTO_ALLOC_INSTANCE is enabled.
* @note The number of supported instances can be set using CONFIG_BT_RAS_RRSP_MAX_ACTIVE_CONN.
*
* @param conn Connection instance.
*
* @return Zero in case of success and error code in case of error.
*/
int bt_ras_rrsp_alloc(struct bt_conn *conn);

/** @brief Free Ranging Responder instance for connection.
*
* This will free an allocated instance of the Ranging Responder service for
* the given connection, if one has been allocated.
* If the connection has no instance allocated, this method has no effect.
*
* @note This method must not be called if CONFIG_BT_RAS_RRSP_AUTO_ALLOC_INSTANCE is enabled.
*
* @param conn Connection instance.
*/
void bt_ras_rrsp_free(struct bt_conn *conn);

/** @brief Register ranging data buffer callbacks.
*
* Register callbacks to monitor ranging data buffer state.
*
* @param cb Callback struct. Must point to memory that remains valid.
*/
void bt_ras_rd_buffer_cb_register(struct bt_ras_rd_buffer_cb *cb);

/** @brief Check if a given ranging counter is available.
*
* Checks if the given ranging counter is stored in the buffer and
* has a valid complete ranging data body stored.
*
* @param conn Connection instance.
* @param ranging_counter CS procedure ranging counter.
*
* @retval true A buffer storing this ranging counter exists and can be claimed.
* @retval false A buffer storing this ranging counter does not exist.
*/
bool bt_ras_rd_buffer_ready_check(struct bt_conn *conn, uint16_t ranging_counter);

/** @brief Claim a buffer with a given ranging counter.
*
* Returns a pointer to a buffer storing a valid complete ranging data body with
* the requested procedure counter, and increments its reference counter.
*
* @param conn Connection instance.
* @param ranging_counter CS procedure ranging counter.
*
* @return Pointer to ranging data buffer structure or NULL if no such buffer exists.
*/
struct ras_rd_buffer *bt_ras_rd_buffer_claim(struct bt_conn *conn, uint16_t ranging_counter);

/** @brief Release a claimed ranging data buffer.
*
* Returns a buffer and decrements its reference counter.
* The buffer will stay available until overwritten by newer ranging data, if
* it has no remaining references.
*
* @param buf Pointer to claimed ranging data buffer.
*
* @retval 0 Success.
* @retval -EINVAL Invalid buffer provided.
*/
int bt_ras_rd_buffer_release(struct ras_rd_buffer *buf);

/** @brief Pull bytes from a ranging data buffer.
*
* Utility method to consume up to max_data_len bytes from a buffer.
* The provided read_cursor will be used as the initial offset and updated.
*
* @param buf Pointer to claimed ranging data buffer.
* @param out_buf Destination to copy up to max_data_len bytes to.
* @param max_data_len Maximum amount of bytes to copy from the buffer.
* @param read_cursor Current offset into procedure subevent buffer, will be read and written to.
* @param empty Set to true if all data has been read from the ranging data buffer.
*
* @return Number of bytes written into out_buf.
*/
int bt_ras_rd_buffer_bytes_pull(struct ras_rd_buffer *buf, uint8_t *out_buf, uint16_t max_data_len,
uint16_t *read_cursor, bool *empty);

#ifdef __cplusplus
}
#endif
Expand Down
1 change: 1 addition & 0 deletions subsys/bluetooth/services/ras/ras_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extern "C" {
#define RASCP_CMD_PARAMS_OFFSET RASCP_CMD_OPCODE_LEN
#define RASCP_CMD_PARAMS_MAX_LEN 4
#define RASCP_WRITE_MAX_LEN (RASCP_CMD_OPCODE_LEN + RASCP_CMD_PARAMS_MAX_LEN)
#define RASCP_ACK_DATA_TIMEOUT K_SECONDS(5)

/** @brief RAS Control Point opcodes as defined in RAS Specification, Table 3.10. */
enum rascp_opcode {
Expand Down
3 changes: 2 additions & 1 deletion subsys/bluetooth/services/ras/rrsp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@

zephyr_library_sources_ifdef(
CONFIG_BT_RAS_RRSP
ras_rrsp.c)
ras_rrsp.c
ras_rd_buffer.c)
35 changes: 35 additions & 0 deletions subsys/bluetooth/services/ras/rrsp/Kconfig.ras_rrsp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,41 @@ menuconfig BT_RAS_RRSP

if BT_RAS_RRSP

config BT_RAS_RRSP_AUTO_ALLOC_INSTANCE
bool "Automatically allocate RRSP instances to new connections"
default y

config BT_RAS_RRSP_MAX_ACTIVE_CONN
int "Number of simultaneously supported RRSP instances"
default BT_MAX_CONN
range 1 BT_MAX_CONN
help
The number of simultaneous connections with an instance of RAS RRSP

config BT_RAS_RRSP_RD_BUFFERS_PER_CONN
int "Number of ranging data buffers per connection"
default 1
range 1 10
help
The number of ranging procedures that can be stored inside RRSP.

config BT_RAS_RRSP_MAX_ANTENNA_PATHS
int "Number of antenna paths supported by RRSP"
default 4
range 1 4
help
The number of antenna paths per step that can be stored inside RRSP.
Must match the capabilities of the local and peer devices.
This affects the per-instance memory usage of RRSP.

config BT_RAS_RRSP_MODE_3_SUPPORTED
bool "Support storing Mode 3 CS steps in RRSP"
default y
help
If enabled, RRSP will allocate memory for storing Mode 3 CS steps.
Must match the capabilities of the local and peer devices.
This affects the per-instance memory usage of RRSP.

module = BT_RAS_RRSP
module-str = RAS_RRSP
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"
Expand Down
Loading

0 comments on commit cf80a30

Please sign in to comment.