2709 lines
104 KiB
C
Executable File
2709 lines
104 KiB
C
Executable File
/****************************************************************************
|
|
|
|
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 "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_sched.h"
|
|
#include "mac_sched_hw.h"
|
|
#include "mac_cmn_hw.h"
|
|
#include "plc_fr.h"
|
|
#include "hw_tonemap.h"
|
|
#include "rate_control.h"
|
|
#include "iot_io.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_dbglog_parser.h"
|
|
#include "mpdu_header.h"
|
|
#include "mac_crc.h"
|
|
#include "mac_cfg.h"
|
|
#include "phy_txrx_pwr.h"
|
|
#include "phy_chn.h"
|
|
#include "plc_mac_cfg.h"
|
|
#include "mac_tx_power.h"
|
|
#include "tx_desc_reg_api.h"
|
|
#include "mac_check_spur_cco.h"
|
|
#include "mac_reset.h"
|
|
#include "rf_beacon_frame.h"
|
|
#include "mac_rf_sched.h"
|
|
#include "mac_cert_test.h"
|
|
#include "mac_rf_tx_hw.h"
|
|
#include "mac_task.h"
|
|
#include "iot_oem_api.h"
|
|
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
|
|
uint32_t mac_tx_detect_bcn(mac_beacon_ctx_t *bcn_ctxt)
|
|
{
|
|
iot_printf("%s\n", __FUNCTION__);
|
|
uint32_t len = sizeof(mac_beacon_ctx_t);
|
|
/* get a temporary pkt for bcn ctxt */
|
|
iot_pkt_t *detect_bcn = iot_pkt_alloc(len, PLC_MAC_BEACON_MID);
|
|
if (detect_bcn == NULL) {
|
|
iot_printf("detect_bcn alloc fail\n");
|
|
return ERR_NOMEM;
|
|
}
|
|
iot_pkt_reserve(detect_bcn, 0);
|
|
iot_pkt_put(detect_bcn, len);
|
|
mac_beacon_ctx_t *bcn =
|
|
(mac_beacon_ctx_t *)iot_pkt_block_ptr(detect_bcn, IOT_PKT_BLOCK_DATA);
|
|
|
|
os_mem_cpy((void *)bcn, (void *)bcn_ctxt, sizeof(mac_beacon_ctx_t));
|
|
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_TIME_SLOT]) {
|
|
/* fill detect bcn */
|
|
uint32_t tdma_dur = bcn->time_slot.bc_slot_dur * (
|
|
bcn->time_slot.cco_bc_cnt + bcn->time_slot.non_cco_bc_info.bc_cnt);
|
|
uint32_t csma_dur = 0;
|
|
for (uint8_t i = 0; i < bcn->time_slot.csma_info.phase_cnt; i++) {
|
|
csma_dur += bcn->time_slot.csma_info.slot_dur[i];
|
|
}
|
|
bcn->time_slot.bp_start_ntb = bcn->time_slot.bp_start_ntb +
|
|
MAC_MS_TO_NTB(tdma_dur) + MAC_MS_TO_NTB(csma_dur);
|
|
|
|
bcn->time_slot.bc_period = 0;
|
|
for (uint8_t j = 0; j < bcn->time_slot.d_csma_info.phase_cnt; j++) {
|
|
bcn->time_slot.bc_period += bcn->time_slot.d_csma_info.slot_dur[j];
|
|
bcn->time_slot.csma_info.phase[j]
|
|
= bcn->time_slot.d_csma_info.phase[j];
|
|
bcn->time_slot.csma_info.slot_dur[j]
|
|
= bcn->time_slot.d_csma_info.slot_dur[j];
|
|
}
|
|
bcn->time_slot.cco_bc_cnt = 1;
|
|
bcn->time_slot.proxy_bc_cnt = 0;
|
|
bcn->time_slot.bc_slot_dur = 15; /* 15ms */
|
|
bcn->time_slot.d_csma_lid = LID_BCSMA_FB_DETECT;
|
|
bcn->time_slot.tdma_slot_dur = 0;
|
|
bcn->time_slot.tdma_lid = 0;
|
|
|
|
/* proxy and discover beacons info */
|
|
bcn->time_slot.non_cco_bc_info.bc_cnt = 0;
|
|
/* csma slot info */
|
|
bcn->time_slot.csma_info.phase_cnt
|
|
= bcn->time_slot.d_csma_info.phase_cnt;
|
|
/* bcsma slot info*/
|
|
os_mem_set(&bcn->time_slot.d_csma_info, 0,
|
|
sizeof(bcn->time_slot.d_csma_info));
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
/* disable detect info */
|
|
uint32_t detect_band = 0xff;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_FB_DETECT]) {
|
|
detect_band = bcn->fb_detect.band_id;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
#if PLC_MAC_TX_DEBUG_LOG >= PLC_MAC_LOG_LEVEL_2
|
|
iot_printf("[spg_dbg] detect_band:%d, detect_start_ntb, "
|
|
"bc_period:%d\n",
|
|
detect_band, bcn->time_slot.bp_start_ntb, bcn->time_slot.bc_period);
|
|
#endif
|
|
|
|
/* init detect buf */
|
|
iot_pkt_t *detect_buff = iot_pkt_alloc(520, PLC_MAC_BEACON_MID);
|
|
if (detect_buff == NULL) {
|
|
iot_pkt_free(detect_bcn);
|
|
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(detect_buff, 0);
|
|
iot_pkt_put(detect_buff, 520);
|
|
|
|
mac_beacon_tx(PHY_PROTO_TYPE_GET(), detect_band,
|
|
bcn, detect_buff);
|
|
|
|
/* free detect bcn buf */
|
|
iot_pkt_free(detect_bcn);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if (PLC_SUPPORT_CCO_ROLE)
|
|
|
|
/* reset cco beacon context */
|
|
static void mac_beacon_cco_reset(mac_beacon_ctx_t *mac_beacon)
|
|
{
|
|
os_mem_set(&mac_beacon->cco, 0, sizeof(mac_beacon->cco));
|
|
}
|
|
|
|
/* cco only beacon update handling */
|
|
uint8_t mac_update_beacon_cco(uint32_t proto, mac_vdev_t *vdev,
|
|
mac_bc_update_t *ent)
|
|
{
|
|
uint64_t tmp;
|
|
uint8_t tx_cnt = 0, tx_req = 1, rf_tx_req = 1;
|
|
uint32_t *bc_period_cnt =
|
|
vdev_get_bc_period_cnt_ptr(proto, vdev);
|
|
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(vdev->ref_pdev_id,
|
|
RF_PDEV_ID, vdev->rf_vdev_id);
|
|
|
|
if (rf_vdev && rf_vdev->tx_rx_suspend) {
|
|
rf_tx_req = 0;
|
|
}
|
|
if (vdev && vdev->tx_rx_suspend) {
|
|
tx_req = 0;
|
|
}
|
|
|
|
/* auto power control */
|
|
/* TODO : There will be more and more follow-up conditions, */
|
|
/* need to input the variables to tx_power module directly later */
|
|
mac_beacon_ctx_t *bcn_ctx = &vdev->bcn_ctx;
|
|
if (ent->peer_cnt >= HIGH_PWR_NETWORK_SCALE_THRE ||
|
|
bcn_ctx->time_slot.bc_period >= HIGH_PWR_BCN_PERIOD_THRE) {
|
|
mac_high_power_req(vdev, HIGH_PWR_REQ_BY_NETWORK_SIZE, true);
|
|
}
|
|
|
|
/* below fields need to be updated for every beacon by mac layer
|
|
* 1. beacon period count
|
|
* 2. bp start ntb
|
|
*/
|
|
if(ent->new_bp_req) {
|
|
/* apply the next beacon period schedule into HW */
|
|
tmp = mac_sched_get_ntb64(vdev);
|
|
tmp += MAC_MS_TO_NTB(MAC_BP_AHEAD_NEXT_BP_DUR);
|
|
if (tmp > vdev->bcn_ctx.cco.next_start_ntb64) {
|
|
/* next bp start too late. adjust the new start ntb */
|
|
iot_printf("%s next bp start too late, start_ntb: %lu-%lu, "
|
|
"curr_ntb %lu-%lu\n", __FUNCTION__,
|
|
iot_uint64_higher32(vdev->bcn_ctx.cco.next_start_ntb64),
|
|
iot_uint64_lower32(vdev->bcn_ctx.cco.next_start_ntb64),
|
|
iot_uint64_higher32(tmp), iot_uint64_lower32(tmp));
|
|
vdev->bcn_ctx.cco.next_start_ntb64 = tmp +
|
|
MAC_MS_TO_NTB(MAC_BP_AHEAD_NEXT_BP_DUR);
|
|
mac_pdev_t *pdev = get_pdev_ptr(vdev->ref_pdev_id);
|
|
if (pdev->mac_pm.mac_pm_flag) {
|
|
vdev->bcn_ctx.cco.next_start_ntb64 +=
|
|
MAC_MS_TO_NTB(MAC_BP_AHEAD_NEXT_BP_DUR);
|
|
}
|
|
}
|
|
|
|
#if SUPPORT_IEEE_1901
|
|
uint16_t dur_compens = vdev->bcn_ctx.time_slot.protected_region_dur
|
|
% MAC_I1901_NN_CCO_PER_DUR_MS;
|
|
if (dur_compens) {
|
|
vdev->bcn_ctx.time_slot.protected_region_dur +=
|
|
MAC_I1901_NN_CCO_PER_DUR_MS - dur_compens;
|
|
}
|
|
#endif
|
|
|
|
#if FORCE_INC_BCN_INV_MS
|
|
vdev->bcn_ctx.cco.next_start_ntb64 += MAC_MS_TO_NTB(FORCE_INC_BCN_INV_MS);
|
|
#endif
|
|
/* config scheduler for next beacon period */
|
|
vdev->bcn_ctx.cco.curr_start_ntb64 = mac_sched_cco_set(vdev,
|
|
&vdev->bcn_ctx.time_slot, vdev->bcn_ctx.cco.next_start_ntb64,
|
|
&vdev->bcn_ctx.cco.next_start_ntb64);
|
|
|
|
/* rf cco schedule set */
|
|
mac_rf_sched_cco_set(rf_vdev, &vdev->bcn_ctx.time_slot,
|
|
vdev->bcn_ctx.cco.curr_start_ntb64,
|
|
vdev->bcn_ctx.cco.next_start_ntb64);
|
|
|
|
/* update beacon period count */
|
|
vdev->bcn_ctx.cco.curr_bp_cnt++;
|
|
if (vdev->bcn_ctx.cco.curr_bp_cnt == 0)
|
|
vdev->bcn_ctx.cco.curr_bp_cnt = 1;
|
|
*bc_period_cnt =
|
|
vdev->bcn_ctx.cco.curr_bp_cnt;
|
|
|
|
/* update beacon period start ntb */
|
|
vdev->bcn_ctx.time_slot.bp_start_ntb =
|
|
iot_uint64_lower32(vdev->bcn_ctx.cco.curr_start_ntb64);
|
|
|
|
/* update tx phase */
|
|
vdev_set_sta_cap_phase(proto, vdev, vdev->l_phase1);
|
|
vdev->bcn_ctx.fc.phase = vdev->l_phase1;
|
|
|
|
if (tx_req) {
|
|
/* trigger new beacon tx */
|
|
tx_cnt = mac_beacon_tx(proto, phy_proto_single_band_id_get(),
|
|
&vdev->bcn_ctx, vdev->bcn_ctx.mac_beacon_buffer[0]);
|
|
}
|
|
|
|
if (rf_tx_req) {
|
|
/* mac rf send beacon.
|
|
* NOTE:enqueue the rf beacon as early as possible.
|
|
*/
|
|
uint32_t ret = mac_rf_assemble_and_send_bcn(proto, vdev,
|
|
(uint8_t)vdev->bcn_ctx.time_slot.rf_std_tx, false);
|
|
if (ret && ret != ERR_NOSUPP) {
|
|
iot_printf("rf beacon send fail\n");
|
|
}
|
|
}
|
|
|
|
if (tx_req) {
|
|
if (vdev->l_phase2) {
|
|
/* update tx phase */
|
|
vdev_set_sta_cap_phase(proto, vdev, vdev->l_phase2);
|
|
vdev->bcn_ctx.fc.phase = vdev->l_phase2;
|
|
|
|
/* trigger new beacon tx */
|
|
mac_beacon_tx(proto, phy_proto_single_band_id_get(),
|
|
&vdev->bcn_ctx, vdev->bcn_ctx.mac_beacon_buffer[1]);
|
|
}
|
|
|
|
if (vdev->l_phase3) {
|
|
/* update tx phase */
|
|
vdev_set_sta_cap_phase(proto, vdev, vdev->l_phase3);
|
|
vdev->bcn_ctx.fc.phase = vdev->l_phase3;
|
|
|
|
/* trigger new beacon tx */
|
|
mac_beacon_tx(proto, phy_proto_single_band_id_get(),
|
|
&vdev->bcn_ctx, vdev->bcn_ctx.mac_beacon_buffer[2]);
|
|
}
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
/* need tx detect pkt */
|
|
if (MAC_BEACON_IS_DETECT == bcn_ctx->is_tx_detect) {
|
|
vdev->bcn_ctx.fc.phase =
|
|
vdev->bcn_ctx.time_slot.d_csma_info.phase[0];
|
|
mac_tx_detect_bcn(bcn_ctx);
|
|
bcn_ctx->is_tx_detect = MAC_BEACON_IS_NORMAL;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
return tx_cnt;
|
|
}
|
|
|
|
#else /* PLC_SUPPORT_CCO_ROLE */
|
|
|
|
#define mac_beacon_cco_reset(mac_beacon)
|
|
|
|
#define mac_update_beacon_cco(proto, vdev, ent) (0)
|
|
|
|
#endif /* PLC_SUPPORT_CCO_ROLE */
|
|
|
|
void mac_beacon_uniq_info_get(uint32_t proto, mac_beacon_ctx_t *bcn_ctx,
|
|
mac_bc_ent_str_info_t *ptr)
|
|
{
|
|
IOT_ASSERT(ptr && bcn_ctx);
|
|
|
|
switch (proto) {
|
|
case PLC_PROTO_TYPE_SG:
|
|
ptr->plh_str_size = sizeof(mac_bc_fp_t);
|
|
ptr->sta_cap_str_size = sizeof(mac_bc_sta_cap_t);
|
|
ptr->rt_param_str_size = sizeof(mac_bc_rt_param_t);
|
|
ptr->simple_param_str_size = sizeof(mac_bc_simple_param_t);
|
|
|
|
ptr->plh_str_ptr =
|
|
(void *)&bcn_ctx->sg_uniq_bc_str.payload_header;
|
|
ptr->sta_cap_str_ptr =
|
|
(void *)&bcn_ctx->sg_uniq_bc_str.sta_cap;
|
|
ptr->rt_param_str_ptr =
|
|
(void *)&bcn_ctx->sg_uniq_bc_str.route_param;
|
|
ptr->simple_param_str_ptr =
|
|
(void *)&bcn_ctx->sg_uniq_bc_str.simple_param;
|
|
|
|
break;
|
|
case PLC_PROTO_TYPE_SPG:
|
|
ptr->plh_str_size = sizeof(mac_bc_fp_spg_t);
|
|
ptr->sta_cap_str_size = sizeof(mac_bc_sta_cap_spg_t);
|
|
ptr->rt_param_str_size = sizeof(mac_bc_rt_param_spg_t);
|
|
ptr->simple_param_str_size = sizeof(mac_bc_simple_param_spg_t);
|
|
|
|
ptr->plh_str_ptr =
|
|
(void *)&bcn_ctx->spg_uniq_bc_str.payload_header;
|
|
ptr->sta_cap_str_ptr =
|
|
(void *)&bcn_ctx->spg_uniq_bc_str.sta_cap;
|
|
ptr->rt_param_str_ptr =
|
|
(void *)&bcn_ctx->spg_uniq_bc_str.route_param;
|
|
ptr->simple_param_str_ptr =
|
|
(void *)&bcn_ctx->spg_uniq_bc_str.simple_param;
|
|
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* sta only beacon update handling */
|
|
uint8_t mac_update_beacon_sta(uint32_t proto, mac_vdev_t *vdev,
|
|
mac_bc_update_t *ent)
|
|
{
|
|
uint64_t curr_ntb;
|
|
uint32_t end_ntb, sta_tx_type;
|
|
uint8_t tx_cnt = 0;
|
|
uint8_t reason = 0;
|
|
uint8_t high_power_req = 0;
|
|
mac_beacon_ctx_t *bcn_ctx = &vdev->bcn_ctx;
|
|
mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
|
|
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(vdev->ref_pdev_id,
|
|
RF_PDEV_ID, vdev->rf_vdev_id);
|
|
mac_rf_pdev_t *rf_pdev = NULL;
|
|
if (rf_vdev) {
|
|
rf_pdev = get_rf_pdev_ptr(PLC_PDEV_ID, rf_vdev->ref_pdev_id);
|
|
}
|
|
|
|
/* auto power control */
|
|
/* TODO : There will be more and more follow-up conditions, */
|
|
/* need to input the variables to tx_power module directly later */
|
|
if (ent->peer_cnt >= HIGH_PWR_NETWORK_SCALE_THRE) {
|
|
high_power_req = 1;
|
|
reason = HIGH_PWR_REQ_BY_NETWORK_SIZE;
|
|
} else if (ent->high_power) {
|
|
high_power_req = 1;
|
|
reason = HIGH_PWR_REQ_BY_CVG;
|
|
}
|
|
if (high_power_req) {
|
|
mac_high_power_req(vdev, reason, true);
|
|
}
|
|
|
|
#if DEBUG_HWQ_SHCED_HANG
|
|
pdev->dbg_status = MAC_TX_HANG_STATUS_4;
|
|
#endif
|
|
/* stop HW scheduler first if it's running */
|
|
mac_sched_stop(vdev);
|
|
|
|
/* rf schedule stop */
|
|
mac_rf_sched_stop(rf_vdev);
|
|
|
|
#if DEBUG_HWQ_SHCED_HANG
|
|
pdev->dbg_status = MACC_TX_HANG_STATUS_MAX;
|
|
#endif
|
|
|
|
/* if last beacon period, there's TDMA frame
|
|
* not done, then we need to clean them now, or else
|
|
* they would be sent in the wrong period
|
|
*/
|
|
mac_tx_flush_all_tdma_queue(&pdev->hwq_hdl);
|
|
|
|
/* flush detest beacon for spg */
|
|
if (vdev->fb_lid_exist) {
|
|
/* check bcsma pending */
|
|
mac_tx_flush_bcsma_pending_queue(&pdev->hwq_hdl);
|
|
vdev->bcsma_non_exist_cnt = 0;
|
|
}
|
|
|
|
if (rf_pdev) {
|
|
/* flush tdma hwq */
|
|
mac_rf_tx_flush_all_tdma_queue(&rf_pdev->hwq_hdl);
|
|
/* flush csma bcn hwq */
|
|
mac_rf_csma_bcn_flush(&rf_pdev->hwq_hdl);
|
|
}
|
|
|
|
if (bcn_ctx->sta.ntb_sync_done == 0) {
|
|
/* config HW to sync up the NTB with the preferred network. */
|
|
if (bcn_ctx->fc.delta_ntb) {
|
|
mac_sched_sync_ntb(vdev, 0, bcn_ctx->fc.delta_ntb);
|
|
}
|
|
#if MAC_ZC_START_FOLLOW_VDEV
|
|
mac_zc_set_func_cmd(vdev->ref_pdev_id, MAC_ZC_FUNC_CMD_NTB_STABLE_NOTIF,
|
|
NULL);
|
|
#else
|
|
mac_zc_set_func_cmd(vdev->ref_pdev_id, MAC_ZC_FUNC_CMD_RESET_HW, NULL);
|
|
#endif
|
|
bcn_ctx->sta.ntb_sync_done = 1;
|
|
} else if (bcn_ctx->sta.force_sw_sync) {
|
|
/* config HW to sync up the NTB with the preferred network. */
|
|
if (bcn_ctx->fc.delta_ntb) {
|
|
mac_sched_sync_ntb(vdev, 0, bcn_ctx->fc.delta_ntb);
|
|
}
|
|
}
|
|
|
|
/* if this beacon is simple beacon, need reuse timeslot */
|
|
if (bcn_ctx->beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM]) {
|
|
mac_bc_time_slot_t *ts = &vdev->bcn_ctx.time_slot;
|
|
mac_bc_simple_param_t *simple_sg =
|
|
&vdev->bcn_ctx.sg_uniq_bc_str.simple_param;
|
|
mac_bc_simple_param_spg_t *simple_spg =
|
|
&vdev->bcn_ctx.spg_uniq_bc_str.simple_param;
|
|
uint16_t csma_dur;
|
|
uint32_t csma_start_ntb;
|
|
if (proto == PLC_PROTO_TYPE_SPG) {
|
|
csma_dur = simple_spg->csma_dur;
|
|
csma_start_ntb = simple_spg->csma_start_ntb;
|
|
} else {
|
|
csma_dur = simple_sg->csma_dur;
|
|
csma_start_ntb = simple_sg->csma_start_ntb;
|
|
}
|
|
os_mem_set(ts, 0, sizeof(mac_bc_time_slot_t));
|
|
ts->csma_info.phase_cnt = 1;
|
|
ts->csma_slot_frag_s = csma_dur;
|
|
ts->csma_info.phase[0] = vdev->l_phase1 ? vdev->l_phase1 : PLC_PHASE_A;
|
|
ts->csma_info.slot_dur[0] = csma_dur;
|
|
ts->bp_start_ntb = csma_start_ntb;
|
|
ts->bc_period = csma_dur;
|
|
}
|
|
|
|
curr_ntb = mac_sched_get_ntb64(vdev);
|
|
end_ntb = bcn_ctx->time_slot.bp_start_ntb +
|
|
MAC_MS_TO_NTB(bcn_ctx->time_slot.bc_period);
|
|
|
|
if ((end_ntb - iot_uint64_lower32(curr_ntb)) >= 0x7FFFFFFF) {
|
|
/* current beacon period is obsolete */
|
|
iot_printf("%s bp already expired start_ntb %lu, "
|
|
"end_ntb %lu, curr_ntb %lu\n", __FUNCTION__,
|
|
bcn_ctx->time_slot.bp_start_ntb, end_ntb,
|
|
iot_uint64_lower32(curr_ntb));
|
|
if (mac_get_cert_test_flag() && vdev->opposite_3ps) {
|
|
bcn_ctx->time_slot.bp_start_ntb = (uint32_t)curr_ntb;
|
|
end_ntb = bcn_ctx->time_slot.bp_start_ntb +
|
|
MAC_MS_TO_NTB(bcn_ctx->time_slot.bc_period);
|
|
goto bc_sched;
|
|
}
|
|
/* config a csma only command list to enable scheduler */
|
|
bcn_ctx->sta.allow_reuse_ts = 0;
|
|
mac_sched_set_csma_only(vdev, curr_ntb,
|
|
(uint8_t)bcn_ctx->time_slot.allow_reuse);
|
|
|
|
/* rf csma only schedule set */
|
|
mac_rf_sched_set_csma_only(rf_vdev, curr_ntb,
|
|
(uint8_t)bcn_ctx->time_slot.allow_reuse);
|
|
} else {
|
|
bc_sched:
|
|
/* apply the next beacon period schedule into HW, at least enable tx
|
|
* for local logical phase.
|
|
*/
|
|
switch (vdev->l_phase1) {
|
|
case PLC_PHASE_A:
|
|
ent->phase_a_tx = 1;
|
|
break;
|
|
case PLC_PHASE_B:
|
|
ent->phase_b_tx = 1;
|
|
break;
|
|
case PLC_PHASE_C:
|
|
ent->phase_c_tx = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
bcn_ctx->sta.bc_d_with_non = ent->bc_d_with_non;
|
|
/* backup tx phase config */
|
|
bcn_ctx->sta.phase_a_tx = ent->phase_a_tx;
|
|
bcn_ctx->sta.phase_b_tx = ent->phase_b_tx;
|
|
bcn_ctx->sta.phase_c_tx = ent->phase_c_tx;
|
|
mac_sched_sta_set(vdev, &vdev->bcn_ctx.time_slot,
|
|
bcn_ctx->time_slot.bp_start_ntb, ent->phase_a_tx,
|
|
ent->phase_b_tx, ent->phase_c_tx, 1);
|
|
|
|
/* rf sta schedule set */
|
|
sta_tx_type = mac_rf_sched_sta_set(rf_vdev, &vdev->bcn_ctx.time_slot,
|
|
bcn_ctx->time_slot.bp_start_ntb, 1);
|
|
|
|
/* check if a new beacon tx is required for the update beacon
|
|
* template. for cco role device, always delay the new beacon tx
|
|
* to the periodical beacon phase.
|
|
*/
|
|
if (ent->tx_req) {
|
|
/* for hplc beacon, do not tx beacon on rf only type */
|
|
if (!HPLC_RF_SUPPORT || ((BEACON_TX_ONLY_RF != sta_tx_type) &&
|
|
!vdev->tx_rx_suspend)) {
|
|
/* always use local phase for beacon tx */
|
|
vdev->bcn_ctx.fc.phase = vdev->l_phase1;
|
|
tx_cnt = mac_beacon_tx(proto, phy_proto_single_band_id_get(),
|
|
&vdev->bcn_ctx, vdev->bcn_ctx.mac_beacon_buffer[0]);
|
|
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
/* need tx detect pkt */
|
|
if (MAC_BEACON_IS_DETECT == bcn_ctx->is_tx_detect) {
|
|
if (phy_band_id_get() ==
|
|
IOT_SUPPORT_TONE_MULTI_BAND021) {
|
|
mac_tx_detect_bcn(bcn_ctx);
|
|
}
|
|
bcn_ctx->is_tx_detect = MAC_BEACON_IS_NORMAL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
uint8_t is_csma_tx = 0, is_std_tx = 0, tx_req = 1;
|
|
|
|
/* tx stardand beacon on HPLC RF type,
|
|
* otherwise tx simple beacon
|
|
*/
|
|
switch (sta_tx_type) {
|
|
case BEACON_TX_ONLY_HPLC:
|
|
/* do not tx beacon on hplc only type */
|
|
tx_req = 0;
|
|
break;
|
|
case BEACON_TX_ONLY_RF:
|
|
/* fix hplc+rf test bed, sta bcast sof process test case fail,
|
|
* BEACON_TX_ONLY_RF need send rf stdandard beacon.
|
|
*/
|
|
is_std_tx = 1;
|
|
break;
|
|
case BEACON_TX_HPLC_SIMPLE_RF:
|
|
case BEACON_TX_HPLC_SIMPLE_RF_SYNC:
|
|
is_std_tx = 0;
|
|
break;
|
|
case BEACON_TX_HPLC_RF:
|
|
case BEACON_TX_HPLC_RF_SYNC:
|
|
is_std_tx = 1;
|
|
break;
|
|
case BEACON_TX_HPLC_CSMA_SIMPLE_RF:
|
|
is_std_tx = 0;
|
|
/* if type is csma simple rf, need tx beacon on csma slot */
|
|
is_csma_tx = 1;
|
|
break;
|
|
default:
|
|
iot_printf("%s err type:%lu\n", __FUNCTION__, sta_tx_type);
|
|
/* if error type, do not tx beacon */
|
|
tx_req = 0;
|
|
break;
|
|
}
|
|
|
|
if (rf_vdev && rf_vdev->tx_rx_suspend) {
|
|
tx_req = 0;
|
|
}
|
|
|
|
if (tx_req) {
|
|
/* mac rf send beacon */
|
|
uint32_t ret = mac_rf_assemble_and_send_bcn(proto, vdev,
|
|
is_std_tx, is_csma_tx);
|
|
if (ret && ret != ERR_NOSUPP) {
|
|
iot_printf("rf beacon send fail\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* judge hplc slot is exist or not */
|
|
if (vdev->bcsma_slot_exist) {
|
|
/* exist hplc bcsma slot, not care */
|
|
vdev->bcsma_non_exist_cnt = 0;
|
|
} else {
|
|
/* do not exist bcsma slot */
|
|
vdev->bcsma_non_exist_cnt++;
|
|
if (vdev->bcsma_non_exist_cnt > BCSMA_NON_EXIST_PD_CNT) {
|
|
vdev->bcsma_non_exist_cnt = 0;
|
|
mac_tx_flush_bcsma_pending_queue(&pdev->hwq_hdl);
|
|
}
|
|
}
|
|
|
|
if (rf_vdev) {
|
|
/* judge rf slot is exist or not */
|
|
if (rf_vdev->bcsma_slot_exist) {
|
|
/* exist rf bcsma slot, not care */
|
|
rf_vdev->bcsma_non_exist_cnt = 0;
|
|
} else {
|
|
/* do not exist bcsma slot */
|
|
rf_vdev->bcsma_non_exist_cnt++;
|
|
if (rf_vdev->bcsma_non_exist_cnt > BCSMA_NON_EXIST_PD_CNT) {
|
|
rf_vdev->bcsma_non_exist_cnt = 0;
|
|
mac_rf_tx_flush_bcsma_pending_queue(&rf_pdev->hwq_hdl);
|
|
}
|
|
}
|
|
}
|
|
return tx_cnt;
|
|
}
|
|
|
|
uint32_t mac_beacon_init(mac_beacon_ctx_t *mac_beacon, void *vdev_ptr)
|
|
{
|
|
mac_vdev_t *vdev = vdev_ptr;
|
|
uint8_t i, j;
|
|
|
|
if (mac_beacon->inited) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
for (i = 0; i < vdev->mac_vdev_cfg.p_phase_cnt; i++) {
|
|
/* TODO: check the alloc size and resv len */
|
|
mac_beacon->mac_beacon_buffer[i] = iot_pkt_alloc(520,
|
|
PLC_MAC_BEACON_MID);
|
|
if (mac_beacon->mac_beacon_buffer[i] == NULL) {
|
|
for (j = 0; j < i; j++) {
|
|
iot_pkt_free(mac_beacon->mac_beacon_buffer[j]);
|
|
mac_beacon->mac_beacon_buffer[j] = NULL;
|
|
}
|
|
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_beacon_buffer[i], 0);
|
|
iot_pkt_put(mac_beacon->mac_beacon_buffer[i], 520);
|
|
|
|
}
|
|
|
|
uint32_t ret = mac_rf_beacon_init(mac_beacon);
|
|
if (!ret) {
|
|
iot_printf("mac rf beacon success!\n");
|
|
}
|
|
|
|
mac_beacon->ref_vdev_ptr = vdev_ptr;
|
|
mac_beacon->inited = 1;
|
|
/* enable/disable force sw ntb sync feature */
|
|
mac_beacon->sta.force_sw_sync = !(PLC_ENABLE_HW_NTB_SYNC);
|
|
mac_beacon->sta.bc_d_with_non = 0;
|
|
return 0;
|
|
}
|
|
|
|
/* reset the beacon ctx */
|
|
uint32_t mac_beacon_reset(mac_beacon_ctx_t *mac_beacon)
|
|
{
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
/* get beacon info */
|
|
mac_bc_ent_str_info_t bc_ent_str = { 0 };
|
|
mac_beacon_uniq_info_get(proto, mac_beacon, &bc_ent_str);
|
|
IOT_ASSERT(bc_ent_str.plh_str_ptr &&
|
|
bc_ent_str.rt_param_str_ptr &&
|
|
bc_ent_str.sta_cap_str_ptr);
|
|
|
|
mac_beacon->nid_inited = 0;
|
|
mac_beacon->entry_sort_cnt = 0;
|
|
mac_beacon->unknown_entry = NULL;
|
|
|
|
os_mem_set(&mac_beacon->beacon_component_enable, 0,
|
|
sizeof(mac_beacon->beacon_component_enable));
|
|
|
|
os_mem_set(&mac_beacon->fc, 0, sizeof(mac_beacon->fc));
|
|
os_mem_set(bc_ent_str.plh_str_ptr, 0,
|
|
bc_ent_str.plh_str_size);
|
|
os_mem_set(bc_ent_str.sta_cap_str_ptr, 0, bc_ent_str.sta_cap_str_size);
|
|
os_mem_set(bc_ent_str.rt_param_str_ptr, 0,
|
|
bc_ent_str.rt_param_str_size);
|
|
os_mem_set(bc_ent_str.simple_param_str_ptr, 0,
|
|
bc_ent_str.simple_param_str_size);
|
|
os_mem_set(&mac_beacon->freq_chg, 0, sizeof(mac_beacon->freq_chg));
|
|
os_mem_set(&mac_beacon->rf_chg, 0, sizeof(mac_beacon->rf_chg));
|
|
os_mem_set(&mac_beacon->rf_route, 0, sizeof(mac_beacon->rf_route));
|
|
os_mem_set(&mac_beacon->time_slot, 0, sizeof(mac_beacon->time_slot));
|
|
os_mem_set(&mac_beacon->meter, 0, sizeof(mac_beacon->meter));
|
|
os_mem_set(&mac_beacon->fb_detect, 0, sizeof(mac_beacon->fb_detect));
|
|
os_mem_set(&mac_beacon->rtc, 0, sizeof(mac_beacon->rtc));
|
|
os_mem_set(&mac_beacon->sta, 0, sizeof(mac_beacon->sta));
|
|
os_mem_set(mac_beacon->entry_sort, 0, sizeof(mac_beacon->entry_sort));
|
|
/* enable/disable force sw ntb sync feature */
|
|
mac_beacon->sta.force_sw_sync = !(PLC_ENABLE_HW_NTB_SYNC);
|
|
mac_beacon->sta.bc_d_with_non = 0;
|
|
mac_beacon_cco_reset(mac_beacon);
|
|
return 0;
|
|
}
|
|
|
|
#if SUPPORT_SMART_GRID
|
|
void mac_beacon_fill_buf_sg(mac_beacon_ctx_t *bcn, uint8_t **tmp)
|
|
{
|
|
uint8_t *p_unknown;
|
|
uint16_t unknown_len;
|
|
|
|
/* 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 {
|
|
fc->vf.bcn.time_stamp =
|
|
mac_sched_get_ntb((mac_vdev_t *)bcn->ref_vdev_ptr);
|
|
#if (MAC_SCHED_DEBUG || RUNTIME_DEBUG)
|
|
iot_printf("%s curr ntb:%lu, start ntb %lu, nid %lu phase %lu\n",
|
|
__FUNCTION__, fc->vf.bcn.time_stamp,
|
|
bcn->time_slot.bp_start_ntb, bcn->fc.nid, bcn->fc.phase);
|
|
iot_dbglog_input(PLC_MAC_BEACON_MID, DBGLOG_INFO,
|
|
IOT_MAC_BEACON_TX_NTB_INFO, 4, fc->vf.bcn.time_stamp,
|
|
bcn->time_slot.bp_start_ntb, bcn->fc.nid, bcn->fc.phase);
|
|
#endif
|
|
|
|
fc->vf.bcn.src_tei = vdev_get_tei(bcn->ref_vdev_ptr);
|
|
fc->vf.bcn.sym_num = 0; /* filled by HW */
|
|
fc->vf.bcn.phase_num = bcn->fc.phase;
|
|
}
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
/* fill in beacon payload fix header */
|
|
beacon_payload_std_header_t *plh =
|
|
(beacon_payload_std_header_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_payload_std_header_t);
|
|
|
|
/* updaet MAC_BC_FIX_P */
|
|
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->rf_channel = bcn->sg_uniq_bc_str.payload_header.rf_channel;
|
|
plh->rf_option = bcn->sg_uniq_bc_str.payload_header.rf_option;
|
|
plh->encrypt_mode = bcn->sg_uniq_bc_str.payload_header.encrypt_mode;
|
|
plh->cek_seq = bcn->sg_uniq_bc_str.payload_header.cek_seq;
|
|
plh->encrypt_algo = bcn->sg_uniq_bc_str.payload_header.encrypt_algo;
|
|
plh->rsvd1 = bcn->sg_uniq_bc_str.payload_header.used_rsvd1;
|
|
plh->rsvd2 = bcn->sg_uniq_bc_str.payload_header.used_rsvd2;
|
|
/* entry count will be filled in later */
|
|
plh->beacon_entry_num = 0;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
/* fill in the beacon control info, CCO itself manage bcn entries fill
|
|
* order, while STA follow CCO's behavior
|
|
*/
|
|
if (PLC_DEV_ROLE_CCO == mac_vdev_cfg_get_node_role(
|
|
(mac_vdev_t *)bcn->ref_vdev_ptr)) {
|
|
os_mem_set(bcn->entry_sort, 0x00, sizeof(bcn->entry_sort));
|
|
bcn->entry_sort_cnt = 8;
|
|
bcn->entry_sort[0] = MAC_BCN_TYPE_ID_STA_CAP;
|
|
bcn->entry_sort[1] = MAC_BCN_TYPE_ID_RT_PARAM;
|
|
bcn->entry_sort[2] = MAC_BCN_TYPE_ID_FREQ_CHQ;
|
|
bcn->entry_sort[3] = MAC_BCN_TYPE_ID_RF_CHANNEL_CHQ;
|
|
bcn->entry_sort[4] = MAC_BCN_TYPE_ID_RF_ROUTE;
|
|
bcn->entry_sort[5] = MAC_BCN_TYPE_ID_RTC;
|
|
bcn->entry_sort[6] = MAC_BCN_TYPE_ID_VENDOR_SPEC;
|
|
bcn->entry_sort[7] = MAC_BCN_TYPE_ID_TIME_SLOT;
|
|
}
|
|
|
|
for (uint8_t k = 0; k < bcn->entry_sort_cnt; k++) {
|
|
switch (bcn->entry_sort[k])
|
|
{
|
|
case MAC_BCN_TYPE_ID_STA_CAP:
|
|
{
|
|
/* fill in sta cap */
|
|
beacon_entry_sta_cap_t *cap = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_STA_CAP]) {
|
|
plh->beacon_entry_num++;
|
|
cap = (beacon_entry_sta_cap_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_sta_cap_t);
|
|
|
|
cap->beacon_entry_type = MAC_BCN_TYPE_ID_STA_CAP;
|
|
cap->beacon_entry_len = sizeof(*cap);
|
|
cap->tei = bcn->sg_uniq_bc_str.sta_cap.tei;
|
|
cap->pco_tei = bcn->sg_uniq_bc_str.sta_cap.proxy;
|
|
iot_mac_addr_cpy(cap->src_mac_addr,
|
|
bcn->sg_uniq_bc_str.sta_cap.addr);
|
|
cap->reach_rate_to_cco =
|
|
bcn->sg_uniq_bc_str.sta_cap.min_ul_dl_sr;
|
|
cap->node_role = bcn->sg_uniq_bc_str.sta_cap.role;
|
|
cap->node_level = bcn->sg_uniq_bc_str.sta_cap.level;
|
|
cap->snr_to_pco = bcn->sg_uniq_bc_str.sta_cap.snr;
|
|
cap->phase = bcn->sg_uniq_bc_str.sta_cap.phase;
|
|
cap->rf_hop = bcn->sg_uniq_bc_str.sta_cap.rf_hop;
|
|
cap->rsvd = bcn->sg_uniq_bc_str.sta_cap.used_rsvd;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_RT_PARAM:
|
|
{
|
|
/* fill in the routing info */
|
|
beacon_entry_route_t *prt = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_RT_PARAM]) {
|
|
plh->beacon_entry_num++;
|
|
prt = (beacon_entry_route_t*)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_route_t);
|
|
prt->beacon_entry_type = MAC_BCN_TYPE_ID_RT_PARAM;
|
|
prt->beacon_entry_len = sizeof(*prt);
|
|
prt->routing_update_intval =
|
|
bcn->sg_uniq_bc_str.route_param.rt_period;
|
|
prt->next_update_countdown =
|
|
bcn->sg_uniq_bc_str.route_param.rt_left_period;
|
|
prt->pco_discover_list_intval =
|
|
bcn->sg_uniq_bc_str.route_param.p_dis_period;
|
|
prt->sta_discover_list_intval =
|
|
bcn->sg_uniq_bc_str.route_param.s_dis_period;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_FREQ_CHQ:
|
|
{
|
|
/* fill in the freq change info */
|
|
beacon_entry_freq_change_t *fqc = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_FREQ_CHG]) {
|
|
plh->beacon_entry_num++;
|
|
fqc = (beacon_entry_freq_change_t*)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_freq_change_t);
|
|
fqc->beacon_entry_type = MAC_BCN_TYPE_ID_FREQ_CHQ;
|
|
fqc->beacon_entry_len = sizeof(*fqc);
|
|
fqc->target_freq = bcn->freq_chg.targer_freq;
|
|
fqc->change_countdown = bcn->freq_chg.time_left;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_RF_CHANNEL_CHQ:
|
|
{
|
|
/* fill in the rf channel change info */
|
|
beacon_entry_rf_channel_chg_t *rf_channel = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_RF_CHANNEL_CHG]) {
|
|
plh->beacon_entry_num++;
|
|
rf_channel = (beacon_entry_rf_channel_chg_t*)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_rf_channel_chg_t);
|
|
rf_channel->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_RF_CHANNEL_CHQ;
|
|
rf_channel->beacon_entry_len = sizeof(*rf_channel);
|
|
rf_channel->target_rf = bcn->rf_chg.target_rf_channel;
|
|
rf_channel->target_option = bcn->rf_chg.target_rf_option;
|
|
rf_channel->time_left = bcn->rf_chg.time_left;
|
|
rf_channel->rsvd = bcn->rf_chg.used_rsvd;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_RF_ROUTE:
|
|
{
|
|
/* fill in the rf route param info */
|
|
beacon_entry_rf_route_t *rf_route = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_RF_ROUTE]) {
|
|
plh->beacon_entry_num++;
|
|
rf_route = (beacon_entry_rf_route_t*)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_rf_route_t);
|
|
rf_route->beacon_entry_type = MAC_BCN_TYPE_ID_RF_ROUTE;
|
|
rf_route->beacon_entry_len = sizeof(*rf_route);
|
|
rf_route->rf_dis_period = bcn->rf_route.rf_dis_period;
|
|
rf_route->rf_age_period = bcn->rf_route.rf_age_period;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_RTC:
|
|
{
|
|
/* fill in the rtc info */
|
|
beacon_entry_rtc_t *rtc = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_RTC]) {
|
|
plh->beacon_entry_num++;
|
|
rtc = (beacon_entry_rtc_t*)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_rtc_t);
|
|
rtc->beacon_entry_type = MAC_BCN_TYPE_ID_RTC;
|
|
rtc->beacon_entry_len = sizeof(*rtc);
|
|
rtc->cco_date = bcn->rtc.cco_date;
|
|
rtc->cco_ntb = bcn->rtc.cco_ntb;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_TIME_SLOT:
|
|
{
|
|
/* fill in the time slot info */
|
|
beacon_entry_time_slot_alloc_t *pts = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_TIME_SLOT]) {
|
|
plh->beacon_entry_num++;
|
|
pts = (beacon_entry_time_slot_alloc_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_time_slot_alloc_t);
|
|
|
|
pts->beacon_entry_type = MAC_BCN_TYPE_ID_TIME_SLOT;
|
|
/* bcn entry len need to be calculated later */
|
|
|
|
/* fixed len area */
|
|
pts->total_slot_non_cco_beacon =
|
|
bcn->time_slot.non_cco_bc_info.bc_cnt;
|
|
pts->total_slot_cco_beacon =
|
|
bcn->time_slot.cco_bc_cnt;
|
|
pts->csma_phase_num =
|
|
bcn->time_slot.csma_info.phase_cnt;
|
|
pts->total_slot_pco_beacon =
|
|
bcn->time_slot.proxy_bc_cnt;
|
|
pts->beacon_slot_period =
|
|
bcn->time_slot.bc_slot_dur; /* unit ms */
|
|
/* unit 10ms */
|
|
pts->csma_slot_period =
|
|
(uint8_t)(bcn->time_slot.csma_slot_frag_s / 10);
|
|
pts->bind_csma_phase_num =
|
|
bcn->time_slot.d_csma_info.phase_cnt; /* 1-3 */
|
|
pts->bind_csma_lid =
|
|
bcn->time_slot.d_csma_lid;
|
|
pts->tdma_period =
|
|
bcn->time_slot.tdma_slot_dur; /* unit ms */
|
|
pts->tdma_lid =
|
|
bcn->time_slot.tdma_lid;
|
|
pts->cur_beacon_timestamp =
|
|
bcn->time_slot.bp_start_ntb;
|
|
pts->beacon_period =
|
|
bcn->time_slot.bc_period; /* unit ms */
|
|
pts->rf_bc_slot_period =
|
|
(uint16_t)bcn->time_slot.rf_bc_slot_dur; /* unit ms */
|
|
pts->rsvd1 = (uint16_t)bcn->time_slot.sg_used_rsvd1;
|
|
pts->rsvd2 = (uint16_t)bcn->time_slot.sg_used_rsvd2;
|
|
|
|
/* non cco beacon area */
|
|
if (bcn->sg_uniq_bc_str.payload_header.type !=
|
|
PLC_BC_TYPE_D || bcn->sta.bc_d_with_non) {
|
|
/* skip beacon slot detail for discovery beacon */
|
|
for (int i = 0; i <
|
|
bcn->time_slot.non_cco_bc_info.bc_cnt; i++) {
|
|
sub_beacon_entry_non_cco_beacon_t *pnc =
|
|
(sub_beacon_entry_non_cco_beacon_t*)(*tmp);
|
|
(*tmp) += sizeof(*pnc);
|
|
pnc->tei_to_send =
|
|
bcn->time_slot.non_cco_bc_info.sta[i].tei;
|
|
pnc->beacon_type =
|
|
bcn->time_slot.non_cco_bc_info.sta[i].type;
|
|
pnc->tx_flag =
|
|
bcn->time_slot.non_cco_bc_info.sta[i].tx_flag;
|
|
}
|
|
}
|
|
|
|
/* csma time slot area */
|
|
for (int i = 0; i < bcn->time_slot.csma_info.phase_cnt;
|
|
i++) {
|
|
sub_beacon_entry_csma_slot_t *pct =
|
|
(sub_beacon_entry_csma_slot_t*)(*tmp);
|
|
(*tmp) += sizeof(*pct);
|
|
|
|
pct->csma_period = bcn->time_slot.csma_info.slot_dur[i];
|
|
pct->phase = bcn->time_slot.csma_info.phase[i];
|
|
pct->resv = bcn->time_slot.csma_info.used_rsvd[i];
|
|
}
|
|
|
|
/* bind csma time slot area */
|
|
for (int i = 0; i < bcn->time_slot.d_csma_info.phase_cnt;
|
|
i++) {
|
|
sub_beacon_entry_bind_csma_slot_t *pbc =
|
|
(sub_beacon_entry_bind_csma_slot_t*)(*tmp);
|
|
(*tmp) += sizeof(*pbc);
|
|
|
|
pbc->bind_csma_period =
|
|
bcn->time_slot.d_csma_info.slot_dur[i];
|
|
pbc->phase = bcn->time_slot.d_csma_info.phase[i];
|
|
pbc->resv = bcn->time_slot.d_csma_info.used_rsvd[i];
|
|
}
|
|
|
|
/* recal the total len, exclude header len */
|
|
pts->beacon_entry_len = (uint16_t)((*tmp) - (uint8_t*)pts);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_VENDOR_SPEC:
|
|
{
|
|
/* fill in the vendor specific info */
|
|
beacon_entry_vendor_spec_t *vendor = NULL;
|
|
beacon_entry_vendor_roam_t *vendor_roam = NULL;
|
|
beacon_entry_vendor_data_t *vendor_data = NULL;
|
|
beacon_entry_vendor_debug_t *vendor_debug = NULL;
|
|
beacon_entry_vendor_tsfm_t *vendor_tsfm = NULL;
|
|
beacon_entry_vendor_security_t *vendor_sec = NULL;
|
|
beacon_entry_vendor_rf_t *vendor_rf = NULL;
|
|
/* check vendor app data size */
|
|
BUILD_BUG_ON(MAC_BC_APP_DATA_MAX == sizeof(vendor_data->data));
|
|
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_VENDOR_SPEC]) {
|
|
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;
|
|
if (bcn->vendor.th_data_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add roaming related vendor entry */
|
|
vendor_roam = (beacon_entry_vendor_roam_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_roam_t);
|
|
os_mem_set(vendor_roam, 0, sizeof(*vendor_roam));
|
|
vendor_roam->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_ROAM;
|
|
vendor_roam->beacon_entry_len = sizeof(*vendor_roam);
|
|
vendor_roam->sta_proxy_weight_rank =
|
|
bcn->vendor.sta_proxy_weight_rank;
|
|
vendor_roam->sta_proxy_good_tf_sr_th =
|
|
bcn->vendor.sta_proxy_good_tf_sr_th;
|
|
vendor_roam->sta_roaming_gap_h =
|
|
bcn->vendor.sta_roaming_gap_h;
|
|
vendor_roam->sta_roaming_gap_l =
|
|
bcn->vendor.sta_roaming_gap_l;
|
|
vendor_roam->cco_phase_check_tf_sr_th =
|
|
bcn->vendor.cco_phase_check_tf_sr_th;
|
|
vendor_roam->cco_phase_gap_own_h =
|
|
bcn->vendor.cco_phase_gap_own_h;
|
|
vendor_roam->cco_phase_gap_own_l =
|
|
bcn->vendor.cco_phase_gap_own_l;
|
|
vendor_roam->cco_phase_gap_other =
|
|
bcn->vendor.cco_phase_gap_other;
|
|
vendor_roam->level_score_h_th =
|
|
bcn->vendor.level_score_h_th;
|
|
vendor_roam->level_score_h =
|
|
bcn->vendor.level_score_h;
|
|
vendor_roam->level_score_l =
|
|
bcn->vendor.level_score_l;
|
|
vendor_roam->cco_good_tf_sr_th =
|
|
bcn->vendor.cco_good_tf_sr_th;
|
|
vendor_roam->cco_good_tx_sr_th =
|
|
bcn->vendor.cco_good_tx_sr_th;
|
|
vendor_roam->cco_good_rx_sr_th =
|
|
bcn->vendor.cco_good_rx_sr_th;
|
|
vendor_roam->pco_good_tf_sr_th =
|
|
bcn->vendor.pco_good_tf_sr_th;
|
|
vendor_roam->pco_good_tx_sr_th =
|
|
bcn->vendor.pco_good_tx_sr_th;
|
|
vendor_roam->pco_good_rx_sr_th =
|
|
bcn->vendor.pco_good_rx_sr_th;
|
|
vendor_roam->clamber_tf_sr_th =
|
|
bcn->vendor.clamber_tf_sr_th;
|
|
vendor_roam->clamber_target_tf_sr_th =
|
|
bcn->vendor.clamber_target_tf_sr_th;
|
|
vendor_roam->proxy_tf_sr_rank =
|
|
bcn->vendor.proxy_tf_sr_rank;
|
|
vendor_roam->roam_learn_cnt =
|
|
bcn->vendor.roam_learn_cnt;
|
|
}
|
|
if (bcn->vendor.app_data_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add app data related vendor entry */
|
|
vendor_data = (beacon_entry_vendor_data_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_data_t);
|
|
os_mem_set(vendor_data, 0, sizeof(*vendor_data));
|
|
vendor_data->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_DATA;
|
|
vendor_data->beacon_entry_len = sizeof(*vendor_data);
|
|
os_mem_cpy(vendor_data->data, bcn->vendor.app_data,
|
|
sizeof(bcn->vendor.app_data));
|
|
}
|
|
if (bcn->vendor.addr_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add debug related vendor entry */
|
|
vendor_debug = (beacon_entry_vendor_debug_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_debug_t);
|
|
os_mem_set(vendor_debug, 0, sizeof(*vendor_debug));
|
|
vendor_debug->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_DEBUG;
|
|
vendor_debug->beacon_entry_len = sizeof(*vendor_debug);
|
|
iot_mac_addr_cpy(vendor_debug->addr, bcn->vendor.addr);
|
|
}
|
|
if (bcn->vendor.tsfm_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add tsfm related vendor entry */
|
|
vendor_tsfm = (beacon_entry_vendor_tsfm_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_tsfm_t);
|
|
os_mem_set(vendor_tsfm, 0, sizeof(*vendor_tsfm));
|
|
vendor_tsfm->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_TSFM;
|
|
vendor_tsfm->beacon_entry_len = sizeof(*vendor_tsfm);
|
|
vendor_tsfm->rpt_tsfm_dur = bcn->vendor.rpt_tsfm_dur;
|
|
vendor_tsfm->tsfm_algorithm =
|
|
bcn->vendor.tsfm_algorithm;
|
|
vendor_tsfm->tsfm_cco_detect_en =
|
|
bcn->vendor.tsfm_cco_detect_en;
|
|
vendor_tsfm->tsfm_low_snr_th =
|
|
bcn->vendor.tsfm_low_snr_th;
|
|
vendor_tsfm->tsfm_snr_stat_high_th =
|
|
bcn->vendor.tsfm_snr_stat_high_th;
|
|
vendor_tsfm->check_tsfm_dur =
|
|
bcn->vendor.check_tsfm_dur;
|
|
vendor_tsfm->tsfm_snr_diff_th1 =
|
|
bcn->vendor.tsfm_snr_diff_th1;
|
|
vendor_tsfm->tsfm_snr_diff_th2 =
|
|
bcn->vendor.tsfm_snr_diff_th2;
|
|
vendor_tsfm->tsfm_level_big_diff_th =
|
|
bcn->vendor.tsfm_level_big_diff_th;
|
|
vendor_tsfm->tsfm_cco_low_snr_th =
|
|
bcn->vendor.tsfm_cco_low_snr_th;
|
|
vendor_tsfm->tsfm_cco_snr_penal =
|
|
bcn->vendor.tsfm_cco_snr_penal;
|
|
vendor_tsfm->tsfm_cco_diff_th1 =
|
|
bcn->vendor.tsfm_cco_diff_th1;
|
|
vendor_tsfm->tsfm_cco_diff_th2 =
|
|
bcn->vendor.tsfm_cco_diff_th2;
|
|
vendor_tsfm->tsfm_zc_diff_th1 =
|
|
bcn->vendor.tsfm_zc_diff_th1;
|
|
vendor_tsfm->tsfm_zc_diff_th2 =
|
|
bcn->vendor.tsfm_zc_diff_th2;
|
|
vendor_tsfm->tsfm_zc_diff_th3 =
|
|
bcn->vendor.tsfm_zc_diff_th3;
|
|
vendor_tsfm->tsfm_zc_diff_th4 =
|
|
bcn->vendor.tsfm_zc_diff_th4;
|
|
vendor_tsfm->tsfm_snr_bc_factor =
|
|
bcn->vendor.tsfm_snr_bc_factor;
|
|
vendor_tsfm->tsfm_snr_sof_factor =
|
|
bcn->vendor.tsfm_snr_sof_factor;
|
|
}
|
|
if (bcn->vendor.passcode_valid) {
|
|
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;
|
|
}
|
|
if (bcn->vendor.rf_power_valid ||
|
|
bcn->vendor.force_link_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add rf related vendor entry */
|
|
vendor_rf = (beacon_entry_vendor_rf_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_rf_t);
|
|
os_mem_set(vendor_rf, 0, sizeof(*vendor_rf));
|
|
vendor_rf->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_RF;
|
|
vendor_rf->beacon_entry_len = sizeof(*vendor_rf);
|
|
vendor_rf->rf_power = bcn->vendor.rf_power;
|
|
vendor_rf->rf_power_valid = bcn->vendor.rf_power_valid;
|
|
vendor_rf->force_link_valid = bcn->vendor.force_link_valid;
|
|
vendor_rf->force_rf_link = bcn->vendor.force_rf_link;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_UNKNOWN:
|
|
{
|
|
/* fill in unknown entry info */
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_UNKNOWN] &&
|
|
bcn->unknown_entry && iot_pkt_data_len(bcn->unknown_entry)) {
|
|
plh->beacon_entry_num++;
|
|
p_unknown = iot_pkt_data(bcn->unknown_entry);
|
|
if (get_bcn_entry_hdr_len(p_unknown[0]) == 3) {
|
|
unknown_len = ((uint16_t)p_unknown[2]) << 8;
|
|
unknown_len |= p_unknown[1];
|
|
} else {
|
|
unknown_len = p_unknown[1];
|
|
}
|
|
os_mem_cpy(*tmp, p_unknown, unknown_len);
|
|
(*tmp) += unknown_len;
|
|
iot_pkt_pull(bcn->unknown_entry, unknown_len);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
void mac_beacon_fill_buf_spg(mac_beacon_ctx_t *bcn, uint8_t **tmp,
|
|
bool_t is_detect)
|
|
{
|
|
uint8_t *p_unknown;
|
|
uint16_t unknown_len;
|
|
|
|
/* fill in FC */
|
|
spg_frame_control_t *spg_fc = (spg_frame_control_t*)(*tmp);
|
|
uint32_t ts;
|
|
(*tmp) += sizeof(spg_frame_control_t);
|
|
if (bcn->beacon_component_enable[MAC_BC_FC_INFO]) {
|
|
|
|
spg_fc->delimiter_type = FC_DELIM_BEACON;
|
|
spg_fc->access_ind = bcn->fc.net_type;
|
|
spg_fc->snid = (uint8_t)bcn->fc.nid;
|
|
ts = mac_sched_get_ntb((mac_vdev_t *)bcn->ref_vdev_ptr);
|
|
if (bcn->fc.is_rf) {
|
|
spg_fc->vf.rf_bcn.time_stamp = ts;
|
|
spg_fc->vf.rf_bcn.src_tei = vdev_get_tei(bcn->ref_vdev_ptr);
|
|
spg_fc->vf.rf_bcn.bcn_period_cnt = bcn->fc.bp_cnt;
|
|
} else {
|
|
spg_fc->vf.bcn.time_stamp = ts;
|
|
spg_fc->vf.bcn.bcn_period_cnt = bcn->fc.bp_cnt;
|
|
spg_fc->vf.bcn.src_tei = vdev_get_tei(bcn->ref_vdev_ptr);
|
|
spg_fc->vf.bcn.sym_num = 0; /* filled by HW */
|
|
spg_fc->vf.bcn.phase_num = bcn->fc.phase;
|
|
}
|
|
#if (MAC_SCHED_DEBUG || RUNTIME_DEBUG)
|
|
iot_printf("%s curr ntb:%lu, start ntb %lu, nid %lu phase %lu\n",
|
|
__FUNCTION__, ts, bcn->time_slot.bp_start_ntb, bcn->fc.nid,
|
|
bcn->fc.phase);
|
|
iot_dbglog_input(PLC_MAC_BEACON_MID, DBGLOG_INFO,
|
|
IOT_MAC_BEACON_TX_NTB_INFO, 4, ts, bcn->time_slot.bp_start_ntb,
|
|
bcn->fc.nid, bcn->fc.phase);
|
|
#endif
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
/* fill in beacon payload fix header */
|
|
spg_beacon_payload_std_header_t *plh =
|
|
(spg_beacon_payload_std_header_t *)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_payload_std_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->short_network_id =
|
|
bcn->spg_uniq_bc_str.payload_header.short_network_id;
|
|
plh->fixed_hdr.simple_beacon =
|
|
bcn->spg_uniq_bc_str.payload_header.simple_beacon;
|
|
plh->rf_channel = bcn->spg_uniq_bc_str.payload_header.rf_channel;
|
|
plh->rf_option = bcn->spg_uniq_bc_str.payload_header.rf_option;
|
|
plh->rsvd1 = bcn->spg_uniq_bc_str.payload_header.used_rsvd1;
|
|
plh->rsvd2 = bcn->spg_uniq_bc_str.payload_header.used_rsvd2;
|
|
/* entry count will be filled in later */
|
|
plh->beacon_entry_num = 0;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
/* fill in the beacon control info, CCO itself manage bcn entries fill
|
|
* order, while STA follow CCO's behavior
|
|
*/
|
|
if (PLC_DEV_ROLE_CCO == mac_vdev_cfg_get_node_role(
|
|
(mac_vdev_t *)bcn->ref_vdev_ptr)) {
|
|
os_mem_set(bcn->entry_sort, 0x00, sizeof(bcn->entry_sort));
|
|
bcn->entry_sort_cnt = 10;
|
|
bcn->entry_sort[0] = SPG_MAC_BCN_TYPE_ID_STA_CAP;
|
|
bcn->entry_sort[1] = SPG_MAC_BCN_TYPE_ID_RT_PARAM;
|
|
bcn->entry_sort[2] = SPG_MAC_BCN_TYPE_ID_FREQ_CHQ;
|
|
bcn->entry_sort[3] = SPG_MAC_BCN_TYPE_ID_RF_CHANNEL_CHQ;
|
|
bcn->entry_sort[4] = SPG_MAC_BCN_TYPE_ID_RF_ROUTE;
|
|
bcn->entry_sort[5] = SPG_MAC_BCN_TYPE_ID_METER;
|
|
bcn->entry_sort[6] = SPG_MAC_BCN_TYPE_ID_FB_DETECT;
|
|
bcn->entry_sort[7] = SPG_MAC_BCN_TYPE_ID_RTC;
|
|
bcn->entry_sort[8] = MAC_BCN_TYPE_ID_VENDOR_SPEC;
|
|
bcn->entry_sort[9] = SPG_MAC_BCN_TYPE_ID_TIME_SLOT;
|
|
}
|
|
|
|
for (uint8_t k = 0; k < bcn->entry_sort_cnt; k++) {
|
|
switch (bcn->entry_sort[k])
|
|
{
|
|
case SPG_MAC_BCN_TYPE_ID_STA_CAP:
|
|
{
|
|
/* fill in sta cap */
|
|
spg_beacon_entry_sta_cap_t *cap = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_STA_CAP]) {
|
|
plh->beacon_entry_num++;
|
|
cap = (spg_beacon_entry_sta_cap_t *)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_sta_cap_t);
|
|
|
|
cap->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_STA_CAP;
|
|
cap->beacon_entry_len = sizeof(*cap);
|
|
cap->tei = bcn->spg_uniq_bc_str.sta_cap.tei;
|
|
cap->pco_tei = bcn->spg_uniq_bc_str.sta_cap.proxy;
|
|
cap->reach_rate_to_cco =
|
|
bcn->spg_uniq_bc_str.sta_cap.min_ul_dl_sr;
|
|
cap->node_role = bcn->spg_uniq_bc_str.sta_cap.role;
|
|
cap->node_level = bcn->spg_uniq_bc_str.sta_cap.level;
|
|
cap->phase = bcn->spg_uniq_bc_str.sta_cap.phase;
|
|
cap->bcn_used_flag =
|
|
bcn->spg_uniq_bc_str.sta_cap.allow_chan_eval;
|
|
iot_mac_addr_cpy(cap->src_mac_addr,
|
|
bcn->spg_uniq_bc_str.sta_cap.addr);
|
|
cap->rf_hop = bcn->spg_uniq_bc_str.sta_cap.rf_hop;
|
|
cap->rsvd = bcn->spg_uniq_bc_str.sta_cap.used_rsvd;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_MAC_BCN_TYPE_ID_RT_PARAM:
|
|
{
|
|
/* fill in the routing info */
|
|
spg_beacon_entry_route_t *prt = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_RT_PARAM]) {
|
|
plh->beacon_entry_num++;
|
|
prt = (spg_beacon_entry_route_t*)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_route_t);
|
|
|
|
prt->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_RT_PARAM;
|
|
prt->beacon_entry_len = sizeof(*prt);
|
|
prt->routing_update_intval =
|
|
bcn->spg_uniq_bc_str.route_param.rt_period;
|
|
prt->next_update_countdown =
|
|
bcn->spg_uniq_bc_str.route_param.rt_left_period;
|
|
prt->rsvd1 = bcn->spg_uniq_bc_str.route_param.used_rsvd1;
|
|
os_mem_cpy(prt->rsvd2,
|
|
bcn->spg_uniq_bc_str.route_param.used_rsvd2,
|
|
sizeof(prt->rsvd2));
|
|
iot_mac_addr_cpy(prt->cco_mac_addr,
|
|
bcn->spg_uniq_bc_str.route_param.cco_addr);
|
|
}
|
|
break;
|
|
}
|
|
case SPG_MAC_BCN_TYPE_ID_FREQ_CHQ:
|
|
{
|
|
/* fill in the freq change info */
|
|
spg_beacon_entry_freq_change_t *fqc = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_FREQ_CHG]) {
|
|
|
|
plh->beacon_entry_num++;
|
|
fqc = (spg_beacon_entry_freq_change_t*)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_freq_change_t);
|
|
fqc->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_FREQ_CHQ;
|
|
fqc->beacon_entry_len = sizeof(*fqc);
|
|
fqc->target_freq = bcn->freq_chg.targer_freq;
|
|
fqc->change_countdown = bcn->freq_chg.time_left;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_MAC_BCN_TYPE_ID_RF_CHANNEL_CHQ:
|
|
{
|
|
/* fill in the rf channel change info */
|
|
spg_beacon_entry_rf_channel_chg_t *rf_channel = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_RF_CHANNEL_CHG]) {
|
|
plh->beacon_entry_num++;
|
|
rf_channel = (spg_beacon_entry_rf_channel_chg_t*)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_rf_channel_chg_t);
|
|
rf_channel->beacon_entry_type =
|
|
SPG_MAC_BCN_TYPE_ID_RF_CHANNEL_CHQ;
|
|
rf_channel->beacon_entry_len = sizeof(*rf_channel);
|
|
rf_channel->target_rf = bcn->rf_chg.target_rf_channel;
|
|
rf_channel->target_option = bcn->rf_chg.target_rf_option;
|
|
rf_channel->time_left = bcn->rf_chg.time_left;
|
|
rf_channel->rsvd = bcn->rf_chg.used_rsvd;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_MAC_BCN_TYPE_ID_RF_ROUTE:
|
|
{
|
|
/* fill in the rf route param info */
|
|
spg_beacon_entry_rf_route_t *rf_route = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_RF_ROUTE]) {
|
|
plh->beacon_entry_num++;
|
|
rf_route = (spg_beacon_entry_rf_route_t*)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_rf_route_t);
|
|
rf_route->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_RF_ROUTE;
|
|
rf_route->beacon_entry_len = sizeof(*rf_route);
|
|
rf_route->rf_dis_period = bcn->rf_route.rf_dis_period;
|
|
rf_route->rf_age_period = bcn->rf_route.rf_age_period;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_MAC_BCN_TYPE_ID_METER:
|
|
{
|
|
/* fill in the meter info */
|
|
spg_beacon_entry_meter_t *meter = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_METER]) {
|
|
plh->beacon_entry_num++;
|
|
meter = (spg_beacon_entry_meter_t*)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_meter_t) + bcn->meter.len;
|
|
meter->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_METER;
|
|
meter->beacon_entry_len = sizeof(*meter) + bcn->meter.len;
|
|
os_mem_cpy(meter->data, bcn->meter.data, bcn->meter.len);
|
|
}
|
|
break;
|
|
}
|
|
case SPG_MAC_BCN_TYPE_ID_FB_DETECT:
|
|
{
|
|
/* fill in the freq band detection info */
|
|
spg_beacon_entry_fb_detect_t *fb_detect = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_FB_DETECT] &&
|
|
!is_detect) {
|
|
plh->beacon_entry_num++;
|
|
fb_detect = (spg_beacon_entry_fb_detect_t*)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_fb_detect_t);
|
|
fb_detect->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_FB_DETECT;
|
|
fb_detect->beacon_entry_len = sizeof(*fb_detect);
|
|
fb_detect->band_id = bcn->fb_detect.band_id;
|
|
fb_detect->d_csma_lid = bcn->fb_detect.d_csma_lid;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_MAC_BCN_TYPE_ID_RTC:
|
|
{
|
|
/* fill in the rtc info */
|
|
spg_beacon_entry_rtc_t *rtc = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_RTC]) {
|
|
plh->beacon_entry_num++;
|
|
rtc = (spg_beacon_entry_rtc_t*)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_rtc_t);
|
|
rtc->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_RTC;
|
|
rtc->beacon_entry_len = sizeof(*rtc);
|
|
rtc->cco_date = bcn->rtc.cco_date;
|
|
rtc->cco_ntb = bcn->rtc.cco_ntb;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_MAC_BCN_TYPE_ID_TIME_SLOT:
|
|
{
|
|
/* fill in the time slot info */
|
|
spg_beacon_entry_time_slot_alloc_t *pts = NULL;
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_TIME_SLOT]) {
|
|
plh->beacon_entry_num++;
|
|
pts = (spg_beacon_entry_time_slot_alloc_t *)(*tmp);
|
|
(*tmp) += sizeof(spg_beacon_entry_time_slot_alloc_t);
|
|
|
|
pts->beacon_entry_type = SPG_MAC_BCN_TYPE_ID_TIME_SLOT;
|
|
/* bcn entry len need to be calculated later */
|
|
|
|
/* fixed len area */
|
|
pts->total_slot_non_cco_beacon =
|
|
bcn->time_slot.non_cco_bc_info.bc_cnt;
|
|
pts->total_slot_cco_beacon =
|
|
bcn->time_slot.cco_bc_cnt;
|
|
pts->csma_phase_num =
|
|
bcn->time_slot.csma_info.phase_cnt;
|
|
pts->total_slot_pco_beacon =
|
|
bcn->time_slot.proxy_bc_cnt;
|
|
pts->beacon_slot_period =
|
|
bcn->time_slot.bc_slot_dur * 10; /* unit 100us */
|
|
/* copy the original value, ignore unit */
|
|
pts->csma_slot_period =
|
|
bcn->time_slot.org_csma_slot_frag_s;
|
|
pts->bind_csma_phase_num =
|
|
bcn->time_slot.d_csma_info.phase_cnt; /* 1-3 */
|
|
pts->bind_csma_lid =
|
|
bcn->time_slot.d_csma_lid;
|
|
pts->tdma_period =
|
|
bcn->time_slot.tdma_slot_dur * 10; /* unit 100us */
|
|
pts->tdma_lid =
|
|
bcn->time_slot.tdma_lid;
|
|
pts->cur_beacon_timestamp =
|
|
bcn->time_slot.bp_start_ntb;
|
|
pts->beacon_period =
|
|
bcn->time_slot.bc_period * 10; /* unit 100us */
|
|
pts->rf_bc_slot_period =
|
|
(uint16_t)bcn->time_slot.rf_bc_slot_dur; /* unit ms */
|
|
pts->rsvd = bcn->time_slot.spg_used_rsvd;
|
|
|
|
/* non cco beacon area */
|
|
if (bcn->spg_uniq_bc_str.payload_header.type != PLC_BC_TYPE_D ||
|
|
bcn->sta.bc_d_with_non) {
|
|
/* skip beacon slot detail for discovery beacon */
|
|
for (int i = 0; i < bcn->time_slot.non_cco_bc_info.bc_cnt;
|
|
i++) {
|
|
spg_sub_beacon_entry_non_cco_beacon_t *pnc =
|
|
(spg_sub_beacon_entry_non_cco_beacon_t*)(*tmp);
|
|
(*tmp) += sizeof(*pnc);
|
|
pnc->tei_to_send =
|
|
bcn->time_slot.non_cco_bc_info.sta[i].tei;
|
|
pnc->beacon_type =
|
|
bcn->time_slot.non_cco_bc_info.sta[i].type;
|
|
pnc->tx_flag =
|
|
bcn->time_slot.non_cco_bc_info.sta[i].tx_flag;
|
|
}
|
|
}
|
|
|
|
/* csma time slot area */
|
|
for (int i = 0; i < bcn->time_slot.csma_info.phase_cnt; i++) {
|
|
spg_sub_beacon_entry_csma_slot_t *pct =
|
|
(spg_sub_beacon_entry_csma_slot_t*)(*tmp);
|
|
(*tmp) += sizeof(*pct);
|
|
|
|
pct->csma_period =
|
|
bcn->time_slot.csma_info.slot_dur[i] * 10;
|
|
pct->phase = bcn->time_slot.csma_info.phase[i];
|
|
}
|
|
|
|
/* bind csma time slot area */
|
|
for (int i = 0; i < bcn->time_slot.d_csma_info.phase_cnt; i++) {
|
|
spg_sub_beacon_entry_bind_csma_slot_t *pbc =
|
|
(spg_sub_beacon_entry_bind_csma_slot_t*)(*tmp);
|
|
(*tmp) += sizeof(*pbc);
|
|
|
|
pbc->bind_csma_period =
|
|
bcn->time_slot.d_csma_info.slot_dur[i] * 10;
|
|
pbc->phase = bcn->time_slot.d_csma_info.phase[i];
|
|
}
|
|
|
|
/* recal the total len, exclude header len */
|
|
pts->beacon_entry_len =
|
|
(uint16_t)((*tmp) - (uint8_t*)pts);
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_VENDOR_SPEC:
|
|
{
|
|
/* fill in the vendor specific info */
|
|
beacon_entry_vendor_spec_t *vendor = NULL;
|
|
beacon_entry_vendor_roam_t *vendor_roam = NULL;
|
|
beacon_entry_vendor_data_t *vendor_data = NULL;
|
|
beacon_entry_vendor_debug_t *vendor_debug = NULL;
|
|
beacon_entry_vendor_tsfm_t *vendor_tsfm = NULL;
|
|
beacon_entry_vendor_security_t *vendor_sec = NULL;
|
|
beacon_entry_vendor_rf_t *vendor_rf = NULL;
|
|
/* check vendor app data size */
|
|
BUILD_BUG_ON(MAC_BC_APP_DATA_MAX == sizeof(vendor_data->data));
|
|
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_VENDOR_SPEC]) {
|
|
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;
|
|
if (bcn->vendor.th_data_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add roaming related vendor entry */
|
|
vendor_roam = (beacon_entry_vendor_roam_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_roam_t);
|
|
os_mem_set(vendor_roam, 0, sizeof(*vendor_roam));
|
|
vendor_roam->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_ROAM;
|
|
vendor_roam->beacon_entry_len = sizeof(*vendor_roam);
|
|
vendor_roam->sta_proxy_weight_rank =
|
|
bcn->vendor.sta_proxy_weight_rank;
|
|
vendor_roam->sta_proxy_good_tf_sr_th =
|
|
bcn->vendor.sta_proxy_good_tf_sr_th;
|
|
vendor_roam->sta_roaming_gap_h =
|
|
bcn->vendor.sta_roaming_gap_h;
|
|
vendor_roam->sta_roaming_gap_l =
|
|
bcn->vendor.sta_roaming_gap_l;
|
|
vendor_roam->cco_phase_check_tf_sr_th =
|
|
bcn->vendor.cco_phase_check_tf_sr_th;
|
|
vendor_roam->cco_phase_gap_own_h =
|
|
bcn->vendor.cco_phase_gap_own_h;
|
|
vendor_roam->cco_phase_gap_own_l =
|
|
bcn->vendor.cco_phase_gap_own_l;
|
|
vendor_roam->cco_phase_gap_other =
|
|
bcn->vendor.cco_phase_gap_other;
|
|
vendor_roam->level_score_h_th =
|
|
bcn->vendor.level_score_h_th;
|
|
vendor_roam->level_score_h =
|
|
bcn->vendor.level_score_h;
|
|
vendor_roam->level_score_l =
|
|
bcn->vendor.level_score_l;
|
|
vendor_roam->cco_good_tf_sr_th =
|
|
bcn->vendor.cco_good_tf_sr_th;
|
|
vendor_roam->cco_good_tx_sr_th =
|
|
bcn->vendor.cco_good_tx_sr_th;
|
|
vendor_roam->cco_good_rx_sr_th =
|
|
bcn->vendor.cco_good_rx_sr_th;
|
|
vendor_roam->pco_good_tf_sr_th =
|
|
bcn->vendor.pco_good_tf_sr_th;
|
|
vendor_roam->pco_good_tx_sr_th =
|
|
bcn->vendor.pco_good_tx_sr_th;
|
|
vendor_roam->pco_good_rx_sr_th =
|
|
bcn->vendor.pco_good_rx_sr_th;
|
|
vendor_roam->clamber_tf_sr_th =
|
|
bcn->vendor.clamber_tf_sr_th;
|
|
vendor_roam->clamber_target_tf_sr_th =
|
|
bcn->vendor.clamber_target_tf_sr_th;
|
|
vendor_roam->proxy_tf_sr_rank =
|
|
bcn->vendor.proxy_tf_sr_rank;
|
|
vendor_roam->roam_learn_cnt =
|
|
bcn->vendor.roam_learn_cnt;
|
|
}
|
|
if (bcn->vendor.app_data_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add app data related vendor entry */
|
|
vendor_data = (beacon_entry_vendor_data_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_data_t);
|
|
os_mem_set(vendor_data, 0, sizeof(*vendor_data));
|
|
vendor_data->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_DATA;
|
|
vendor_data->beacon_entry_len = sizeof(*vendor_data);
|
|
os_mem_cpy(vendor_data->data, bcn->vendor.app_data,
|
|
sizeof(bcn->vendor.app_data));
|
|
}
|
|
if (bcn->vendor.addr_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add debug related vendor entry */
|
|
vendor_debug = (beacon_entry_vendor_debug_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_debug_t);
|
|
os_mem_set(vendor_debug, 0, sizeof(*vendor_debug));
|
|
vendor_debug->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_DEBUG;
|
|
vendor_debug->beacon_entry_len = sizeof(*vendor_debug);
|
|
iot_mac_addr_cpy(vendor_debug->addr, bcn->vendor.addr);
|
|
}
|
|
if (bcn->vendor.tsfm_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add tsfm related vendor entry */
|
|
vendor_tsfm = (beacon_entry_vendor_tsfm_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_tsfm_t);
|
|
os_mem_set(vendor_tsfm, 0, sizeof(*vendor_tsfm));
|
|
vendor_tsfm->beacon_entry_type =
|
|
MAC_BCN_TYPE_ID_VENDOR_TSFM;
|
|
vendor_tsfm->beacon_entry_len = sizeof(*vendor_tsfm);
|
|
vendor_tsfm->rpt_tsfm_dur = bcn->vendor.rpt_tsfm_dur;
|
|
vendor_tsfm->tsfm_algorithm = bcn->vendor.tsfm_algorithm;
|
|
vendor_tsfm->tsfm_cco_detect_en =
|
|
bcn->vendor.tsfm_cco_detect_en;
|
|
vendor_tsfm->tsfm_low_snr_th = bcn->vendor.tsfm_low_snr_th;
|
|
vendor_tsfm->tsfm_snr_stat_high_th =
|
|
bcn->vendor.tsfm_snr_stat_high_th;
|
|
vendor_tsfm->check_tsfm_dur = bcn->vendor.check_tsfm_dur;
|
|
vendor_tsfm->tsfm_snr_diff_th1 =
|
|
bcn->vendor.tsfm_snr_diff_th1;
|
|
vendor_tsfm->tsfm_snr_diff_th2 =
|
|
bcn->vendor.tsfm_snr_diff_th2;
|
|
vendor_tsfm->tsfm_level_big_diff_th =
|
|
bcn->vendor.tsfm_level_big_diff_th;
|
|
vendor_tsfm->tsfm_cco_low_snr_th =
|
|
bcn->vendor.tsfm_cco_low_snr_th;
|
|
vendor_tsfm->tsfm_cco_snr_penal =
|
|
bcn->vendor.tsfm_cco_snr_penal;
|
|
vendor_tsfm->tsfm_cco_diff_th1 =
|
|
bcn->vendor.tsfm_cco_diff_th1;
|
|
vendor_tsfm->tsfm_cco_diff_th2 =
|
|
bcn->vendor.tsfm_cco_diff_th2;
|
|
vendor_tsfm->tsfm_zc_diff_th1 =
|
|
bcn->vendor.tsfm_zc_diff_th1;
|
|
vendor_tsfm->tsfm_zc_diff_th2 =
|
|
bcn->vendor.tsfm_zc_diff_th2;
|
|
vendor_tsfm->tsfm_zc_diff_th3 =
|
|
bcn->vendor.tsfm_zc_diff_th3;
|
|
vendor_tsfm->tsfm_zc_diff_th4 =
|
|
bcn->vendor.tsfm_zc_diff_th4;
|
|
vendor_tsfm->tsfm_snr_bc_factor =
|
|
bcn->vendor.tsfm_snr_bc_factor;
|
|
vendor_tsfm->tsfm_snr_sof_factor =
|
|
bcn->vendor.tsfm_snr_sof_factor;
|
|
}
|
|
if (bcn->vendor.passcode_valid) {
|
|
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;
|
|
}
|
|
if (bcn->vendor.rf_power_valid ||
|
|
bcn->vendor.force_link_valid) {
|
|
plh->beacon_entry_num++;
|
|
/* add rf related vendor entry */
|
|
vendor_rf = (beacon_entry_vendor_rf_t *)(*tmp);
|
|
(*tmp) += sizeof(beacon_entry_vendor_rf_t);
|
|
os_mem_set(vendor_rf, 0, sizeof(*vendor_rf));
|
|
vendor_rf->beacon_entry_type = MAC_BCN_TYPE_ID_VENDOR_RF;
|
|
vendor_rf->beacon_entry_len = sizeof(*vendor_rf);
|
|
vendor_rf->rf_power = bcn->vendor.rf_power;
|
|
vendor_rf->rf_power_valid = bcn->vendor.rf_power_valid;
|
|
vendor_rf->force_link_valid = bcn->vendor.force_link_valid;
|
|
vendor_rf->force_rf_link = bcn->vendor.force_rf_link;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BCN_TYPE_ID_UNKNOWN:
|
|
{
|
|
/* fill in unknown entry info */
|
|
if (bcn->beacon_component_enable[MAC_BC_BMI_UNKNOWN] &&
|
|
bcn->unknown_entry && iot_pkt_data_len(bcn->unknown_entry)) {
|
|
plh->beacon_entry_num++;
|
|
p_unknown = iot_pkt_data(bcn->unknown_entry);
|
|
if (get_bcn_entry_hdr_len_spg(p_unknown[0]) == 3) {
|
|
unknown_len = ((uint16_t)p_unknown[2]) << 8;
|
|
unknown_len |= p_unknown[1];
|
|
} else {
|
|
unknown_len = p_unknown[1];
|
|
}
|
|
os_mem_cpy(*tmp, p_unknown, unknown_len);
|
|
(*tmp) += unknown_len;
|
|
iot_pkt_pull(bcn->unknown_entry, unknown_len);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
void mac_beacon_fill_pld_icv(uint32_t proto, uint8_t *data,
|
|
iot_pkt_t* bcn_buf)
|
|
{
|
|
IOT_ASSERT(data);
|
|
uint8_t fc_len = mac_get_mpdu_fc_len(proto);
|
|
|
|
switch (proto) {
|
|
case PLC_PROTO_TYPE_SG:
|
|
{
|
|
#if SUPPORT_IEEE_1901
|
|
i1901_beacon_payload_icv_t *icv = NULL;
|
|
icv = (i1901_beacon_payload_icv_t*)data;
|
|
icv->icv = iot_getcrc32_update(CRC32_INIT_VECT_I1901,
|
|
iot_pkt_data(bcn_buf) + fc_len,
|
|
(uint32_t)(data - iot_pkt_data(bcn_buf) - fc_len));
|
|
#else
|
|
beacon_payload_icv_t *icv = NULL;
|
|
icv = (beacon_payload_icv_t*)data;
|
|
icv->icv =
|
|
iot_getcrc32(iot_pkt_data(bcn_buf) + fc_len,
|
|
(uint32_t)(data - iot_pkt_data(bcn_buf) - fc_len));
|
|
#endif
|
|
break;
|
|
}
|
|
case PLC_PROTO_TYPE_SPG:
|
|
{
|
|
spg_beacon_payload_icv_t *icv = NULL;
|
|
icv = (spg_beacon_payload_icv_t*)data;
|
|
icv->icv =
|
|
iot_getcrc32(iot_pkt_data(bcn_buf) + fc_len,
|
|
(uint32_t)(data - iot_pkt_data(bcn_buf) - fc_len));
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void mac_beacon_fill_fc_tmi(uint32_t proto, void *fc, uint32_t tmi)
|
|
{
|
|
IOT_ASSERT(fc);
|
|
|
|
switch (proto) {
|
|
case PLC_PROTO_TYPE_SG:
|
|
{
|
|
frame_control_t *sg_fc = (frame_control_t *)fc;
|
|
sg_fc->vf.bcn.tmi = tmi & 0xf;
|
|
break;
|
|
}
|
|
case PLC_PROTO_TYPE_SPG:
|
|
{
|
|
spg_frame_control_t *spg_fc = (spg_frame_control_t *)fc;
|
|
spg_fc->vf.bcn.tmi = tmi & 0xf;
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint32_t mac_tx_fl_cal_bcn(uint8_t proto, uint8_t rate_mode,
|
|
uint32_t proto_band_id, uint8_t tmi, uint8_t ext_tmi)
|
|
{
|
|
uint32_t tx_fl = 0;
|
|
/* fl = symbol + fc + payload + bifs. then:
|
|
* symbol + fc = mac_rx_get_delim();
|
|
* payload = phy_get_flppb_from_table * 1. (for beacon, only 1pb num)
|
|
* bifs = mac_get_tx_bifs
|
|
*/
|
|
(void)proto; //TODO: check proto
|
|
//if (PLC_PROTO_TYPE_SG == proto)
|
|
{
|
|
uint32_t hw_band_id = phy_proto_band_to_hw_band(proto_band_id);
|
|
tx_fl = mac_rx_get_delim(rate_mode, hw_band_id)
|
|
+ phy_get_flppb_from_table(hw_band_id, tmi, ext_tmi)
|
|
+ mac_get_tx_bifs(proto);
|
|
}
|
|
|
|
return tx_fl;
|
|
}
|
|
|
|
/* beacon payload to send, it would add some FC or PB info into the iot_pkt_t
|
|
and to form an Beacon MPDU.
|
|
*/
|
|
uint8_t mac_beacon_tx(uint32_t proto, uint32_t proto_band_id,
|
|
mac_beacon_ctx_t *bcn, iot_pkt_t* bcn_buf)
|
|
{
|
|
uint8_t rid;
|
|
uint32_t tmi, ext_tmi;
|
|
uint32_t rate_mode;
|
|
uint32_t tx_power = PHY_FULL_PWR_DBUV;
|
|
uint32_t pb_size;
|
|
uint32_t fl;
|
|
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);
|
|
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));
|
|
#if SUPPORT_SMART_GRID
|
|
if (PLC_PROTO_TYPE_SG == proto) {
|
|
/* fill sg fill beacon payload */
|
|
mac_beacon_fill_buf_sg(bcn, &tmp);
|
|
#if SUPPORT_IEEE_1901
|
|
bc_pld_icv_len = sizeof(i1901_beacon_payload_icv_t);
|
|
#else
|
|
bc_pld_icv_len = sizeof(beacon_payload_icv_t);
|
|
#endif
|
|
bc_pb_resv_len = 0;
|
|
}
|
|
#endif
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
if (PLC_PROTO_TYPE_SPG == proto) {
|
|
bool_t is_detect = false;
|
|
if (phy_proto_single_band_id_get() != proto_band_id) {
|
|
is_detect = true;
|
|
}
|
|
/* fill spg beacon payload */
|
|
mac_beacon_fill_buf_spg(bcn, &tmp, is_detect);
|
|
bc_pld_icv_len = sizeof(spg_beacon_payload_icv_t);
|
|
bc_pb_resv_len = SPG_BCN_PB_RESV_LEN;
|
|
}
|
|
#endif
|
|
|
|
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;
|
|
|
|
/* get rate idx */
|
|
if (mac_bcn_get_rate(bcn->ref_vdev_ptr,
|
|
proto, true, bcn_len, proto_band_id, &rid, &rate_mode)) {
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
/* get pbsz, tmi and ext emi if not GP */
|
|
phy_get_tmi_by_rid(proto, rid, &tmi, &ext_tmi);
|
|
phy_get_rt_pbsz(proto, rid, &pb_size);
|
|
|
|
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_beacon_fill_fc_tmi(proto, fc, tmi);
|
|
|
|
IOT_ASSERT(iot_pkt_set_tail(bcn_buf, tmp));
|
|
fl = mac_tx_fl_cal_bcn((uint8_t)proto, (uint8_t)rate_mode,
|
|
proto_band_id, (uint8_t)tmi, (uint8_t)ext_tmi);
|
|
if (phy_proto_single_band_id_get() == proto_band_id) {
|
|
/* slot unit: 1ms, fl unit: 1us, bifs unit: 1us.
|
|
* for tx bcn, the mac hw will calculate how many count can be sent in this
|
|
* slot.
|
|
* 1. the last time for tx bcn, mac hw not care the bifs.
|
|
* 2. each slot must be reserved some time for hw operation.
|
|
*/
|
|
tx_cnt = (uint8_t)((bcn->time_slot.bc_slot_dur * 1000
|
|
+ mac_get_tx_bifs(proto)
|
|
- mac_tx_get_slot_guard((uint8_t)proto, (uint8_t)FC_DELIM_BEACON))
|
|
/ fl);
|
|
} else {
|
|
tx_cnt = PLC_BCN_DEF_DETECT_RETRY_CNT;
|
|
}
|
|
/* fix GW hplc + rf dual mode test bed channel conflict case, test bed
|
|
* always get history beacon frames from buffer pool, we should not retry
|
|
* tx beacon so as to let it get more new beacon frames
|
|
*/
|
|
if (PLC_DEV_ROLE_CCO == mac_vdev_cfg_get_node_role(
|
|
(mac_vdev_t *)bcn->ref_vdev_ptr)) {
|
|
if (mac_get_cert_test_flag() &&
|
|
/* modify retry cnt = 0 for sanxi cert test
|
|
* after received the beacon,
|
|
* the console sends an association request immediately,
|
|
* which will collide with the retry packet,
|
|
* so the retry is removed.
|
|
*/
|
|
(USER_TYPE_STATE_GRID_XIAN == iot_oem_get_user_type() ||
|
|
/* fix gw hplc test bed center beacon case, test bed not received phase
|
|
* A center beacon when using kl3 hardware device. we should retry
|
|
* phase A beacon
|
|
*/
|
|
bcn->fc.phase != PLC_PHASE_A)) {
|
|
retry_cnt = 0;
|
|
goto label_1;
|
|
}
|
|
}
|
|
retry_cnt = mac_cfg_get_bcn_def_retry_cnt();
|
|
label_1:
|
|
//default tx cnt = retry cnt + 1, 1 means this time is sent normally
|
|
tx_cnt = min(tx_cnt, retry_cnt + 1);
|
|
if (0 == tx_cnt) {
|
|
iot_printf("%s:tx_cnt=%d, fl=%d, bc_slot=%d,"
|
|
"bc_period=%d, band_id=%d, rid=%d, rate_mode=%d\n",
|
|
__FUNCTION__, tx_cnt, fl, bcn->time_slot.bc_slot_dur,
|
|
bcn->time_slot.bc_period, proto_band_id, rid, rate_mode);
|
|
IOT_ASSERT(0);
|
|
} else if (retry_cnt && (tx_cnt < (retry_cnt + 1))) {
|
|
retry_cnt = tx_cnt - 1;
|
|
}
|
|
|
|
mac_send_bcn(proto, proto_band_id,
|
|
((mac_vdev_t *)bcn->ref_vdev_ptr)->ref_pdev_id,
|
|
bcn_buf, rate_mode, bcn->fc.phase, retry_cnt, tx_power);
|
|
|
|
return tx_cnt;
|
|
}
|
|
|
|
uint32_t mac_beacon_rx_icv_get(uint8_t proto, iot_pkt_t* buf)
|
|
{
|
|
uint32_t bcn_icv = 0;
|
|
IOT_ASSERT(buf);
|
|
|
|
switch(proto) {
|
|
#if SUPPORT_SMART_GRID
|
|
case PLC_PROTO_TYPE_SG:
|
|
{
|
|
beacon_payload_icv_t *icv;
|
|
#if SUPPORT_IEEE_1901
|
|
icv = (beacon_payload_icv_t*)(iot_pkt_block_ptr(buf, IOT_PKT_BLOCK_TAIL)
|
|
- sizeof(beacon_payload_icv_t) - I1901_BCN_PB_CRC_LEN);
|
|
#else
|
|
icv = (beacon_payload_icv_t*)(iot_pkt_block_ptr(buf, IOT_PKT_BLOCK_TAIL)
|
|
- sizeof(beacon_payload_icv_t) - SG_BCN_PB_CRC_LEN);
|
|
#endif
|
|
bcn_icv = icv->icv;
|
|
break;
|
|
}
|
|
#endif
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
case PLC_PROTO_TYPE_SPG:
|
|
{
|
|
spg_beacon_payload_icv_t *icv;
|
|
icv = (spg_beacon_payload_icv_t*)(iot_pkt_block_ptr(buf,
|
|
IOT_PKT_BLOCK_TAIL) - sizeof(spg_beacon_payload_icv_t)
|
|
- SPG_BCN_PB_CRC_LEN - SPG_BCN_PB_RESV_LEN);
|
|
bcn_icv = icv->icv;
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return bcn_icv;
|
|
}
|
|
|
|
static void mac_beacon_rx_plh_get(uint8_t proto, bcn_pld_hdr_t *msg,
|
|
uint8_t *tmp, mac_rx_info_t *rx_info)
|
|
{
|
|
IOT_ASSERT(msg);
|
|
|
|
switch(proto) {
|
|
#if SUPPORT_SMART_GRID
|
|
case PLC_PROTO_TYPE_SG:
|
|
{
|
|
beacon_payload_fixed_header_t *plh_sg =
|
|
(beacon_payload_fixed_header_t *)tmp;
|
|
msg->beacon_type = plh_sg->beacon_type;
|
|
msg->beacon_seq_num = plh_sg->beacon_seq_num;
|
|
iot_mac_addr_cpy(msg->cco_addr, plh_sg->cco_mac_addr);
|
|
break;
|
|
}
|
|
#endif
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
case PLC_PROTO_TYPE_SPG:
|
|
{
|
|
spg_frame_control_t *fc_spg =
|
|
(spg_frame_control_t *)rx_info->fc;
|
|
spg_beacon_payload_fixed_header_t *plh_spg =
|
|
(spg_beacon_payload_fixed_header_t *)tmp;
|
|
msg->beacon_type = plh_spg->beacon_type;
|
|
msg->beacon_seq_num = fc_spg->vf.bcn.bcn_period_cnt;
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool_t mac_beacon_is_cco_type(uint32_t proto, bcn_pld_hdr_t *plh,
|
|
mac_vdev_t *vdev)
|
|
{
|
|
IOT_ASSERT(plh && vdev);
|
|
bool_t targ_cco_bc = true;
|
|
switch (proto) {
|
|
#if SUPPORT_SMART_GRID
|
|
case PLC_PROTO_TYPE_SG:
|
|
if (!iot_mac_addr_cmp(plh->cco_addr,
|
|
vdev->bcn_ctx.sg_uniq_bc_str.payload_header.cco_addr))
|
|
targ_cco_bc = false;
|
|
break;
|
|
#endif
|
|
#if SUPPORT_SOUTHERN_POWER_GRID
|
|
case PLC_PROTO_TYPE_SPG:
|
|
if (PLC_BC_TYPE_C != plh->beacon_type)
|
|
targ_cco_bc = false;
|
|
break;
|
|
#endif
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
|
|
return targ_cco_bc;
|
|
}
|
|
|
|
#if (!IOT_HTBUS_EN)
|
|
|
|
uint32_t mac_beacon_rx(uint8_t proto, void *vdev_ptr, iot_pkt_t* buf)
|
|
{
|
|
mac_vdev_t *vdev = (mac_vdev_t *)vdev_ptr;
|
|
uint8_t *tmp, new_bp = 0;
|
|
uint32_t i = 0;
|
|
uint32_t crc = 0;
|
|
uint32_t bcn_icv = 0;
|
|
mac_rx_info_t *rx_info;
|
|
|
|
if (!vdev || !buf) {
|
|
IOT_ASSERT(0);
|
|
goto err;
|
|
}
|
|
|
|
if (vdev->start_cfg.mac_bc_rx_func == NULL) {
|
|
goto err;
|
|
}
|
|
|
|
tmp = iot_pkt_block_ptr(buf, IOT_PKT_BLOCK_DATA);
|
|
rx_info = (mac_rx_info_t *)(tmp - sizeof(*rx_info));
|
|
|
|
/* check crc */
|
|
uint32_t bcn_len = \
|
|
iot_pkt_block_len(buf, IOT_PKT_BLOCK_DATA);
|
|
#if PLC_MAC_RX_DEBUG_LOG
|
|
if (rx_info->phy.is_rf) {
|
|
iot_printf("rx bcn len %d on option:%d, channel:%d\n",
|
|
bcn_len, rx_info->phy.rf_option, rx_info->phy.channel_id);
|
|
} else {
|
|
iot_printf("rx bcn len %d on band %d\n", bcn_len, rx_info->phy.band_id);
|
|
}
|
|
#endif
|
|
/* check beacon payload crc */
|
|
bcn_icv = mac_beacon_rx_icv_get(proto, buf);
|
|
uint32_t ret = 0;
|
|
ret = mac_crc_get_bcn_swcrc(proto, iot_pkt_data(buf), bcn_len, &crc);
|
|
if(ret == ERR_CRC_LEN)
|
|
{
|
|
iot_printf("pld len err, when mac calu crc!\n");
|
|
mem_dump((uint32_t *)buf, 21); // 4iot_pkt addr + 16desc + 1DW plod
|
|
goto err;
|
|
}
|
|
if (crc != bcn_icv) {
|
|
/* TODO: check with accurate len,
|
|
*/
|
|
mac_add_rx_bcn_err_cnt();
|
|
iot_printf("bcn crcerrcnt: %lu,"
|
|
"bcn_icv=0x%x, crc_cal=0x%x"
|
|
"\n", mac_get_rx_bcn_err_cnt(), bcn_icv, crc);
|
|
#if PLC_HW_ISSUE_ASSERT_LEVEL <= PLC_HW_ISSUE_ASSERT_ALL
|
|
IOT_ASSERT(0);
|
|
#endif
|
|
goto err;
|
|
}
|
|
|
|
/* get fixed header and fc info */
|
|
bcn_pld_hdr_t plh = { 0 };
|
|
rx_fc_msg_t rx_fc = { 0 };
|
|
mac_beacon_rx_plh_get(proto, &plh, tmp, rx_info);
|
|
mac_beacon_rx_fc_info_get(proto, rx_info, &rx_fc);
|
|
/* sync sta/pco's timestamp */
|
|
if ((mac_vdev_cfg_get_node_role(vdev) != PLC_DEV_ROLE_CCO) &&
|
|
(rx_fc.nid == vdev->bcn_ctx.fc.nid)) {
|
|
bool_t targ_cco_bc = \
|
|
mac_beacon_is_cco_type(proto, &plh, vdev);
|
|
uint32_t bc_period_cnt = vdev_get_bc_period_cnt(proto, vdev);
|
|
|
|
if (targ_cco_bc) {
|
|
#if ((HW_PLATFORM == HW_PLATFORM_SIMU) && (SCHED_SUPPORT == 0))
|
|
/* for HW scheduler not supported case, device may receive
|
|
* discovery beacon ahead of proxy beacon. ignore discovery beacon
|
|
* as the beacon slot detail of each tei is not available in
|
|
* discovery beacon. local device won't be able to decide if
|
|
* local device need to send out beacon for current beacon period.
|
|
*/
|
|
if (mac_get_tei(vdev) != PLC_TEI_INVAL &&
|
|
plh.beacon_type == PLC_BC_TYPE_D) {
|
|
goto err;
|
|
}
|
|
#endif
|
|
if (bc_period_cnt == 0) {
|
|
/* always accept the first beacon */
|
|
i = 1;
|
|
} else {
|
|
i = plh.beacon_seq_num - bc_period_cnt;
|
|
}
|
|
if (i && i <= PLC_BCN_DUPLICATE_GUARD) {
|
|
/* new beacon period, sync up the time stamp and save the
|
|
* start ntb
|
|
*/
|
|
new_bp = 1;
|
|
#if (MAC_SCHED_DEBUG || RUNTIME_DEBUG)
|
|
iot_printf("%s bc recv ntb %lu, bc send ntb %lu, "
|
|
"bp cnt %lu\n", __FUNCTION__,
|
|
mac_sched_get_ntb(vdev), rx_fc.time_stamp,
|
|
bc_period_cnt);
|
|
iot_dbglog_input(PLC_MAC_DATA_MID, DBGLOG_INFO,
|
|
IOT_MAC_BEACON_RX_NTB_INFO, 3, mac_sched_get_ntb(vdev),
|
|
rx_fc.time_stamp, bc_period_cnt);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
mac_add_rx_bcn_upload_cnt();
|
|
vdev->start_cfg.mac_bc_rx_func(vdev->start_cfg.mac_callback_arg,
|
|
buf, new_bp);
|
|
|
|
return ERR_OK;
|
|
|
|
err:
|
|
iot_pkt_free(buf);
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
uint32_t mac_update_beacon_internal(uint8_t pdev_id, uint8_t vdev_id,
|
|
mac_bc_update_t *ent, uint8_t *tx_cnt)
|
|
{
|
|
uint8_t is_boost = 0;
|
|
uint32_t ret = 0;
|
|
mac_vdev_t *vdev;
|
|
uint32_t proto = PHY_PROTO_TYPE_GET();
|
|
|
|
*tx_cnt = 0;
|
|
vdev = get_vdev_ptr(pdev_id, vdev_id);
|
|
if (vdev == NULL) {
|
|
ret = ERR_INVAL;
|
|
goto out;
|
|
}
|
|
|
|
/* boost mac task priority so as to update beacons quickly */
|
|
if ((mac_vdev_cfg_get_node_role(vdev) != PLC_DEV_ROLE_CCO)
|
|
&& ent->tx_req) {
|
|
is_boost = 1;
|
|
mac_boost_task_prio();
|
|
}
|
|
|
|
mac_beacon_ctx_t *bcn_ctxt =
|
|
&vdev->bcn_ctx;
|
|
/* get beacon info */
|
|
mac_bc_ent_str_info_t bc_ent_str = { 0 };
|
|
mac_beacon_uniq_info_get(proto, bcn_ctxt, &bc_ent_str);
|
|
IOT_ASSERT(bc_ent_str.plh_str_ptr &&
|
|
bc_ent_str.rt_param_str_ptr &&
|
|
bc_ent_str.sta_cap_str_ptr);
|
|
|
|
/* alwasy disable optional beacon entry for each update by default */
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_FC_INFO] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_FIX_P] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_STA_CAP] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_RT_PARAM] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_FREQ_CHG] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_TIME_SLOT] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_VENDOR_SPEC] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_METER] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_FB_DETECT] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_RF_CHANNEL_CHG] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_RF_ROUTE] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_RF_SIMPLE_PARAM] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_RTC] = 0;
|
|
bcn_ctxt->beacon_component_enable[MAC_BC_BMI_UNKNOWN] = 0;
|
|
bcn_ctxt->is_tx_detect = MAC_BEACON_IS_NORMAL;
|
|
bcn_ctxt->entry_sort_cnt = ent->entry_sort_cnt;
|
|
os_mem_cpy(bcn_ctxt->entry_sort, ent->entry_sort,
|
|
sizeof(bcn_ctxt->entry_sort));
|
|
|
|
for (int i = 0; i < ent->count; i++) {
|
|
switch (ent->entry[i].type)
|
|
{
|
|
case MAC_BC_FC_INFO:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->fc, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->fc));
|
|
bcn_ctxt->fc.nid = mac_mask_input_nid(bcn_ctxt->fc.nid);
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_FIX_P:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(bc_ent_str.plh_str_ptr,
|
|
ent->entry[i].data,
|
|
bc_ent_str.plh_str_size);
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_STA_CAP:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(bc_ent_str.sta_cap_str_ptr, ent->entry[i].data,
|
|
bc_ent_str.sta_cap_str_size);
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
#if CPLC_IOT_CERT_ENABLE
|
|
mac_check_power_by_level(vdev,
|
|
bcn_ctxt->sg_uniq_bc_str.sta_cap.level);
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_RT_PARAM:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(bc_ent_str.rt_param_str_ptr,
|
|
ent->entry[i].data, bc_ent_str.rt_param_str_size);
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_FREQ_CHG:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->freq_chg, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->freq_chg));
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_RF_CHANNEL_CHG:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->rf_chg, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->rf_chg));
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type] = 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_RF_ROUTE:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->rf_route, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->rf_route));
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type] = 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_TIME_SLOT:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->time_slot, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->time_slot));
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_METER:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->meter, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->meter));
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_FB_DETECT:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->fb_detect, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->fb_detect));
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
bcn_ctxt->is_tx_detect = MAC_BEACON_IS_DETECT;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_RTC:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->rtc, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->rtc));
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_VENDOR_SPEC:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(&bcn_ctxt->vendor, ent->entry[i].data,
|
|
sizeof(bcn_ctxt->vendor));
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_RF_SIMPLE_PARAM:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
os_mem_cpy(bc_ent_str.simple_param_str_ptr,
|
|
ent->entry[i].data, bc_ent_str.simple_param_str_size);
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
case MAC_BC_BMI_UNKNOWN:
|
|
{
|
|
if (ent->action[i] == MAC_BC_ACT_ADD) {
|
|
bcn_ctxt->unknown_entry = ent->entry[i].data;
|
|
bcn_ctxt->beacon_component_enable[ent->entry[i].type]
|
|
= 1;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
/* config NID to HW once the NID is available */
|
|
vdev_set_nid(vdev, bcn_ctxt->fc.nid);
|
|
|
|
if (mac_vdev_cfg_get_node_role(vdev) != PLC_DEV_ROLE_CCO) {
|
|
bcn_ctxt->sta.allow_reuse_ts = 1;
|
|
*tx_cnt = mac_update_beacon_sta(proto, vdev, ent);
|
|
} else {
|
|
*tx_cnt = mac_update_beacon_cco(proto, vdev, ent);
|
|
}
|
|
#if PLC_SUPPORT_DBG_PKT_MODE
|
|
vdev_set_block_dbg_pkt_4_rx_only(vdev, true);
|
|
#endif
|
|
|
|
out:
|
|
/* restore mac task default priority */
|
|
if (is_boost) {
|
|
mac_restore_task_prio();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#endif /* (!IOT_HTBUS_EN) */
|
|
|
|
uint32_t mac_update_beacon(uint8_t pdev_id, uint8_t vdev_id,
|
|
mac_bc_update_t *ent, uint8_t *tx_cnt)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_msg_sync_t *msg = mac_alloc_msg_sync();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->msg.type = MAC_MSG_TYPE_CVG;
|
|
msg->msg.id = MAC_MSG_ID_CVG_UPDATE_BC;
|
|
msg->msg.data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
|
|
msg->msg.data2 = ent;
|
|
mac_queue_msg_sync(msg, MAC_MSG_QUEUE_HP);
|
|
/* get result */
|
|
ret = msg->msg.data1;
|
|
*tx_cnt = (uint8_t)(((uint32_t)msg->msg.data2) & 0xFF);
|
|
mac_free_msg_sync(msg);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
#if (PLC_SUPPORT_CCO_ROLE)
|
|
|
|
uint32_t mac_start_beacon(uint8_t pdev_id, uint8_t vdev_id)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_msg_t *msg = mac_alloc_msg();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->type = MAC_MSG_TYPE_CVG;
|
|
msg->id = MAC_MSG_ID_CVG_START_BC;
|
|
msg->data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
|
|
mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t mac_start_beacon_internal(uint8_t pdev_id, uint8_t vdev_id)
|
|
{
|
|
mac_vdev_t *mac_vdev;
|
|
mac_beacon_ctx_t *bcn_ctx;
|
|
mac_rf_vdev_t *rf_vdev = NULL;
|
|
|
|
mac_vdev = get_vdev_ptr(pdev_id, vdev_id);
|
|
if (mac_vdev == NULL) {
|
|
return ERR_INVAL;
|
|
}
|
|
rf_vdev = get_rf_vdev_ptr(mac_vdev->ref_pdev_id,
|
|
RF_PDEV_ID, mac_vdev->rf_vdev_id);
|
|
|
|
bcn_ctx = &mac_vdev->bcn_ctx;
|
|
if (bcn_ctx->cco.started)
|
|
goto ret;
|
|
|
|
/* stop HW scheduler first if it's running */
|
|
mac_sched_stop(mac_vdev);
|
|
/* rf schedule stop */
|
|
mac_rf_sched_stop(rf_vdev);
|
|
|
|
/* set beacon period to be started in the near future */
|
|
bcn_ctx->cco.curr_start_ntb64 = mac_sched_get_ntb64(mac_vdev);
|
|
bcn_ctx->cco.curr_start_ntb64 += MAC_MS_TO_NTB(MAC_BP_AHEAD_NEXT_BP_DUR);
|
|
/* set command list scheduler and start the next beacon period */
|
|
bcn_ctx->cco.curr_start_ntb64 = mac_sched_cco_set(mac_vdev,
|
|
&bcn_ctx->time_slot, bcn_ctx->cco.curr_start_ntb64,
|
|
&bcn_ctx->cco.next_start_ntb64);
|
|
|
|
/* rf cco schedule set, start cco tx simple beacon */
|
|
mac_rf_sched_cco_set(rf_vdev, &mac_vdev->bcn_ctx.time_slot,
|
|
mac_vdev->bcn_ctx.cco.curr_start_ntb64,
|
|
mac_vdev->bcn_ctx.cco.next_start_ntb64);
|
|
|
|
bcn_ctx->cco.started = 1;
|
|
mac_config_tei(mac_vdev, vdev_get_tei(mac_vdev));
|
|
|
|
/* start check spur period timer */
|
|
mac_pdev_t *pdev = get_pdev_ptr(pdev_id);
|
|
mac_cco_check_spur_start_timer(&pdev->mac_check_spur_ctxt,
|
|
MAC_CCO_CHECK_SPUR_WAIT_PERIOD_START,
|
|
MAC_CHECK_SPUR_PD_MS);
|
|
|
|
ret:
|
|
return 0;
|
|
}
|
|
|
|
uint32_t mac_stop_beacon(uint8_t pdev_id, uint8_t vdev_id)
|
|
{
|
|
uint32_t ret = 0;
|
|
mac_msg_t *msg = mac_alloc_msg();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
msg->type = MAC_MSG_TYPE_CVG;
|
|
msg->id = MAC_MSG_ID_CVG_STOP_BC;
|
|
msg->data1 = (((uint32_t)pdev_id) << 8) | vdev_id;
|
|
mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t mac_stop_beacon_internal(uint8_t pdev_id, uint8_t vdev_id)
|
|
{
|
|
uint64_t start_ntb;
|
|
mac_vdev_t *mac_vdev;
|
|
mac_beacon_ctx_t *bcn_ctx;
|
|
mac_rf_vdev_t *rf_vdev = NULL;
|
|
|
|
mac_vdev = get_vdev_ptr(pdev_id, vdev_id);
|
|
if (mac_vdev == NULL) {
|
|
return ERR_INVAL;
|
|
}
|
|
rf_vdev = get_rf_vdev_ptr(mac_vdev->ref_pdev_id,
|
|
RF_PDEV_ID, mac_vdev->rf_vdev_id);
|
|
|
|
bcn_ctx = &mac_vdev->bcn_ctx;
|
|
if (bcn_ctx->cco.started == 0)
|
|
goto ret;
|
|
|
|
/* stop current HW scheduler */
|
|
mac_sched_stop(mac_vdev);
|
|
|
|
/* rf schedule stop */
|
|
mac_rf_sched_stop(rf_vdev);
|
|
|
|
/* start HW scheduler in rx only mode */
|
|
start_ntb = mac_sched_get_ntb64(mac_vdev);
|
|
mac_sched_set_csma_only(mac_vdev, start_ntb, 0);
|
|
|
|
/* rf csma only schedule set */
|
|
mac_rf_sched_set_csma_only(rf_vdev, start_ntb, 0);
|
|
|
|
bcn_ctx->cco.started = 0;
|
|
|
|
ret:
|
|
return 0;
|
|
}
|
|
|
|
#endif /* PLC_SUPPORT_CCO_ROLE */
|
|
|
|
uint32_t mac_send_bcn(uint32_t proto, uint32_t proto_band_id,
|
|
pdevid_t pdev_id, iot_pkt_t* bcn_buf,
|
|
uint32_t rate_mode, uint8_t phase, uint8_t retry_cnt, uint32_t tx_power)
|
|
{
|
|
uint32_t bcn_len, hw_retry_cnt, hw_band_id;
|
|
tx_mpdu_end *mpdu_end;
|
|
tx_mpdu_start *mpdu;
|
|
tx_pb_start *pb_start = NULL;
|
|
tx_dummy_node *dummy = NULL;
|
|
mac_queue_t swq_id;
|
|
uint8_t hwqid;
|
|
|
|
mac_pdev_t *pdev = g_mac_pdev[pdev_id];
|
|
uint32_t pb_hdr_resv_crc_len =
|
|
mac_get_pb_hdr_resv_crc_len(FC_DELIM_BEACON, proto);
|
|
uint8_t fc_len = mac_get_mpdu_fc_len(proto);
|
|
tx_fc_msg_t fc_info = { 0 };
|
|
|
|
mac_desc_get(&g_mac_desc_eng, PLC_TX_MPDU_END_POOL, (void **)&mpdu_end);
|
|
mac_desc_get(&g_mac_desc_eng, PLC_TX_MPDU_START_POOL, (void **)&mpdu);
|
|
mac_desc_get(&g_mac_desc_eng, PLC_TX_PB_START_POOL, (void **)&pb_start);
|
|
if (!(mpdu && mpdu_end && pb_start)) {
|
|
IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
|
|
mac_get_tx_msg_from_fc(proto, FC_DELIM_BEACON,
|
|
iot_pkt_data(bcn_buf), &fc_info);
|
|
|
|
iot_pkt_pull(bcn_buf, fc_len);
|
|
mac_beacon_send_fill_pb_start(proto, pb_start,
|
|
(uint32_t)iot_pkt_block_ptr(bcn_buf, IOT_PKT_BLOCK_DATA));
|
|
|
|
/*
|
|
* fill in mpdu start
|
|
*/
|
|
bcn_len = (uint16_t)iot_pkt_block_len(bcn_buf, IOT_PKT_BLOCK_DATA);
|
|
mac_tx_mpdu_fill_total_len(mpdu, bcn_len);
|
|
|
|
uint32_t pb_num = 1; /* bcn is 1 fixed */
|
|
uint32_t need_encry = 0;
|
|
uint32_t need_ack = 0;
|
|
/* for bcn the buffer is reused now */
|
|
uint32_t pb_buf_reuse = 1;
|
|
uint32_t sw_buf_offset = 0;
|
|
|
|
/*recovery pkt*/
|
|
iot_pkt_push(bcn_buf, fc_len);
|
|
|
|
uint32_t region_type;
|
|
lid_t lid;
|
|
bool_t is_tx_3phase = false;
|
|
bool_t is_sta = false;
|
|
if (phy_proto_single_band_id_get() == proto_band_id) {
|
|
/* if normal bcn, use PLC_BCN_REGION_BCN */
|
|
region_type = PLC_BCN_REGION_BCN;
|
|
lid = 0;
|
|
/* if normal bcn, beacon_mpdu->dummy */
|
|
mac_desc_get(&g_mac_desc_eng, PLC_TX_DUMMY_NODE_POOL, (void**)&dummy);
|
|
if (!dummy) {
|
|
IOT_ASSERT(0);
|
|
return ERR_NOMEM;
|
|
}
|
|
/* set dummy desc type */
|
|
dummy->desc_type = DESC_TYPE_TX_DUMMY;
|
|
} else {
|
|
mac_vdev_t *vdev = get_vdev_ptr(pdev_id, PLC_DEFAULT_VDEV);
|
|
is_sta = (mac_vdev_cfg_get_node_role(vdev) != PLC_DEV_ROLE_CCO);
|
|
/* detect bcn, use PLC_BCN_REGION_BCSMA */
|
|
region_type = PLC_BCN_REGION_BCSMA;
|
|
lid = LID_BCSMA_START;
|
|
is_tx_3phase = true;
|
|
pb_buf_reuse = 0;
|
|
/* calculate sw_buf_offset */
|
|
iot_pkt_pull(bcn_buf, fc_len);
|
|
uint8_t *data = iot_pkt_block_ptr(bcn_buf, IOT_PKT_BLOCK_DATA);
|
|
sw_buf_offset = (uint32_t)(data - (uint8_t *)bcn_buf);
|
|
}
|
|
/* get swq type id */
|
|
swq_id = mac_q_get_swq_type(region_type,
|
|
is_sta ? PLC_PHASE_A : phase, lid);
|
|
/* check if swq type is support */
|
|
if (swq_id == MAX_MAC_QUE_NUM)
|
|
{
|
|
/* swq type error */
|
|
IOT_ASSERT(0);
|
|
}
|
|
/* check if the hwq already enabled */
|
|
hwqid = mac_q_get_hwqid(&pdev->hwq_hdl, swq_id);
|
|
if (hwqid == INV_MAC_HWQ_ID) {
|
|
/* hw queue is not enabled, try to alloc it */
|
|
hwqid = mac_q_alloc_hwq(&pdev->hwq_hdl, swq_id);
|
|
}
|
|
|
|
uint32_t tx_port = HW_DESC_TX_PORT_PLC;
|
|
uint32_t ppdu_mode = 0;
|
|
uint32_t tone_amp_tbl_idx = 0;
|
|
/* get pb mod */
|
|
uint32_t pb_mod, ext_tmi = 0;
|
|
|
|
IOT_ASSERT(0 == phy_get_pb_mod(proto,
|
|
fc_info.tmi, ext_tmi, &pb_mod));
|
|
|
|
hw_band_id = phy_proto_band_to_hw_band(proto_band_id);
|
|
uint32_t tx_symbnum_ppb = phy_get_symppb_from_table(
|
|
hw_band_id, fc_info.tmi, ext_tmi);
|
|
uint32_t sw_tx_fl_ppb = phy_get_flppb_from_table(
|
|
hw_band_id, fc_info.tmi, ext_tmi);
|
|
if (tx_symbnum_ppb == 0 || sw_tx_fl_ppb == 0) {
|
|
iot_printf("%s,sym_ppb or fl_ppb = 0,band_id:%d, tmi:%d, exttmi:%d\n",
|
|
__FUNCTION__, hw_band_id, fc_info.tmi, ext_tmi);
|
|
IOT_ASSERT(0);
|
|
}
|
|
|
|
//TODO: extension for modify actual hw retry cnt
|
|
hw_retry_cnt = retry_cnt;
|
|
mac_tx_mpdu_fill_macinfo(mpdu, swq_id, pb_num,
|
|
need_encry, need_ack, tx_symbnum_ppb,
|
|
sw_tx_fl_ppb, 0, pb_hdr_resv_crc_len, hw_retry_cnt,
|
|
1, 1, mpdu_end, pb_start, (tx_mpdu_start *)dummy,
|
|
pb_buf_reuse, sw_buf_offset, 0, 0, 0, 0, 0
|
|
);
|
|
mac_tx_mpdu_fill_phyinfo(
|
|
mpdu, tx_port, tx_power, is_tx_3phase ? PLC_PHASE_ALL : phase,
|
|
hw_band_id, ppdu_mode, tone_amp_tbl_idx, pb_mod, rate_mode);
|
|
|
|
mac_tx_mpdu_fill_fcinfo(
|
|
mpdu, proto, pb_num, phase, FC_DELIM_BEACON,
|
|
fc_info.network_type, fc_info.nid, fc_info.bcn_period_cnt,
|
|
fc_info.tmi, ext_tmi,
|
|
0xfff, fc_info.src_tei, 0, 1, 0, 0, 0 , 0, NULL
|
|
);
|
|
|
|
return mac_tx_hw_mpdu(&pdev->hwq_hdl, hwqid, mpdu);
|
|
}
|
|
|
|
uint32_t mac_beacon_cal_biggest_csma_phase(mac_beacon_ctx_t *bcn_ctx,
|
|
uint8_t *biggest_phase)
|
|
{
|
|
uint32_t ret = ERR_INVAL;
|
|
if (!bcn_ctx || !biggest_phase) {
|
|
IOT_ASSERT(0);
|
|
return ret;
|
|
}
|
|
mac_bc_cmsa_si_t *ci = &bcn_ctx->time_slot.csma_info;
|
|
uint32_t max_slot_dur = 0;
|
|
for (int i = 0; i < ci->phase_cnt; i++)
|
|
{
|
|
if (ci->slot_dur[i] > max_slot_dur) {
|
|
max_slot_dur = ci->slot_dur[i];
|
|
*biggest_phase = ci->phase[i];
|
|
ret = ERR_OK;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|