summaryrefslogtreecommitdiff
path: root/mac/fira_session.c
diff options
context:
space:
mode:
Diffstat (limited to 'mac/fira_session.c')
-rw-r--r--mac/fira_session.c136
1 files changed, 118 insertions, 18 deletions
diff --git a/mac/fira_session.c b/mac/fira_session.c
index 6f673ad..90f6dc3 100644
--- a/mac/fira_session.c
+++ b/mac/fira_session.c
@@ -25,6 +25,7 @@
#include "fira_crypto.h"
#include "fira_round_hopping_sequence.h"
#include "fira_access.h"
+#include "fira_trace.h"
#include "mcps802154_i.h"
#include <linux/errno.h>
@@ -275,13 +276,68 @@ bool fira_session_is_ready(struct fira_local *local,
round_duration_dtu < params->block_duration_dtu;
}
-void fira_session_round_hopping(struct fira_session *session)
+static int fira_next_in_bitfield_u8(u8 bitfield, int prev)
+{
+ u32 padded_bitfield = 1 << 16 | bitfield << 8 | bitfield;
+ u32 rotated_bitfield = padded_bitfield >> (prev + 1);
+
+ return (ffs(rotated_bitfield) + prev) % 8;
+}
+
+static void fira_update_antennas_id(struct fira_session *session)
+{
+ const struct fira_session_params *p = &session->params;
+
+ session->tx_ant = fira_next_in_bitfield_u8(p->tx_antenna_selection,
+ session->tx_ant);
+
+ switch (p->rx_antenna_switch) {
+ default:
+ case FIRA_RX_ANTENNA_SWITCH_BETWEEN_ROUND:
+ /* Switch pairs between round. */
+ session->rx_ant_pair[0] = session->rx_ant_pair[1] =
+ fira_next_in_bitfield_u8(p->rx_antenna_selection,
+ session->rx_ant_pair[0]);
+ break;
+ case FIRA_RX_ANTENNA_SWITCH_DURING_ROUND:
+ session->rx_ant_pair[0] = p->rx_antenna_pair_azimuth;
+ session->rx_ant_pair[1] = p->rx_antenna_pair_elevation;
+ break;
+ case FIRA_RX_ANTENNA_SWITCH_TWO_RANGING:
+ /* Switch from one ranging to another. */
+ if (session->rx_ant_pair[0] == p->rx_antenna_pair_azimuth)
+ session->rx_ant_pair[0] = p->rx_antenna_pair_elevation;
+ else
+ session->rx_ant_pair[0] = p->rx_antenna_pair_azimuth;
+ session->rx_ant_pair[1] = session->rx_ant_pair[0];
+ break;
+ }
+}
+
+void fira_session_prepare(struct fira_local *local,
+ struct fira_session *session)
+{
+ fira_update_antennas_id(session);
+ if (session->params.device_type == FIRA_DEVICE_TYPE_CONTROLLER) {
+ session->next_block_stride_len =
+ session->params.block_stride_len;
+ if (session->params.round_hopping) {
+ u32 next_block_index = session->block_index +
+ session->next_block_stride_len +
+ 1;
+ trace_region_fira_next_block(session, next_block_index);
+ session->next_round_index =
+ fira_round_hopping_sequence_get(
+ session, next_block_index);
+ }
+ }
+}
+
+void fira_session_update_round_index(struct fira_session *session)
{
if (session->hopping_sequence_generation) {
session->round_index = fira_round_hopping_sequence_get(
session, session->block_index);
- session->next_round_index = fira_round_hopping_sequence_get(
- session, session->block_index + 1);
} else {
session->round_index = session->next_round_index;
session->hopping_sequence_generation =
@@ -293,35 +349,75 @@ static void fira_session_update(struct fira_local *local,
struct fira_session *session,
u32 next_timestamp_dtu)
{
+ u32 access_dtu;
s32 diff_dtu;
int block_duration_margin_dtu = 0;
if (session->params.device_type == FIRA_DEVICE_TYPE_CONTROLEE)
block_duration_margin_dtu =
fira_session_get_block_duration_margin(local, session);
- diff_dtu = session->block_start_dtu +
- fira_session_get_round_slot(session) *
- session->params.slot_duration_dtu -
- block_duration_margin_dtu - next_timestamp_dtu;
+
+ /* Do we have the time to participate in the current block? */
+ access_dtu = session->block_start_dtu +
+ fira_session_get_round_slot(session) *
+ session->params.slot_duration_dtu -
+ block_duration_margin_dtu;
+ diff_dtu = access_dtu - next_timestamp_dtu;
if (diff_dtu < 0) {
int block_duration_dtu = session->params.block_duration_dtu;
int block_duration_slots =
block_duration_dtu / session->params.slot_duration_dtu;
- int add_blocks;
+ int block_stride_len = session->block_stride_len;
+ int block_stride_duration_dtu =
+ block_duration_dtu * (block_stride_len + 1);
+ int add_blocks, add_strides;
+
+ /*
+ * No time in current block, which block should we try? The
+ * result of this can be 0, meaning that we are still in the
+ * same block, but the access was earlier in this block.
+ */
+ diff_dtu = session->block_start_dtu -
+ block_duration_margin_dtu - next_timestamp_dtu;
+ add_strides = -diff_dtu / block_stride_duration_dtu;
+ add_blocks = add_strides * (block_stride_len + 1);
- add_blocks = (-diff_dtu + block_duration_dtu - 1) /
- block_duration_dtu;
session->block_start_dtu += add_blocks * block_duration_dtu;
session->block_index += add_blocks;
session->sts_index += add_blocks * block_duration_slots;
- if (add_blocks != 1)
- session->hopping_sequence_generation =
- session->params.round_hopping;
- fira_session_round_hopping(session);
+ if (add_blocks != 0) {
+ /*
+ * More than one ranging round skipped, can not trust
+ * last hopping instructions.
+ */
+ if (add_blocks > block_stride_len + 1)
+ session->hopping_sequence_generation =
+ session->params.round_hopping;
+ fira_session_update_round_index(session);
+ }
+
+ /* Retry in the found block. */
+ access_dtu = session->block_start_dtu +
+ fira_session_get_round_slot(session) *
+ session->params.slot_duration_dtu -
+ block_duration_margin_dtu;
+ diff_dtu = access_dtu - next_timestamp_dtu;
+
+ if (diff_dtu < 0) {
+ /* Still no time, next one will be OK. */
+ add_blocks = block_stride_len + 1;
+ session->block_start_dtu +=
+ add_blocks * block_duration_dtu;
+ session->block_index += add_blocks;
+ session->sts_index += add_blocks * block_duration_slots;
+ fira_session_update_round_index(session);
+ }
+ trace_region_fira_block_index(session, session->block_index);
}
}
+
static inline bool
fira_session_has_higher_priority(const struct fira_session *session,
const struct fira_session *selected_session)
@@ -397,9 +493,11 @@ static struct fira_session *fira_session_find_next(struct fira_local *local,
access_duration_dtu = demand.duration_dtu;
unsync_access_duration_dtu = U32_MAX;
if (session->params.max_rr_retry) {
- int nb_blocks = session->params.max_rr_retry +
- session->last_block_index -
- session->block_index;
+ int nb_blocks =
+ session->params.max_rr_retry *
+ (session->block_stride_len + 1) +
+ session->last_block_index -
+ session->block_index;
unsync_access_duration_dtu =
min((u32)session->params.block_duration_dtu *
@@ -457,7 +555,8 @@ fira_session_check_max_number_of_measurements(struct fira_local *local,
static bool fira_session_check_max_rr_retry(struct fira_session *session)
{
if (session->params.max_rr_retry &&
- !((s32)(session->block_index - session->last_block_index -
+ !((s32)((session->block_index - session->last_block_index) /
+ (session->block_stride_len + 1) -
session->params.max_rr_retry) < 0)) {
session->stop_no_response = true;
return true;
@@ -638,5 +737,6 @@ void fira_session_access_done(struct fira_local *local,
if (session == local->current_session) {
fira_session_stop_expired_sessions(local);
+ session->block_stride_len = session->next_block_stride_len;
}
}