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 */
 |