Skip to content

Commit 3c94a8a

Browse files
committed
bluetooth: services: RAS: Add rreq parse function
This parses both local and peer ranging data at the same time, so the user can extract useful information. Signed-off-by: Sean Madigan <[email protected]>
1 parent c4d2187 commit 3c94a8a

File tree

2 files changed

+148
-0
lines changed
  • include/bluetooth/services
  • subsys/bluetooth/services/ras/rreq

2 files changed

+148
-0
lines changed

include/bluetooth/services/ras.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <stdint.h>
1111
#include <zephyr/kernel.h>
1212
#include <zephyr/bluetooth/conn.h>
13+
#include <zephyr/bluetooth/cs.h>
1314
#include <zephyr/bluetooth/uuid.h>
1415
#include <zephyr/bluetooth/hci_types.h>
1516
#include <bluetooth/gatt_dm.h>
@@ -226,6 +227,14 @@ struct ras_rd_buffer {
226227
} procedure;
227228
};
228229

230+
/** @brief Subevent result step */
231+
struct ras_rd_cs_subevent_step {
232+
/** CS step mode. */
233+
uint8_t mode;
234+
/** Pointer to role- and mode-specific information. */
235+
const uint8_t *data;
236+
};
237+
229238
/** @brief Allocate Ranging Responder instance for connection.
230239
*
231240
* This will allocate an instance of the Ranging Responder service for the given connection.
@@ -477,6 +486,52 @@ int bt_ras_rreq_rd_overwritten_subscribe(struct bt_conn *conn, bt_ras_rreq_rd_ov
477486
*/
478487
int bt_ras_rreq_rd_overwritten_unsubscribe(struct bt_conn *conn);
479488

489+
/** @brief Provide step header for each step back to the user.
490+
*
491+
* @param[in] subevent_header Subevent header data.
492+
* @param[in] user_data User data.
493+
*
494+
* @retval true If should continue parsing data.
495+
* false If data parsing should be stopped.
496+
*/
497+
typedef bool (*bt_ras_rreq_subevent_header_cb_t)(struct ras_subevent_header *subevent_header,
498+
void *user_data);
499+
500+
/** @brief Provide step data for each step back to the user.
501+
*
502+
* @param[in] local_step Local step data.
503+
* @param[in] peer_step Peer step data.
504+
* @param[in] user_data User data.
505+
*
506+
* @retval true If should continue parsing data.
507+
* false If data parsing should be stopped.
508+
*/
509+
typedef bool (*bt_ras_rreq_step_data_cb_t)(struct bt_le_cs_subevent_step *local_step,
510+
struct bt_le_cs_subevent_step *peer_step,
511+
void *user_data);
512+
513+
/** @brief Parse peer ranging data buffer and local step data buffer.
514+
*
515+
* A helper for parsing ranging data-formatted buffer, as populated by @ref
516+
* bt_ras_rreq_cp_get_ranging_data, and local step data buffer,
517+
* where step_data_buf from le_cs_subevent_data_available has been placed together in a struct
518+
* net_buf_simple.
519+
*
520+
* @note All data will be removed from the buffers in this function.
521+
*
522+
* @param[in] peer_ranging_data_buf Buffer to the peer ranging data to parse.
523+
* @param[in] local_step_data_buf Buffer to the local step data to parse.
524+
* @param[in] cs_role Channel sounding role of local device.
525+
* @param[in] subevent_header_cb Callback called with each subevent header.
526+
* @param[in] step_data_cb Callback called with each peer and local step data.
527+
* @param[in] user_data User data to be passed to the callbacks.
528+
*/
529+
void bt_ras_rreq_rd_subevent_data_parse(struct net_buf_simple *peer_ranging_data_buf,
530+
struct net_buf_simple *local_step_data_buf,
531+
enum bt_conn_le_cs_role cs_role,
532+
bt_ras_rreq_subevent_header_cb_t subevent_header_cb,
533+
bt_ras_rreq_step_data_cb_t step_data_cb, void *user_data);
534+
480535
#ifdef __cplusplus
481536
}
482537
#endif

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

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <zephyr/bluetooth/conn.h>
8+
#include <zephyr/bluetooth/cs.h>
89
#include <zephyr/bluetooth/gatt.h>
910
#include <zephyr/logging/log.h>
1011
#include <zephyr/net_buf.h>
@@ -859,3 +860,95 @@ int bt_ras_rreq_cp_get_ranging_data(struct bt_conn *conn, struct net_buf_simple
859860

860861
return 0;
861862
}
863+
864+
void bt_ras_rreq_rd_subevent_data_parse(struct net_buf_simple *peer_ranging_data_buf,
865+
struct net_buf_simple *local_step_data_buf,
866+
enum bt_conn_le_cs_role cs_role,
867+
bt_ras_rreq_subevent_header_cb_t subevent_header_cb,
868+
bt_ras_rreq_step_data_cb_t step_data_cb, void *user_data)
869+
{
870+
if (!peer_ranging_data_buf || !local_step_data_buf) {
871+
LOG_ERR("Tried to parse empty step data.");
872+
return;
873+
}
874+
875+
/* Remove ranging data header. */
876+
net_buf_simple_pull_mem(peer_ranging_data_buf, sizeof(struct ras_ranging_header));
877+
878+
while (peer_ranging_data_buf->len >= sizeof(struct ras_subevent_header)) {
879+
struct ras_subevent_header *peer_subevent_header_data = net_buf_simple_pull_mem(
880+
peer_ranging_data_buf, sizeof(struct ras_subevent_header));
881+
882+
if (subevent_header_cb &&
883+
!subevent_header_cb(peer_subevent_header_data, user_data)) {
884+
return;
885+
}
886+
887+
if (peer_subevent_header_data->num_steps_reported == 0 ||
888+
peer_ranging_data_buf->len == 0) {
889+
return;
890+
}
891+
892+
for (uint8_t i = 0; i < peer_subevent_header_data->num_steps_reported; i++) {
893+
struct bt_le_cs_subevent_step local_step;
894+
struct bt_le_cs_subevent_step peer_step;
895+
896+
if (local_step_data_buf->len < sizeof(struct bt_le_cs_subevent_step) ||
897+
peer_ranging_data_buf->len < sizeof(struct ras_rd_cs_subevent_step)) {
898+
LOG_WRN("Step data appears malformed.");
899+
}
900+
901+
local_step.mode = net_buf_simple_pull_u8(local_step_data_buf);
902+
local_step.channel = net_buf_simple_pull_u8(local_step_data_buf);
903+
local_step.data_len = net_buf_simple_pull_u8(local_step_data_buf);
904+
905+
peer_step.mode = net_buf_simple_pull_u8(peer_ranging_data_buf);
906+
peer_step.channel = local_step.channel;
907+
908+
if (peer_step.mode != local_step.mode) {
909+
LOG_WRN("Mismatch of local and peer step mode %d != %d",
910+
peer_step.mode, local_step.mode);
911+
return;
912+
}
913+
914+
if (local_step.data_len == 0) {
915+
LOG_WRN("Encountered zero-length step data.");
916+
return;
917+
}
918+
919+
peer_step.data = peer_ranging_data_buf->data;
920+
local_step.data = local_step_data_buf->data;
921+
922+
peer_step.data_len = local_step.data_len;
923+
924+
if (peer_step.mode == 0) {
925+
/* Only occassion where peer step mode length is not equal to local
926+
* step mode length is mode 0 steps.
927+
*/
928+
peer_step.data_len =
929+
(cs_role == BT_CONN_LE_CS_ROLE_INITIATOR)
930+
? sizeof(struct
931+
bt_hci_le_cs_step_data_mode_0_reflector)
932+
: sizeof(struct
933+
bt_hci_le_cs_step_data_mode_0_initiator);
934+
}
935+
936+
if (local_step.data_len > local_step_data_buf->len ||
937+
peer_step.data_len > peer_ranging_data_buf->len) {
938+
LOG_WRN("Step data appears malformed.");
939+
return;
940+
}
941+
942+
if (step_data_cb && !step_data_cb(&local_step, &peer_step, user_data)) {
943+
return;
944+
}
945+
946+
net_buf_simple_pull(peer_ranging_data_buf, peer_step.data_len);
947+
net_buf_simple_pull(local_step_data_buf, local_step.data_len);
948+
}
949+
}
950+
951+
if (local_step_data_buf->len != 0 || peer_ranging_data_buf->len != 0) {
952+
LOG_WRN("Peer or local buffers not fully drained at the end of parsing.");
953+
}
954+
}

0 commit comments

Comments
 (0)