1431 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1431 lines
		
	
	
		
			47 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.
 | 
						|
 | 
						|
****************************************************************************/
 | 
						|
/* os_shim header files */
 | 
						|
#include "os_utils_api.h"
 | 
						|
 | 
						|
/* iot common header files */
 | 
						|
#include "iot_app_api.h"
 | 
						|
#include "iot_utils_api.h"
 | 
						|
#include "iot_upgrade_api.h"
 | 
						|
#include "iot_oem_api.h"
 | 
						|
#include "iot_board_api.h"
 | 
						|
#include "iot_bitmap_api.h"
 | 
						|
#include "iot_io_api.h"
 | 
						|
#include "iot_system_api.h"
 | 
						|
#include "iot_plc_hw_topo_api.h"
 | 
						|
#include "iot_plc_hw_tsfm_api.h"
 | 
						|
 | 
						|
/* smart grid internal header files */
 | 
						|
#include "iot_sg.h"
 | 
						|
#include "iot_sg_sta.h"
 | 
						|
#include "proto_645.h"
 | 
						|
#include "proto_645_vendor.h"
 | 
						|
#include "proto_645_topo.h"
 | 
						|
#include "iot_sg_sta_tsfm.h"
 | 
						|
#include "iot_sg_sta_ext.h"
 | 
						|
#include "proto_hw_tsfm.h"
 | 
						|
 | 
						|
#if (IOT_SMART_GRID_BRANCH_DETECT_ENABLE)
 | 
						|
 | 
						|
/* define branch recognition launch max length */
 | 
						|
#define proto_645_vendor_br_lunch_max_len        10
 | 
						|
 | 
						|
/* define effective time of branch1 sn, uint is 1s. */
 | 
						|
#define PROTO_645_EXT_TOPO_SN_VALID_TIME         30 * 60
 | 
						|
 | 
						|
/* define send mode, zero-crossing perturbance method. */
 | 
						|
#define PROTO_645_EXT_SEND_MODE_ZC               0
 | 
						|
/* define send mode, encoded pulse current injection method. */
 | 
						|
#define PROTO_645_EXT_SEND_MODE_ENCODED_LOAD     1
 | 
						|
/* define send mode, pulse current injection method done by PA */
 | 
						|
#define PROTO_645_EXT_SEND_MODE_PA               2
 | 
						|
 | 
						|
#pragma pack(push)      /* save the pack status */
 | 
						|
#pragma pack(1)         /* 1 byte align */
 | 
						|
 | 
						|
/* branch recognition launch optional payload */
 | 
						|
typedef struct _proto_645_ext_br_launch_opt {
 | 
						|
    /* encode frequncy tone num for pa mode. each tone num is 75MHz/(1 << 14) */
 | 
						|
    uint16_t pa_freq_tone_num;
 | 
						|
    /* reserved for further use */
 | 
						|
    uint8_t  rsvd[16];
 | 
						|
} proto_645_ext_br_launch_opt_t;
 | 
						|
 | 
						|
/* branch recognition launch payload */
 | 
						|
typedef struct _proto_645_ext_br_launch {
 | 
						|
    /* node sequence number */
 | 
						|
    uint16_t node_seq;
 | 
						|
    /* ahead interval time of sending data relative to zero-crossing point,
 | 
						|
     * uint is 1us. less than or equal to IOT_PLC_HW_TSFM_MAX_AHEAD_TIME,
 | 
						|
     * greater than or equal to IOT_PLC_HW_TSFM_MIN_AHEAD_TIME.
 | 
						|
     * If mode is IOT_PLC_HW_TSFM_MODE_PA
 | 
						|
     * or IOT_PLC_HW_TSFM_SEND_MODE_ENCODED_LOAD, uint is 1ms,
 | 
						|
     * ahead mean that transmitter send delay, greater than or equal to
 | 
						|
     * IOT_PLC_HW_TSFM_SEND_DELAY_MIN, less than or equal to
 | 
						|
     * IOT_PLC_HW_TSFM_SEND_DELAY_MAX.
 | 
						|
     */
 | 
						|
    uint16_t ahead;
 | 
						|
    /* duration of bit data output, uint is 1us
 | 
						|
     * less than or equal to IOT_PLC_HW_TSFM_OUTPUT_MAX_TIME,
 | 
						|
     * greater than or equal to IOT_PLC_HW_TSFM_OUTPUT_MIN_TIME.
 | 
						|
     */
 | 
						|
    uint16_t dur_output;
 | 
						|
    /* repeat cnt */
 | 
						|
    uint8_t repeat_cnt;
 | 
						|
    /* send mode, see IOT_PLC_HW_TSFM_SEND_MODE_XXX */
 | 
						|
    uint16_t send_mode   : 4,
 | 
						|
    /* branch detect launch sequence number */
 | 
						|
             launch_sn   : 8,
 | 
						|
    /* whether enable opt_data area
 | 
						|
     * 0 - not enable(opt_data length is 0); 1 - enable.
 | 
						|
     */
 | 
						|
             opt_data_en : 1,
 | 
						|
    /* reserved for further use */
 | 
						|
             rsvd        : 3;
 | 
						|
    /* optional data */
 | 
						|
    proto_645_ext_br_launch_opt_t opt_data[0];
 | 
						|
} proto_645_ext_br_launch_t;
 | 
						|
 | 
						|
/* br test command payload */
 | 
						|
typedef struct _proto_645_ext_br_test_req {
 | 
						|
    /* specified phase for br test, see PROTO_645_2007_EXT_BRM_PHASE_XXX */
 | 
						|
    uint8_t phase       : 2,
 | 
						|
    /* plc rising edge zc send tsfm flag, it's phase negative zc flag. */
 | 
						|
            rising_send : 1,
 | 
						|
    /* reserved for further use */
 | 
						|
            rsvd        : 5;
 | 
						|
    /* send mode, see PROTO_645_EXT_SEND_MODE_XXX */
 | 
						|
    uint8_t send_mode;
 | 
						|
} proto_645_ext_br_test_req_t;
 | 
						|
 | 
						|
/* query br test reasult response */
 | 
						|
typedef struct _proto_645_ext_br_test_query_rsp_opt {
 | 
						|
    /* energy */
 | 
						|
    uint32_t energy[IOT_PLC_PHASE_CNT];
 | 
						|
    /* current, unit is 1uA */
 | 
						|
    uint32_t current[IOT_PLC_PHASE_CNT];
 | 
						|
    /* reserved for further use */
 | 
						|
    uint8_t rsvd[7];
 | 
						|
} proto_645_ext_br_test_query_rsp_opt_t;
 | 
						|
 | 
						|
/* query br test reasult response */
 | 
						|
typedef struct _proto_645_ext_br_test_query_rsp {
 | 
						|
    /* tsfm topo rec phase info
 | 
						|
     * bit0 represent phase A
 | 
						|
     * bit1 represent phase B
 | 
						|
     * bit2 represent phase C
 | 
						|
     */
 | 
						|
    uint8_t phase       :3,
 | 
						|
    /* weather enable optional result data,
 | 
						|
     * 0 - not enable(the length of opt_data is 0); 1 - enable
 | 
						|
     */
 | 
						|
            opt_data_en :1,
 | 
						|
    /* reserve for future */
 | 
						|
            rsvd        :4;
 | 
						|
    /* optional result data */
 | 
						|
    proto_645_ext_br_test_query_rsp_opt_t opt_data[0];
 | 
						|
} proto_645_ext_br_test_query_rsp_t;
 | 
						|
 | 
						|
/* branch recognition info query payload */
 | 
						|
typedef struct _proto_645_ext_br_info_query {
 | 
						|
    /* data block sequence */
 | 
						|
    uint8_t block_seq  : 6,
 | 
						|
    /* phase type, see PROTO_645_2007_EXT_BRM_PHASE_XXX */
 | 
						|
            phase_type : 2;
 | 
						|
} proto_645_ext_br_info_query_t;
 | 
						|
 | 
						|
/* branch recognition receive optional payload */
 | 
						|
typedef struct _proto_645_ext_br_receive_opt {
 | 
						|
    /* encode frequncy tone num for pa mode. each tone num is 75MHz/(1 << 14) */
 | 
						|
    uint16_t pa_freq_tone_num;
 | 
						|
    /* reserved for further use */
 | 
						|
    uint8_t  rsvd[16];
 | 
						|
} proto_645_ext_br_receive_opt_t;
 | 
						|
 | 
						|
/* branch recognition information clean down-link.
 | 
						|
 * for PROTO_645_2007_EXT_DI_BR_INFO_CLEAN
 | 
						|
 */
 | 
						|
typedef struct _proto_645_07_ext_brm_clean_dl {
 | 
						|
    /* receive phase, see PROTO_645_2007_EXT_BRM_PHASE_XXX */
 | 
						|
    uint8_t  phase          : 2,
 | 
						|
    /* reserve for future */
 | 
						|
             reserve        : 5,
 | 
						|
    /* whether enable opt_data area
 | 
						|
     * 0 - not enable(opt_data length is 0); 1 - enable.
 | 
						|
     */
 | 
						|
             opt_data_en    : 1;
 | 
						|
    /* optional data */
 | 
						|
    proto_645_ext_br_receive_opt_t opt_data[0];
 | 
						|
} proto_645_07_ext_brm_clean_dl_t;
 | 
						|
 | 
						|
#pragma pack(pop)   /* restore the pack status */
 | 
						|
 | 
						|
uint32_t proto_645_vendor_br_rsp_check(proto_645_header_t *hdr,
 | 
						|
    proto_645_ext_br_rsp_cache_t *br_cache)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_INVAL;
 | 
						|
    proto_645_ext_br_rsp_data_t *rsp_data;
 | 
						|
 | 
						|
    if (hdr->control.dir != PROTO_645_DIR_SLAVE) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (hdr->control.fn != PROTO_645_2007_EXT_FN_BR) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (hdr->control.ack != PROTO_645_ACK_NORMAL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (hdr->len < sizeof(*rsp_data)) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (br_cache != NULL) {
 | 
						|
        proto_645_sub33_handle(hdr->data, hdr->len);
 | 
						|
        rsp_data = (proto_645_ext_br_rsp_data_t *)hdr->data;
 | 
						|
        br_cache->di = rsp_data->di;
 | 
						|
        br_cache->result = rsp_data->result;
 | 
						|
        br_cache->format = rsp_data->format;
 | 
						|
        iot_mac_addr_cpy(br_cache->addr, hdr->addr);
 | 
						|
        br_cache->data_len = hdr->len - sizeof(*rsp_data);
 | 
						|
        if (br_cache->data_len) {
 | 
						|
            br_cache->data = rsp_data->data;
 | 
						|
        } else {
 | 
						|
            br_cache->data = NULL;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_645_vendor_conn_fwd_br_rsp_check(uint8_t **data,
 | 
						|
    uint32_t *data_len)
 | 
						|
{
 | 
						|
    uint32_t di, ret = ERR_FAIL;
 | 
						|
    proto_645_header_t *hdr;
 | 
						|
    hdr = proto_645_format_check(*data, *data_len, PROTO_645_DIR_SLAVE);
 | 
						|
    if (!hdr) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (hdr->control.fn != PROTO_645_2007_EXT_FN_BR) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (hdr->control.ack != PROTO_645_ACK_NORMAL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    if (ERR_OK != proto_645_get_di_by_sub33(hdr->data, hdr->len,
 | 
						|
        PROTO_645_2007_ID, &di)) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    if (di != PROTO_645_2007_EXT_BRM_FWD_DATA) {
 | 
						|
        ret = ERR_NOSUPP;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    proto_645_sub33_handle(hdr->data, hdr->len);
 | 
						|
    *data = hdr->data + PROTO_645_2007_DI_LEN;
 | 
						|
    *data_len = hdr->len - PROTO_645_2007_DI_LEN;
 | 
						|
    ret = ERR_OK;
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_launch_req(uint8_t *addr,
 | 
						|
    uint8_t *fwd_addr, uint16_t node_seq, uint16_t ahead, uint16_t dur_output,
 | 
						|
    uint8_t repeat_cnt, uint8_t send_mode, uint8_t launch_sn, uint16_t pa_freq)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt, *temp_pkt;
 | 
						|
    uint8_t data_buff[sizeof(proto_645_ext_br_launch_t) +
 | 
						|
        sizeof(proto_645_ext_br_launch_opt_t)] = { 0 };
 | 
						|
    proto_645_ext_br_launch_t *br_launch;
 | 
						|
    proto_645_ext_br_launch_opt_t *br_launch_opt;
 | 
						|
    br_launch = (proto_645_ext_br_launch_t *)data_buff;
 | 
						|
    br_launch->ahead = ahead;
 | 
						|
    br_launch->dur_output = dur_output;
 | 
						|
    br_launch->node_seq = node_seq;
 | 
						|
    br_launch->repeat_cnt = repeat_cnt;
 | 
						|
    br_launch->send_mode = send_mode;
 | 
						|
    br_launch->launch_sn = launch_sn;
 | 
						|
    br_launch->opt_data_en = 1;
 | 
						|
    br_launch_opt = br_launch->opt_data;
 | 
						|
    br_launch_opt->pa_freq_tone_num = pa_freq;
 | 
						|
 | 
						|
    temp_pkt = proto_645_vendor_build_br_msg(addr, data_buff,
 | 
						|
        sizeof(data_buff), PROTO_645_2007_EXT_DI_BR_LAUNCH,
 | 
						|
        PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL);
 | 
						|
    if (!fwd_addr) {
 | 
						|
        return temp_pkt;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!temp_pkt) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    pkt = proto_645_vendor_build_br_msg(fwd_addr, iot_pkt_data(temp_pkt),
 | 
						|
        (uint8_t)iot_pkt_data_len(temp_pkt), PROTO_645_2007_EXT_BRM_FWD_DATA,
 | 
						|
        PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL);
 | 
						|
    iot_pkt_free(temp_pkt);
 | 
						|
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_launch_state_req(uint8_t *addr,
 | 
						|
    uint8_t *fwd_addr)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt, *temp_pkt;
 | 
						|
 | 
						|
    temp_pkt = proto_645_vendor_build_br_msg(addr, NULL, 0,
 | 
						|
        PROTO_645_2007_EXT_DI_BR_LAUNCH_STATE, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL);
 | 
						|
    if (!fwd_addr) {
 | 
						|
        return temp_pkt;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!temp_pkt) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    pkt = proto_645_vendor_build_br_msg(fwd_addr, iot_pkt_data(temp_pkt),
 | 
						|
        (uint8_t)iot_pkt_data_len(temp_pkt), PROTO_645_2007_EXT_BRM_FWD_DATA,
 | 
						|
        PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL);
 | 
						|
    iot_pkt_free(temp_pkt);
 | 
						|
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_query_req(uint8_t *addr, uint8_t seq,
 | 
						|
    uint8_t phase_type)
 | 
						|
{
 | 
						|
    proto_645_ext_br_info_query_t req;
 | 
						|
    req.block_seq = seq;
 | 
						|
    req.phase_type = phase_type;
 | 
						|
    return proto_645_vendor_build_br_msg(addr, (uint8_t *)&req, sizeof(req),
 | 
						|
        PROTO_645_2007_EXT_DI_BR_INFO_QUERY, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL);
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_tsfm_addr_clear_req(uint8_t *addr)
 | 
						|
{
 | 
						|
    return proto_645_vendor_build_br_msg(addr, NULL, 0,
 | 
						|
        PROTO_645_2007_EXT_DI_TSFM_LAUNCH_CLEAR, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL);
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_clean_req(uint8_t *addr,
 | 
						|
    uint8_t send_phase, uint16_t pa_freq)
 | 
						|
{
 | 
						|
    proto_645_07_ext_brm_clean_dl_t *req;
 | 
						|
    proto_645_ext_br_receive_opt_t *opt_data;
 | 
						|
    uint8_t buff[sizeof(*req) + sizeof(*opt_data)] = { 0 };
 | 
						|
    uint8_t len = sizeof(*req);
 | 
						|
    req = (proto_645_07_ext_brm_clean_dl_t *)buff;
 | 
						|
    req->phase = send_phase;
 | 
						|
    req->opt_data_en = 1;
 | 
						|
    len += sizeof(*opt_data);
 | 
						|
    opt_data = req->opt_data;
 | 
						|
    opt_data->pa_freq_tone_num = pa_freq;
 | 
						|
    return proto_645_vendor_build_br_msg(addr, buff, len,
 | 
						|
        PROTO_645_2007_EXT_DI_BR_INFO_CLEAN, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL);
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_nei_node_info_query_req(uint8_t *addr,
 | 
						|
    uint8_t seq)
 | 
						|
{
 | 
						|
    proto_645_07_ext_brm_nei_node_info_dl_t qr = { 0 };
 | 
						|
    qr.sn = seq;
 | 
						|
    return proto_645_vendor_build_br_msg(addr, (uint8_t *)&qr, sizeof(qr),
 | 
						|
        PROTO_645_2007_EXT_BRM_DI_NEI_NODE_INFO, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL);
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_tsfm_info_query_req(uint8_t *addr,
 | 
						|
    uint8_t *fwd_addr)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt, *temp_pkt;
 | 
						|
 | 
						|
    temp_pkt = proto_645_vendor_build_br_msg(addr, NULL, 0,
 | 
						|
        PROTO_645_2007_EXT_BRM_DI_CONN_NODE_TSFM_INFO, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL);
 | 
						|
    if (!temp_pkt) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    pkt = proto_645_vendor_build_br_msg(fwd_addr, iot_pkt_data(temp_pkt),
 | 
						|
        (uint8_t)iot_pkt_data_len(temp_pkt), PROTO_645_2007_EXT_BRM_FWD_DATA,
 | 
						|
        PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL);
 | 
						|
    iot_pkt_free(temp_pkt);
 | 
						|
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_meter_info_query_req(uint8_t *addr,
 | 
						|
    uint8_t seq, uint8_t ver)
 | 
						|
{
 | 
						|
    proto_645_ext_br_meter_query_t qr = { 0 };
 | 
						|
    qr.block_seq = seq;
 | 
						|
    qr.ver = ver;
 | 
						|
    return proto_645_vendor_build_br_msg(addr,(uint8_t *) &qr, sizeof(qr),
 | 
						|
        PROTO_645_2007_EXT_DI_BR_METER_QUERY, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL);
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_add_pm_req(uint8_t *addr,
 | 
						|
    uint8_t *data, uint8_t len)
 | 
						|
{
 | 
						|
    return proto_645_vendor_build_br_msg(addr, data, len,
 | 
						|
        PROTO_645_2007_EXT_BRM_CCO_ADD_PM, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL);
 | 
						|
}
 | 
						|
 | 
						|
#if IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_BJ
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_launch_req_bj(uint8_t *addr,
 | 
						|
    uint16_t node_seq, uint16_t bit_dur, uint16_t high_dur, uint16_t low_dur,
 | 
						|
    uint8_t launch_sn)
 | 
						|
{
 | 
						|
    proto_645_ext_br_launch_bj_t br_launch = { 0 };
 | 
						|
    br_launch.node_seq = node_seq;
 | 
						|
    br_launch.chara_bit_dur = bit_dur;
 | 
						|
    br_launch.pulse_high_dur = high_dur;
 | 
						|
    br_launch.pulse_low_dur = low_dur;
 | 
						|
    br_launch.launch_sn = launch_sn;
 | 
						|
    return proto_645_build_msg(addr, (uint8_t *)&br_launch, sizeof(br_launch),
 | 
						|
        PROTO_645_2007_EXT_DI_BR_BJ_LAUNCH, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_WRITE_DATA, PROTO_645_2007_ID,
 | 
						|
        PROTO_645_FOLLOW_INVALID);
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_query_req_bj(uint8_t *addr,
 | 
						|
    uint16_t start_idx, uint8_t num)
 | 
						|
{
 | 
						|
    proto_645_ext_br_info_query_bj_t req = { 0 };
 | 
						|
    uint8_t max_num = (PROTO_645_MAX_DATA_LEN - PROTO_645_2007_DI_LEN -
 | 
						|
        sizeof(proto_645_ext_br_energy_rsp_bj_t)) /
 | 
						|
        sizeof(proto_645_ext_br_energy_unit_bj_t);
 | 
						|
    req.start_index = start_idx;
 | 
						|
    req.num = min(num, max_num);
 | 
						|
    return proto_645_build_msg(addr, (uint8_t *)&req, sizeof(req),
 | 
						|
        PROTO_645_2007_EXT_DI_BR_BJ_INFO_QUERY, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_READ_DATA, PROTO_645_2007_ID,
 | 
						|
        PROTO_645_FOLLOW_INVALID);
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_clean_req_bj(uint8_t *addr,
 | 
						|
    uint16_t bit_dur, uint32_t freq)
 | 
						|
{
 | 
						|
    proto_645_ext_br_init_bj_t req = { 0 };
 | 
						|
    req.chara_bit_dur = bit_dur;
 | 
						|
    req.freq[0] = freq & 0xff;
 | 
						|
    req.freq[1] = (freq >> 8) & 0xff;
 | 
						|
    req.freq[2] = (freq >> 16) & 0xff;
 | 
						|
    return proto_645_build_msg(addr, (uint8_t *)&req, sizeof(req),
 | 
						|
        PROTO_645_2007_EXT_DI_BR_BJ_INIT, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_WRITE_DATA, PROTO_645_2007_ID,
 | 
						|
        PROTO_645_FOLLOW_INVALID);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_BJ */
 | 
						|
 | 
						|
#if IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_ZJ
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_launch_req_zj(uint8_t *addr,
 | 
						|
    uint16_t bit_dur, uint16_t high_dur, uint16_t low_dur, uint32_t freq,
 | 
						|
    uint8_t *code, uint8_t code_len, proto_645_07_time_ymdhms_t *timep)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt;
 | 
						|
    uint16_t pkt_len, len;
 | 
						|
    proto_645_header_t *hdr;
 | 
						|
    proto_645_ext_br2_launch_zj_hdr_t *br_launch;
 | 
						|
    proto_645_ext_br2_launch_zj_tail_t *br_tail;
 | 
						|
 | 
						|
    len = sizeof(proto_645_ext_br2_launch_zj_hdr_t) +
 | 
						|
        sizeof(proto_645_ext_br2_launch_zj_tail_t) + code_len;
 | 
						|
 | 
						|
    pkt_len = PROTO_645_PREAMBLE_LEN + sizeof(proto_645_header_t) +
 | 
						|
        PROTO_645_2007_DI_LEN + len + sizeof(proto_645_tailer_t);
 | 
						|
 | 
						|
    pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_pkt_reserve(pkt, PROTO_645_PREAMBLE_LEN);
 | 
						|
 | 
						|
    hdr = (proto_645_header_t *)iot_pkt_data(pkt);
 | 
						|
    proto_645_header_init(hdr, addr, PROTO_645_2007_FN_WRITE_DATA,
 | 
						|
        PROTO_645_DIR_MASTER, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
 | 
						|
 | 
						|
    proto_645_2007_di_to_byte(PROTO_645_2007_EXT_DI_BR2_LAUNCH_ZJ, hdr->data);
 | 
						|
    hdr->len += PROTO_645_2007_DI_LEN;
 | 
						|
 | 
						|
    br_launch = (proto_645_ext_br2_launch_zj_hdr_t *)(hdr->data +
 | 
						|
        PROTO_645_2007_DI_LEN);
 | 
						|
    br_launch->trans_type = PROTO_645_EXT_BR2_HANDLE;
 | 
						|
    if (timep) {
 | 
						|
        br_launch->tm = *timep;
 | 
						|
    } else {
 | 
						|
        os_mem_set(&br_launch->tm, 0xff, sizeof(br_launch->tm));
 | 
						|
    }
 | 
						|
    br_launch->chara_bit_dur = bit_dur;
 | 
						|
    br_launch->freq[0] = freq & 0xff;
 | 
						|
    br_launch->freq[1] = (freq >> 8) & 0xff;
 | 
						|
    br_launch->freq[2] = (freq >> 16) & 0xff;
 | 
						|
 | 
						|
    br_launch->code_len = code_len;
 | 
						|
    os_mem_cpy(br_launch->code, code, code_len);
 | 
						|
 | 
						|
    br_tail = (proto_645_ext_br2_launch_zj_tail_t*)(br_launch->code + code_len);
 | 
						|
    br_tail->pulse_high_dur = high_dur;
 | 
						|
    br_tail->pulse_low_dur = low_dur;
 | 
						|
    os_mem_set(&br_tail->code, 0, sizeof(br_tail->code));
 | 
						|
    hdr->len += len;
 | 
						|
 | 
						|
    proto_645_add33_handle(hdr->data, hdr->len);
 | 
						|
    /* fill tail */
 | 
						|
    proto_645_tail_init(hdr);
 | 
						|
 | 
						|
    iot_pkt_put(pkt, pkt_len - PROTO_645_PREAMBLE_LEN);
 | 
						|
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_query_req_zj(uint8_t *addr,
 | 
						|
    uint16_t start_idx, uint8_t cnt, proto_645_corr_time_t *start_time)
 | 
						|
{
 | 
						|
    proto_645_ext_br2_recv_rec_dl_t req = {0};
 | 
						|
    req.start_time = *start_time;
 | 
						|
    req.start_index = start_idx;
 | 
						|
    req.cnt = cnt;
 | 
						|
 | 
						|
    return proto_645_build_msg(addr, (uint8_t *)&req, sizeof(req),
 | 
						|
        PROTO_645_2007_EXT_DI_BR2_RECV_RECORD_ZJ, PROTO_645_DIR_MASTER,
 | 
						|
        PROTO_645_ACK_NORMAL, PROTO_645_2007_FN_READ_DATA, PROTO_645_2007_ID,
 | 
						|
        PROTO_645_FOLLOW_INVALID);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_ZJ */
 | 
						|
 | 
						|
static uint8_t proto_645_vendor_br_ret_to_result(uint32_t ret)
 | 
						|
{
 | 
						|
    uint8_t result;
 | 
						|
    switch (ret) {
 | 
						|
    case ERR_OK:
 | 
						|
    {
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_OK;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case ERR_BUSY:
 | 
						|
    {
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_BUSY;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case ERR_NOSUPP:
 | 
						|
    {
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_NOSUPP;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case ERR_FAIL:
 | 
						|
    {
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_FAIL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case ERR_INVAL:
 | 
						|
    default:
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_INVAL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_645_vendor_br_launch(uint8_t *data, uint8_t len,
 | 
						|
    hw_tsfm_send_cfg_t *cfg)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_INVAL;
 | 
						|
 | 
						|
    if (!len || len > proto_645_vendor_br_lunch_max_len) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    ret = iot_plc_hw_tsfm_get_transmitter_state();
 | 
						|
    if (ret == ERR_OK) {
 | 
						|
        iot_plc_hw_tsfm_send(data, len, cfg);
 | 
						|
    }
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static uint8_t proto_645_vendor_send_mode_auto_adap(uint8_t send_mode)
 | 
						|
{
 | 
						|
    uint8_t mode, supp_mode;
 | 
						|
 | 
						|
    supp_mode = iot_plc_hw_tsfm_get_supp_mode();
 | 
						|
 | 
						|
    if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_PA &&
 | 
						|
        supp_mode & (1 << IOT_PLC_HW_TSFM_SEND_MODE_LOAD)) {
 | 
						|
        mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
 | 
						|
    } else if (!(supp_mode & (1 << send_mode))) {
 | 
						|
        if (supp_mode & (1 << IOT_PLC_HW_TSFM_SEND_MODE_ZC)) {
 | 
						|
            mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
 | 
						|
        } else if (supp_mode & (1 << IOT_PLC_HW_TSFM_SEND_MODE_LOAD)) {
 | 
						|
            mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
 | 
						|
        } else if (supp_mode & (1 << IOT_PLC_HW_TSFM_SEND_MODE_PA)) {
 | 
						|
            mode = IOT_PLC_HW_TSFM_SEND_MODE_PA;
 | 
						|
        } else {
 | 
						|
            mode = IOT_PLC_HW_TSFM_SEND_MODE_INVALID;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        mode = send_mode;
 | 
						|
    }
 | 
						|
    return mode;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_launch_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
 | 
						|
{
 | 
						|
    uint8_t reason = 0, dev_type, send_mode, len;
 | 
						|
    uint8_t data[PROTO_645_VENDOR_BR_DATA_LEN];
 | 
						|
    uint8_t addr[IOT_MAC_ADDR_LEN];
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    proto_645_ext_br_launch_t *br_launch = NULL;
 | 
						|
    proto_645_ext_br_launch_opt_t *br_launch_opt = NULL;
 | 
						|
    hw_tsfm_send_cfg_t cfg = { 0 };
 | 
						|
    proto_hw_tsfm_hdr_t *topo_hdr;
 | 
						|
    proto_hw_tsfm_topo_sn_t *topo_data;
 | 
						|
    iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
 | 
						|
    uint8_t result, repeat_cnt, encode = 0;
 | 
						|
    uint32_t ret = ERR_OK, last_ts, now_ts;
 | 
						|
    proto_645_ext_br_rsp_data_t *rsp = NULL;
 | 
						|
    proto_645_ext_br_send_rsp_t *rsp_data = NULL;
 | 
						|
    proto_645_header_t *build_hdr;
 | 
						|
 | 
						|
    if (hdr->len < sizeof(*br_launch) + PROTO_645_2007_DI_LEN) {
 | 
						|
        reason = 1;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
 | 
						|
    iot_mac_addr_reverse(addr);
 | 
						|
    if (!iot_mac_addr_cmp(addr, hdr->addr) && flag_addr_check) {
 | 
						|
        reason = 2;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    proto_645_sub33_handle(hdr->data, hdr->len);
 | 
						|
    br_launch = (proto_645_ext_br_launch_t *)(hdr->data +
 | 
						|
        PROTO_645_2007_DI_LEN);
 | 
						|
    if (br_launch->opt_data_en && (hdr->len >= sizeof(*br_launch) +
 | 
						|
        sizeof(*br_launch_opt) + PROTO_645_2007_DI_LEN)) {
 | 
						|
        br_launch_opt = br_launch->opt_data;
 | 
						|
    }
 | 
						|
    last_ts = sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.last_ts;
 | 
						|
    now_ts = (uint32_t)(os_boot_time64() / 1000);
 | 
						|
    if (((now_ts - last_ts) >= PROTO_645_EXT_TOPO_SN_VALID_TIME) && last_ts) {
 | 
						|
        sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_is_valid = 0;
 | 
						|
        sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn = 0;
 | 
						|
    }
 | 
						|
    if (br_launch->launch_sn == sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn
 | 
						|
        && sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_is_valid) {
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_OK;
 | 
						|
        send_mode = sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_send_mode;
 | 
						|
        reason = 4;
 | 
						|
        goto resp;
 | 
						|
    }
 | 
						|
    if (br_launch->send_mode < IOT_PLC_HW_TSFM_SEND_MODE_MAX) {
 | 
						|
        send_mode = (uint8_t)br_launch->send_mode;
 | 
						|
        encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_1;
 | 
						|
    } else {
 | 
						|
        if (sta_glb->drv) {
 | 
						|
            dev_type = (uint8_t)sta_glb->drv->get_device_type();
 | 
						|
            dev_type = iot_sg_sta_to_plc_dev_type(dev_type);
 | 
						|
            if (dev_type == IOT_PLC_DEV_TYPE_BRK_MONITOR
 | 
						|
                || dev_type == IOT_PLC_DEV_TYPE_TSFM_MONITOR
 | 
						|
                || dev_type == IOT_PLC_DEV_TYPE_SWITCH_MONITOR) {
 | 
						|
                send_mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
 | 
						|
            } else {
 | 
						|
                send_mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
 | 
						|
                encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_1;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            send_mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
 | 
						|
            encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    send_mode = proto_645_vendor_send_mode_auto_adap(send_mode);
 | 
						|
    if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_INVALID) {
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_NOSUPP;
 | 
						|
        goto resp;
 | 
						|
    }
 | 
						|
    if (send_mode != IOT_PLC_HW_TSFM_SEND_MODE_PA) {
 | 
						|
        if (((now_ts - last_ts) < PROTO_645_EXT_TOPO_REPEAT_INTERVAL)
 | 
						|
            && last_ts) {
 | 
						|
            result = PROTO_645_2007_EXT_BR_RESULT_BUSY;
 | 
						|
            reason = 5;
 | 
						|
            goto resp;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    cfg.phase = IOT_PLC_PHASE_A;
 | 
						|
    repeat_cnt = br_launch->repeat_cnt;
 | 
						|
    cfg.mod_mode = send_mode;
 | 
						|
    if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_LOAD) {
 | 
						|
        cfg.cnt = repeat_cnt + 1;
 | 
						|
        repeat_cnt = 0;
 | 
						|
        if (encode) {
 | 
						|
            encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_2;
 | 
						|
        }
 | 
						|
        cfg.para.load.encode = encode;
 | 
						|
        cfg.para.load.pulse_high_dur = IOT_PLC_HW_TSFM_LOAD_SIG_HIGH_DUR_DEF;
 | 
						|
        cfg.para.load.pulse_low_dur = IOT_PLC_HW_TSFM_LOAD_SIG_LOW_DUR_DEF;
 | 
						|
        /* the characteristic bit duration is assigned to 0, and the
 | 
						|
         * corresponding value is determined by the lower layer according
 | 
						|
         * to the actual hardware configuration.
 | 
						|
         */
 | 
						|
        cfg.para.load.chara_bit_dur = 0;
 | 
						|
    } else if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_PA) {
 | 
						|
        cfg.cnt = repeat_cnt + 1;
 | 
						|
        repeat_cnt = 0;
 | 
						|
        cfg.para.pa.offset_time = br_launch->ahead;
 | 
						|
        if (br_launch_opt) {
 | 
						|
            cfg.para.pa.freq_tone_num = br_launch_opt->pa_freq_tone_num;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        cfg.cnt = 1;
 | 
						|
        cfg.para.zc.ahead = br_launch->ahead;
 | 
						|
        cfg.para.zc.dur_output = br_launch->dur_output;
 | 
						|
    }
 | 
						|
    if (send_mode == IOT_PLC_HW_TSFM_SEND_MODE_LOAD ||
 | 
						|
        send_mode == IOT_PLC_HW_TSFM_SEND_MODE_PA) {
 | 
						|
        topo_data = (proto_hw_tsfm_topo_sn_t*)data;
 | 
						|
        topo_data->sn = br_launch->node_seq;
 | 
						|
        len = sizeof(*topo_data);
 | 
						|
    } else {
 | 
						|
        topo_hdr = (proto_hw_tsfm_hdr_t*)data;
 | 
						|
        topo_hdr->data_id = PROTO_HW_TSFM_ID_TOPO_SN;
 | 
						|
        topo_hdr->data_len = sizeof(*topo_data);
 | 
						|
        topo_data = (proto_hw_tsfm_topo_sn_t*)topo_hdr->data;
 | 
						|
        topo_data->sn = br_launch->node_seq;
 | 
						|
        len = PROTO_645_VENDOR_BR_DATA_LEN;
 | 
						|
    }
 | 
						|
    if (!sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt) {
 | 
						|
        ret = proto_645_vendor_br_launch(data, len, &cfg);
 | 
						|
        sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_send_mode = send_mode;
 | 
						|
    } else {
 | 
						|
        ret = ERR_BUSY;
 | 
						|
    }
 | 
						|
    result = proto_645_vendor_br_ret_to_result(ret);
 | 
						|
    iot_printf("%s ahead %lu, dur_output %lu, sn %lu, result %lu, repeat cnt "
 | 
						|
        "%lu\n", __FUNCTION__, br_launch->ahead, br_launch->dur_output,
 | 
						|
        br_launch->node_seq, result, repeat_cnt);
 | 
						|
    if (result == PROTO_645_2007_EXT_BR_RESULT_OK) {
 | 
						|
        sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn_is_valid = 1;
 | 
						|
        sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.sn = br_launch->launch_sn;
 | 
						|
        sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.last_ts = now_ts;
 | 
						|
        if (!sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt && repeat_cnt) {
 | 
						|
            if (repeat_cnt > PROTO_645_EXT_BRM_REPEAT_CNT_MAX) {
 | 
						|
                sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt =
 | 
						|
                    PROTO_645_EXT_BRM_REPEAT_CNT_MAX;
 | 
						|
            } else {
 | 
						|
                sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt = repeat_cnt;
 | 
						|
            }
 | 
						|
            sta_glb->hw_tsfm_info.tsfm_topo_info.send_mode = send_mode;
 | 
						|
            sta_glb->hw_tsfm_info.tsfm_topo_info.branch2.encode =
 | 
						|
                cfg.para.load.encode;
 | 
						|
            sta_glb->hw_tsfm_info.tsfm_topo_info.branch1.ahead =
 | 
						|
                br_launch->ahead;
 | 
						|
            sta_glb->hw_tsfm_info.tsfm_topo_info.branch1.dur_output =
 | 
						|
                br_launch->dur_output;
 | 
						|
            sta_glb->hw_tsfm_info.tsfm_topo_info.branch1.sn =
 | 
						|
                br_launch->node_seq;
 | 
						|
        }
 | 
						|
    }
 | 
						|
resp:
 | 
						|
    pkt = iot_pkt_alloc(sizeof(*rsp) + sizeof(*rsp_data) +
 | 
						|
        sizeof(*build_hdr) + sizeof(proto_645_tailer_t), IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    build_hdr = (proto_645_header_t *)iot_pkt_data(pkt);
 | 
						|
    proto_645_header_init(build_hdr, hdr->addr, PROTO_645_2007_EXT_FN_BR,
 | 
						|
        PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
 | 
						|
    build_hdr->len = sizeof(*rsp) + sizeof(*rsp_data);
 | 
						|
    rsp = (proto_645_ext_br_rsp_data_t *)build_hdr->data;
 | 
						|
    proto_645_2007_di_to_byte(di, rsp);
 | 
						|
    rsp->result = result;
 | 
						|
    rsp->format = 1;
 | 
						|
    rsp_data = (proto_645_ext_br_send_rsp_t *)rsp->data;
 | 
						|
    rsp_data->send_mode = send_mode;
 | 
						|
    switch (iot_plc_hw_tsfm_get_load_capacity()) {
 | 
						|
    case IOT_PLC_HW_TSFM_LOAD_CAP_2000MA:
 | 
						|
    {
 | 
						|
        rsp_data->load_capacity = PROTO_645_EXT_BR_LOAD_CAP_2000MA;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        rsp_data->load_capacity = PROTO_645_EXT_BR_LOAD_CAP_400MA;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    os_mem_set(rsp_data->rsvd, 0, sizeof(rsp_data->rsvd));
 | 
						|
    if (result != PROTO_645_2007_EXT_BR_RESULT_OK) {
 | 
						|
        os_mem_set(rsp_data, 0, sizeof(*rsp_data));
 | 
						|
    }
 | 
						|
    proto_645_add33_handle(build_hdr->data, build_hdr->len);
 | 
						|
    proto_645_tail_init(build_hdr);
 | 
						|
    iot_pkt_put(pkt, sizeof(*rsp) + sizeof(*rsp_data) +
 | 
						|
        sizeof(*build_hdr) + sizeof(proto_645_tailer_t));
 | 
						|
out:
 | 
						|
    if (reason) {
 | 
						|
        iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
 | 
						|
    }
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_launch_state_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
 | 
						|
{
 | 
						|
    uint8_t reason;
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t addr[IOT_MAC_ADDR_LEN];
 | 
						|
    uint8_t result;
 | 
						|
    uint32_t ret;
 | 
						|
    iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
 | 
						|
 | 
						|
    if (hdr->len < PROTO_645_2007_DI_LEN) {
 | 
						|
        reason = 1;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
 | 
						|
    iot_mac_addr_reverse(addr);
 | 
						|
    if (!iot_mac_addr_cmp(addr, hdr->addr) && flag_addr_check) {
 | 
						|
        reason = 2;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    if (!sta_glb->hw_tsfm_info.tsfm_topo_info.repeat_cnt) {
 | 
						|
        ret = iot_plc_hw_tsfm_get_transmitter_state();
 | 
						|
    } else {
 | 
						|
        ret = ERR_BUSY;
 | 
						|
    }
 | 
						|
    result = proto_645_vendor_br_ret_to_result(ret);
 | 
						|
    iot_printf("%s result %lu\n", __FUNCTION__, result);
 | 
						|
    pkt = proto_645_vendor_build_br_msg(hdr->addr, &result, sizeof(result), di,
 | 
						|
        PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL);
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_recv_init_bj(proto_645_header_t *hdr)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t addr[IOT_MAC_ADDR_LEN];
 | 
						|
    uint8_t reason = PROTO_645_2007_ERR_OK;
 | 
						|
    proto_645_ext_br_init_bj_t *cmd;
 | 
						|
    iot_sg_ext_cus_topo_rcv_cfg_t cfg = { 0 };
 | 
						|
 | 
						|
    os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
 | 
						|
    iot_mac_addr_reverse(addr);
 | 
						|
    if (!iot_mac_addr_cmp(addr, hdr->addr)) {
 | 
						|
        return pkt;
 | 
						|
    }
 | 
						|
    if (hdr->len < (sizeof(*cmd) + PROTO_645_2007_DI_LEN)) {
 | 
						|
        reason = PROTO_645_2007_ERR_OTHER;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
    proto_645_sub33_handle(hdr->data, hdr->len);
 | 
						|
    cmd = (proto_645_ext_br_init_bj_t*)(hdr->data +
 | 
						|
        PROTO_645_2007_DI_LEN);
 | 
						|
    cfg.fc = (cmd->freq[0]) | (cmd->freq[1] << 8) |
 | 
						|
        (cmd->freq[2] << 16);
 | 
						|
    cfg.chara_bit_dur = cmd->chara_bit_dur;
 | 
						|
    if (cfg.chara_bit_dur > PROTO_645_EXT_BR_BJ_CHARA_BIT_DUR_MAX) {
 | 
						|
        cfg.chara_bit_dur = PROTO_645_EXT_BR_BJ_CHARA_BIT_DUR_DEFAULT;
 | 
						|
    }
 | 
						|
    cfg.fr_code_len = 0;
 | 
						|
    cfg.similarity_thr = cmd->similarity_thr;
 | 
						|
    iot_sg_ext_topo_rcv_cfg_to_cus(&cfg);
 | 
						|
    iot_sg_sta_clear_tsfm_topo_info();
 | 
						|
out:
 | 
						|
    if (reason) {
 | 
						|
        iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
 | 
						|
        pkt = proto_645_2007_build_nack_msg(reason, hdr->addr,
 | 
						|
            PROTO_645_2007_FN_WRITE_DATA);
 | 
						|
    } else {
 | 
						|
        pkt = proto_645_2007_build_ack_msg(hdr->addr,
 | 
						|
            PROTO_645_2007_FN_WRITE_DATA);
 | 
						|
    }
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_info_query_req_bj(
 | 
						|
    proto_645_header_t *hdr)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t *data;
 | 
						|
    uint8_t addr[IOT_MAC_ADDR_LEN], reason = 0, report_num = 0, data_len = 0;
 | 
						|
    uint16_t max_unit_count, map_len, i, idx;
 | 
						|
    proto_645_header_t *resp_hdr;
 | 
						|
    proto_645_ext_br_info_query_bj_t *br_info_query;
 | 
						|
    proto_645_ext_br_energy_rsp_bj_t *resp_data;
 | 
						|
    proto_645_ext_br_energy_unit_bj_t *energy_uint;
 | 
						|
    iot_sg_sta_hw_tsfm_t *hw_tsfm = &p_sg_glb->desc.sta->hw_tsfm_info;
 | 
						|
    iot_sg_sta_tsfm_topo_bm_t *local_bm = hw_tsfm->tsfm_topo_info.sn_bm;
 | 
						|
 | 
						|
    if (!local_bm) {
 | 
						|
        reason = 1;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    if (hdr->len < sizeof(*br_info_query) + PROTO_645_2007_DI_LEN) {
 | 
						|
        reason = 2;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
 | 
						|
    iot_mac_addr_reverse(addr);
 | 
						|
    if (!iot_mac_addr_cmp(addr, hdr->addr)) {
 | 
						|
        reason = 3;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    proto_645_sub33_handle(hdr->data, hdr->len);
 | 
						|
    br_info_query = (proto_645_ext_br_info_query_bj_t *)(hdr->data +
 | 
						|
        PROTO_645_2007_DI_LEN);
 | 
						|
    if ( br_info_query->start_index >= PROTO_645_EXT_BR_BJ_NODE_ID_MAX) {
 | 
						|
        reason = 4;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    pkt = iot_pkt_alloc(sizeof(*resp_hdr) + PROTO_645_MAX_DATA_LEN +
 | 
						|
        sizeof(proto_645_tailer_t), IOT_SMART_GRID_MID);
 | 
						|
    if (pkt == NULL) {
 | 
						|
        reason = 5;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    data = iot_pkt_data(pkt);
 | 
						|
    resp_hdr = (proto_645_header_t*)data;
 | 
						|
    proto_645_header_init(resp_hdr, hdr->addr, hdr->control.fn,
 | 
						|
        PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
 | 
						|
        PROTO_645_FOLLOW_INVALID);
 | 
						|
    proto_645_2007_di_to_byte(PROTO_645_2007_EXT_DI_BR_BJ_INFO_QUERY,
 | 
						|
        resp_hdr->data);
 | 
						|
    data_len += PROTO_645_2007_DI_LEN;
 | 
						|
    resp_data = (proto_645_ext_br_energy_rsp_bj_t *)(resp_hdr->data +
 | 
						|
        PROTO_645_2007_DI_LEN);
 | 
						|
    /* count all valid sn in bitmap of topo sn in all phase */
 | 
						|
    resp_data->total_number = (uint16_t)iot_bitmap_cbs(local_bm->map,
 | 
						|
        sizeof(local_bm->map));
 | 
						|
    max_unit_count = (PROTO_645_MAX_DATA_LEN - PROTO_645_2007_DI_LEN -
 | 
						|
        sizeof(*resp_data)) / sizeof(*energy_uint);
 | 
						|
    max_unit_count = min(max_unit_count, br_info_query->num);
 | 
						|
    map_len = sizeof(local_bm->map);
 | 
						|
    for (i = 1, idx = 0; i < map_len * 8; i++) {
 | 
						|
        if (!iot_bitmap_is_set(local_bm->map, map_len, i + 1))
 | 
						|
            continue;
 | 
						|
        if (idx >= br_info_query->start_index) {
 | 
						|
            resp_data->energy_list[report_num].sn = i;
 | 
						|
            resp_data->energy_list[report_num].energy = local_bm->table[i - 1];
 | 
						|
            report_num++;
 | 
						|
            if (report_num >= max_unit_count) {
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        idx++;
 | 
						|
    }
 | 
						|
    data_len += sizeof(*resp_data) + report_num * sizeof(*energy_uint);
 | 
						|
    resp_data->start_index = br_info_query->start_index;
 | 
						|
    resp_data->report_number = report_num;
 | 
						|
    resp_hdr->len = data_len;
 | 
						|
    proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
 | 
						|
    proto_645_tail_init(resp_hdr);
 | 
						|
    iot_pkt_put(pkt, data_len + sizeof(*resp_hdr) + sizeof(proto_645_tailer_t));
 | 
						|
drop:
 | 
						|
    if (reason)
 | 
						|
        iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_info_query_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t addr[IOT_MAC_ADDR_LEN], reason;
 | 
						|
    uint16_t data_len, total_len;
 | 
						|
    uint32_t ret;
 | 
						|
    iot_sg_sta_tsfm_topo_desc_t bitmap_info = {0};
 | 
						|
    proto_645_ext_br_info_query_t *br_info_query;
 | 
						|
    proto_645_ext_br_rsp_data_t *resp_data;
 | 
						|
    proto_645_ext_br_info_rsp_t *br_info;
 | 
						|
    proto_645_ext_br_energy_rsp_t *br1_info;
 | 
						|
    proto_645_ext_br_energy_unit_t *energy_uint;
 | 
						|
    proto_645_header_t *resp_hdr;
 | 
						|
 | 
						|
    if (hdr->len < sizeof(*br_info_query) + PROTO_645_2007_DI_LEN) {
 | 
						|
        reason = 1;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
 | 
						|
    iot_mac_addr_reverse(addr);
 | 
						|
    if (!iot_mac_addr_cmp(addr, hdr->addr) && flag_addr_check) {
 | 
						|
        reason = 2;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    proto_645_sub33_handle(hdr->data, hdr->len);
 | 
						|
    br_info_query = (proto_645_ext_br_info_query_t *)(hdr->data +
 | 
						|
        PROTO_645_2007_DI_LEN);
 | 
						|
    ret = iot_sg_sta_get_tsfm_topo_bitmap_info(&bitmap_info,
 | 
						|
        br_info_query->phase_type, br_info_query->block_seq);
 | 
						|
    data_len = sizeof(*resp_data);
 | 
						|
    if (ret) {
 | 
						|
        data_len = data_len + sizeof(*br_info);
 | 
						|
        iot_printf("%s resp nack %lu\n", __FUNCTION__);
 | 
						|
    } else {
 | 
						|
        if (bitmap_info.energy_cnt) {
 | 
						|
            iot_printf("%s energy_list start %lu, cnt %lu\n",
 | 
						|
                __FUNCTION__, bitmap_info.energy_idx, bitmap_info.energy_cnt);
 | 
						|
            data_len = data_len + sizeof(*br1_info) +
 | 
						|
                bitmap_info.energy_cnt * sizeof(*energy_uint);
 | 
						|
        } else if (bitmap_info.length) {
 | 
						|
            iot_printf("%s bitmap len %lu, first sn %lu, phase %lu\n",
 | 
						|
                __FUNCTION__, bitmap_info.length, bitmap_info.first_sn,
 | 
						|
                br_info_query->phase_type);
 | 
						|
            data_len = data_len + sizeof(*br_info) + bitmap_info.length;
 | 
						|
        } else {
 | 
						|
            IOT_ASSERT(0);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    total_len = data_len + sizeof(*resp_hdr) + sizeof(proto_645_tailer_t);
 | 
						|
    pkt = iot_pkt_alloc(total_len, IOT_SMART_GRID_MID);
 | 
						|
    if (pkt) {
 | 
						|
        resp_hdr = (proto_645_header_t *)iot_pkt_data(pkt);
 | 
						|
        /* fill in 645 header */
 | 
						|
        proto_645_header_init(resp_hdr, hdr->addr, PROTO_645_2007_EXT_FN_BR,
 | 
						|
            PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
 | 
						|
            PROTO_645_FOLLOW_INVALID);
 | 
						|
        resp_hdr->len = (uint8_t)data_len;
 | 
						|
        resp_data = (proto_645_ext_br_rsp_data_t*)resp_hdr->data;
 | 
						|
        proto_645_2007_di_to_byte(di, (uint8_t*)&resp_data->di);
 | 
						|
        resp_data->result = PROTO_645_2007_EXT_BR_RESULT_OK;
 | 
						|
        if (bitmap_info.energy_cnt) {
 | 
						|
            resp_data->format = 1;
 | 
						|
            br1_info = (proto_645_ext_br_energy_rsp_t*)resp_data->data;
 | 
						|
            br1_info->data_block_total = bitmap_info.block_cnt;
 | 
						|
            br1_info->data_block_seq = bitmap_info.curr_seq;
 | 
						|
            br1_info->phase_type = br_info_query->phase_type;
 | 
						|
            br1_info->energy_cnt = (uint8_t)bitmap_info.energy_cnt;
 | 
						|
            iot_sg_sta_tsfm_topo_fill_energy_info(
 | 
						|
                (uint8_t*)&br1_info->energy_list,
 | 
						|
                br_info_query->phase_type,
 | 
						|
                bitmap_info.energy_idx,
 | 
						|
                bitmap_info.energy_cnt);
 | 
						|
        } else {
 | 
						|
            resp_data->format = 0;
 | 
						|
            br_info = (proto_645_ext_br_info_rsp_t*)resp_data->data;
 | 
						|
            br_info->data_block_total = bitmap_info.block_cnt;
 | 
						|
            br_info->data_block_seq = bitmap_info.curr_seq;
 | 
						|
            br_info->phase_type = br_info_query->phase_type;
 | 
						|
            br_info->bm_data_len = (uint8_t)bitmap_info.length +
 | 
						|
                sizeof(br_info->start_index);
 | 
						|
            br_info->start_index = bitmap_info.first_sn;
 | 
						|
            iot_sg_sta_tsfm_topo_fill_bitmap_info(br_info->bitmap,
 | 
						|
                &bitmap_info, br_info_query->phase_type);
 | 
						|
        }
 | 
						|
        proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
 | 
						|
        /* fill in 645 tailer */
 | 
						|
        proto_645_tail_init(resp_hdr);
 | 
						|
        iot_pkt_put(pkt, total_len);
 | 
						|
    }
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_info_clean_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
 | 
						|
{
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    uint8_t addr[IOT_MAC_ADDR_LEN], reason;
 | 
						|
    uint16_t total_len, data_len;
 | 
						|
    uint8_t user_type = iot_oem_get_user_type();
 | 
						|
    proto_645_header_t *resp_hdr;
 | 
						|
    proto_645_ext_br_rsp_data_t *rsp_hdr;
 | 
						|
    proto_645_ext_br_clear_rsp_t *rsp_clear;
 | 
						|
    proto_645_07_ext_brm_clean_dl_t *clean_info;
 | 
						|
    iot_sg_ext_cus_topo_rcv_cfg_t cfg = { 0 };
 | 
						|
 | 
						|
    if (hdr->len < (sizeof(*clean_info) + PROTO_645_2007_DI_LEN)) {
 | 
						|
        reason = 1;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    os_mem_cpy(addr, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
 | 
						|
    iot_mac_addr_reverse(addr);
 | 
						|
    if (!iot_mac_addr_cmp(addr, hdr->addr) && flag_addr_check) {
 | 
						|
        reason = 2;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    data_len = sizeof(*rsp_hdr) + sizeof(*rsp_clear);
 | 
						|
    total_len = sizeof(*resp_hdr) + data_len + sizeof(proto_645_tailer_t);
 | 
						|
    pkt = iot_pkt_alloc(total_len, IOT_SMART_GRID_MID);
 | 
						|
    if (!pkt) {
 | 
						|
        reason = 3;
 | 
						|
        goto drop;
 | 
						|
    }
 | 
						|
    resp_hdr = (proto_645_header_t *)iot_pkt_put(pkt, total_len);
 | 
						|
    /* fill in 645 header */
 | 
						|
    proto_645_header_init(resp_hdr, hdr->addr, PROTO_645_2007_EXT_FN_BR,
 | 
						|
        PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
 | 
						|
    resp_hdr->len = (uint8_t)data_len;
 | 
						|
    rsp_hdr = (proto_645_ext_br_rsp_data_t *)resp_hdr->data;
 | 
						|
    proto_645_2007_di_to_byte(di, (uint8_t *)&rsp_hdr->di);
 | 
						|
    rsp_hdr->result = PROTO_645_2007_EXT_BR_RESULT_OK;
 | 
						|
    rsp_clear = (proto_645_ext_br_clear_rsp_t *)rsp_hdr->data;
 | 
						|
    proto_645_sub33_handle(hdr->data, hdr->len);
 | 
						|
    if (user_type == USER_TYPE_BRM_SMALL_LOAD_GOLDEN) {
 | 
						|
        cfg.chara_bit_dur = IOT_PLC_HW_TSFM_LOAD_CHARA_DUR_TEST / 1000;
 | 
						|
    } else {
 | 
						|
        cfg.chara_bit_dur = 300;
 | 
						|
    }
 | 
						|
    cfg.fc = IOT_HW_TOPO_DECODE_FREQ_LOAD_DEF;
 | 
						|
 | 
						|
    iot_sg_ext_topo_rcv_cfg_to_cus(&cfg);
 | 
						|
    iot_sg_sta_clear_tsfm_topo_info();
 | 
						|
 | 
						|
    iot_printf("%s chara bit dur: %d, fc: %lu\n", __FUNCTION__,
 | 
						|
        cfg.chara_bit_dur, cfg.fc);
 | 
						|
    if (IOT_BSRM_MODE || IOT_BRM_ENABLE) {
 | 
						|
        rsp_clear->br_ident = 1;
 | 
						|
    }
 | 
						|
    rsp_clear->send_supp_mode = iot_plc_hw_tsfm_get_supp_mode();
 | 
						|
    proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
 | 
						|
    /* fill in 645 tailer */
 | 
						|
    proto_645_tail_init(resp_hdr);
 | 
						|
    goto out;
 | 
						|
drop:
 | 
						|
    iot_printf("%s fail reason %lu\n", __FUNCTION__, reason);
 | 
						|
out:
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_test_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di)
 | 
						|
{
 | 
						|
    uint8_t data[PROTO_645_VENDOR_BR_DATA_LEN];
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    hw_tsfm_send_cfg_t cfg = { 0 };
 | 
						|
    proto_hw_tsfm_hdr_t *topo_hdr;
 | 
						|
    proto_hw_tsfm_topo_sn_t *topo_data;
 | 
						|
    uint8_t result, len;
 | 
						|
    proto_645_ext_br_test_req_t *br_test_req;
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
 | 
						|
    if (hdr->len < PROTO_645_2007_DI_LEN + sizeof(*br_test_req)) {
 | 
						|
        cfg.phase = PROTO_645_2007_EXT_BRM_PHASE_A;
 | 
						|
        cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
 | 
						|
        goto send;
 | 
						|
    }
 | 
						|
    br_test_req = (proto_645_ext_br_test_req_t *)(hdr->data + \
 | 
						|
        PROTO_645_2007_DI_LEN);
 | 
						|
    if (br_test_req->phase > PROTO_645_2007_EXT_MAX_PHASE_NUM) {
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_INVAL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    cfg.phase = br_test_req->phase;
 | 
						|
    switch (br_test_req->send_mode) {
 | 
						|
    case PROTO_645_EXT_SEND_MODE_ZC:
 | 
						|
    {
 | 
						|
        cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
 | 
						|
        cfg.cnt = 1;
 | 
						|
        cfg.para.zc.ahead = 500;
 | 
						|
        cfg.para.zc.dur_output = 300;
 | 
						|
        cfg.para.zc.is_rising = br_test_req->rising_send;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_EXT_SEND_MODE_ENCODED_LOAD:
 | 
						|
    {
 | 
						|
        cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_LOAD;
 | 
						|
        cfg.cnt = 1;
 | 
						|
        cfg.para.load.encode = IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_2;
 | 
						|
        cfg.para.load.pulse_high_dur = IOT_PLC_HW_TSFM_LOAD_SIG_HIGH_DUR_DEF;
 | 
						|
        cfg.para.load.pulse_low_dur = IOT_PLC_HW_TSFM_LOAD_SIG_LOW_DUR_DEF;
 | 
						|
        /* the characteristic bit duration is assigned to 0, and the
 | 
						|
         * corresponding value is determined by the lower layer according
 | 
						|
         * to the actual hardware configuration.
 | 
						|
         */
 | 
						|
        cfg.para.load.chara_bit_dur = 0;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    case PROTO_645_EXT_SEND_MODE_PA:
 | 
						|
    {
 | 
						|
        cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_PA;
 | 
						|
        cfg.cnt = 2;
 | 
						|
        cfg.para.pa.offset_time = 500;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    default:
 | 
						|
        result = PROTO_645_2007_EXT_BR_RESULT_INVAL;
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
send:
 | 
						|
    if (cfg.mod_mode == IOT_PLC_HW_TSFM_SEND_MODE_ZC) {
 | 
						|
        topo_hdr = (proto_hw_tsfm_hdr_t *)data;
 | 
						|
        topo_hdr->data_id = PROTO_HW_TSFM_ID_TOPO_TEST;
 | 
						|
        topo_hdr->data_len = 0;
 | 
						|
        len = sizeof(*topo_hdr) + topo_hdr->data_len;
 | 
						|
    } else {
 | 
						|
        topo_data = (proto_hw_tsfm_topo_sn_t *)data;
 | 
						|
        topo_data->sn = PROTO_HW_TSFM_ID_TOPO_TEST;
 | 
						|
        len = sizeof(*topo_data);
 | 
						|
    }
 | 
						|
    ret = proto_645_vendor_br_launch(data, len, &cfg);
 | 
						|
    result = proto_645_vendor_br_ret_to_result(ret);
 | 
						|
    iot_printf("%s mode %lu ahead %lu, dur_output %lu, result %lu\n",
 | 
						|
        __FUNCTION__, cfg.mod_mode, cfg.para.zc.ahead, cfg.para.zc.dur_output,
 | 
						|
        result);
 | 
						|
out:
 | 
						|
    pkt = proto_645_vendor_build_br_msg(hdr->addr, &result, sizeof(result),
 | 
						|
        di, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL);
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_test_query_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di)
 | 
						|
{
 | 
						|
    proto_645_ext_br_test_query_rsp_t *rsp = NULL;
 | 
						|
    proto_645_ext_br_test_query_rsp_opt_t *rsp_opt = NULL;
 | 
						|
    uint8_t data_buff[sizeof(*rsp) + sizeof(*rsp_opt)] = { 0 };
 | 
						|
    iot_pkt_t *pkt = NULL;
 | 
						|
    iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
 | 
						|
    uint8_t i;
 | 
						|
 | 
						|
    rsp = (proto_645_ext_br_test_query_rsp_t *)data_buff;
 | 
						|
    rsp_opt = rsp->opt_data;
 | 
						|
    rsp->phase = sta_glb->hw_tsfm_info.topo_phase_rec & 0x07;
 | 
						|
    rsp->opt_data_en = 1;
 | 
						|
    for (i = 0; i < IOT_PLC_PHASE_CNT; i++) {
 | 
						|
        rsp_opt->energy[i] = sta_glb->hw_tsfm_info.topo_energy_rec[i];
 | 
						|
    }
 | 
						|
    iot_printf("%s phase rec info %02x, energy [%lu, %lu, %lu], "
 | 
						|
        "current [%lu, %lu, %lu]\n", __FUNCTION__, rsp->phase,
 | 
						|
        rsp_opt->energy[0], rsp_opt->energy[1], rsp_opt->energy[2],
 | 
						|
        rsp_opt->current[0], rsp_opt->current[1], rsp_opt->current[2]);
 | 
						|
    pkt = proto_645_vendor_build_br_msg(hdr->addr, data_buff, sizeof(data_buff),
 | 
						|
        di, PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL);
 | 
						|
    return pkt;
 | 
						|
}
 | 
						|
 | 
						|
#else /* IOT_SMART_GRID_BRANCH_DETECT_ENABLE */
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_launch_req(uint8_t *addr,
 | 
						|
    uint8_t *fwd_addr, uint16_t node_seq, uint16_t ahead, uint16_t dur_output,
 | 
						|
    uint8_t repeat_cnt, uint8_t send_mode, uint8_t launch_sn, uint16_t pa_freq)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)fwd_addr;
 | 
						|
    (void)node_seq;
 | 
						|
    (void)ahead;
 | 
						|
    (void)dur_output;
 | 
						|
    (void)repeat_cnt;
 | 
						|
    (void)send_mode;
 | 
						|
    (void)launch_sn;
 | 
						|
    (void)pa_freq;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_launch_state_req(uint8_t *addr,
 | 
						|
    uint8_t *fwd_addr)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)fwd_addr;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_recv_init_bj(proto_645_header_t *hdr)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_query_req(uint8_t *addr,
 | 
						|
    uint8_t seq, uint8_t phase_type)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)seq;
 | 
						|
    (void)phase_type;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_tsfm_addr_clear_req(uint8_t *addr)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_clean_req(uint8_t *addr,
 | 
						|
    uint8_t send_phase, uint16_t pa_freq)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)send_phase;
 | 
						|
    (void)pa_freq;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_nei_node_info_query_req(uint8_t *addr,
 | 
						|
    uint8_t seq)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)seq;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_tsfm_info_query_req(uint8_t *addr,
 | 
						|
    uint8_t *fwd_addr)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)fwd_addr;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_meter_info_query_req(uint8_t *addr,
 | 
						|
    uint8_t seq, uint8_t ver)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)seq;
 | 
						|
    (void)ver;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_add_pm_req(uint8_t *addr,
 | 
						|
    uint8_t *data, uint8_t len)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)data;
 | 
						|
    (void)len;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
#if IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_BJ
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_launch_req_bj(uint8_t *addr,
 | 
						|
    uint16_t node_seq, uint16_t bit_dur, uint16_t high_dur, uint16_t low_dur,
 | 
						|
    uint8_t launch_sn)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)node_seq;
 | 
						|
    (void)bit_dur;
 | 
						|
    (void)high_dur;
 | 
						|
    (void)low_dur;
 | 
						|
    (void)launch_sn;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_query_req_bj(uint8_t *addr,
 | 
						|
    uint16_t start_idx, uint8_t num)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)start_idx;
 | 
						|
    (void)num;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_build_br_info_clean_req_bj(uint8_t *addr,
 | 
						|
    uint16_t bit_dur, uint32_t freq)
 | 
						|
{
 | 
						|
    (void)addr;
 | 
						|
    (void)bit_dur;
 | 
						|
    (void)freq;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* IOT_SMART_GTID_BRANCH_DETECT_SUPPORT_BJ */
 | 
						|
 | 
						|
uint32_t proto_645_vendor_br_rsp_check(proto_645_header_t *hdr,
 | 
						|
    proto_645_ext_br_rsp_cache_t *br_rsp)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    (void)br_rsp;
 | 
						|
    return ERR_NOSUPP;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_645_vendor_conn_fwd_br_rsp_check(uint8_t **data,
 | 
						|
    uint32_t *data_len)
 | 
						|
{
 | 
						|
    (void)data;
 | 
						|
    (void)data_len;
 | 
						|
    return ERR_NOSUPP;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_launch_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    (void)di;
 | 
						|
    (void)flag_addr_check;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_launch_state_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    (void)di;
 | 
						|
    (void)flag_addr_check;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_info_query_req_bj(
 | 
						|
    proto_645_header_t *hdr)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_info_query_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    (void)di;
 | 
						|
    (void)flag_addr_check;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_info_clean_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di, uint8_t flag_addr_check)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    (void)di;
 | 
						|
    (void)flag_addr_check;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t proto_645_vendor_br_launch(uint8_t *data, uint8_t len,
 | 
						|
    hw_tsfm_send_cfg_t *cfg)
 | 
						|
{
 | 
						|
    (void)data;
 | 
						|
    (void)len;
 | 
						|
    (void)cfg;
 | 
						|
    return ERR_NOSUPP;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_test_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    (void)di;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *proto_645_vendor_handle_br_test_query_req(
 | 
						|
    proto_645_header_t *hdr, uint32_t di)
 | 
						|
{
 | 
						|
    (void)hdr;
 | 
						|
    (void)di;
 | 
						|
    return NULL;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* IOT_SMART_GRID_BRANCH_DETECT_ENABLE */
 |