Files
kunlun/app/smart_grid/protocol/proto_645_vendor.c
2024-09-28 14:24:04 +08:00

2250 lines
75 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_adc_api.h"
#include "iot_version_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_topo.h"
#include "iot_sg_sta_ext.h"
#include "iot_sg_sta_conn_less.h"
#include "proto_hw_tsfm.h"
#include "iot_sg_sta_zc.h"
#if (IOT_SMART_GRID_ENABLE || IOT_BSRM_MODE)
void proto_645_vendor_build_ver_info_base(proto_645_ext_read_ver_rsp_t *ver_rsp)
{
iot_build_info_t build_info;
iot_oem_base_cfg_t *base_cfg = NULL;
IOT_ASSERT(ver_rsp);
ver_rsp->type_ver = iot_version_type();
ver_rsp->firmware_version = iot_version_hex();
iot_version_get_user_build_info(&build_info);
ver_rsp->sw_ver = build_info.sw_ver;
ver_rsp->app_ver = build_info.app_ver;
ver_rsp->year = build_info.year;
ver_rsp->month = build_info.month;
ver_rsp->day = build_info.day;
ver_rsp->hour = build_info.hour;
ver_rsp->min = build_info.min;
ver_rsp->sec = build_info.sec;
iot_oem_get_base_cfg(&base_cfg);
os_mem_cpy(ver_rsp->dev_id, base_cfg->dev_id,
PROTO_645_2007_EXT_DEVICE_ID_LEN);
iot_oem_get_chip_mmid(ver_rsp->chip_mmid,
PROTO_645_2007_EXT_CHIP_MMID_ID_LEN);
#if IOT_BSRM_MODE
ver_rsp->img_check_result = 1;
ver_rsp->vendor_id = iot_board_load_user_vendor_id();
#else
ver_rsp->vendor_id = iot_sg_get_vendor_id();
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (!sta_glb->flag_img_check) {
sta_glb->img_check_result = iot_upgrade_fw_hdr_img_crc_check();
sta_glb->flag_img_check = 1;
}
ver_rsp->img_check_result = sta_glb->img_check_result;
#endif /* IOT_BSRM_MODE */
if (IOT_BSRM_MODE || IOT_BRM_ENABLE) {
ver_rsp->br_ident = 1;
} else {
ver_rsp->br_ident = 0;
}
if (iot_plc_get_comm_type()) {
ver_rsp->rf = 1;
} else {
ver_rsp->rf = 0;
}
ver_rsp->reserve = 0;
ver_rsp->hw_ver = iot_board_hw_version_hex();
iot_oem_get_module_mac(ver_rsp->mod_addr);
ver_rsp->user_type = iot_oem_get_user_type();
}
#endif /* (IOT_SMART_GRID_ENABLE || IOT_BSRM_MODE) */
#if IOT_BSRM_MODE
iot_pkt_t *proto_645_vendor_build_tcz_ver_info(uint8_t *addr)
{
uint32_t length, di = PROTO_645_2007_EXT_DI_TCZ_READ_VER;
iot_pkt_t *pkt;
proto_645_header_t *hdr = NULL;
proto_645_ext_read_tcz_ver_rsp_t *rsp = NULL;
iot_build_info_t build_info = { 0 };
length = PROTO_645_2007_READ_DATA_PKT_LEN +
sizeof(proto_645_ext_read_tcz_ver_rsp_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(proto_645_ext_read_tcz_ver_rsp_t) +
PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, hdr->data);
rsp = (proto_645_ext_read_tcz_ver_rsp_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
rsp->vendor_id = iot_sg_get_vendor_id();
rsp->chip_type = 'H';
rsp->module_type = 'D';
iot_version_get_user_build_info(&build_info);
rsp->year = iot_byte_to_bcd(build_info.year);
rsp->month = iot_byte_to_bcd(build_info.month);
rsp->day = iot_byte_to_bcd(build_info.day);
rsp->sw_ver = build_info.sw_ver;
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
#else
iot_pkt_t *proto_645_vendor_build_tcz_ver_info(uint8_t *addr)
{
(void)addr;
return NULL;
}
#endif
#if (IOT_SMART_GRID_ENABLE)
static iot_pkt_t *proto_645_vendor_zc_check();
static iot_pkt_t *proto_645_vendor_get_mod_sw_ver();
static iot_pkt_t *proto_645_vendor_build_ver_info(uint8_t *addr)
{
uint32_t length, di = PROTO_645_2007_EXT_DI_READ_VER;
iot_pkt_t *pkt;
proto_645_header_t *hdr = NULL;
proto_645_ext_read_ver_rsp_t *rsp = NULL;
length = PROTO_645_2007_READ_DATA_PKT_LEN +
sizeof(proto_645_ext_read_ver_rsp_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(proto_645_ext_read_ver_rsp_t) + PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, hdr->data);
rsp = (proto_645_ext_read_ver_rsp_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
proto_645_vendor_build_ver_info_base(rsp);
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
static iot_pkt_t *proto_645_vendor_build_ver2_info(uint8_t *addr)
{
uint32_t length, di = PROTO_645_2007_EXT_DI_READ_VER_2;
iot_build_info_t build_info;
iot_oem_hw_ver_info_t ver_info;
iot_pkt_t *pkt;
proto_645_header_t *hdr = NULL;
proto_645_ext_read_ver_rsp_v2_t *rsp = NULL;
length = PROTO_645_2007_READ_DATA_PKT_LEN +
sizeof(proto_645_ext_read_ver_rsp_v2_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(proto_645_ext_read_ver_rsp_v2_t) +
PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, hdr->data);
rsp = (proto_645_ext_read_ver_rsp_v2_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
rsp->vendor_id = iot_sg_get_vendor_id();
rsp->chip_code = iot_sg_get_chip_code();
iot_oem_get_hw_ver_info(&ver_info);
iot_version_get_user_build_info(&build_info);
os_mem_cpy(rsp->module_ver, ver_info.module_version,
min(sizeof(rsp->module_ver), sizeof(ver_info.module_version)));
rsp->module_ver_year = ver_info.module_version_year;
rsp->module_ver_month = ver_info.module_version_month;
rsp->module_ver_day = ver_info.module_version_day;
rsp->sw_ver[0] = ((uint8_t)build_info.sw_ver & 0x0f) + 0x30;
rsp->sw_ver[1] = ((uint8_t)(build_info.sw_ver >> 4) & 0x0f) + 0x30;
rsp->sw_ver[2] = ((uint8_t)(build_info.sw_ver >> 8) & 0x0f) + 0x30;
rsp->sw_ver[3] = 0x56;
rsp->build_sw_ver = iot_version_hex();
rsp->sw_year = iot_byte_to_bcd(build_info.year);
rsp->sw_month = iot_byte_to_bcd(build_info.month);
rsp->sw_day = iot_byte_to_bcd(build_info.day);
os_mem_cpy(rsp->chip_ver, ver_info.chip_ver,
min(sizeof(rsp->chip_ver), sizeof(ver_info.chip_ver)));
rsp->chip_ver_year = ver_info.chip_year;
rsp->chip_ver_month = ver_info.chip_month;
rsp->chip_ver_day = ver_info.chip_day;
iot_oem_get_module_mac(rsp->dev_mac_addr);
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
iot_pkt_t *proto_645_vendor_build_mac_and_ver_info(uint8_t *addr,
uint8_t fn)
{
uint32_t length, di = PROTO_645_2007_READ_NW_VER;
iot_pkt_t *pkt;
proto_645_header_t *hdr = NULL;
proto_645_ext_mac_and_ver_info_t *rsp = NULL;
iot_build_info_t build_info;
length = PROTO_645_2007_READ_DATA_PKT_LEN +
sizeof(proto_645_ext_mac_and_ver_info_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, fn, PROTO_645_DIR_SLAVE,
PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(proto_645_ext_mac_and_ver_info_t) +
PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, hdr->data);
proto_645_add33_handle(hdr->data, PROTO_645_2007_DI_LEN);
rsp = (proto_645_ext_mac_and_ver_info_t*)(hdr->data +
PROTO_645_2007_DI_LEN);
iot_oem_get_module_mac(rsp->mac);
rsp->vendor_id = iot_sg_get_vendor_id();
iot_version_get_user_build_info(&build_info);
os_mem_cpy(rsp->module_ver, (uint8_t *)&build_info.sw_ver,
sizeof(build_info.sw_ver));
rsp->module_ver_year = build_info.year;
rsp->module_ver_month = build_info.month;
rsp->module_ver_day = build_info.day;
rsp->chip_code = iot_sg_get_chip_code();
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
iot_pkt_t *proto_645_vendor_build_basic_info(uint8_t *addr, uint32_t di)
{
uint8_t chip_name_len;
uint8_t chip_name_buf[IOT_CHIP_NAME_BUFFER_MIN_LEN] = { 0 };
uint32_t length;
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr = NULL;
proto_645_07_ext_basic_info_t *basic_info;
iot_build_info_t build_info;
chip_name_len = iot_board_chip_name_get(chip_name_buf,
IOT_CHIP_NAME_BUFFER_MIN_LEN);
length = PROTO_645_2007_READ_DATA_PKT_LEN +
sizeof(proto_645_07_ext_basic_info_t) + chip_name_len;
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(proto_645_07_ext_basic_info_t) + chip_name_len +
PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, hdr->data);
basic_info = (proto_645_07_ext_basic_info_t*)(hdr->data +
PROTO_645_2007_DI_LEN);
basic_info->cpu_num = 0;
basic_info->vendor_id = iot_sg_get_vendor_id();
iot_version_get_user_build_info(&build_info);
basic_info->ver_year = build_info.year;
basic_info->ver_month = build_info.month;
basic_info->ver_day = build_info.day;
basic_info->hw_ver = 1;
basic_info->sw_ver = build_info.sw_ver;
basic_info->mcu_name_len = chip_name_len;
if (chip_name_len) {
os_mem_cpy(basic_info->mcu_name, chip_name_buf, chip_name_len);
}
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
iot_pkt_t *proto_645_vendor_build_check_code(uint8_t *check_code,
uint8_t check_code_len, uint8_t *addr, uint32_t di)
{
uint32_t length;
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr = NULL;
if (!check_code || !addr) {
goto out;
}
if (check_code_len != IOT_SG_SHA1_CHECK_CODE_LEN) {
goto out;
}
length = PROTO_645_2007_READ_DATA_PKT_LEN + check_code_len;
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = PROTO_645_2007_DI_LEN + check_code_len;
proto_645_2007_di_to_byte(di, hdr->data);
os_mem_cpy(hdr->data + PROTO_645_2007_DI_LEN, check_code,
check_code_len);
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
out:
return pkt;
}
iot_pkt_t *proto_645_vendor_build_core_temperature_info(uint8_t *addr)
{
uint8_t len;
uint32_t di = PROTO_645_2007_EXT_READ_CORE_TEMPERATURE;
proto_645_header_t *hdr = NULL;
proto_645_ext_core_temperature_t *core_temp = NULL;
iot_pkt_t *pkt = NULL;
float temp_cali, temp_not_cali;
len = sizeof(*hdr) + PROTO_645_2007_DI_LEN + sizeof(*core_temp) +
sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = PROTO_645_2007_DI_LEN + sizeof(*core_temp);
proto_645_2007_di_to_byte(di, hdr->data);
core_temp = (proto_645_ext_core_temperature_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
temp_cali = iot_adc_get_core_temperature(1) * 100;
if (temp_cali < 0) {
core_temp->temp_cali_sign = 1;
} else {
core_temp->temp_cali_sign = 0;
}
core_temp->temp_cali = (uint32_t)IOT_ABS(temp_cali);
temp_not_cali = iot_adc_get_core_temperature(0) * 100;
if (temp_not_cali < 0) {
core_temp->temp_not_cali_sign = 1;
} else {
core_temp->temp_not_cali_sign = 0;
}
core_temp->temp_not_cali = (uint32_t)IOT_ABS(temp_not_cali);
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, len);
}
return pkt;
}
iot_pkt_t *proto_645_vendor_build_id_info(uint8_t *addr, uint8_t info_type)
{
uint8_t *data;
uint32_t length;
iot_pkt_t *pkt;
iot_oem_base_cfg_t *base_cfg = NULL;
proto_645_header_t *hdr = NULL;
proto_645_ext_query_module_id_rsp_t *module_rsp;
proto_645_ext_query_chip_id_rsp_t *chip_rsp;
length = sizeof(*hdr) + sizeof(proto_645_tailer_t);
switch (info_type) {
case PROTO_645_2007_EXT_CHIP_ID:
{
length += sizeof(*chip_rsp);
break;
}
case PROTO_645_2007_EXT_MODULE_ID:
{
length += sizeof(*module_rsp);
break;
}
case PROTO_645_2007_EXT_VER_ID:
{
pkt = proto_645_vendor_build_ver_info(addr);
goto out;
}
case PROTO_645_2007_EXT_VER2_ID:
{
pkt = proto_645_vendor_build_ver2_info(addr);
goto out;
}
case PROTO_645_2007_EXT_NW_VER_ID:
{
pkt = proto_645_vendor_build_mac_and_ver_info(addr,
PROTO_645_2007_FN_READ_DATA);
goto out;
}
#if IOT_SMART_GRID_ZH_FTM_CMD_ENABLE
case PROTO_645_2007_EXT_ZC_INFO_ID:
{
pkt = proto_645_vendor_zc_check();
goto out;
}
case PROTO_645_2007_EXT_INTER_VER_ID:
{
pkt = proto_645_vendor_get_mod_sw_ver();
goto out;
}
#endif
default:
length += PROTO_645_2007_EXT_QUERY_ID_ERR_LEN;
break;
}
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
data = iot_pkt_data(pkt);
hdr = (proto_645_header_t *)data;
/* fill in 645 header */
proto_645_header_init(hdr, addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
switch (info_type) {
case PROTO_645_2007_EXT_CHIP_ID:
{
hdr->len = sizeof(*chip_rsp);
chip_rsp = (proto_645_ext_query_chip_id_rsp_t*)hdr->data;
chip_rsp->info_type = info_type;
chip_rsp->info_len = PROTO_645_2007_EXT_CHIP_MMID_ID_LEN;
iot_oem_get_chip_mmid(chip_rsp->chip_mmid,
PROTO_645_2007_EXT_CHIP_MMID_ID_LEN);
break;
}
case PROTO_645_2007_EXT_MODULE_ID:
{
hdr->len = sizeof(*module_rsp);
module_rsp = (proto_645_ext_query_module_id_rsp_t*)hdr->data;
module_rsp->info_type = info_type;
module_rsp->info_len = PROTO_645_2007_EXT_DEVICE_ID_LEN;
iot_oem_get_base_cfg(&base_cfg);
os_mem_cpy(module_rsp->dev_id, base_cfg->dev_id,
PROTO_645_2007_EXT_DEVICE_ID_LEN);
break;
}
default:
hdr->control.ack = PROTO_645_ACK_ABNORMAL;
hdr->len = PROTO_645_2007_EXT_QUERY_ID_ERR_LEN;
hdr->data[0] = PROTO_645_2007_EXT_QUERY_ID_ERR;
break;
}
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
out:
return pkt;
}
static iot_pkt_t *proto_645_vendor_build_hn_id_info(uint8_t *addr)
{
uint32_t length;
iot_pkt_t *pkt;
iot_oem_base_cfg_t *base_cfg = NULL;
proto_645_header_t *hdr = NULL;
length = sizeof(*hdr) + sizeof(proto_645_tailer_t)
+ PROTO_645_2007_EXT_DEVICE_ID_LEN;
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
/* fill in 645 header */
proto_645_header_init(hdr, addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = PROTO_645_2007_EXT_DEVICE_ID_LEN;
iot_oem_get_base_cfg(&base_cfg);
os_mem_cpy(hdr->data, base_cfg->dev_id,
PROTO_645_2007_EXT_DEVICE_ID_LEN);
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
static uint32_t proto_645_vendor_set_module_id(uint8_t *data, uint8_t force)
{
uint32_t ret;
iot_oem_base_cfg_t *oem_base_cfg;
iot_oem_get_base_cfg(&oem_base_cfg);
if (!force && iot_bitmap_cbs(oem_base_cfg->dev_id,
PROTO_645_2007_EXT_DEVICE_ID_LEN)) {
ret = ERR_EXIST;
goto out;
}
os_mem_cpy(oem_base_cfg->dev_id, data, PROTO_645_2007_EXT_DEVICE_ID_LEN);
ret = iot_oem_set_base_cfg(oem_base_cfg);
out:
return ret;
}
uint32_t proto_645_vendor_set_id_info(proto_645_ext_set_id_info_req_t *req,
uint8_t force)
{
uint32_t ret = ERR_INVAL;
proto_645_ext_mc_id_info_t *mc_id;
switch (req->id_type) {
case PROTO_645_2007_EXT_CHIP_ID:
{
if (req->data_len < PROTO_645_2007_EXT_CHIP_MMID_ID_LEN) {
goto out;
}
ret = iot_oem_set_chip_mmid(req->data,
PROTO_645_2007_EXT_CHIP_MMID_ID_LEN, force);
break;
}
case PROTO_645_2007_EXT_MODULE_ID:
{
if (req->data_len < PROTO_645_2007_EXT_DEVICE_ID_LEN) {
goto out;
}
ret = proto_645_vendor_set_module_id(req->data, force);
break;
}
case PROTO_645_2007_EXT_MC_ID:
{
if (req->data_len < PROTO_645_2007_EXT_DEVICE_ID_LEN +
PROTO_645_2007_EXT_CHIP_MMID_ID_LEN) {
goto out;
}
mc_id = (proto_645_ext_mc_id_info_t *)req->data;
if (!iot_oem_set_chip_mmid(mc_id->chip_mmid,
PROTO_645_2007_EXT_CHIP_MMID_ID_LEN, force)) {
ret = ERR_OK;
}
if (!proto_645_vendor_set_module_id(mc_id->mod_id, force)) {
ret = ERR_OK;
}
break;
}
default:
goto out;
}
out:
return ret;
}
static iot_pkt_t *proto_645_vendor_build_set_id_info_rsp(uint8_t *addr,
uint32_t ret)
{
uint32_t length, di = PROTO_645_2007_EXT_DI_SET_ID_INFO;
uint8_t ack, ret_code;
iot_pkt_t *pkt;
proto_645_ext_set_id_info_rsp_t *rsp;
proto_645_header_t *hdr;
length = sizeof(*hdr) + sizeof(proto_645_tailer_t) + sizeof(*rsp) +
PROTO_645_2007_DI_LEN;
if (ret == ERR_OK) {
ack = PROTO_645_ACK_NORMAL;
ret_code = ERR_OK_SET_ID_INFO;
} else if (ret == ERR_EXIST) {
ack = PROTO_645_ACK_ABNORMAL;
ret_code = ERR_EXIST_SET_ID_INFO;
} else {
ack = PROTO_645_ACK_ABNORMAL;
ret_code = ERR_INVAL_SET_ID_INFO;
}
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
/* fill in 645 header */
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_WRITE_DATA,
PROTO_645_DIR_SLAVE, ack, PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(*rsp) + PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, hdr->data);
rsp = (proto_645_ext_set_id_info_rsp_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
rsp->ret = ret_code;
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
static uint32_t proto_645_vendor_handle_set_id_info_req(proto_645_header_t *hdr,
uint32_t len)
{
uint32_t ret = ERR_INVAL, data_len;
uint8_t link_type;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
proto_645_ext_set_id_info_req_t *req;
link_type = sta_glb->req.link_type;
if (link_type != IOT_SG_LINK_TYPE_PLC_CONN_LESS) {
goto out;
}
if (hdr->control.fn != PROTO_645_2007_FN_WRITE_DATA) {
goto out;
}
data_len = len - sizeof(*hdr) - sizeof(proto_645_tailer_t);
if (hdr->len > data_len) {
goto out;
}
if (hdr->len < (sizeof(*req) + PROTO_645_2007_DI_LEN)) {
goto out;
}
req = (proto_645_ext_set_id_info_req_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
data_len = data_len - PROTO_645_2007_DI_LEN - sizeof(*req);
if (req->data_len > data_len) {
goto out;
}
ret = proto_645_vendor_set_id_info(req, 0);
out:
return ret;
}
iot_pkt_t *proto_645_vendor_build_br_msg(uint8_t *addr, uint8_t *data,
uint8_t len, uint32_t di, uint8_t dir, uint8_t ack)
{
uint8_t data_len = len + PROTO_645_2007_DI_LEN;
iot_pkt_t *pkt;
proto_645_header_t *hdr;
pkt = iot_pkt_alloc(data_len + sizeof(*hdr) + sizeof(proto_645_tailer_t),
IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
/* fill in 645 header */
proto_645_header_init(hdr, addr, PROTO_645_2007_EXT_FN_BR,
dir, ack, PROTO_645_FOLLOW_INVALID);
hdr->len = data_len;
proto_645_2007_di_to_byte(di, hdr->data);
if (data) {
os_mem_cpy(hdr->data + PROTO_645_2007_DI_LEN, data, len);
}
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, data_len + sizeof(*hdr) + sizeof(proto_645_tailer_t));
}
return pkt;
}
iot_pkt_t *proto_645_vendor_build_tsfm_launch_req(uint8_t *addr,
uint8_t *tsfm_addr, uint16_t dur_output, uint16_t ahead,
uint8_t repeat_cnt, uint16_t send_interval, uint8_t sn, uint8_t is_rising)
{
proto_645_ext_tsfm_launch_req_t req = { 0 };
req.ahead = ahead;
req.dur_output = dur_output;
req.repeat_cnt = repeat_cnt;
req.send_interval = send_interval;
req.is_rising = is_rising;
req.sn = sn;
iot_mac_addr_cpy(req.tsfm_addr, tsfm_addr);
return proto_645_vendor_build_br_msg(addr, (uint8_t *)&req, sizeof(req),
PROTO_645_2007_EXT_DI_TSFM_LAUNCH, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
}
iot_pkt_t *proto_645_vendor_build_tsfm_clear_req(proto_645_header_t *hdr,
uint32_t di)
{
iot_pkt_t *pkt = NULL;
uint8_t result = PROTO_645_2007_EXT_BR_RESULT_OK;
iot_sg_sta_tsfm_info_t info;
uint8_t addr[IOT_MAC_ADDR_LEN];
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)) {
iot_printf("%s fail for addr\n", __FUNCTION__);
goto out;
}
os_mem_set(&info, 0, sizeof(info));
iot_sg_sta_save_tsfm_info(&info);
pkt = proto_645_vendor_build_br_msg(hdr->addr, &result, sizeof(result), di,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL);
out:
return pkt;
}
iot_pkt_t *proto_645_vendor_build_br_correct_time_req(uint8_t *addr,
iot_time_tm_t *tm)
{
proto_645_corr_time_t time;
time.year = iot_byte_to_bcd((uint8_t)(tm->tm_year - 2000));
time.month = iot_byte_to_bcd(tm->tm_mon);
time.day = iot_byte_to_bcd(tm->tm_mday);
time.hour = iot_byte_to_bcd(tm->tm_hour);
time.minute = iot_byte_to_bcd(tm->tm_min);
time.second = iot_byte_to_bcd(tm->tm_sec);
return proto_645_vendor_build_br_msg(addr, (uint8_t*)&time, sizeof(time),
PROTO_645_2007_EXT_BRM_CONN_CORRECT, PROTO_645_DIR_MASTER,
PROTO_645_ACK_NORMAL);
}
static uint32_t proto_645_vendor_br2_addr_check(uint8_t *addr)
{
uint8_t mac[IOT_MAC_ADDR_LEN] = {0}, dev_addr[IOT_MAC_ADDR_LEN] = {0};
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
os_mem_cpy(mac, p_sg_glb->plc_state.addr, IOT_MAC_ADDR_LEN);
iot_mac_addr_reverse(mac);
sta_glb->drv->get_device_addr(dev_addr);
if (!iot_mac_addr_cmp(mac, addr) && !iot_mac_addr_cmp(dev_addr, addr)) {
return ERR_FAIL;
}
return ERR_OK;
}
static iot_pkt_t *proto_645_vendor_handle_br2_launch_yns_req(
proto_645_header_t *hdr)
{
uint8_t result_err, reason = 0;
uint8_t req_data_len, resp_len, is_trans = 1, flag_sub33 = 0;
uint32_t di = PROTO_645_2007_EXT_DI_BR2_LAUNCH;
iot_pkt_t *result_pkt = NULL;
iot_time_tm_t now_tm;
proto_645_header_t *result_hdr;
proto_645_ext_br2_launch_t *br_launch = NULL;
proto_645_ext_br2_launch_result_t result;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_topo_info_t *topo_info = &sta_glb->hw_tsfm_info.tsfm_topo_info;
if (!sta_glb->br2_enable) {
reason = 1;
goto out;
}
if (proto_645_vendor_br2_addr_check(hdr->addr)) {
reason = 2;
goto out;
}
req_data_len = sizeof(*br_launch) + PROTO_645_2007_DI_LEN;
if (hdr->len < req_data_len) {
reason = 3;
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
flag_sub33 = 1;
br_launch = (proto_645_ext_br2_launch_t*)(hdr->data +
PROTO_645_2007_DI_LEN);
req_data_len = req_data_len + br_launch->code_len +
sizeof(proto_645_ext_br2_pulse_width_t);
if (hdr->len < req_data_len) {
reason = 4;
goto out;
}
switch (br_launch->trans_type) {
case PROTO_645_EXT_BR2_HANDLE:
{
is_trans = 0;
break;
}
case PROTO_645_EXT_BR2_TRANS:
{
reason = 5;
is_trans = 1;
goto out;
}
case PROTO_645_EXT_BR2_HANDLE_AND_TRANS:
{
is_trans = 1;
break;
}
default:
reason = 6;
is_trans = 1;
goto out;
}
if (br_launch->sn == topo_info->branch2.sn
&& topo_info->branch2.sn_is_valid) {
reason = 7;
result_err = 0;
goto resp;
}
result_err = iot_sg_sta_tsfm_topo_br2_launch_start(NULL,
br_launch->code, br_launch->code_len,
IOT_SG_STA_TSFM_BR2_PULSE_HIGH_DUR_DEF,
IOT_SG_STA_TSFM_BR2_PULSE_LOW_DUR_DEF,
IOT_SG_STA_TSFM_BR2_CHARA_BIT_DUR_DEF, NULL,
IOT_PLC_HW_TSFM_LOAD_ENCODE_RAW);
if (result_err) {
reason = 8;
result_err = 1;
goto resp;
}
topo_info->branch2.sn_is_valid = 1;
topo_info->branch2.sn = br_launch->sn;
result_err = 0;
resp:
if (is_trans) {
goto out;
}
result.sn = br_launch->sn;
if (result_err) {
/* if there is an error, fill in 0xFF */
os_mem_set((uint8_t*)&result.tm, 0xFF, sizeof(result.tm));
} else {
iot_sg_sta_rtc_get(&now_tm, 0);
proto_645_rtctime_to_YYMMDDhhmmss(&now_tm, (uint8_t*)&result.tm);
}
resp_len = sizeof(*result_hdr) + sizeof(result) + PROTO_645_2007_DI_LEN
+ sizeof(proto_645_tailer_t);
result_pkt = iot_pkt_alloc(resp_len, IOT_SMART_GRID_MID);
if (result_pkt) {
result_hdr = (proto_645_header_t*)iot_pkt_data(result_pkt);
/* fill in 645 header */
proto_645_header_init(result_hdr, hdr->addr,
PROTO_645_2007_FN_WRITE_DATA, PROTO_645_DIR_SLAVE,
PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
result_hdr->len = sizeof(result) + PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, result_hdr->data);
os_mem_cpy(result_hdr->data + PROTO_645_2007_DI_LEN, &result,
sizeof(result));
proto_645_add33_handle(result_hdr->data, result_hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(result_hdr);
iot_pkt_put(result_pkt, resp_len);
}
out:
if (reason) {
iot_printf("%s err %lu, is_trans %lu\n", __FUNCTION__, reason,
is_trans);
}
if (flag_sub33) {
proto_645_add33_handle(hdr->data, hdr->len);
}
return result_pkt;
}
static iot_pkt_t *proto_645_vendor_handle_br2_launch_zj_req(
proto_645_header_t *hdr)
{
uint8_t result_err = 0;
uint8_t req_data_len, is_trans = 1, flag_sub33 = 0;
uint32_t reason = 0;
iot_pkt_t *result_pkt = NULL;
proto_645_07_time_ymdhms_t launch_tm = {0};
proto_645_ext_br2_launch_zj_hdr_t *br_hdr = NULL;
proto_645_ext_br2_launch_zj_tail_t *br_tail = NULL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_ext_cus_topo_rcv_cfg_t cfg = {0};
(void)launch_tm;
if (!sta_glb->br2_enable) {
reason = 1;
goto out;
}
if (proto_645_vendor_br2_addr_check(hdr->addr)) {
reason = 2;
goto out;
}
req_data_len = sizeof(*br_hdr) + PROTO_645_2007_DI_LEN
+ sizeof(*br_tail);
if (hdr->len < req_data_len) {
reason = 3;
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
flag_sub33 = 1;
br_hdr = (proto_645_ext_br2_launch_zj_hdr_t*)(hdr->data +
PROTO_645_2007_DI_LEN);
req_data_len += br_hdr->code_len;
if (hdr->len < req_data_len) {
reason = 4;
goto out;
}
br_tail = (proto_645_ext_br2_launch_zj_tail_t*)(br_hdr->code +
br_hdr->code_len);
switch (br_hdr->trans_type) {
case PROTO_645_EXT_BR2_HANDLE:
{
is_trans = 0;
break;
}
case PROTO_645_EXT_BR2_TRANS:
{
reason = 5;
is_trans = 1;
goto out;
}
case PROTO_645_EXT_BR2_HANDLE_AND_TRANS:
{
is_trans = ((IOT_BSRM_MODE == IOT_BSRM_MODE_CUS_APP) || IOT_BRM_ENABLE)
? 0 : 1;
break;
}
default:
reason = 6;
is_trans = 1;
goto out;
}
if (br_hdr->tm.year != 0xff && br_hdr->tm.month != 0xff
&& br_hdr->tm.day != 0xff && br_hdr->tm.hour != 0xff
&& br_hdr->tm.minute != 0xff && br_hdr->tm.second != 0xff) {
launch_tm.year = iot_byte_to_bcd(br_hdr->tm.year);
launch_tm.month = iot_byte_to_bcd(br_hdr->tm.month);
launch_tm.day = iot_byte_to_bcd(br_hdr->tm.day);
launch_tm.hour = iot_byte_to_bcd(br_hdr->tm.hour);
launch_tm.minute = iot_byte_to_bcd(br_hdr->tm.minute);
launch_tm.second = iot_byte_to_bcd(br_hdr->tm.second);
} else {
launch_tm.year = 0xff;
launch_tm.month = 0xff;
launch_tm.day = 0xff;
launch_tm.hour = 0xff;
launch_tm.minute = 0xff;
launch_tm.second = 0xff;
}
cfg.fc = (br_hdr->freq[0]) | (br_hdr->freq[1] << 8) |
(br_hdr->freq[2] << 16);
cfg.chara_bit_dur = br_hdr->chara_bit_dur;
cfg.pulse_high_dur = br_tail->pulse_high_dur;
cfg.pulse_low_dur = br_tail->pulse_low_dur;
cfg.fr_code_len = br_hdr->code_len;
os_mem_cpy(cfg.fr_code, br_hdr->code, br_hdr->code_len);
iot_sg_ext_topo_rcv_cfg_to_cus(&cfg);
result_err = iot_sg_sta_tsfm_topo_br2_launch_start(&launch_tm,
br_hdr->code, br_hdr->code_len, br_tail->pulse_high_dur,
br_tail->pulse_low_dur, br_hdr->chara_bit_dur, NULL,
IOT_PLC_HW_TSFM_LOAD_ENCODE_RAW);
if (result_err) {
reason = 7;
goto resp;
}
result_err = 0;
resp:
if (is_trans) {
goto out;
}
if (result_err) {
result_pkt = proto_645_2007_build_nack_msg(result_err, hdr->addr,
PROTO_645_2007_FN_WRITE_DATA);
} else {
result_pkt = proto_645_2007_build_w_rsp(hdr->addr);
}
out:
if (reason) {
iot_printf("%s err %lu, is_trans %lu\n", __FUNCTION__, reason,
is_trans);
}
if (flag_sub33) {
proto_645_add33_handle(hdr->data, hdr->len);
}
return result_pkt;
}
static iot_pkt_t *proto_645_vendor_handle_br_launch_req_bj(
proto_645_header_t *hdr)
{
uint8_t req_data_len, ret;
uint32_t reason = 0;
iot_pkt_t *result_pkt = NULL;
proto_645_ext_br_launch_bj_t *br_launch = NULL;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_topo_info_t *topo_info = &sta_glb->hw_tsfm_info.tsfm_topo_info;
uint8_t launch_code[2];
(void)launch_code;
if (proto_645_vendor_br2_addr_check(hdr->addr)) {
goto out;
}
req_data_len = sizeof(*br_launch) + PROTO_645_2007_DI_LEN;
if (hdr->len < req_data_len) {
reason = 1;
goto resp;
}
proto_645_sub33_handle(hdr->data, hdr->len);
br_launch = (proto_645_ext_br_launch_bj_t*)(hdr->data +
PROTO_645_2007_DI_LEN);
if (br_launch->launch_sn == topo_info->branch2.sn
&& topo_info->branch2.sn_is_valid) {
goto resp;
}
launch_code[0] = (uint8_t)br_launch->node_seq & 0xFF;
launch_code[1] = (uint8_t)((br_launch->node_seq >> 8) & 0xFF);
if (PROTO_645_EXT_BR_BJ_NODE_ID_MAX < br_launch->node_seq ||
br_launch->node_seq == 0) {
reason = 2;
goto resp;
}
if (br_launch->chara_bit_dur > IOT_SG_STA_TSFM_BR2_CHARA_BIT_DUR_DEF) {
reason = 3;
goto resp;
}
ret = iot_sg_sta_tsfm_topo_br2_launch_start(NULL, launch_code,
sizeof(launch_code), br_launch->pulse_high_dur,
br_launch->pulse_low_dur, br_launch->chara_bit_dur, NULL,
IOT_PLC_HW_TSFM_LOAD_ENCODE_HAMMING_PREAMBLE_2);
if (ret) {
reason = 4;
}
topo_info->branch2.sn_is_valid = 1;
topo_info->branch2.sn = br_launch->launch_sn;
resp:
if (reason) {
iot_printf("%s err %lu\n", __FUNCTION__, reason);
result_pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER,
hdr->addr, PROTO_645_2007_FN_WRITE_DATA);
} else {
result_pkt = proto_645_2007_build_ack_msg(hdr->addr,
PROTO_645_2007_FN_WRITE_DATA);
}
out:
return result_pkt;
}
iot_pkt_t *proto_645_vendor_handle_br2_launch_xiongan_req(
proto_645_header_t *hdr)
{
uint8_t result_err, req_data_len, reason = 0;
uint8_t code[] = {0xAA, 0xE9}, data_len = 2;
iot_pkt_t *result_pkt = NULL;
proto_645_07_time_ymdhms_t *launch_start = NULL;
(void)code;
(void)data_len;
req_data_len = sizeof(*launch_start) + PROTO_645_2007_DI_LEN +
PROTO_645_2007_PASSWORD_LEN + PROTO_645_2007_OPERATOR_LEN;
if (hdr->len < req_data_len) {
reason = 1;
goto out;
}
if (proto_645_vendor_br2_addr_check(hdr->addr)) {
reason = 2;
goto out;
}
if (iot_sg_sta_tsfm_supp_mode_check(IOT_PLC_HW_TSFM_SEND_MODE_LOAD)) {
reason = 3;
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
launch_start = (proto_645_07_time_ymdhms_t *)(hdr->data +
PROTO_645_2007_DI_LEN + PROTO_645_2007_PASSWORD_LEN +
PROTO_645_2007_OPERATOR_LEN);
if (launch_start->year == 0xFF && launch_start->month == 0xFF &&
launch_start->day == 0xFF && launch_start->hour == 0xFF &&
launch_start->minute == 0xFF && launch_start->second == 0xFF) {
launch_start = NULL;
}
result_err = iot_sg_sta_tsfm_topo_br2_launch_start(launch_start, code,
data_len, IOT_SG_STA_TSFM_BR2_PULSE_HIGH_DUR_DEF,
IOT_SG_STA_TSFM_BR2_PULSE_LOW_DUR_DEF,
IOT_SG_STA_TSFM_BR2_CHARA_BIT_DUR_DEF, NULL,
IOT_PLC_HW_TSFM_LOAD_ENCODE_RAW);
if (result_err) {
result_pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER,
hdr->addr, PROTO_645_2007_FN_WRITE_DATA);
} else {
result_pkt = proto_645_2007_build_ack_msg(hdr->addr,
PROTO_645_2007_FN_WRITE_DATA);
}
out:
if (reason) {
iot_printf("%s err %lu\n", __FUNCTION__, reason);
}
return result_pkt;
}
iot_pkt_t *proto_645_vendor_handle_tsfm_send_req(proto_645_header_t *hdr_645)
{
uint8_t *data;
uint8_t size;
uint32_t ret;
iot_pkt_t *resp_pkt = NULL;
proto_645_header_t *resp_hdr;
uint8_t addr[IOT_MAC_ADDR_LEN];
proto_645_ext_tsfm_launch_req_t *head_device;
proto_645_ext_tsfm_launch_rsp_t *resp_result;
hw_tsfm_send_cfg_t cfg = { 0 };
iot_mac_addr_cpy(addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(addr);
if (!iot_mac_addr_cmp(addr, hdr_645->addr)) {
return NULL;
}
proto_645_sub33_handle(hdr_645->data, hdr_645->len);
if (hdr_645->len < (sizeof(*head_device) + PROTO_645_2007_DI_LEN)) {
return resp_pkt;
}
size = sizeof(*resp_hdr) + sizeof(proto_645_tailer_t)
+ sizeof(*resp_result);
resp_pkt = iot_pkt_alloc(size, IOT_SMART_GRID_MID);
IOT_ASSERT(resp_pkt);
data = iot_pkt_data(resp_pkt);
resp_hdr = (proto_645_header_t*)data;
proto_645_header_init(resp_hdr, hdr_645->addr, hdr_645->control.fn,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
resp_hdr->len = sizeof(*resp_result);
resp_result = (proto_645_ext_tsfm_launch_rsp_t *)resp_hdr->data;
head_device = (proto_645_ext_tsfm_launch_req_t *)
(hdr_645->data + PROTO_645_2007_DI_LEN);
if (head_device->repeat_cnt > PROTO_645_EXT_TSFM_SEND_REPEAT_CNT_MAX) {
head_device->repeat_cnt = PROTO_645_EXT_TSFM_SEND_REPEAT_CNT_DEF;
}
if (head_device->send_interval < PROTO_645_EXT_TSFM_SEND_INTERVAL_MIN ||
head_device->send_interval > PROTO_645_EXT_TSFM_SEND_INTERVAL_MAX) {
head_device->send_interval = PROTO_645_EXT_TSFM_SEND_INTERVAL_DEF;
}
cfg.mod_mode = IOT_PLC_HW_TSFM_SEND_MODE_ZC;
cfg.para.zc.dur_output = head_device->dur_output;
cfg.para.zc.ahead = head_device->ahead;
cfg.para.zc.is_rising = head_device->is_rising;
cfg.phase = IOT_PLC_PHASE_ALL;
ret = iot_sg_sta_tsfm_send_restart(head_device->repeat_cnt,
head_device->send_interval, head_device->tsfm_addr, &cfg,
head_device->sn);
iot_printf("%s ahead %lu, dur_output %lu, phase %lu is_rising: %d\n",
__FUNCTION__, cfg.para.zc.ahead, cfg.para.zc.dur_output, cfg.phase,
cfg.para.zc.is_rising);
if (ret == ERR_OK) {
resp_result->ret = PROTO_645_2007_EXT_TSFM_RESULT_OK;
} else {
resp_result->ret = PROTO_645_2007_EXT_TSFM_RESULT_BUSY;
}
proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
proto_645_tail_init(resp_hdr);
iot_pkt_put(resp_pkt, size);
return resp_pkt;
}
static iot_pkt_t *proto_645_vendor_handle_query_signal(proto_645_header_t *hdr,
int8_t snr, int8_t rssi)
{
uint8_t *fill_data, fill_len;
uint32_t resp_len;
iot_pkt_t *pkt = NULL;
proto_645_header_t *resp_hdr;
proto_645_07_ext_signal_resp_t *signal_resp;
uint32_t di = PROTO_645_2007_EXT_QUERY_SIGNAL_ID;
proto_645_sub33_handle(hdr->data, hdr->len);
fill_data = &hdr->data[PROTO_645_2007_DI_LEN];
fill_len = hdr->len - PROTO_645_2007_DI_LEN;
resp_len = sizeof(*resp_hdr) + PROTO_645_2007_DI_LEN
+ sizeof(*signal_resp) + fill_len + sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(resp_len, IOT_SMART_GRID_MID);
if (!pkt) {
goto drop;
}
resp_hdr = (proto_645_header_t*)iot_pkt_put(pkt, resp_len);
proto_645_header_init(resp_hdr, hdr->addr,
PROTO_645_2007_FN_READ_DATA, PROTO_645_DIR_SLAVE,
PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
resp_hdr->len = PROTO_645_2007_DI_LEN + sizeof(*signal_resp) + fill_len;
proto_645_2007_di_to_byte(di, resp_hdr->data);
signal_resp =
(proto_645_07_ext_signal_resp_t*)&resp_hdr->data[PROTO_645_2007_DI_LEN];
signal_resp->dl_snr = snr;
signal_resp->dl_rssi = rssi;
os_mem_cpy(signal_resp->fill_data, fill_data, fill_len);
proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
proto_645_tail_init(resp_hdr);
goto out;
drop:
iot_printf("%s fail\n", __FUNCTION__);
out:
return pkt;
}
static iot_pkt_t *proto_645_vendor_handle_conn_tsfm_query(
proto_645_header_t *hdr_645)
{
uint8_t *data, size, addr[IOT_MAC_ADDR_LEN], flag_3p = 0, v_rps = 0;
uint32_t di = PROTO_645_2007_EXT_BRM_DI_CONN_NODE_TSFM_INFO;
iot_pkt_t *resp_pkt = NULL;
proto_645_header_t *resp_hdr;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_properties_global_t *phase_info = &sta_glb->node_properties;
iot_sg_sta_app_info_t *sta_pib = iot_sg_sta_get_rw_pib();
proto_645_ext_br_rsp_data_t *resp_data;
proto_645_07_ext_brm_nei_node_tsfm_ul_t *resp_result;
iot_sg_sta_node_desc_t *node;
iot_mac_addr_cpy(addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(addr);
if (!iot_mac_addr_cmp(addr, hdr_645->addr) || !sta_pib) {
goto drop;
}
size = sizeof(*resp_hdr) + sizeof(proto_645_tailer_t)
+ sizeof(*resp_result) + sizeof(*resp_data);
resp_pkt = iot_pkt_alloc(size, IOT_SMART_GRID_MID);
if (!resp_pkt) {
goto drop;
}
data = iot_pkt_data(resp_pkt);
resp_hdr = (proto_645_header_t*)data;
proto_645_header_init(resp_hdr, hdr_645->addr, hdr_645->control.fn,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
resp_hdr->len = sizeof(*resp_result) + sizeof(*resp_data);
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;
resp_result = (proto_645_07_ext_brm_nei_node_tsfm_ul_t*)resp_data->data;
iot_mac_addr_cpy(addr, p_sg_glb->plc_state.cco_addr);
iot_mac_addr_reverse(addr);
iot_mac_addr_cpy(resp_result->cco_addr, addr);
iot_mac_addr_cpy(resp_result->tsfm_addr, sta_pib->tsfm_addr);
resp_result->phase_1 = GW_APP_DATA_PHASE_DEFAULT;
resp_result->phase_2 = GW_APP_DATA_PHASE_DEFAULT;
resp_result->phase_3 = GW_APP_DATA_PHASE_DEFAULT;
switch (sta_pib->phase) {
case IOT_PLC_PHASE_A:
{
resp_result->phase_1 = GW_APP_DATA_PHASE_A;
break;
}
case IOT_PLC_PHASE_B:
{
resp_result->phase_1 = GW_APP_DATA_PHASE_B;
break;
}
case IOT_PLC_PHASE_C:
{
resp_result->phase_1 = GW_APP_DATA_PHASE_C;
break;
}
default:
goto finish;
}
if ((phase_info->detect_state && (phase_info->phase > 1))
|| iot_sg_sta_is_3p_module()) {
v_rps = phase_info->opposite_phase;
flag_3p = 1;
} else {
iot_mac_addr_cpy(addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(addr);
node = iot_sg_sta_node_find_by_addr(addr);
if (sta_glb->drv && (sta_glb->drv->get_device_type() ==
IOT_SG_STA_DEV_TYPE_POWER_METER) && node) {
v_rps = node->v_rps;
flag_3p = node->is_three_phase;
}
}
if (flag_3p) {
switch (resp_result->phase_1) {
case GW_APP_DATA_PHASE_A:
{
if (v_rps) {
resp_result->phase_2 = GW_APP_DATA_PHASE_C;
resp_result->phase_3 = GW_APP_DATA_PHASE_B;
} else {
resp_result->phase_2 = GW_APP_DATA_PHASE_B;
resp_result->phase_3 = GW_APP_DATA_PHASE_C;
}
break;
}
case GW_APP_DATA_PHASE_B:
{
if (v_rps) {
resp_result->phase_2 = GW_APP_DATA_PHASE_A;
resp_result->phase_3 = GW_APP_DATA_PHASE_C;
} else {
resp_result->phase_2 = GW_APP_DATA_PHASE_C;
resp_result->phase_3 = GW_APP_DATA_PHASE_A;
}
break;
}
case GW_APP_DATA_PHASE_C:
{
if (v_rps) {
resp_result->phase_2 = GW_APP_DATA_PHASE_B;
resp_result->phase_3 = GW_APP_DATA_PHASE_A;
} else {
resp_result->phase_2 = GW_APP_DATA_PHASE_A;
resp_result->phase_3 = GW_APP_DATA_PHASE_B;
}
break;
}
default:
break;
}
}
finish:
proto_645_add33_handle(resp_hdr->data, resp_hdr->len);
proto_645_tail_init(resp_hdr);
iot_pkt_put(resp_pkt, size);
goto out;
drop:
iot_printf("%s fail\n", __FUNCTION__);
out:
return resp_pkt;
}
static void proto_645_vendor_handle_br_correct_time_req(
proto_645_header_t *hdr)
{
uint8_t *data, len;
iot_time_tm_t iot_ts = { 0 };
proto_645_corr_time_t *time;
proto_645_sub33_handle(hdr->data, hdr->len);
data = hdr->data + PROTO_645_2007_DI_LEN;
len = hdr->len - PROTO_645_2007_DI_LEN;
if (iot_bcd_data_check(data, len) && (len >= sizeof(*time))) {
time = (proto_645_corr_time_t*)data;
/* the year is incomplete in DL/T 645 protocol,
* so it add 2000
*/
iot_ts.tm_year = iot_bcd_to_byte(time->year) + 2000;
iot_ts.tm_mon = iot_bcd_to_byte(time->month);
iot_ts.tm_mday = iot_bcd_to_byte(time->day);
iot_ts.tm_hour = iot_bcd_to_byte(time->hour);
iot_ts.tm_min = iot_bcd_to_byte(time->minute);
iot_ts.tm_sec = iot_bcd_to_byte(time->second);
if (iot_sg_sta_get_user_type() == USER_TYPE_BRM_PEIWANG_DUAL_NET) {
iot_sg_sta_rtc_set(&iot_ts, 1);
iot_sg_sta_start_get_time();
}
}
}
static iot_pkt_t *proto_645_vendor_handle_br2_launch_record_query(
proto_645_header_t *hdr, uint32_t di, uint32_t *handle)
{
uint8_t resp_data_len, last_idx = 0;
uint32_t resp_size;
iot_time_tm_t *tm;
iot_pkt_t *result_pkt = NULL;
proto_645_header_t *result_hdr;
proto_645_ext_br2_record_cnt_rsp_t *resp_cnt;
proto_645_ext_br2_record_resp_t *resp_record;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
iot_sg_sta_topo_info_t *topo_info = &sta_glb->hw_tsfm_info.tsfm_topo_info;
iot_sg_sta_tsfm_topo_record_t *record = &topo_info->send_record;
if (!sta_glb->br2_enable) {
if (handle) {
*handle = 0;
}
goto out;
}
if (proto_645_vendor_br2_addr_check(hdr->addr)) {
goto out;
}
if (di == PROTO_645_2007_EXT_DI_BR2_RECORD_CNT) {
resp_data_len = PROTO_645_2007_DI_LEN + sizeof(*resp_cnt);
} else {
resp_data_len = PROTO_645_2007_DI_LEN + sizeof(*resp_record);
last_idx = (uint8_t)(di & 0x000000ff);
if (last_idx > record->cnt) {
goto out;
}
}
resp_size = sizeof(*result_hdr) + resp_data_len +
sizeof(proto_645_tailer_t);
result_pkt = iot_pkt_alloc(resp_size, IOT_SMART_GRID_MID);
if (result_pkt) {
result_hdr = (proto_645_header_t*)iot_pkt_data(result_pkt);
/* fill in 645 header */
proto_645_header_init(result_hdr, hdr->addr,
PROTO_645_2007_FN_READ_DATA, PROTO_645_DIR_SLAVE,
PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
result_hdr->len = resp_data_len;
proto_645_2007_di_to_byte(di, result_hdr->data);
if (di == PROTO_645_2007_EXT_DI_BR2_RECORD_CNT) {
resp_cnt = (proto_645_ext_br2_record_cnt_rsp_t*)
&result_hdr->data[PROTO_645_2007_DI_LEN];
resp_cnt->record_cnt = iot_byte_to_bcd(record->cnt);
} else {
if (last_idx > record->idx) {
last_idx = IOT_SG_STA_TSFM_TOPO_RECORD_CNT_MAX + record->idx -
last_idx;
} else {
last_idx = record->idx - last_idx;
}
resp_record = (proto_645_ext_br2_record_resp_t*)
&result_hdr->data[PROTO_645_2007_DI_LEN];
tm = &record->list[last_idx].start_tm;
resp_record->start_tm.year = iot_byte_to_bcd((uint8_t)(tm->tm_year -
2000));
resp_record->start_tm.month = iot_byte_to_bcd(tm->tm_mon);
resp_record->start_tm.day = iot_byte_to_bcd(tm->tm_mday);
resp_record->start_tm.hour = iot_byte_to_bcd(tm->tm_hour);
resp_record->start_tm.minute = iot_byte_to_bcd(tm->tm_min);
resp_record->start_tm.second = iot_byte_to_bcd(tm->tm_sec);
tm = &record->list[last_idx].end_tm;
resp_record->end_tm.year = iot_byte_to_bcd((uint8_t)(tm->tm_year -
2000));
resp_record->end_tm.month = iot_byte_to_bcd(tm->tm_mon);
resp_record->end_tm.day = iot_byte_to_bcd(tm->tm_mday);
resp_record->end_tm.hour = iot_byte_to_bcd(tm->tm_hour);
resp_record->end_tm.minute = iot_byte_to_bcd(tm->tm_min);
resp_record->end_tm.second = iot_byte_to_bcd(tm->tm_sec);
}
proto_645_add33_handle(result_hdr->data, result_hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(result_hdr);
iot_pkt_put(result_pkt, resp_size);
}
out:
return result_pkt;
}
static iot_pkt_t *proto_645_vendor_handle_br2_launch_hn_req(
proto_645_header_t *hdr)
{
uint8_t result_err, req_data_len, reason = 0, flag_sub33 = 0;
iot_pkt_t *result_pkt = NULL;
proto_645_ext_br2_launch_fn_t *launch_start = NULL;
if (iot_sg_sta_tsfm_supp_mode_check(IOT_PLC_HW_TSFM_SEND_MODE_LOAD)) {
reason = 1;
goto out;
}
if (proto_645_vendor_br2_addr_check(hdr->addr)) {
reason = 2;
goto out;
}
req_data_len = sizeof(*launch_start) + PROTO_645_2007_DI_LEN;
if (hdr->len < req_data_len) {
reason = 3;
goto out;
}
proto_645_sub33_handle(hdr->data, hdr->len);
flag_sub33 = 1;
launch_start = (proto_645_ext_br2_launch_fn_t*)(hdr->data +
PROTO_645_2007_DI_LEN);
req_data_len = req_data_len + launch_start->code_len;
if (hdr->len < req_data_len) {
reason = 4;
goto out;
}
result_err = iot_sg_sta_tsfm_topo_br2_launch_start(NULL,
launch_start->code, launch_start->code_len,
IOT_SG_STA_TSFM_BR2_PULSE_HIGH_DUR_DEF,
IOT_SG_STA_TSFM_BR2_PULSE_LOW_DUR_DEF,
IOT_SG_STA_TSFM_BR2_CHARA_BIT_DUR_DEF, NULL,
IOT_PLC_HW_TSFM_LOAD_ENCODE_RAW);
if (result_err) {
result_pkt = proto_645_2007_build_nack_msg(PROTO_645_2007_ERR_OTHER,
hdr->addr, PROTO_645_1997_FN_WRITE_DATA);
} else {
result_pkt = proto_645_2007_build_ack_msg(hdr->addr,
PROTO_645_1997_FN_WRITE_DATA);
}
out:
if (reason) {
iot_printf("%s err %lu\n", __FUNCTION__, reason);
}
if (flag_sub33) {
proto_645_add33_handle(hdr->data, hdr->len);
}
return result_pkt;
}
/**
* @brief Verify whether the message format is trigger topology.
* The message uses the fn 0x04 (only DL/T 645.97), but uses 4-byte
* Di(only DL/T 645.07), so special verification is required.
*/
static uint32_t proto_645_vendor_br2_launch_hn_format_check(
proto_645_header_t *hdr)
{
uint32_t ret = ERR_FAIL;
uint32_t di = 0;
proto_645_ext_br2_launch_fn_t *start = NULL;
uint8_t length = PROTO_645_2007_DI_LEN + sizeof(*start);
uint8_t len_tmp = 0;
if (!hdr && hdr->len < length) {
goto out;
}
if (ERR_OK == proto_645_get_di_by_sub33(hdr->data, hdr->len,
PROTO_645_2007_ID, &di)) {
if (di == PROTO_645_EXT_BR2_LAUNCH_START) {
start = (proto_645_ext_br2_launch_fn_t*)(hdr->data +
PROTO_645_2007_DI_LEN);
len_tmp = start->code_len;
proto_645_sub33_handle(&len_tmp, sizeof(len_tmp));
length += len_tmp;
if (hdr->len == length) {
ret = ERR_OK;
}
}
}
out:
return ret;
}
/**
* @brief Parse the PPM Ping package and return the data.
*/
static iot_pkt_t *proto_645_vendor_handle_ppm_ping(proto_645_header_t *hdr)
{
int reason = 0;
iot_pkt_t *rsp_pkt = NULL;
uint32_t length = 0;
uint8_t mac[IOT_MAC_ADDR_LEN] = {0};
proto_645_header_t *rsp_header = NULL;
iot_sg_plc_state_t *plc_glb = &p_sg_glb->plc_state;
if (hdr->len < (sizeof(proto_645_ext_brm_ppm_ping_t) +
PROTO_645_2007_DI_LEN)) {
reason = 1;
goto drop;
}
iot_mac_addr_cpy(mac, hdr->addr);
iot_mac_addr_reverse(mac);
if (!iot_mac_addr_cmp(mac, plc_glb->addr)) {
reason = 2;
goto drop;
}
length = sizeof(*hdr) + hdr->len + sizeof(proto_645_tailer_t);
rsp_pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (!rsp_pkt) {
reason = 2;
goto drop;
}
rsp_header = (proto_645_header_t *)iot_pkt_data(rsp_pkt);
proto_645_header_init(rsp_header, hdr->addr, hdr->control.fn,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL, PROTO_645_FOLLOW_INVALID);
rsp_header->len = hdr->len;
os_mem_cpy(rsp_header->data, hdr->data, hdr->len);
proto_645_tail_init(rsp_header);
iot_pkt_put(rsp_pkt, length);
goto out;
drop:
if (rsp_pkt) {
iot_pkt_free(rsp_pkt);
rsp_pkt = NULL;
}
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
out:
return rsp_pkt;
}
static iot_pkt_t *proto_645_vendor_handle_query_pt_info(uint8_t *addr)
{
uint32_t length, di = PROTO_645_2007_EXT_QUERY_PT_INFO;
iot_pkt_t *pkt;
proto_645_header_t *hdr = NULL;
proto_645_ext_read_pt_info_rsp_t *rsp = NULL;
iot_board_pt_info_t pt_info = {0};
length = PROTO_645_2007_READ_DATA_PKT_LEN +
sizeof(proto_645_ext_read_pt_info_rsp_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, addr, PROTO_645_2007_FN_READ_DATA,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(proto_645_ext_read_pt_info_rsp_t) +
PROTO_645_2007_DI_LEN;
proto_645_2007_di_to_byte(di, hdr->data);
rsp = (proto_645_ext_read_pt_info_rsp_t *)(hdr->data +
PROTO_645_2007_DI_LEN);
os_mem_set((uint8_t *)rsp, 0, sizeof(*rsp));
iot_board_get_pt_info(&pt_info);
/* production test ppm */
if (pt_info.ppm_valid) {
rsp->local_pt_ppm_valid = 1;
rsp->local_pt_ppm = pt_info.ppm;
}
/* compensation ppm, not used for sta/cco */
rsp->local_tool_ppm_valid = 0;
/* basic production test info */
if (pt_info.basic_info_valid) {
rsp->basic_data_valid = 1;
iot_mac_addr_cpy(rsp->basic_data.golden_mac,
pt_info.basic_info.golden_mac);
rsp->basic_data.year = pt_info.basic_info.year;
rsp->basic_data.month = pt_info.basic_info.month;
rsp->basic_data.day = pt_info.basic_info.day;
rsp->basic_data.hour = pt_info.basic_info.hour;
rsp->basic_data.min = pt_info.basic_info.min;
rsp->basic_data.golden_fw_ver = pt_info.basic_info.golden_fw_ver;
rsp->basic_data.pt_tool_ver = pt_info.basic_info.pt_tool_ver;
rsp->basic_data.pt_board_ver = pt_info.basic_info.pt_board_ver;
}
/* the dut firmware version, which supported the production test */
if (pt_info.pt_dut_ver_valid) {
rsp->pt_dut_fw_valid = 1;
rsp->pt_dut_fw_ver = pt_info.pt_dut_ver;
}
/* fix ppm ,not used for sta/cco */
rsp->local_fix_ppm_valid = 0;
proto_645_add33_handle(hdr->data, hdr->len);
/* fill in 645 tailer */
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
uint32_t proto_645_handle_vendor_proto(uint8_t *data, uint32_t len,
int8_t snr, int8_t rssi)
{
uint32_t handled = 0, di, ret;
uint8_t fn, data_type, user_type = iot_sg_sta_get_user_type();
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
data_type = (uint8_t)sta_glb->mr.data_type;
hdr = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
if (!hdr) {
goto out;
}
if (hdr->control.fn == PROTO_645_1997_FN_WRITE_DATA) {
if (proto_645_vendor_br2_launch_hn_format_check(hdr) == ERR_OK) {
pkt = proto_645_vendor_handle_br2_launch_hn_req(hdr);
if (pkt) {
handled = 1;
}
goto out;
}
}
ret = proto_645_get_di(data, len, PROTO_645_DIR_MASTER, &di, &fn);
switch (hdr->control.fn) {
case PROTO_645_2007_EXT_FN_QUERY_ID:
{
if (hdr->len == PROTO_645_EXT_QUERY_ID_DATA_LEN) {
handled = 1;
pkt = proto_645_vendor_build_id_info(hdr->addr, hdr->data[0]);
} else if (hdr->len == PROTO_645_2007_DI_LEN &&
di == PROTO_645_2007_EXT_DI_TCZ_READ_VER) {
handled = 1;
pkt = proto_645_vendor_build_tcz_ver_info(hdr->addr);
} else if (!hdr->len) {
handled = 1;
pkt = proto_645_vendor_build_hn_id_info(hdr->addr);
}
break;
}
case PROTO_645_2007_EXT_FN_BR:
{
if (ret != ERR_OK) {
goto out;
}
switch (di) {
case PROTO_645_2007_EXT_DI_BR_LAUNCH:
{
handled = 1;
pkt = proto_645_vendor_handle_br_launch_req(hdr, di, 1);
break;
}
case PROTO_645_2007_EXT_DI_BR_LAUNCH_STATE:
{
handled = 1;
pkt = proto_645_vendor_handle_br_launch_state_req(hdr, di, 1);
break;
}
case PROTO_645_2007_EXT_DI_BR_INFO_QUERY:
{
handled = 1;
pkt = proto_645_vendor_handle_br_info_query_req(hdr, di, 1);
break;
}
case PROTO_645_2007_EXT_DI_BR_INFO_CLEAN:
{
handled = 1;
pkt = proto_645_vendor_handle_br_info_clean_req(hdr, di, 1);
break;
}
case PROTO_645_2007_EXT_DI_TSFM_LAUNCH:
{
handled = 1;
pkt = proto_645_vendor_handle_tsfm_send_req(hdr);
break;
}
case PROTO_645_2007_EXT_DI_TSFM_LAUNCH_CLEAR:
{
handled = 1;
pkt = proto_645_vendor_build_tsfm_clear_req(hdr, di);
break;
}
case PROTO_645_2007_EXT_BRM_DI_CONN_NODE_TSFM_INFO:
{
handled = 1;
pkt = proto_645_vendor_handle_conn_tsfm_query(hdr);
break;
}
case PROTO_645_2007_EXT_BRM_CONN_CORRECT:
{
handled = 1;
proto_645_vendor_handle_br_correct_time_req(hdr);
break;
}
case PROTO_645_2007_EXT_BRM_PPM_PING:
{
handled = 1;
pkt = proto_645_vendor_handle_ppm_ping(hdr);
break;
}
default:
break;
}
break;
}
default:
if (ret != ERR_OK) {
goto out;
}
switch (di) {
case PROTO_645_2007_EXT_DI_READ_VER:
{
handled = 1;
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_build_ver_info(hdr->addr);
}
break;
}
case PROTO_645_2007_EXT_DI_READ_VER_2:
{
handled = 1;
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_build_ver2_info(hdr->addr);
}
break;
}
case PROTO_645_2007_EXT_DI_READ_TSFM_INFO:
case PROTO_645_2007_EXT_DI_WRITE_TSFM_INFO:
{
ret = iot_sg_sta_tsfm_msg_handle_from_cco(data_type, data, len);
if (ret == ERR_OK) {
return 1;
}
break;
}
case PROTO_645_2007_EXT_DI_SET_ID_INFO:
{
handled = 1;
ret = proto_645_vendor_handle_set_id_info_req(hdr, len);
/* set MC_ID only responds OK or INVAL */
pkt = proto_645_vendor_build_set_id_info_rsp(hdr->addr, ret);
break;
}
case PROTO_645_2007_READ_NW_VER:
{
handled = 1;
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_build_mac_and_ver_info(hdr->addr,
PROTO_645_2007_FN_READ_DATA);
}
break;
}
case PROTO_645_2007_DI_START_SCORE:
{
handled = 1;
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA &&
iot_mac_addr_cmp(hdr->addr, proto_645_bcast_addr) &&
!sta_glb->ext_info.score_info.enable) {
sta_glb->ext_info.score_info.enable = 1;
sta_glb->ext_info.score_info.score_en_ts =
os_boot_time64() / 1000;
}
break;
}
case PROTO_645_2007_EXT_QUERY_SIGNAL_ID:
{
if (user_type == USER_TYPE_STATE_GRID_FUJIAN) {
goto out;
}
handled = 1;
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_handle_query_signal(hdr, snr, rssi);
}
break;
}
case PROTO_645_2007_EXT_QUERY_PT_INFO:
{
handled = 1;
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_handle_query_pt_info(hdr->addr);
}
break;
}
case PROTO_645_2007_EXT_DI_BR2_RECORD_CNT:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST1:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST2:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST3:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST4:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST5:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST6:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST7:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST8:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST9:
case PROTO_645_2007_EXT_DI_BR2_RECORD_LAST10:
{
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
handled = 1;
pkt = proto_645_vendor_handle_br2_launch_record_query(hdr, di,
&handled);
}
break;
}
case PROTO_645_2007_EXT_DI_BR2_LAUNCH_ZJ:
{
if (hdr->control.fn == PROTO_645_2007_FN_WRITE_DATA) {
pkt = proto_645_vendor_handle_br2_launch_zj_req(hdr);
if (pkt) {
handled = 1;
}
}
break;
}
case PROTO_645_2007_EXT_DI_BR2_LAUNCH:
{
if (hdr->control.fn == PROTO_645_2007_FN_WRITE_DATA) {
pkt = proto_645_vendor_handle_br2_launch_yns_req(hdr);
if (pkt) {
handled = 1;
}
}
break;
}
case PROTO_645_2007_EXT_DI_BR_BJ_INIT:
{
if (hdr->control.fn == PROTO_645_2007_FN_WRITE_DATA) {
pkt = proto_645_vendor_handle_br_recv_init_bj(hdr);
if (pkt) {
handled = 1;
}
}
break;
}
case PROTO_645_2007_EXT_DI_BR_BJ_LAUNCH:
{
if (hdr->control.fn == PROTO_645_2007_FN_WRITE_DATA) {
pkt = proto_645_vendor_handle_br_launch_req_bj(hdr);
if (pkt) {
handled = 1;
}
}
break;
}
case PROTO_645_2007_EXT_DI_BR_BJ_INFO_QUERY:
{
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_handle_br_info_query_req_bj(hdr);
if (pkt) {
handled = 1;
}
}
break;
}
case PROTO_645_2007_EXT_DI_BR2_LAUNCH_XIONGAN:
{
if (hdr->control.fn == PROTO_645_2007_FN_WRITE_DATA) {
pkt = proto_645_vendor_handle_br2_launch_xiongan_req(hdr);
if (pkt) {
handled = 1;
}
}
break;
}
case PROTO_645_2007_EXT_READ_CORE_TEMPERATURE:
{
handled = 1;
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_build_core_temperature_info(hdr->addr);
}
break;
}
default:
break;
}
break;
}
out:
if (handled) {
iot_sg_sta_meter_read_done_framework(data_type, pkt);
}
return handled;
}
iot_pkt_t *proto_645_handle_vendor_proto_cco(uint8_t *cco_addr,
uint8_t *data, uint32_t len, int8_t snr, int8_t rssi)
{
uint32_t di, ret;
uint8_t fn;
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr;
hdr = proto_645_format_check(data, len, PROTO_645_DIR_MASTER);
if (!hdr) {
goto out;
}
if (!iot_mac_addr_cmp(hdr->addr, cco_addr)) {
goto out;
}
ret = proto_645_get_di(data, len, PROTO_645_DIR_MASTER, &di, &fn);
if (ret != ERR_OK) {
goto out;
}
switch (di) {
case PROTO_645_2007_EXT_QUERY_SIGNAL_ID:
{
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_handle_query_signal(hdr, snr, rssi);
}
break;
}
case PROTO_645_2007_EXT_QUERY_PT_INFO:
{
if (hdr->control.fn == PROTO_645_2007_FN_READ_DATA) {
pkt = proto_645_vendor_handle_query_pt_info(hdr->addr);
}
break;
}
default:
break;
}
out:
return pkt;
}
static iot_pkt_t *proto_645_vendor_get_mod_sw_ver()
{
uint32_t length = 0;
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr = NULL;
proto_645_ext_ft_mode_code_t *func = NULL;
proto_645_ext_ft_mode_sw_ver_resp_t *sw_ver = NULL;
uint8_t buf_addr[IOT_MAC_ADDR_LEN];
iot_build_info_t build_info;
length = sizeof(*hdr) + sizeof(proto_645_tailer_t) + sizeof(*func) +
sizeof(*sw_ver);
iot_mac_addr_cpy(buf_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(buf_addr);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, buf_addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(*func) + sizeof(*sw_ver);
iot_version_get_user_build_info(&build_info);
func = (proto_645_ext_ft_mode_code_t *)hdr->data;
func->ft_mode = PROTO_645_EXT_FT_MODE_GET_SW_VER;
sw_ver = (proto_645_ext_ft_mode_sw_ver_resp_t *)func->data;
sw_ver->day = iot_byte_to_bcd(build_info.day);
sw_ver->mon = iot_byte_to_bcd(build_info.month);
sw_ver->year = iot_byte_to_bcd(build_info.year);
sw_ver->ver = iot_version_packed();
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
static iot_pkt_t *proto_645_vendor_set_chip_mmid(proto_645_header_t *header)
{
uint8_t reason = 0;
uint32_t ret = ERR_FAIL, length = 0;
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr = NULL;
proto_645_ext_ft_mode_code_t *func;
uint8_t buf_addr[IOT_MAC_ADDR_LEN];
if (header->len < (sizeof(*func) + IOT_CHIP_MMID_LEN)) {
reason = 1;
goto out;
}
func = (proto_645_ext_ft_mode_code_t *)header->data;
ret = iot_oem_set_chip_mmid(func->data, IOT_CHIP_MMID_LEN, 1);
if (ret != ERR_OK) {
reason = 2;
goto out;
}
length = sizeof(*hdr) + sizeof(*func) + IOT_CHIP_MMID_LEN +
sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
iot_mac_addr_cpy(buf_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(buf_addr);
proto_645_header_init(hdr, buf_addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = IOT_CHIP_MMID_LEN + sizeof(proto_645_ext_ft_mode_code_t);
func = (proto_645_ext_ft_mode_code_t *)hdr->data;
func->ft_mode = PROTO_645_EXT_FT_MODE_GET_CHIP_MMID;
iot_oem_get_chip_mmid(func->data, IOT_CHIP_MMID_LEN);
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
out:
if (reason) {
iot_sg_printf("%s reason %lu\n", __FUNCTION__, reason);
}
return pkt;
}
static iot_pkt_t *proto_645_vendor_get_chip_mmid(proto_645_header_t *header)
{
uint32_t length = 0;
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr = NULL;
proto_645_ext_ft_mode_code_t *func = NULL;
uint8_t buf_addr[IOT_MAC_ADDR_LEN];
(void)header;
length = sizeof(*hdr) + sizeof(*func) + IOT_CHIP_MMID_LEN +
sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
iot_mac_addr_cpy(buf_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(buf_addr);
proto_645_header_init(hdr, buf_addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(*func) + IOT_CHIP_MMID_LEN;
func = (proto_645_ext_ft_mode_code_t *)hdr->data;
func->ft_mode = PROTO_645_EXT_FT_MODE_GET_CHIP_MMID;
iot_oem_get_chip_mmid(func->data, IOT_CHIP_MMID_LEN);
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
static iot_pkt_t *proto_645_vendor_zc_check()
{
iot_pkt_t *pkt = NULL;
uint32_t length = 0;
uint8_t i, buf_addr[IOT_MAC_ADDR_LEN];
iot_sg_sta_zc_check_t *check = &p_sg_glb->desc.sta->check;
proto_645_header_t *hdr = NULL;
proto_645_ext_ft_mode_code_t *func = NULL;
proto_645_ext_ft_mode_zc_check_info_t *zc_info = NULL;
iot_mac_addr_cpy(buf_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(buf_addr);
iot_sg_sta_zc_start();
os_delay(500);
iot_sg_sta_zc_stop();
length = sizeof(*hdr) + sizeof(*func) + sizeof(*zc_info) +
sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
proto_645_header_init(hdr, buf_addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(*func) + sizeof(*zc_info);
func = (proto_645_ext_ft_mode_code_t *)hdr->data;
func->ft_mode = PROTO_645_EXT_FT_MODE_ZC_CHECK;
zc_info = (proto_645_ext_ft_mode_zc_check_info_t *)func->data;
zc_info->clct_type = PROTO_645_EXT_ZC_CLCT_MODE_RISING;
zc_info->meter_type = iot_sg_sta_is_3p_module()
? PROTO_645_EXT_ZC_METER_PHASE_THREE
: PROTO_645_EXT_ZC_METER_PHASE_SINGLE;
for (i = 0; i < IOT_PLC_PHASE_CNT; i++) {
if (check->trig_cnt[i] == 0) {
continue;
}
zc_info->data[i].exist = 1;
zc_info->data[i].period =
(check->total_time[i] / check->trig_cnt[i]) * 25;
}
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
iot_pkt_t *proto_645_vendor_set_comm_address(proto_645_header_t *header)
{
uint8_t reason = 0;
uint32_t length = 0;
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr = NULL;
proto_645_ext_ft_mode_code_t *func = NULL;
uint8_t buf_addr[IOT_MAC_ADDR_LEN];
(void)header;
if (header->len != (sizeof(*func) + IOT_MAC_ADDR_LEN)) {
reason = 1;
goto out;
}
func = (proto_645_ext_ft_mode_code_t *)header->data;
iot_mac_addr_reverse(func->data);
iot_oem_set_module_mac(func->data);
length = sizeof(*hdr) + sizeof(*func) + IOT_MAC_ADDR_LEN +
sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
iot_mac_addr_cpy(buf_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(buf_addr);
proto_645_header_init(hdr, buf_addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(*func) + IOT_MAC_ADDR_LEN;
func = (proto_645_ext_ft_mode_code_t *)hdr->data;
func->ft_mode = PROTO_645_EXT_FT_MODE_SET_COMM_ADDR;
if (iot_oem_get_module_mac(func->data)) {
os_mem_set(func->data, 0xFF, IOT_MAC_ADDR_LEN);
} else {
iot_mac_addr_reverse(func->data);
}
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
out:
if (reason) {
iot_sg_printf("%s reason %u\n", __FUNCTION__, reason);
if (pkt) {
iot_pkt_free(pkt);
pkt = NULL;
}
}
return pkt;
}
iot_pkt_t *proto_645_vendor_get_comm_address(proto_645_header_t *header)
{
uint32_t length = 0;
iot_pkt_t *pkt = NULL;
proto_645_header_t *hdr = NULL;
proto_645_ext_ft_mode_code_t *func = NULL;
uint8_t buf_addr[IOT_MAC_ADDR_LEN];
(void)header;
length = sizeof(*hdr) + sizeof(*func) + IOT_MAC_ADDR_LEN +
sizeof(proto_645_tailer_t);
pkt = iot_pkt_alloc(length, IOT_SMART_GRID_MID);
if (pkt) {
hdr = (proto_645_header_t *)iot_pkt_data(pkt);
iot_mac_addr_cpy(buf_addr, p_sg_glb->plc_state.addr);
iot_mac_addr_reverse(buf_addr);
proto_645_header_init(hdr, buf_addr, PROTO_645_2007_EXT_FN_QUERY_ID,
PROTO_645_DIR_SLAVE, PROTO_645_ACK_NORMAL,
PROTO_645_FOLLOW_INVALID);
hdr->len = sizeof(*func) + IOT_MAC_ADDR_LEN;
func = (proto_645_ext_ft_mode_code_t *)hdr->data;
func->ft_mode = PROTO_645_EXT_FT_MODE_GET_COMM_ADDR;
if (iot_oem_get_module_mac(func->data)) {
os_mem_set(func->data, 0xFF, IOT_MAC_ADDR_LEN);
} else {
iot_mac_addr_reverse(func->data);
}
proto_645_tail_init(hdr);
iot_pkt_put(pkt, length);
}
return pkt;
}
iot_pkt_t *proto_645_vendor_sta_nw_ext_uart_cmd_handle(
proto_645_header_t *header)
{
iot_pkt_t *pkt = NULL;
proto_645_ext_ft_mode_code_t *func = NULL;
if (header->len < sizeof(*func)) {
goto out;
}
func = (proto_645_ext_ft_mode_code_t *)header->data;
switch (func->ft_mode) {
case PROTO_645_EXT_FT_MODE_GET_CHIP_MMID:
{
pkt = proto_645_vendor_get_chip_mmid(header);
break;
}
case PROTO_645_EXT_FT_MODE_SET_CHIP_MMID:
{
pkt = proto_645_vendor_set_chip_mmid(header);
break;
}
case PROTO_645_EXT_FT_MODE_ZC_CHECK:
{
pkt = proto_645_vendor_zc_check();
break;
}
case PROTO_645_EXT_FT_MODE_GET_SW_VER:
{
pkt = proto_645_vendor_get_mod_sw_ver();
break;
}
case PROTO_645_EXT_FT_MODE_SET_COMM_ADDR:
{
pkt = proto_645_vendor_set_comm_address(header);
break;
}
case PROTO_645_EXT_FT_MODE_GET_COMM_ADDR:
{
pkt = proto_645_vendor_get_comm_address(header);
break;
}
default:
break;
}
out:
return pkt;
}
#endif /* IOT_SMART_GRID_ENABLE && PLC_SUPPORT_STA_ROLE */