2250 lines
75 KiB
C
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 */
|