|
5 | 5 | */ |
6 | 6 |
|
7 | 7 | #include <zephyr/bluetooth/conn.h> |
| 8 | +#include <zephyr/bluetooth/cs.h> |
8 | 9 | #include <zephyr/bluetooth/gatt.h> |
9 | 10 | #include <zephyr/logging/log.h> |
10 | 11 | #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 |
859 | 860 |
|
860 | 861 | return 0; |
861 | 862 | } |
| 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