openaliro
Aliro reader: UWB/CCC core and ESP32-S3/C5/C6 port
Loading...
Searching...
No Matches
ccc_shim.h File Reference

— map a per-frame STS index to the (dURSK, STS-V) pair the DW3000 STS engine loads. More...

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "ccc_kdf.h"
Include dependency graph for ccc_shim.h:

Go to the source code of this file.

Macros

#define WOZ_CCC_PREPOLL_LISTEN   1
 BENCH toggle — run the standalone SP0 Pre-POLL listener instead of the FiRa session.
 

Functions

int ccc_shim_bind (const uint8_t mursk[CCC_MURSK_LEN], const uint8_t salted_hash[CCC_SALTED_HASH_LEN], uint32_t sts_index0, uint16_t n_slot_per_round)
 Bind the shim to a ranging session's derived key material.
 
int ccc_shim_bind_from_ursk (const uint8_t ursk[CCC_URSK_LEN], const uint8_t *ranging_config, size_t rc_len, uint32_t sts_index0, uint16_t n_slot_per_round)
 Bind the shim, deriving mURSK + SaltedHash from the URSK + RangingConfiguration.
 
void ccc_shim_unbind (void)
 Unbind the shim; ccc_shim_active returns false afterward.
 
bool ccc_shim_active (void)
 Whether the per-frame STS interception is live (bound AND not suspended).
 
void ccc_shim_suspend (bool suspend)
 Suspend/resume the per-frame IV wrap without unbinding.
 
int ccc_shim_sts_for_index (uint32_t sts_index, uint8_t dursk[CCC_DURSK_LEN], uint8_t sts_v[CCC_STS_V_LEN])
 Map a per-frame STS index to its CCC dURSK (per-cycle) + STS-V (per-PPDU).
 
int ccc_shim_dudsk_for_index (uint32_t sts_index, uint8_t dudsk[CCC_DUDSK_LEN])
 Derive the dUDSK (per-cycle Final_Data key) for the ranging cycle containing sts_index.
 
int ccc_shim_sts_for_slot (uint32_t slot, uint8_t dursk[CCC_DURSK_LEN], uint8_t sts_v[CCC_STS_V_LEN])
 Map a ranging-slot offset (STS_Index0 + slot) to its CCC dURSK + STS-V.
 
uint32_t ccc_shim_index_from_iv (const uint8_t iv16[16])
 Extract the STS index the blob packed into a DW3000 STS IV (index at bytes 7..4).
 
uint32_t ccc_shim_blob_to_ccc_index (uint32_t blob_idx, uint32_t *block, uint32_t *sub)
 Map the blob's raw provisioned STS index to a CCC-schedule STS index (origin/stride auto-calibrated from the first two indices).
 
void ccc_shim_pin_index (uint32_t ccc_index)
 Pin the substituted STS to one fixed CCC index (bench validation).
 
void ccc_shim_unpin (void)
 Release the debug pin; STS resumes advancing with the blob index.
 
void ccc_shim_wrap_log_reset (void)
 Reset the wrap's first-N-frame IV log budget (target only).
 
void ccc_shim_rx_log_reset (void)
 Reset the responder-RX wrap's first-N-arm log budget (target only).
 
void ccc_shim_rx_notify_rx (uint32_t status)
 Feed each RX event's status word to the empirical STS-index tracker (target only).
 
void ccc_shim_rx_try_prepoll (uint16_t datalength)
 Decode a received SP0 Pre-POLL frame to read Apple's exact POLL STS index (target only).
 
bool ccc_shim_rx_awaiting_poll (void)
 True while an SP3 POLL RX is armed (the next RX-good event is its result).
 
bool ccc_shim_rx_deadline_pending (void)
 True while the responder still owes the current ranging block a radio event: an armed POLL RX (a few slots out) or an armed Final RX (~2 ms out).
 
bool ccc_shim_rx_awaiting_final (void)
 True while an SP3 Final RX is armed.
 
int ccc_prepoll_listen (uint8_t channel, uint8_t preamble_code)
 BENCH: bring up a raw continuous SP0 receiver for the CCC Pre-POLL (target only).
 
int ccc_prepoll_prewarm (uint8_t channel, uint8_t preamble_code)
 Pre-apply the expected session PHY (radio configured, TRX off, RX not armed) so a following ccc_prepoll_listen() with the same params skips the dwt_configure long pole.
 
void ccc_prepoll_stop (void)
 Stop the Pre-POLL listener: close the self-rearm listen-gate, then force the radio off (target only).
 
uint32_t ccc_shim_sts_index0 (void)
 The bound session's STS_Index0 (for UAD/Pre-POLL derivation); 0 if unbound.
 

Detailed Description

— map a per-frame STS index to the (dURSK, STS-V) pair the DW3000 STS engine loads.

Function Documentation

◆ ccc_shim_bind()

int ccc_shim_bind ( const uint8_t  mursk[CCC_MURSK_LEN],
const uint8_t  salted_hash[CCC_SALTED_HASH_LEN],
uint32_t  sts_index0,
uint16_t  n_slot_per_round 
)

Bind the shim to a ranging session's derived key material.

Parameters
murskmURSK bytes.
salted_hashSaltedHash bytes.
sts_index0Initial STS index for this session.
n_slot_per_roundSlots per ranging cycle.
Returns
0 on success; -EINVAL if any input is invalid.

◆ ccc_shim_bind_from_ursk()

int ccc_shim_bind_from_ursk ( const uint8_t  ursk[CCC_URSK_LEN],
const uint8_t *  ranging_config,
size_t  rc_len,
uint32_t  sts_index0,
uint16_t  n_slot_per_round 
)

Bind the shim, deriving mURSK + SaltedHash from the URSK + RangingConfiguration.

Bind the shim, deriving mURSK + SaltedHash from the URSK + RangingConfiguration.

Parameters
ursk256-bit URSK input key.
ranging_configSerialized ranging configuration bytes (may be NULL if rc_len is 0).
rc_lenLength of ranging_config in bytes.
sts_index0Initial STS index for this session.
n_slot_per_roundSlots per ranging cycle.
Returns
0 on success; propagated error from derivation otherwise.

◆ ccc_shim_blob_to_ccc_index()

uint32_t ccc_shim_blob_to_ccc_index ( uint32_t  blob_idx,
uint32_t *  block,
uint32_t *  sub 
)

Map the blob's raw provisioned STS index to a CCC-schedule STS index (origin/stride auto-calibrated from the first two indices).

Map the blob's raw provisioned STS index to a CCC-schedule STS index (origin/stride auto-calibrated from the first two indices).

Parameters
blob_idxBlob provisioned STS index.
blockOutput pointer receiving the ranging-cycle block index (may be NULL).
subOutput pointer receiving the intra-block sub-offset (may be NULL).
Returns
CCC-space STS index.

◆ ccc_shim_dudsk_for_index()

int ccc_shim_dudsk_for_index ( uint32_t  sts_index,
uint8_t  dudsk[CCC_DUDSK_LEN] 
)

Derive the dUDSK (per-cycle Final_Data key) for the ranging cycle containing sts_index.

Derive the dUDSK (per-cycle Final_Data key) for the ranging cycle containing sts_index.

Parameters
sts_indexSTS index in the ranging schedule.
dudskOutput buffer receiving dUDSK.
Returns
0 on success; -EINVAL if shim is not active or dudsk is NULL.

◆ ccc_shim_index_from_iv()

uint32_t ccc_shim_index_from_iv ( const uint8_t  iv16[16])

Extract the STS index the blob packed into a DW3000 STS IV (index at bytes 7..4).

Extract the STS index the blob packed into a DW3000 STS IV (index at bytes 7..4).

Parameters
iv1616-byte STS IV.
Returns
STS index.

◆ ccc_shim_pin_index()

void ccc_shim_pin_index ( uint32_t  ccc_index)

Pin the substituted STS to one fixed CCC index (bench validation).

Parameters
ccc_indexCCC index to pin for all subsequent frames.

◆ ccc_shim_rx_awaiting_final()

bool ccc_shim_rx_awaiting_final ( void  )

True while an SP3 Final RX is armed.

Sample it BEFORE chaining to the blob's RX handler and it says "the reception being serviced IS the Final" — the handler clears the flag and immediately re-arms an SP0 listen. That pre-chain instant is the only point in a ranging block where the radio is idle: no auto-re-enable is configured, so a completed RX leaves the DW3000 in IDLE until the shim arms the next one. The accumulator can only be read there. Reading it after the re-arm returns a fixed non-physical blob, byte-identical at every offset — the receiver is overwriting the accumulator underneath the read (bench runs 2-4, and cir probe shows a clean, correctly-addressed, repeatable window once the session ends). Target only.

True while an SP3 Final RX is armed.

◆ ccc_shim_rx_awaiting_poll()

bool ccc_shim_rx_awaiting_poll ( void  )

True while an SP3 POLL RX is armed (the next RX-good event is its result).

Target only.

True while an SP3 POLL RX is armed (the next RX-good event is its result).

Returns
true if awaiting POLL, false otherwise.

◆ ccc_shim_rx_deadline_pending()

bool ccc_shim_rx_deadline_pending ( void  )

True while the responder still owes the current ranging block a radio event: an armed POLL RX (a few slots out) or an armed Final RX (~2 ms out).

Sample it AFTER chaining to the blob's RX handler and it names the reception just serviced: only the Final leaves it false, with the whole ~192 ms inter-block gap as slack. Diagnostics that need a long SPI burst (the windowed-CIR read) must run only then — bench-proven to cost the round otherwise. Target only.

True while the responder still owes the current ranging block a radio event: an armed POLL RX (a few slots out) or an armed Final RX (~2 ms out).

◆ ccc_shim_rx_log_reset()

void ccc_shim_rx_log_reset ( void  )

Reset the responder-RX wrap's first-N-arm log budget (target only).

Reset the responder-RX wrap's first-N-arm log budget (target only).

◆ ccc_shim_rx_notify_rx()

void ccc_shim_rx_notify_rx ( uint32_t  status)

Feed each RX event's status word to the empirical STS-index tracker (target only).

Feed each RX event's status word to the empirical STS-index tracker (target only).

Parameters
statusDW3000 status register value.

◆ ccc_shim_rx_try_prepoll()

void ccc_shim_rx_try_prepoll ( uint16_t  datalength)

Decode a received SP0 Pre-POLL frame to read Apple's exact POLL STS index (target only).

Decode a received SP0 Pre-POLL frame to read Apple's exact POLL STS index (target only).

The decode only feeds the NEXT block's warm (the SP3 arm keys on the pre-warmed prediction, not this block's fresh index), so it has the ~190 ms idle to run in. Running it inline — on the single DW3000 workqueue, ahead of the queued POLL RX-OK callback — pushed the Response TX arm past its slot (dx-now < 0 => HPDWARN). So read the bytes now (cheap SPI), then:

  • bootstrap (no warm yet): decode inline to seed the first arm's STS — this block is not armed, so blocking its POLL is harmless;
  • steady state: mark pending; prepoll_rx_rearm runs prepoll_decode after the Response TX is armed. A pending decode orphaned by a missed POLL is flushed on the next Pre-POLL so the warm never goes more than one block stale.

◆ ccc_shim_sts_for_index()

int ccc_shim_sts_for_index ( uint32_t  sts_index,
uint8_t  dursk[CCC_DURSK_LEN],
uint8_t  sts_v[CCC_STS_V_LEN] 
)

Map a per-frame STS index to its CCC dURSK (per-cycle) + STS-V (per-PPDU).

Map a per-frame STS index to its CCC dURSK (per-cycle) + STS-V (per-PPDU).

Parameters
sts_indexSTS index in the ranging schedule.
durskOutput buffer receiving dURSK.
sts_vOutput buffer receiving STS-V.
Returns
0 on success; -EINVAL if shim is not active or output pointers are NULL.

◆ ccc_shim_sts_for_slot()

int ccc_shim_sts_for_slot ( uint32_t  slot,
uint8_t  dursk[CCC_DURSK_LEN],
uint8_t  sts_v[CCC_STS_V_LEN] 
)

Map a ranging-slot offset (STS_Index0 + slot) to its CCC dURSK + STS-V.

Map a ranging-slot offset (STS_Index0 + slot) to its CCC dURSK + STS-V.

Parameters
slotSlot offset from STS_Index0.
durskOutput buffer receiving dURSK.
sts_vOutput buffer receiving STS-V.
Returns
0 on success; -EINVAL if shim is not active.

◆ ccc_shim_suspend()

void ccc_shim_suspend ( bool  suspend)

Suspend/resume the per-frame IV wrap without unbinding.

Suspend/resume the per-frame IV wrap without unbinding.

Parameters
suspendTrue to suspend, false to resume.

◆ ccc_shim_wrap_log_reset()

void ccc_shim_wrap_log_reset ( void  )

Reset the wrap's first-N-frame IV log budget (target only).

Reset the wrap's first-N-frame IV log budget (target only).