summaryrefslogtreecommitdiff
path: root/cesar/mac/pbproc/src/fsm_tx_rts_cts.c
blob: 00aa587f0806556fb45f81d4c6497ce616cf9687 (plain)
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
/* Maria project {{{
 *
 * Copyright (C) 2007 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    mac/pbproc/src/fsm_tx_rts_cts.c
 * \brief   FSM TX RTS CTS part.
 * \ingroup mac_pbproc
 */
#include "common/std.h"

#include "mac/pbproc/inc/context.h"
#include "mac/pbproc/inc/fc.h"

#include "mac/pbproc/inc/fsm_top.h"
#include "mac/pbproc/inc/fsm_tx_data.h"
#include "mac/pbproc/inc/fsm_tx_sound.h"
#include "mac/pbproc/inc/fsm_handle_fc.h"
#include "mac/pbproc/inc/prep_mpdu.h"

#include "mac/pbproc/inc/fsm_tx_rts_cts.h"

void
pbproc_ftrc_init (pbproc_t *ctx)
{
    dbg_assert (ctx);
    ctx->fsm.states[PBPROC_FSM_STATE_TX_WAIT_CTS].rx_fc_cb =
        CALLBACK (pbproc_ftrc__tx_wait_cts__rx_fc);
    ctx->fsm.states[PBPROC_FSM_STATE_TX_WAIT_CTS].access_cb =
        CALLBACK (pbproc_ftrc__tx_wait_cts__access);
}

void ARCH_ILRAM
pbproc_ftrc__handle (pbproc_t *ctx)
{
    dbg_claim (ctx);
    if (PHY_FC_MODE_IS_HYBRID (ctx->prep_mpdu.fc_mode))
        phy_tx_fc10 (ctx->phy, ctx->prep_mpdu.rts_tx_date,
                     ctx->prep_mpdu.fc10);
    phy_tx_param_short (ctx->phy, ctx->prep_mpdu.fc_mode);
    phy_tx_frame (ctx->phy, ctx->prep_mpdu.rts_tx_date, false, true,
                  ctx->prep_mpdu.rts_fc_av.words);
    ca_access_vcs_restart_eifs (ctx->ca, ctx->prep_mpdu.rts_tx_date);
    phy_rx_activate (ctx->phy, false,
                     ctx->prep_mpdu.rts_tx_date
                     + ctx->times.rts_rcg_tck, true);
    pbproc_fsm_change_state (ctx, PBPROC_FSM_STATE_TX_WAIT_CTS);
}

static void
pbproc_ftrc_tx_cancel (pbproc_t *ctx)
{
    dbg_claim (ctx);
    ctx->stats.rts_fail++;
    pbproc_prep_mpdu_t *prep = &ctx->prep_mpdu;
    if (prep->sound_reason_code != TONEMAP_SRC_NULL)
        pbproc_prep_mpdu_sound_ack (ctx, false);
    else
        pbproc_prep_mpdu_cancel_burst (ctx);
}

void ARCH_ILRAM_PRIO (2)
pbproc_ftrc__tx_wait_cts__rx_fc (pbproc_t *ctx, u32 rx_date,
                                 const pbproc_fc_t *fc_av)
{
    dbg_claim (ctx);
    /* Is it our CTS. */
    if (fc_av
        && fc_av->generic.dt_av == PBPROC_FC_DT_RTS_CTS
        && fc_av->rts_cts.rtsf == false
        && fc_av->generic.access == false
        && fc_av->generic.snid == ctx->alloc.snid
        && fc_av->rts_cts.stei == ctx->prep_mpdu.rts_fc_av.rts_cts.dtei
        && fc_av->rts_cts.dtei == ctx->config->tei
        && fc_av->rts_cts.lid == ctx->prep_mpdu.lid
        && less_mod2p32 (ctx->prep_mpdu.rts_tx_date + ctx->times.rts_rcg_tck
                         - MAC_TOLERANCE_TCK, rx_date)
        && !less_mod2p32 (ctx->prep_mpdu.rts_tx_date + ctx->times.rts_rcg_tck
                         + MAC_TOLERANCE_TCK, rx_date))
    {
        /* Prepare reception of FC only. Unblock the HW.*/
        phy_rx_prepare_short (ctx->phy);
        /* XXX Could add some checks, for duration for example. */
        /* Ok, now transmit data/sound. */
        if (ctx->prep_mpdu.sound_reason_code != TONEMAP_SRC_NULL)
            pbproc_ftso__handle (ctx);
        else
            pbproc_ftda__handle (ctx);
    }
    else
    {
        /* Not our CTS. */
        pbproc_fhfc_handle_fc (ctx, rx_date, fc_av);
        /* Cancel the transmission. */
        pbproc_ftrc_tx_cancel (ctx);
    }
}

void ARCH_ILRAM_PRIO (2)
pbproc_ftrc__tx_wait_cts__access (pbproc_t *ctx)
{
    dbg_claim (ctx);
    /* Cancel the transmission. */
    pbproc_ftrc_tx_cancel (ctx);
    pbproc_ftop__idle__access (ctx);
}