Files
kunlun/plc/halmac/beacon/rf_beacon_frame.c
2024-09-28 14:24:04 +08:00

656 lines
24 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "rf_beacon_frame.h"
#include "beacon_frame.h"
#include "beacon.h"
#include "iot_errno.h"
#include "mac_bcm_api.h"
#include "mac_data_api.h"
#include "mpdu_frame.h"
#include "mac_tx_hw.h"
#include "mac.h"
#include "mac_msg.h"
#include "mac_desc_engine.h"
#include "iot_crc.h"
#include "mac_cmn_hw.h"
#include "plc_fr.h"
#include "iot_io.h"
#include "mpdu_header.h"
#include "mac_crc.h"
#include "phy_txrx_pwr.h"
#include "plc_mac_cfg.h"
#include "mac_tx_power.h"
#include "tx_desc_reg_api.h"
#include "mac_reset.h"
#include "mac_rf_tx_hw.h"
#include "mac_rf.h"
#if HPLC_RF_DEV_SUPPORT
#include "rf_tx_mpdu_desc.h"
#include "mac_rf_common_hw.h"
#include "rf_rate_control.h"
#include "rf_hw_tonemap.h"
static uint8_t mac_rf_beacon_tx(uint32_t proto, mac_beacon_ctx_t *bcn,
iot_pkt_t* bcn_buf, uint8_t is_std_bcn, uint8_t is_csma_tx);
static void mac_rf_beacon_fill_fc_mcs_pb_idx(uint32_t proto, void *fc,
uint8_t mcs, uint8_t pb_sz_idx)
{
IOT_ASSERT(fc);
switch (proto) {
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
frame_control_t *sg_fc = (frame_control_t *)fc;
sg_fc->vf.rf_bcn.mcs = mcs & 0xf;
sg_fc->vf.rf_bcn.pb_sz_idx = pb_sz_idx & 0xf;
break;
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
spg_frame_control_t *spg_fc = (spg_frame_control_t *)fc;
spg_fc->vf.rf_bcn.mcs = mcs & 0xf;
spg_fc->vf.rf_bcn.pb_sz_idx = pb_sz_idx & 0xf;
break;
}
#endif
default:
(void)proto;
(void)fc;
(void)mcs;
(void)pb_sz_idx;
IOT_ASSERT(0);
break;
}
}
static uint32_t mac_rf_send_bcn(uint32_t proto, pdevid_t pdev_id,
iot_pkt_t* bcn_buf, uint8_t retry_cnt, uint32_t tx_power, uint32_t option,
uint8_t is_csma_tx, uint32_t phr_mcs)
{
rf_tx_mpdu_start *mpdu;
rf_tx_pb_start *pb_start;
rf_tx_dummy_node *rf_dummy;
rf_tx_mpdu_end *tx_status;
uint8_t fc_len = mac_get_mpdu_fc_len(proto);
uint32_t sw_buf_offset;
uint32_t hwq_id, swq_id;
uint32_t tx_fl = 0;
tx_fc_msg_t fc_info = { 0 };
mac_rf_pdev_t *rf_pdev = get_rf_pdev_ptr(pdev_id, RF_PDEV_ID);
mac_get_tx_msg_from_fc(proto, FC_DELIM_BEACON, iot_pkt_data(bcn_buf),
&fc_info);
/* get tx desc from mem pool */
BUILD_BUG_ON((sizeof(rf_tx_mpdu_start) == sizeof(tx_mpdu_start)) &&
(sizeof(rf_tx_mpdu_end) == sizeof(tx_mpdu_end)) &&
(sizeof(rf_tx_pb_start) == sizeof(tx_pb_start)) &&
(sizeof(rf_tx_dummy_node) == sizeof(tx_dummy_node)));
mac_desc_get(&g_mac_desc_eng, PLC_TX_MPDU_START_POOL, (void **)&mpdu);
mac_desc_get(&g_mac_desc_eng, PLC_TX_MPDU_END_POOL, (void **)&tx_status);
mac_desc_get(&g_mac_desc_eng, PLC_TX_PB_START_POOL, (void **)&pb_start);
mac_desc_get(&g_mac_desc_eng, PLC_TX_DUMMY_NODE_POOL, (void**)&rf_dummy);
if (!(mpdu && tx_status && pb_start && rf_dummy)) {
IOT_ASSERT(0);
return ERR_NOMEM;
}
/* get swq type id */
if (is_csma_tx) {
swq_id = mac_rf_q_get_swq_type(PLC_BCN_REGION_CSMA, LID_CSMA_CAP3, 0);
} else {
swq_id = mac_rf_q_get_swq_type(PLC_BCN_REGION_BCN, 0, 0);
}
/* check if swq type is support */
if (swq_id == MAX_MAC_RF_QUE_NUM) {
/* swq type error */
IOT_ASSERT(0);
}
/* check if the hwq already enabled */
hwq_id = mac_rf_q_get_hwqid(&rf_pdev->hwq_hdl, swq_id);
if (hwq_id == INV_MAC_HWQ_ID) {
/* hw queue is not enabled, try to alloc it */
hwq_id = mac_rf_q_alloc_hwq(&rf_pdev->hwq_hdl, MAC_RF_QUE_BCN);
}
/* fill in rf pb start */
mac_rf_tx_mpdu_fill_pb_start_info(pb_start,
(uint32_t)iot_pkt_pull(bcn_buf, fc_len), 0);
iot_pkt_push(bcn_buf, fc_len);
sw_buf_offset = 0;
/* fill rf phy header */
mac_rf_tx_mpdu_fill_phrinfo(mpdu,
proto,
FC_DELIM_BEACON,
fc_info.network_type,
fc_info.nid,
fc_info.bcn_period_cnt,
fc_info.src_tei,
0xfff,
fc_info.rf_mcs,
0,
fc_info.rf_pb_sz_idx, /* pb size index */
0, /* is retry */
0, /* is encry */
1 /* is bcast */);
/* fill dummy */
mac_rf_tx_mpdu_fill_dummy((rf_tx_dummy_node *)rf_dummy);
/* fill rf_mpdu_start */
mac_rf_tx_mpdu_fill_macinfo(mpdu, (rf_tx_mpdu_start *)rf_dummy,
pb_start, tx_status, proto, 0, retry_cnt, tx_power,
1, /* retry bit en */
0, /* is msdu */
1, /* pb buf reue */
0, /* tx desc reuse */
sw_buf_offset,
1, /* is list start */
0, /* is list end */
phr_mcs, /* fc mcs */
1, /* print timestamp in phy header */
0, /* print timestamp offset */
fc_info.rf_mcs, /* pld_mcs */
fc_info.rf_pb_sz_idx, /* pb size index */
1, /* crc32 enable */
0, /* crc32 offset */
hwq_id,
option, /* option */
1, /* pb num */
tx_fl /* tx_fl */);
return mac_rf_tx_hw_mpdu(&rf_pdev->hwq_hdl, hwq_id, mpdu);
}
#if SUPPORT_SMART_GRID
void mac_rf_simple_beacon_fill_buf_sg(mac_beacon_ctx_t *bcn, uint8_t **tmp)
{
/* fill in FC */
frame_control_t *fc = (frame_control_t*)(*tmp);
(*tmp) += sizeof(frame_control_t);
if (bcn->beacon_component_enable[MAC_BC_FC_INFO]) {
fc->delimiter_type = FC_DELIM_BEACON;
fc->network_type = bcn->fc.net_type;
fc->nid = bcn->fc.nid;
if (bcn->fc.is_rf) {
fc->vf.rf_bcn.time_stamp =
mac_sched_get_ntb((mac_vdev_t *)bcn->ref_vdev_ptr);
fc->vf.rf_bcn.src_tei = vdev_get_tei(bcn->ref_vdev_ptr);
} else {
IOT_ASSERT(0);
}
} else {
IOT_ASSERT(0);
}
/* fill in beacon payload fix header */
beacon_payload_simple_header_t *plh =
(beacon_payload_simple_header_t *)(*tmp);
(*tmp) += sizeof(beacon_payload_simple_header_t);
if (bcn->beacon_component_enable[MAC_BC_FIX_P]) {
plh->fixed_hdr.beacon_type = bcn->sg_uniq_bc_str.payload_header.type;
plh->fixed_hdr.sg_forming_complete =
bcn->sg_uniq_bc_str.payload_header.assoc_done;
plh->fixed_hdr.allow_assoc =
bcn->sg_uniq_bc_str.payload_header.allow_assoc;
plh->fixed_hdr.allow_chan_eval =
bcn->sg_uniq_bc_str.payload_header.allow_chan_eval;
plh->fixed_hdr.sg_forming_cnt =
bcn->sg_uniq_bc_str.payload_header.network_sn;
plh->fixed_hdr.beacon_seq_num =
bcn->sg_uniq_bc_str.payload_header.bc_period_cnt;
plh->fixed_hdr.simple_beacon =
bcn->sg_uniq_bc_str.payload_header.simple_beacon;
plh->fixed_hdr.auth_enable =
(uint8_t)bcn->sg_uniq_bc_str.payload_header.auth_enable;
iot_mac_addr_cpy(plh->fixed_hdr.cco_mac_addr,
bcn->sg_uniq_bc_str.payload_header.cco_addr);
plh->beacon_entry_num = 1;
} else {
IOT_ASSERT(0);
}
/* fill in rf simple param */
beacon_entry_simple_param_t *simple = NULL;
if (bcn->beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM]) {
simple = (beacon_entry_simple_param_t *)(*tmp);
(*tmp) += sizeof(beacon_entry_simple_param_t);
simple->beacon_entry_type = MAC_BCN_TYPE_ID_RF_SIMPLE_PARAM;
simple->beacon_entry_len = sizeof(*simple);
simple->tei = bcn->sg_uniq_bc_str.simple_param.tei;
simple->pco_tei = bcn->sg_uniq_bc_str.simple_param.pco_tei;
simple->role = bcn->sg_uniq_bc_str.simple_param.role;
simple->level = bcn->sg_uniq_bc_str.simple_param.level;
iot_mac_addr_cpy(simple->src_mac_addr,
bcn->sg_uniq_bc_str.simple_param.addr);
simple->rf_hop = bcn->sg_uniq_bc_str.simple_param.rf_hop;
simple->csma_start_ntb= bcn->sg_uniq_bc_str.simple_param.csma_start_ntb;
simple->csma_dur = bcn->sg_uniq_bc_str.simple_param.csma_dur;
simple->encrypt_mode = bcn->sg_uniq_bc_str.simple_param.encrypt_mode;
simple->encrypt_algo = bcn->sg_uniq_bc_str.simple_param.encrypt_algo;
simple->rsvd = bcn->sg_uniq_bc_str.simple_param.used_rsvd;
}
/* fill in vendor */
beacon_entry_vendor_spec_t *vendor;
beacon_entry_vendor_security_t *vendor_sec = NULL;
if (bcn->beacon_component_enable[MAC_BC_BMI_VENDOR_SPEC] &&
bcn->vendor.passcode_valid) {
plh->beacon_entry_num++;
vendor = (beacon_entry_vendor_spec_t *)(*tmp);
(*tmp) += sizeof(beacon_entry_vendor_spec_t);
os_mem_set(vendor, 0, sizeof(*vendor));
vendor->beacon_entry_type = MAC_BCN_TYPE_ID_VENDOR_SPEC;
vendor->beacon_entry_len = sizeof(*vendor);
vendor->power = bcn->vendor.power;
vendor->allowed_cco_tf_sr = bcn->vendor.allowed_cco_tf_sr;
vendor->proxy_select_dur = bcn->vendor.proxy_select_dur;
vendor->fixed_rate = bcn->vendor.fixed_rate;
vendor->pco_snr_rpt = bcn->vendor.pco_snr_rpt;
vendor->dm_tx_cfg = bcn->vendor.dm_tx_cfg;
vendor->cco_debug = bcn->vendor.cco_debug;
vendor->vendor_id = bcn->vendor.vendor_id;
plh->beacon_entry_num++;
/* add security related vendor entry */
vendor_sec = (beacon_entry_vendor_security_t *)(*tmp);
(*tmp) += sizeof(beacon_entry_vendor_security_t);
os_mem_set(vendor_sec, 0, sizeof(*vendor_sec));
vendor_sec->beacon_entry_type =
MAC_BCN_TYPE_ID_VENDOR_SECURITY;
vendor_sec->beacon_entry_len = sizeof(*vendor_sec);
vendor_sec->passcode = bcn->vendor.passcode;
}
}
uint32_t mac_rf_assemble_and_send_bcn_sg(mac_vdev_t *vdev, uint8_t is_std_tx,
uint8_t is_csma_tx)
{
if (MAC_RF_SEND_SIMPLE_BCN == is_std_tx) {
vdev->bcn_ctx.fc.is_rf = 1;
/* modify tidy beacon flag */
vdev->bcn_ctx.sg_uniq_bc_str.payload_header.simple_beacon = 1;
mac_bc_sta_cap_t *sta_cap = &vdev->bcn_ctx.sg_uniq_bc_str.sta_cap;
mac_bc_fp_t *pld_header = &vdev->bcn_ctx.sg_uniq_bc_str.payload_header;
mac_bc_simple_param_t *simple =
&vdev->bcn_ctx.sg_uniq_bc_str.simple_param;
simple->tei = sta_cap->tei;
simple->pco_tei = sta_cap->proxy;
simple->role = sta_cap->role;
simple->level = sta_cap->level;
simple->rf_hop = sta_cap->rf_hop;
simple->encrypt_mode = (uint8_t)pld_header->encrypt_mode;
simple->encrypt_algo = (uint8_t)pld_header->encrypt_algo;
iot_mac_addr_cpy(simple->addr, sta_cap->addr);
/* calculate csma start ntb and csma dur */
mac_bc_time_slot_t *ts = &vdev->bcn_ctx.time_slot;
uint32_t bc_slot_dur = ts->cco_bc_cnt * ts->bc_slot_dur;
uint32_t non_slot_dur = ts->non_cco_bc_info.bc_cnt * ts->bc_slot_dur;
uint32_t tdma_dur = (ts->cco_bc_cnt + ts->non_cco_bc_info.bc_cnt)
* ts->tdma_slot_dur;
/* calculate csma start ntb */
simple->csma_start_ntb = ts->bp_start_ntb + MAC_MS_TO_NTB(bc_slot_dur +
non_slot_dur + tdma_dur);
simple->csma_dur = 0;
/* calculate csma duration */
for (uint8_t i = 0; i < ts->csma_info.phase_cnt; i++) {
simple->csma_dur += (uint16_t)ts->csma_info.slot_dur[i];
}
vdev->bcn_ctx.beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM] = 1;
} else if (MAC_RF_SEND_STD_BCN == is_std_tx) {
vdev->bcn_ctx.fc.is_rf = 1;
/* modify tidy beacon flag */
vdev->bcn_ctx.sg_uniq_bc_str.payload_header.simple_beacon = 0;
vdev->bcn_ctx.beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM] = 0;
}
/* trigger new beacon tx */
mac_rf_beacon_tx(PLC_PROTO_TYPE_SG, &vdev->bcn_ctx,
vdev->bcn_ctx.mac_bcn_rf_buffer, is_std_tx, is_csma_tx);
/* recover some data */
vdev->bcn_ctx.beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM] = 0;
vdev->bcn_ctx.fc.is_rf = 0;
vdev->bcn_ctx.sg_uniq_bc_str.payload_header.simple_beacon = 0;
return 0;
}
extern void mac_beacon_fill_buf_sg(mac_beacon_ctx_t *bcn, uint8_t **tmp);
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
void mac_rf_simple_beacon_fill_buf_spg(mac_beacon_ctx_t *bcn, uint8_t **tmp)
{
/* fill in FC */
spg_frame_control_t *fc = (spg_frame_control_t *)(*tmp);
(*tmp) += sizeof(spg_frame_control_t);
if (bcn->beacon_component_enable[MAC_BC_FC_INFO]) {
fc->delimiter_type = FC_DELIM_BEACON;
fc->snid = (uint8_t)bcn->fc.nid;
fc->access_ind = bcn->fc.net_type;
if (bcn->fc.is_rf) {
fc->vf.rf_bcn.bcn_period_cnt = bcn->fc.bp_cnt;
fc->vf.rf_bcn.time_stamp =
mac_sched_get_ntb((mac_vdev_t *)bcn->ref_vdev_ptr);
fc->vf.rf_bcn.src_tei = vdev_get_tei(bcn->ref_vdev_ptr);
} else {
IOT_ASSERT(0);
}
} else {
IOT_ASSERT(0);
}
/* fill in beacon payload fix header */
spg_beacon_payload_simple_header_t *plh =
(spg_beacon_payload_simple_header_t *)(*tmp);
(*tmp) += sizeof(spg_beacon_payload_simple_header_t);
if (bcn->beacon_component_enable[MAC_BC_FIX_P]) {
plh->fixed_hdr.beacon_type = bcn->spg_uniq_bc_str.payload_header.type;
plh->fixed_hdr.spg_forming_complete =
bcn->spg_uniq_bc_str.payload_header.assoc_done;
plh->fixed_hdr.allow_assoc =
bcn->spg_uniq_bc_str.payload_header.allow_assoc;
plh->fixed_hdr.multi_select_func_swt =
bcn->spg_uniq_bc_str.payload_header.multi_select;
plh->fixed_hdr.spg_forming_sn =
bcn->spg_uniq_bc_str.payload_header.network_sn;
plh->fixed_hdr.simple_beacon =
bcn->spg_uniq_bc_str.payload_header.simple_beacon;
IOT_ASSERT(plh->fixed_hdr.simple_beacon);
plh->fixed_hdr.allow_chan_eval =
bcn->spg_uniq_bc_str.payload_header.allow_chan_eval;
iot_mac_addr_cpy(plh->cco_mac_addr,
bcn->spg_uniq_bc_str.payload_header.cco_addr);
plh->beacon_seq_num = bcn->fc.bp_cnt;
plh->beacon_entry_num = 1;
} else {
IOT_ASSERT(0);
}
/* fill in rf simple param */
spg_beacon_entry_simple_param_t *simple = NULL;
if (bcn->beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM]) {
simple = (spg_beacon_entry_simple_param_t *)(*tmp);
(*tmp) += sizeof(spg_beacon_entry_simple_param_t);
simple->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_RF_SIMPLE_PARAM;
simple->beacon_entry_len = sizeof(*simple);
simple->tei = bcn->spg_uniq_bc_str.simple_param.tei;
simple->pco_tei = bcn->spg_uniq_bc_str.simple_param.pco_tei;
simple->role = bcn->spg_uniq_bc_str.simple_param.role;
simple->level = bcn->spg_uniq_bc_str.simple_param.level;
iot_mac_addr_cpy(simple->src_mac_addr,
bcn->spg_uniq_bc_str.simple_param.addr);
simple->rf_hop = bcn->spg_uniq_bc_str.simple_param.rf_hop;
simple->csma_start_ntb=
bcn->spg_uniq_bc_str.simple_param.csma_start_ntb;
simple->csma_dur = bcn->spg_uniq_bc_str.simple_param.csma_dur;
simple->freq_band = (uint8_t)phy_proto_single_band_id_get();
simple->rsvd = bcn->spg_uniq_bc_str.simple_param.used_rsvd;
}
/* fill in vendor */
beacon_entry_vendor_spec_t *vendor;
beacon_entry_vendor_security_t *vendor_sec = NULL;
if (bcn->beacon_component_enable[MAC_BC_BMI_VENDOR_SPEC] &&
bcn->vendor.passcode_valid) {
plh->beacon_entry_num++;
vendor = (beacon_entry_vendor_spec_t *)(*tmp);
(*tmp) += sizeof(beacon_entry_vendor_spec_t);
os_mem_set(vendor, 0, sizeof(*vendor));
vendor->beacon_entry_type = MAC_BCN_TYPE_ID_VENDOR_SPEC;
vendor->beacon_entry_len = sizeof(*vendor);
vendor->power = bcn->vendor.power;
vendor->allowed_cco_tf_sr = bcn->vendor.allowed_cco_tf_sr;
vendor->proxy_select_dur = bcn->vendor.proxy_select_dur;
vendor->fixed_rate = bcn->vendor.fixed_rate;
vendor->pco_snr_rpt = bcn->vendor.pco_snr_rpt;
vendor->dm_tx_cfg = bcn->vendor.dm_tx_cfg;
vendor->cco_debug = bcn->vendor.cco_debug;
vendor->vendor_id = bcn->vendor.vendor_id;
plh->beacon_entry_num++;
/* add security related vendor entry */
vendor_sec = (beacon_entry_vendor_security_t *)(*tmp);
(*tmp) += sizeof(beacon_entry_vendor_security_t);
os_mem_set(vendor_sec, 0, sizeof(*vendor_sec));
vendor_sec->beacon_entry_type =
MAC_BCN_TYPE_ID_VENDOR_SECURITY;
vendor_sec->beacon_entry_len = sizeof(*vendor_sec);
vendor_sec->passcode = bcn->vendor.passcode;
}
}
uint32_t mac_rf_assemble_and_send_bcn_spg(mac_vdev_t *vdev, uint8_t is_std_tx,
uint8_t is_csma_tx)
{
if (MAC_RF_SEND_SIMPLE_BCN == is_std_tx) {
vdev->bcn_ctx.fc.is_rf = 1;
/* modify tidy beacon flag */
vdev->bcn_ctx.spg_uniq_bc_str.payload_header.simple_beacon = 1;
mac_bc_sta_cap_spg_t *sta_cap = &vdev->bcn_ctx.spg_uniq_bc_str.sta_cap;
mac_bc_simple_param_spg_t *simple =
&vdev->bcn_ctx.spg_uniq_bc_str.simple_param;
simple->tei = sta_cap->tei;
simple->pco_tei = sta_cap->proxy;
simple->role = sta_cap->role;
simple->level = sta_cap->level;
simple->rf_hop = sta_cap->rf_hop;
iot_mac_addr_cpy(simple->addr, sta_cap->addr);
/* calculate csma start ntb and csma dur */
mac_bc_time_slot_t *ts = &vdev->bcn_ctx.time_slot;
uint32_t bc_slot_dur = ts->cco_bc_cnt * ts->bc_slot_dur;
uint32_t non_slot_dur = ts->non_cco_bc_info.bc_cnt * ts->bc_slot_dur;
uint32_t tdma_dur = (ts->cco_bc_cnt + ts->non_cco_bc_info.bc_cnt)
* ts->tdma_slot_dur;
/* calculate csma start ntb */
simple->csma_start_ntb = ts->bp_start_ntb + MAC_MS_TO_NTB(bc_slot_dur +
non_slot_dur + tdma_dur);
simple->csma_dur = 0;
/* calculate csma duration */
for (uint8_t i = 0; i < ts->csma_info.phase_cnt; i++) {
simple->csma_dur += (uint16_t)ts->csma_info.slot_dur[i];
}
vdev->bcn_ctx.beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM] = 1;
} else if (MAC_RF_SEND_STD_BCN == is_std_tx) {
vdev->bcn_ctx.fc.is_rf = 1;
/* modify tidy beacon flag */
vdev->bcn_ctx.spg_uniq_bc_str.payload_header.simple_beacon = 0;
vdev->bcn_ctx.beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM] = 0;
}
/* trigger new beacon tx */
mac_rf_beacon_tx(PLC_PROTO_TYPE_SPG, &vdev->bcn_ctx,
vdev->bcn_ctx.mac_bcn_rf_buffer, is_std_tx, is_csma_tx);
/* recover some data */
vdev->bcn_ctx.beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM] = 0;
vdev->bcn_ctx.fc.is_rf = 0;
vdev->bcn_ctx.spg_uniq_bc_str.payload_header.simple_beacon = 0;
return 0;
}
extern void mac_beacon_fill_buf_spg(mac_beacon_ctx_t *bcn, uint8_t **tmp);
#endif
/* beacon payload to send, it would add some FC or PB info into the iot_pkt_t
and to form an Beacon MPDU.
*/
static uint8_t mac_rf_beacon_tx(uint32_t proto, mac_beacon_ctx_t *bcn,
iot_pkt_t* bcn_buf, uint8_t is_std_bcn, uint8_t is_csma_tx)
{
uint8_t phr_mcs, mcs, pb_sz_idx;
uint32_t tx_power = PHY_FULL_PWR_DBUV;
uint32_t pb_size;
uint8_t tx_cnt, retry_cnt;
uint8_t *tmp = iot_pkt_block_ptr(bcn_buf, IOT_PKT_BLOCK_DATA);
uint8_t bc_pb_crc_len = mac_get_pb_crc_len(FC_DELIM_BEACON, proto);
uint8_t bc_pld_icv_len = 0;
uint8_t bc_pb_resv_len = 0;
uint8_t fc_len = mac_get_mpdu_fc_len(proto);
/* TODO: get option parameter in rf phy corresponding api */
uint32_t option = mac_rf_get_self_option();
void *fc = (void *)tmp;
os_mem_set(tmp, 0, iot_pkt_block_len(bcn_buf, IOT_PKT_BLOCK_DATA) +
iot_pkt_block_len(bcn_buf, IOT_PKT_BLOCK_TAIL));
switch (proto) {
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
/* fill sg fill beacon payload */
if (is_std_bcn) {
mac_beacon_fill_buf_sg(bcn, &tmp);
} else {
mac_rf_simple_beacon_fill_buf_sg(bcn, &tmp);
}
bc_pld_icv_len = sizeof(beacon_payload_icv_t);
bc_pb_resv_len = 0;
break;
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
if (is_std_bcn) {
mac_beacon_fill_buf_spg(bcn, &tmp);
} else {
mac_rf_simple_beacon_fill_buf_spg(bcn, &tmp);
}
bc_pld_icv_len = sizeof(spg_beacon_payload_icv_t);
bc_pb_resv_len = SPG_BCN_PB_RESV_LEN;
break;
}
#endif
default:
IOT_ASSERT(0);
break;
}
(void)is_std_bcn;
uint32_t bcn_len;
/* bcn_len is payload length for mac_bcn_get_rate,
* not including FC
*/
bcn_len = tmp - iot_pkt_data(bcn_buf) + bc_pld_icv_len + bc_pb_crc_len
+ bc_pb_resv_len - fc_len;
uint32_t slot_dur_us;
if (MAC_RF_SEND_SIMPLE_BCN == is_std_bcn) {
slot_dur_us = bcn->time_slot.bc_slot_dur * 1000;
} else {
slot_dur_us = max(bcn->time_slot.rf_bc_slot_dur,
bcn->time_slot.bc_slot_dur) * 1000;
}
/* get pbidx phr mcs mcs */
mac_rf_bcn_get_rate(bcn_len, option, is_csma_tx,
slot_dur_us, &pb_sz_idx, &phr_mcs, &mcs);
/* get pb idx */
pb_size = phy_rf_get_pbsz(pb_sz_idx);
IOT_ASSERT(bcn_len <= pb_size);
tmp = iot_pkt_data(bcn_buf) + fc_len + pb_size
- bc_pb_crc_len - bc_pb_resv_len - bc_pld_icv_len;
/* fill icv */
mac_beacon_fill_pld_icv(proto, tmp, bcn_buf);
tmp += bc_pld_icv_len;
/* fill the correct tmi now,
* as the bcn len is got into
* consideration
*/
mac_rf_beacon_fill_fc_mcs_pb_idx(proto, fc, mcs, pb_sz_idx);
IOT_ASSERT(iot_pkt_set_tail(bcn_buf, tmp));
tx_cnt = 1;
if (PLC_DEV_ROLE_CCO == mac_vdev_cfg_get_node_role(
(mac_vdev_t *)bcn->ref_vdev_ptr)) {
retry_cnt = PLC_BCN_DEF_CCO_RETRY_CNT;
} else {
retry_cnt = PLC_BCN_DEF_STA_RETRY_CNT;
}
mac_rf_send_bcn(proto, ((mac_vdev_t *)bcn->ref_vdev_ptr)->ref_pdev_id,
bcn_buf, retry_cnt, tx_power, option, is_csma_tx, phr_mcs);
return tx_cnt;
}
uint32_t mac_rf_assemble_and_send_bcn(uint32_t proto, mac_vdev_t *vdev,
uint8_t is_std_tx, uint8_t is_csma_tx)
{
switch (proto) {
#if SUPPORT_SMART_GRID
case PLC_PROTO_TYPE_SG:
{
return mac_rf_assemble_and_send_bcn_sg(vdev, is_std_tx, is_csma_tx);
}
#endif
#if SUPPORT_SOUTHERN_POWER_GRID
case PLC_PROTO_TYPE_SPG:
{
return mac_rf_assemble_and_send_bcn_spg(vdev, is_std_tx, is_csma_tx);
}
#endif
default:
return ERR_FAIL;
}
}
uint32_t mac_rf_beacon_init(mac_beacon_ctx_t *mac_beacon)
{
if (mac_beacon->inited) {
return ERR_INVAL;
}
mac_beacon->mac_bcn_rf_buffer = iot_pkt_alloc(520, PLC_MAC_BEACON_MID);
if (mac_beacon->mac_bcn_rf_buffer == NULL) {
IOT_ASSERT(0);
return ERR_NOMEM;
}
/* bcn tx no need to reserve any space,
* we put all after the first byte :
* FC + BCN PB payload + PB CRC
*/
iot_pkt_reserve(mac_beacon->mac_bcn_rf_buffer, 0);
iot_pkt_put(mac_beacon->mac_bcn_rf_buffer, 520);
return ERR_OK;
}
#endif /* HPLC_RF_DEV_SUPPORT */