yincheng.zhong
2024-08-20 7744fffacb03dc81cc9dbaf9f5d86a0f21e79c03
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
/*
 * Copyright (c) 2019-2023 Beijing Hanwei Innovation Technology Ltd. Co. and
 * its subsidiaries and affiliates (collectly called MKSEMI).
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into an MKSEMI
 *    integrated circuit in a product or a software update for such product,
 *    must reproduce the above copyright notice, this list of conditions and
 *    the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of MKSEMI nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    MKSEMI integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be
 *    reverse engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY MKSEMI "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL MKSEMI OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#ifndef LIB_FIRA_H_
#define LIB_FIRA_H_
#include "mk_common.h"
#include "mk_uwb.h"
#include "uwb_api.h"
#include "uwb_fira_message.h"
#include "wsf_msg.h"
 
/**
 * @addtogroup MK8000_FIRA_LIB
 * @{
 */
 
/// Static STS session key
#define SESSION_KEY_STATIC_STS "StaticTSStaticTS"
 
/// Dynamic STS session key for test
#define SESSION_KEY_DYNAMIC_STS_TEST "DynamicSTSNoRot0"
 
// the index to store slot of message in responder_slot_idx[]
#define SLOT_RESPONSE 0
#define SLOT_FINAL 1
#define SLOT_REPORT 2
#define SLOT_RESULT 3
 
/** STS config definition */
enum FIRA_STS_CFG_T
{
    FIRA_STATIC_STS = 0, /*!< static sts config */
    FIRA_DYNAMIC_STS = 1 /*!< dynamic sts config */
};
 
/** FiRa message type */
enum FIRA_MSG_TYPE_T
{
    FIRA_MSG_RANG_INIT = 0x0,      /*!< Ranging Initiation Message */
    FIRA_MSG_RANG_RESP = 0x1,      /*!< Ranging Response Message */
    FIRA_MSG_RANG_FINAL = 0x2,     /*!< Ranging Final Message */
    FIRA_MSG_CONTROL = 0x3,        /*!< Control Message */
    FIRA_MSG_MEASURE_RPT = 0x4,    /*!< Measurement Report Message */
    FIRA_MSG_RESULT_RPT = 0x5,     /*!< Ranging Result Report Message */
    FIRA_MSG_CONTROL_UPDATE = 0x6, /*!< Control Update Message*/
    FIRA_MSG_OWR = 0x7,            /*!< OWR Message*/
    FIRA_MSG_DM = 0x8,             /*!< Data Message*/
};
 
/** General key data structure */
struct FIRA_KEY_T
{
    union
    {
        uint8_t keyByte[16];
        uint32_t keyWord[4];
    } ukey;
};
 
/** Fira UWB session configuration, used for key derivation */
struct FIRA_SESSSION_CFG_T
{
    uint8_t rgMethod;
    uint8_t firaStsCfg;
    uint8_t multiMode;
    uint8_t chan;
    uint8_t slotDur[2]; /* NOTE: saved as big endian, uint: us (RSTU*416/499.2) */
    uint8_t fcsType;
    uint8_t spCfg;
    uint8_t preCidx;
    uint8_t sfdId;
    uint8_t dataRate;
    uint8_t preLen;
    uint8_t macCfg;
    uint8_t sessionId[4]; /* NOTE: saved as big endian */
};
 
/** FiRa key list */
struct FIRA_KEY_LIST_T
{
    struct FIRA_KEY_T sessKey;
    struct FIRA_KEY_T dataProKey;
    struct FIRA_KEY_T devAuthIv;
    struct FIRA_KEY_T devAuthKey;
    struct FIRA_KEY_T devPayKey;
    struct FIRA_KEY_T privacyKey;
    uint32_t phyStsIdxInit;
    uint8_t digest[16];     /* store the calculated digest result to avoid calculate again, need to update when session cfg changed */
    uint8_t staticStsIv[6]; /* transferred over UCI */
    uint8_t vendorId[2];    /* transferred over UCI */
};
 
/** Responder node structure */
struct RESPONDER_NODE_T
{
    uint8_t addr_is_valid; /* 0 is invalid, 1 is valid */
    uint8_t main_ant_id;
    uint16_t short_add;
};
 
/** FiRa ranging environment variable */
struct RANGING_ENV_T
{
    int64_t tx_poll_time;
    int64_t tx_response_time;
    int64_t tx_final_time;
    int64_t rx_poll_time;
    int64_t rx_response_time[RESPONDER_NUM_MAX];
    int64_t rx_final_time;
    uint8_t slot_bitmap_tx[BIT_MAP_SIZE_MAX];
    uint8_t slot_bitmap_rx[BIT_MAP_SIZE_MAX];
 
    uint32_t anchor_point;
    uint32_t ranging_period;
    uint32_t round_duration;
    uint32_t round_offset_in_block;
    uint32_t slot_interval;
    uint32_t phy_sts_index;
    uint32_t tof;
 
    uint32_t uwb_period_prefetch_time;
    uint32_t uwb_evt_prefetch_time;
    uint32_t uwb_rx_open_in_advance;
    uint32_t uwb_rx_window;
    uint32_t uwb_rx_open_in_advance_wakeup;
    uint32_t uwb_rx_window_wakeup;
 
    uint32_t random_num[10];
    int32_t freq_offset_filter;
 
    uint8_t lost_cnt;
    uint8_t enable;
    uint8_t slot_idx;
    uint8_t responder_num;
    struct RESPONDER_NODE_T responder_list[RESPONDER_NUM_MAX];
    uint8_t responder_slot_idx[4];
    uint32_t responder_response_flag;
    uint16_t result_flag; // responder_idx || status (1: update, 2: complete)
    uint8_t rcm_flag;
    uint8_t repeat;
    uint16_t slots_per_block;
    uint8_t count;
    uint8_t count_last;
 
    uint8_t is_hopping;
    uint8_t stride_length;
    uint16_t curr_round_index;
    uint16_t next_round_index;
    uint16_t nround_inblock;
#if FIRA_TEST_EN
    uint16_t num_of_measure;
#endif
    struct RANGE_DATA_T range_data;
};
 
/** UWB packet TX done indication */
struct UWB_PKT_TX_DONE_IND_T
{
    wsfMsgHdr_t hdr;
#if MCTT_TEST_EN
    uint32_t timestamp;
    uint32_t phy_shr_duration;
#endif
    uint8_t ranging_stage;
    uint8_t slot_idx;
    uint16_t status;
    uint16_t tx_len;
    uint8_t tx_data[];
};
 
/** UWB packet RX done indication */
struct UWB_PKT_RX_DONE_IND_T
{
    wsfMsgHdr_t hdr;
#if MCTT_TEST_EN
    uint32_t timestamp;
    uint32_t phy_header;
#endif
    uint8_t slot_idx;
    uint8_t ranging_stage;
    uint16_t status;
    int8_t rssi;
    int8_t snr;
    uint16_t rx_len;
    uint8_t rx_data[];
};
 
#ifdef __cplusplus
extern "C" {
#endif
 
extern struct FIRA_SESSSION_CFG_T session_config;
extern struct FIRA_KEY_LIST_T fira_key;
 
extern struct RANGING_ENV_T ranging_env;
extern uint8_t fira_uwb_tx_buf[PHY_PAYLOAD_LEN_MAX];
 
extern uint8_t *tx_msg;
extern uint16_t tx_msg_len;
 
/**
 * @brief Calculate timestamp difference.
 * @param[in] ts_a          Ranging timestamp a
 * @param[in] ts_b          Ranging timestamp b
 * @return ts_a - ts_b
 */
int64_t ranging_timestamp_diff(int64_t ts_a, int64_t ts_b);
 
/**
 * @brief Calculate ranging Tround.
 * @param[in] role          Device role @enum DEV_ROLE_T
 * @param[in] dev_idx       Device index in one-to-many case
 * @return Tround value, unit: 15.6ps
 */
int64_t ranging_tround(enum DEV_ROLE_T role, uint8_t dev_idx);
 
/**
 * @brief Calculate ranging Treply.
 * @param[in] role          Device role @enum DEV_ROLE_T
 * @param[in] dev_idx       Device index in one-to-many case
 * @return Treply value, unit: 15.6ps
 */
int64_t ranging_treply(enum DEV_ROLE_T role, uint8_t dev_idx);
 
/**
 * @brief Set local device short address.
 * @param[in] short_addr          Device short address
 */
void ranging_local_addr_set(uint16_t short_addr);
 
/**
 * @brief Set peer device short address.
 * @param[in] short_addr          Device short address
 */
void ranging_peer_addr_set(uint16_t short_addr);
 
/**
 * @brief Get initiator short address.
 * @return short address of initiator
 */
uint16_t ranging_initiator_addr_get(void);
 
/**
 * @brief Add responder device into responder device list for one-to-many case.
 * @param[in] addr              Device short address
 * @return 1: successful, 0: fail
 */
uint8_t ranging_responder_addr_add(uint16_t addr);
 
/**
 * @brief Clear responder list.
 */
void ranging_responder_list_clr(void);
 
/**
 * @brief Dynamic Update of Multicast List for Controlees
 * @param[in] action            0x00: Update the multicast list by adding requested controlee short address
 *                              0x01: Delete the requested short address from multicast list
 * @param[in] addr              Device short address
 * @return 0x01: successful, 0x07: short address is not found, 0x08: short address is already present
 */
uint8_t ranging_dynamic_update_respoder_list(uint8_t action, uint16_t addr);
 
/**
 * @brief Get responder short address from responder device list.
 * @param[in] idx               Responder device index
 * @return short address of responder
 */
uint16_t ranging_responder_addr_get(uint8_t idx);
 
/**
 * @brief Get responder devices number.
 * @return number of responder
 */
uint8_t ranging_responder_num_get(void);
 
/**
 * @brief Update ranging slot index, based on this informantion to generate STS or encryted packet every slot.
 * @param[in] slot_idx              Slot index
 */
void ranging_update_slot_index(uint32_t slot_idx);
 
/**
 * @brief Get the current block index.
 * @return Block index value
 */
uint32_t ranging_get_block_index(void);
 
/**
 * @brief Get the current round index.
 * @return Round index value
 */
uint16_t ranging_get_curr_round_index(void);
 
/**
 * @brief Get the next round index.
 * @param[in] session_id              Fira Ranging session Id
 * @param[in] block_index             Block index
 * @return Next block index value
 */
uint16_t ranging_get_next_round_index(uint32_t session_id, uint32_t block_index);
 
/**
 * @brief Callback function for PHY timer, to program MAC TX or RX event in advance.
 * @param[in] dev                   Pointer of timer device
 * @param[in] time                  Last time setting
 */
void session_timer_callback(void *dev, uint32_t time);
 
/**
 * @brief Session FSM, to process MAC TX or RX done event in MAC interrupt handler.
 * @param[in] ind                   Pointer of MAC HW report
 * @return next ranging stage
 */
enum RANGING_STAGE_T session_fsm(const struct MAC_HW_REPORT_T *ind);
 
/**
 * @brief Indicate UWB packet TX done.
 * @param[in] tx                Pointer of MAC HW report for TX
 * @param[in] stage             Stage of ranging FSM @enum RANGING_STAGE_T
 * @param[in] slot_idx          Slot index
 */
void uwb_pkt_tx_done_ind(const struct MAC_HW_REPORT_T *tx, enum RANGING_STAGE_T stage, uint8_t slot_idx);
 
/**
 * @brief Indicate UWB packet RX done.
 * @param[in] rx                Pointer of MAC HW report for RX
 * @param[in] stage             Stage of ranging FSM @enum RANGING_STAGE_T
 * @param[in] slot_idx          Slot index
 * @return RX status
 */
uint16_t uwb_pkt_rx_done_ind(const struct MAC_HW_REPORT_T *rx, enum RANGING_STAGE_T stage, uint8_t slot_idx);
 
/**
 * @brief Generate FiRa ranging session configuration.
 * @param[out] pFiraSesscfg          Pointer of FiRa session configuration
 * @param[in] pFiraUwbcfg            Pointer of FiRa UWB configuration
 */
void fira_session_cfg_generate(struct FIRA_SESSSION_CFG_T *pFiraSesscfg, struct UWB_APP_CFG_T *pFiraUwbcfg);
 
/**
 * @brief Generate FiRa ranging keys.
 * @param[out] pFiraKeyList          Pointer of FiRa ranging key list
 * @param[in] pFiraSesscfg           Pointer of FiRa session configuration
 * @param[in] stsCfg                 Static STS or dynamic STS @enum FIRA_STS_CFG_T
 * @param[in] pSessionKey            Pointer of ranging session key
 */
void fira_key_list_generate(struct FIRA_KEY_LIST_T *pFiraKeyList, struct FIRA_SESSSION_CFG_T *pFiraSesscfg, enum FIRA_STS_CFG_T stsCfg, uint8_t *pSessionKey);
 
/**
 * @brief Update STS key configuration
 * @param[in] firaStsCfg             Static STS or dynamic STS @enum FIRA_STS_CFG_T
 * @param[in] pFiraKeyList           Pointer of FiRa ranging key list
 * @param[in] write_en               Write updated STS configuration to registers directly, for dynamic STS key rotation
 */
void fira_sts_keys_update(enum FIRA_STS_CFG_T firaStsCfg, struct FIRA_KEY_LIST_T *pFiraKeyList, uint8_t write_en);
 
/**
 * @brief Generate FiRa keys.
 * @note The fira key is generated by session_config and fira_key global variables.
 */
void fira_keys_generate(void);
 
/**
 * @brief Rotation FiRa key.
 * @param[in] pFiraKeyList           Pointer of FiRa ranging key list
 * @param[in] cryptoStsIdx           PHY STS index, +1 every slot
 */
void fira_key_rotation(struct FIRA_KEY_LIST_T *pFiraKeyList, uint32_t cryptoStsIdx);
 
/**
 * @brief Encrypt vendor IE data.
 * @param[in] input             Plaintext of vendor IE data
 * @param[out] output           Cyphertext of vendor IE data
 */
void fira_vendor_ie_encrypt(uint8_t *input, uint8_t *output);
 
/**
 * @brief Decrypt vendor IE data.
 * @param[in] input             Cyphertext of vendor IE data
 * @param[out] output           Plaintext of vendor IE data
 */
void fira_vendor_ie_decrypt(uint8_t *input, uint8_t *output);
 
/**
 * @brief Decrypt vendor IE data to get phyStsIndex for Dynamic STS case.
 * @param[in] rx_buf            Pointer of RX buffer
 */
uint32_t fira_vendor_oui_process(uint8_t *rx_buf);
 
/**
 * @brief Encrypt payload data.
 * @param[in] input             Plaintext of payload data
 * @param[out] output           Cyphertext of payload data
 * @param[in] input_len         Input data total length
 * @param[in] associate_len     Authentication data length
 * @param[in] sec_lvl           Security level
 * @param[in] slot_idx          Slot index
 */
uint16_t RAM_FUNC fira_packet_encrypt(uint8_t *input, uint8_t *output, uint16_t input_len, uint16_t associate_len, uint8_t sec_lvl, uint32_t slot_idx);
 
/**
 * @brief Decrypt payload data.
 * @param[in] input             Cyphertext of payload data
 * @param[out] output           Plaintext of payload data
 * @param[in] input_len         Input data total length
 * @param[in] slot_idx          Slot index
 */
uint16_t fira_packet_decrypt(uint8_t *input, uint8_t *output, uint16_t input_len, uint32_t slot_idx);
 
#ifdef __cplusplus
}
#endif
 
/**
 * @}
 */
 
#endif /* LIB_FIRA_H_ */