summaryrefslogtreecommitdiff
path: root/cesar/bsu/src/interface.c
blob: d4f0c82c5b109bf4da44db3b16cba60b232bfb9d (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
110
111
112
113
114
/* Cesar project {{{
 *
 * Copyright (C) 2010 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    bsu/src/interface.c
 * \brief   BSU interface functions.
 * \ingroup bsu
 *
 * BSU interface functions with the SAR and upper layer.
 */
#include "common/std.h"
#include "hal/arch/arch.h"
#include "lib/fixed.h"
#include "lib/bitstream.h"
#include "bsu/bsu.h"
#include "bsu/inc/bsu.h"
#include "bsu/inc/context.h"

void
bsu_beacon_send_upper_layer (bsu_t *ctx, bsu_beacon_t *beacon,
                             bsu_beacon_direction_t direction)
{
    beacon->params.direction = direction;
    (*ctx->ul_cb) (ctx->ul_data, beacon);
}

/**
 * Get the MFS from the MAC store.
 * \param  ctx  the module context.
 * \param  type  the beacon type.
 * \return  the MFS.
 */
static inline mfs_tx_t*
bsu_beacon_send_mfs_get (bsu_t *ctx, bsu_beacon_type_t type)
{
    bool added;
    mfs_tx_t *mfs;
    /* Get lid from the beacon type. */
    switch (type)
    {
    case BSU_BEACON_TYPE_CENTRAL:
        mfs = mac_store_mfs_add_tx (ctx->mac_store, true, false,
                                    MAC_LID_SPC_CENTRAL, MAC_TEI_BCAST,
                                    &added);
        break;
    case BSU_BEACON_TYPE_DISCOVER:
        mfs = mac_store_mfs_add_tx (ctx->mac_store, true, false,
                                    MAC_LID_DISCOVER, MAC_TEI_BCAST,
                                    &added);
        break;
    default:
        dbg_assert_default ();
    }
    dbg_assert (mfs);
    ctx->mfs_beacons[type] = mfs;
    /* If the MFS is new, configure it. */
    if (added)
    {
        /* Highest priority for central beacon. */
        if (type == BSU_BEACON_TYPE_CENTRAL)
            mfs->cap = 0x3;
        else
            mfs->cap = 0x2;
        mfs->beacon = true;
        ca_mfs_add (ctx->ca, mfs);
    }
    return mfs;
}

void
bsu_beacon_send (bsu_t *ctx, bsu_beacon_type_t beacon_type,
                 pb_beacon_t *beacon, void *bto_bpsto)
{
    dbg_assert (ctx);
    dbg_assert (beacon);
    dbg_assert (beacon_type < BSU_BEACON_TYPE_NB);
    dbg_assert (bto_bpsto);
    dbg_assert (bitstream_direct_read (beacon->data, 32, 3) == beacon_type);
    mfs_tx_t *mfs = ctx->mfs_beacons[beacon_type];
    if (!mfs)
        mfs = bsu_beacon_send_mfs_get (ctx, beacon_type);
    /* Hold the segment until the next beacon period. Only for central
     * beacons. To be done each time, the CA only held until the next beacon
     * period it is not forever. */
    ctx->beacon_nb_sent[beacon_type]++;
    if (beacon_type == BSU_BEACON_TYPE_CENTRAL)
        ca_mfs_hold (ctx->ca, mfs);
    mfs->cfp = ctx->sta_avln->beacon.vf.hm == MAC_COEXISTENCE_AV_ONLY_MODE;
    /* Provide the beacon to the SAR. */
    sar_beacon_send (ctx->sar, beacon, mfs, bto_bpsto);
    BSU_TRACE (BEACON_SEND, phy_date (), beacon_type);
}

void
bsu_beacon_recv (bsu_t *ctx, pb_beacon_t *beacon,
                 pbproc_rx_beacon_params_t *params)
{
    dbg_assert (ctx);
    dbg_assert (beacon);
    dbg_assert (params);
    /* Load beacon into the cache. */
    arch_load_cache (&beacon->first_data_word, 1);
    arch_load_cache ((u32*) beacon->data, BLK_SIZE / 4);
    /* Process the beacon received from the SAR. */
    bsu_beacon_t *bsu_beacon = bsu_beacon_process (ctx, beacon, params);
    if (bsu_beacon)
        bsu_beacon_send_upper_layer (ctx, bsu_beacon,
                                     BSU_BEACON_DIRECTION_FROM_PLC);
    blk_release_desc ((blk_t*) beacon);
}