blob: 4f025968fa6d6179e13717f6bc92c387bb955a96 [file] [log] [blame]
/*
* This file is part of the UWB stack for linux.
*
* Copyright (c) 2020-2022 Qorvo US, Inc.
*
* This software is provided under the GNU General Public License, version 2
* (GPLv2), as well as under a Qorvo commercial license.
*
* You may choose to use this software under the terms of the GPLv2 License,
* version 2 ("GPLv2"), as published by the Free Software Foundation.
* You should have received a copy of the GPLv2 along with this program. If
* not, see <http://www.gnu.org/licenses/>.
*
* This program is distributed under the GPLv2 in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GPLv2 for more
* details.
*
* If you cannot meet the requirements of the GPLv2, you may not use this
* software for any purpose without first obtaining a commercial license from
* Qorvo. Please contact Qorvo to inquire about licensing terms.
*/
#ifndef NET_MCPS802154_FIRA_SESSION_H
#define NET_MCPS802154_FIRA_SESSION_H
#include "fira_session_fsm.h"
#include "fira_region.h"
#include "fira_sts.h"
#include "fira_crypto.h"
#include "fira_round_hopping_crypto_impl.h"
/**
* enum fira_controlee_state - State of controlee.
* @FIRA_CONTROLEE_STATE_PENDING_RUN: The controlee will be set to running state
* at the end of round.
* @FIRA_CONTROLEE_STATE_RUNNING: The controlee is running.
* @FIRA_CONTROLEE_STATE_PENDING_STOP: The controlee will be set to stopping
* state at the end of round.
* @FIRA_CONTROLEE_STATE_STOPPING: The controlee is stopping.
* @FIRA_CONTROLEE_STATE_PENDING_DEL: The controlee will be set to deleting
* state at the end of round.
* @FIRA_CONTROLEE_STATE_DELETING: The controlee is being deleted.
*/
enum fira_controlee_state {
FIRA_CONTROLEE_STATE_PENDING_RUN,
FIRA_CONTROLEE_STATE_RUNNING,
FIRA_CONTROLEE_STATE_PENDING_STOP,
FIRA_CONTROLEE_STATE_STOPPING,
FIRA_CONTROLEE_STATE_PENDING_DEL,
FIRA_CONTROLEE_STATE_DELETING,
};
/**
* struct fira_controlee - Represent a controlee.
*/
struct fira_controlee {
/**
* @sub_session_id: Sub-session ID used by the controlee.
*/
__u32 sub_session_id;
/**
* @short_addr: Short address of the controlee.
*/
__le16 short_addr;
/**
* @sub_session_key_len: Length of the sub-session key used by
* the controlee.
*/
__u8 sub_session_key_len;
/**
* @sub_session_key: Sub-session key used by the controlee.
*/
char sub_session_key[FIRA_KEY_SIZE_MAX];
/**
* @sub_session: Is the controlee using a sub-session.
*/
bool sub_session;
/**
* @state: Current state of the controlee.
*/
enum fira_controlee_state state;
/**
* @entry: Entry in list of controlees.
*/
struct list_head entry;
};
struct fira_measurement_sequence_step {
enum fira_measurement_type type;
u8 n_measurements;
s8 rx_ant_set_nonranging;
s8 rx_ant_sets_ranging[2];
s8 tx_ant_set_nonranging;
s8 tx_ant_set_ranging;
};
struct fira_measurement_sequence {
struct fira_measurement_sequence_step
steps[FIRA_MEASUREMENT_SEQUENCE_STEP_MAX];
size_t n_steps;
};
struct fira_session_params {
/* Main parameters. */
enum fira_device_type device_type;
enum fira_ranging_round_usage ranging_round_usage;
enum fira_multi_node_mode multi_node_mode;
__le16 short_addr;
__le16 controller_short_addr;
/* Timings parameters. */
int initiation_time_ms;
int slot_duration_dtu;
int block_duration_dtu;
int round_duration_slots;
/* Behaviour parameters. */
u32 block_stride_len;
u32 max_number_of_measurements;
u32 max_rr_retry;
bool round_hopping;
u8 priority;
bool result_report_phase;
/* Radio. */
int channel_number;
int preamble_code_index;
enum fira_rframe_config rframe_config;
enum fira_preambule_duration preamble_duration;
enum fira_sfd_id sfd_id;
enum fira_sts_segments number_of_sts_segments;
enum fira_psdu_data_rate psdu_data_rate;
enum fira_mac_fcs_type mac_fcs_type;
enum fira_prf_mode prf_mode;
enum fira_phr_data_rate phr_data_rate;
/* STS and crypto. */
enum fira_sts_mode sts_config;
u8 vupper64[FIRA_VUPPER64_SIZE];
u8 session_key_len;
u8 session_key[FIRA_KEY_SIZE_MAX];
bool key_rotation;
u8 key_rotation_rate;
bool aoa_result_req;
bool report_tof;
bool report_aoa_azimuth;
bool report_aoa_elevation;
bool report_aoa_fom;
enum fira_rssi_report_type report_rssi;
struct fira_measurement_sequence meas_seq;
u32 data_vendor_oui;
u8 data_payload[FIRA_DATA_PAYLOAD_SIZE_MAX];
u32 data_payload_seq;
int data_payload_len;
bool report_diagnostics;
enum fira_ranging_diagnostics_frame_report_flags diagnostic_report_flags;
/* Misc */
enum fira_sts_length sts_length;
enum fira_range_data_ntf_config range_data_ntf_config;
u32 range_data_ntf_proximity_near_mm;
u32 range_data_ntf_proximity_far_mm;
};
/**
* struct fira_session - Session information.
*/
struct fira_session {
/**
* @id: Session identifier.
*/
u32 id;
/**
* @sequence_number: Session notification counter.
*/
u32 sequence_number;
/**
* @entry: Entry in list of sessions.
*/
struct list_head entry;
/**
* @state: State of the session.
*/
const struct fira_session_fsm_state *state;
/**
* @params: Session parameters, mostly read only while the session is
* active.
*/
struct fira_session_params params;
/**
* @hrp_uwb_params: HRP UWB parameters, read only while the session is
* active.
*/
struct mcps802154_hrp_uwb_params hrp_uwb_params;
/**
* @event_portid: Port identifier to use for notifications.
*/
u32 event_portid;
/**
* @block_start_valid: True when block_start_dtu is valid.
* It's false on the first access wo initiation delay.
*/
bool block_start_valid;
/**
* @block_start_dtu: Block start timestamp in dtu of the last
* get_access.
*/
u32 block_start_dtu;
/**
* @next_access_timestamp_dtu: Next access timestamp in dtu.
* It's equal to block_start_dtu when the hopping is disabled.
* Otherwise it's beyond the block_start_dtu.
* It's updated after each good or missed ranging round.
*/
u32 next_access_timestamp_dtu;
/**
* @last_access_timestamp_dtu: Last timestamp where the session got
* the access.
* It's used only on session's election, when a negotiation between
* two session fails.
*/
u32 last_access_timestamp_dtu;
/**
* @block_index: Block index used on the last access.
*/
u32 block_index;
/**
* @block_stride_len: Stride length indicates how many ranging blocks
* will be skipped.
* The value is updated at the beginning of an access.
*/
int block_stride_len;
/**
* @round_index: Round index used on the last access.
*/
int round_index;
/**
* @next_round_index: Next round index a announced in measurement
* report message.
*/
int next_round_index;
/**
* @stop_request: Session has been requested to stop.
*/
bool stop_request;
/**
* @stop_inband: Session has been requested to stop by controller. This
* field is only used for controlee sessions.
*/
bool stop_inband;
/**
* @stop_no_response: Session has been requested to stop because ranging
* failed for max_rr_retry consecutive rounds.
*/
bool stop_no_response;
/**
* @n_ranging_round_retry: Number of ranging round failed.
* Counter reset on ranging round success.
*/
int n_ranging_round_retry;
/**
* @round_hopping_sequence: Round hopping sequence generation context.
*/
struct fira_round_hopping_sequence round_hopping_sequence;
/**
* @controlee: Group of persistent variable(s) used when session
* is a controlee.
*/
struct {
/**
* @synchronised: Whether a controlee session was synchronised.
*/
bool synchronised;
/**
* @block_index_sync: Last block index received.
*/
int block_index_sync;
/**
* @hopping_mode: True when hopping is enabled on last
* measurement frame.
*/
bool hopping_mode;
/**
* @next_round_index_valid: True when the next round index
* is present in measurement report frame.
*/
bool next_round_index_valid;
} controlee;
/**
* @controller: Group of persistent variable(s) used when session
* is a controller.
*/
struct {
/**
* @next_block_index: Next block index built on get access with
* next round index.
* It's only to avoid to rebuild the next round index on next
* access, when this last occur in time as block index will
* match.
*/
u32 next_block_index;
} controller;
/**
* @data_payload: Local context for data_payload feature.
*/
struct {
/**
* @seq: Sequence number of last sent data.
*/
u32 seq;
/**
* @sent: True when data have been send during ranging round.
*/
bool sent;
} data_payload;
/**
* @current_controlees: Current list of controlees.
*/
struct list_head current_controlees;
/**
* @n_current_controlees: Number of elements in the list of current
* controlees.
*/
size_t n_current_controlees;
/**
* @measurements: Measurement configurations which influence diagnostics.
*/
struct {
/**
* @sequence: Copy of the meas_seq parameter on get_access
* event.
*/
struct fira_measurement_sequence sequence;
/**
* @index: Index of the step in sequence array.
*/
int index;
/**
* @n_achieved: Number of measurements done inside a step.
*/
int n_achieved;
/**
* @n_total_achieved: Total number of measurements done.
*/
int n_total_achieved;
/**
* @reset: True when new parameters have to be retrieved.
*/
bool reset;
} measurements;
/**
* @rx_ctx: Custom rx context for all controlees.
*/
void *rx_ctx[FIRA_CONTROLEES_MAX];
/**
* @crypto: crypto related variables.
*/
struct fira_crypto *crypto;
/**
* @sts: sts related variables.
*/
struct {
/**
* @phy_sts_index_init: Initial phy_sts_index deduced at context init.
*/
u32 phy_sts_index_init;
/**
* @last_rotation_block_index: index to the last block where the
* rotation occurred.
*/
u32 last_rotation_block_index;
} sts;
/*
* @last_error: last error that occurred during the active session.
*/
int last_error;
};
/**
* struct fira_session_demand - Next access information for one FiRa session.
*/
struct fira_session_demand {
/**
* @block_start_dtu: Block start in dtu.
*/
u32 block_start_dtu;
/**
* @timestamp_dtu: Access timestamp in dtu.
*/
u32 timestamp_dtu;
/**
* @max_duration_dtu: Maximum duration for the access.
*/
int max_duration_dtu;
/**
* @add_blocks: Number of block to add.
*/
int add_blocks;
/**
* @round_index: Round index to apply for the access.
*/
int round_index;
/**
* @rx_timeout_dtu: timeout to apply when first frame of the controlee.
*/
int rx_timeout_dtu;
};
/**
* struct fira_report_info - Report information for all peer.
*/
struct fira_report_info {
/**
* @ranging_data: Base address of ranging data per peer, or null
* pointer.
*/
const struct fira_ranging_info *ranging_data;
/**
* @n_ranging_data: Number of entry in ranging_data above.
*/
size_t n_ranging_data;
/**
* @stopped_controlees: NULL, or short address of all stopped controlees.
*/
const __le16 *stopped_controlees;
/**
* @n_stopped_controlees: Number of controlees stopped in array above.
*/
size_t n_stopped_controlees;
/**
* @diagnostics: Array of diagnostic collected per slots.
*/
const struct fira_diagnostic *diagnostics;
/**
* @slots: Array of information slots.
*/
const struct fira_slot *slots;
/**
* @n_slots: Number of slots above.
*/
size_t n_slots;
/**
* @stopped: True when the session is stopped.
*/
bool stopped;
};
/**
* fira_session_new() - Create a new session.
* @local: FiRa context.
* @session_id: Session identifier, must be unique.
*
* Return: The new session or NULL on error.
*/
struct fira_session *fira_session_new(struct fira_local *local, u32 session_id);
/**
* fira_session_free() - Remove a session.
* @local: FiRa context.
* @session: Session to remove, must be inactive.
*/
void fira_session_free(struct fira_local *local, struct fira_session *session);
/**
* fira_session_set_controlees() - Set controlees.
* @local: FiRa context.
* @session: Session.
* @controlees: List of controlees.
* @n_controlees: Number of controlees.
*
* Return: 0 or error.
*/
int fira_session_set_controlees(struct fira_local *local,
struct fira_session *session,
struct list_head *controlees, int n_controlees);
/**
* fira_session_new_controlees() - Add new controlees.
* @session: Session.
* @controlees: List of controlees to add.
* @n_controlees: Number of controlees.
* @async: True is the controlees must be added asynchronously.
*
* Return: 0 or error.
*/
int fira_session_new_controlees(struct fira_session *session,
struct list_head *controlees, int n_controlees,
bool async);
/**
* fira_session_restart_controlees() - Restart controlee and erase pending del.
* @session: FiRa session context.
*
* Return: Number of controlee removed.
*/
void fira_session_restart_controlees(struct fira_session *session);
/**
* fira_session_del_controlees() - Delete controlees.
* @session: Session.
* @controlees: List of controlees to delete.
* @async: True is the controlees must be deleted asynchronously.
*
* Return: 0 or error.
*/
int fira_session_del_controlees(struct fira_session *session,
struct list_head *controlees, bool async);
/**
* fira_session_stop_controlees() - Stop controlees.
* @session: Session.
*/
void fira_session_stop_controlees(struct fira_session *session);
/**
* fira_session_controlees_running_count() - Get the number of running controlees.
* @session: Session.
*
* Return: Number of running controlees.
*/
int fira_session_controlees_running_count(const struct fira_session *session);
/**
* fira_session_update_controlees() - Update controlee's states.
* @local: FiRa context.
* @session: Session to test.
*/
void fira_session_update_controlees(struct fira_local *local,
struct fira_session *session);
/**
* fira_session_is_ready() - Test whether a session is ready to be started.
* @local: FiRa context.
* @session: Session to test.
*
* Return: true if the session can be started.
*/
bool fira_session_is_ready(const struct fira_local *local,
const struct fira_session *session);
/**
* fira_session_get_meas_seq_step() - Get current measurement step.
* @session: Session.
*
* Return: Current Measurement Sequence step for given session.
*/
static inline const struct fira_measurement_sequence_step *
fira_session_get_meas_seq_step(const struct fira_session *session)
{
const struct fira_measurement_sequence *seq =
&session->measurements.sequence;
return &seq->steps[session->measurements.index];
}
/**
* fira_session_get_rx_ant_set() - Get Rx antenna set for a given message ID.
* @session: Session.
* @message_id: Message ID of FiRa frame.
*
* Return: Adequate antenna set id for given frame and session parameters.
*/
static inline int
fira_session_get_rx_ant_set(const struct fira_session *session,
enum fira_message_id message_id)
{
const struct fira_session_params *params = &session->params;
const struct fira_measurement_sequence_step *step =
fira_session_get_meas_seq_step(session);
if (message_id > FIRA_MESSAGE_ID_RFRAME_MAX)
return step->rx_ant_set_nonranging;
/* TODO: replace this test by device_role == FIRA_DEVICE_ROLE_INITIATOR
* as soon as this feature is supported */
if (params->device_type == FIRA_DEVICE_TYPE_CONTROLLER)
return step->rx_ant_sets_ranging[0];
else
switch (step->type) {
case FIRA_MEASUREMENT_TYPE_RANGE:
case FIRA_MEASUREMENT_TYPE_AOA:
case FIRA_MEASUREMENT_TYPE_AOA_AZIMUTH:
case FIRA_MEASUREMENT_TYPE_AOA_ELEVATION:
return step->rx_ant_sets_ranging[0];
case FIRA_MEASUREMENT_TYPE_AOA_AZIMUTH_ELEVATION:
return step->rx_ant_sets_ranging
[message_id == FIRA_MESSAGE_ID_RANGING_FINAL];
default:
return -1;
}
return -1;
}
/**
* fira_session_report() - Report state change and ranging result for a session.
* @local: FiRa context.
* @session: Session to report.
* @report_info: report information to exploit for the reporting.
*/
void fira_session_report(struct fira_local *local, struct fira_session *session,
const struct fira_report_info *report_info);
/**
* fira_session_controlee_active() - Return whether the controlee is currently active.
* @controlee: Controlee.
*
* Return: True if the controlee is currently active.
*/
static inline bool
fira_session_controlee_active(struct fira_controlee *controlee)
{
switch (controlee->state) {
case FIRA_CONTROLEE_STATE_RUNNING:
case FIRA_CONTROLEE_STATE_PENDING_STOP:
case FIRA_CONTROLEE_STATE_PENDING_DEL:
return true;
default:
return false;
}
}
#endif /* NET_MCPS802154_FIRA_SESSION_H */