656 lines
24 KiB
C
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 */
|